def addLabelAbbrToken(self, tok: str, timestamp: HumNumIn, part: int, staff: int, voice: int, maxPart: int) -> GridSlice: ts: HumNum = opFrac(timestamp) gs: GridSlice if not self.slices or self.slices[-1].timestamp < ts: # add a new GridSlice to an empty list or at end of list if timestamp # is after last entry in list. gs = GridSlice(self, ts, SliceType.LabelAbbrs, maxPart) gs.addToken(tok, part, staff, voice) self.slices.append(gs) return gs # search for existing line with same timestamp and the same slice type for gridSlice in self.slices: if gridSlice.timestamp == ts and gridSlice.isLabelAbbrSlice: gridSlice.addToken(tok, part, staff, voice) gs = gridSlice return gs # Couldn't find a place for the label abbr, so place at beginning of measure gs = GridSlice(self, ts, SliceType.LabelAbbrs, maxPart) gs.addToken(tok, part, staff, voice) self.slices.insert(0, gs) return gs
def addLayoutParameter(self, associatedSlice: GridSlice, partIndex: int, staffIndex: int, voiceIndex: int, locomment: str) -> None: # add this '!LO:' string just before this associatedSlice if len(self.slices) == 0: # something strange happened: expecting at least one item in measure. # associatedSlice is supposed to already be in the measure. return associatedSliceIdx: t.Optional[int] = None if associatedSlice is None: # place at end of measure (associate with imaginary slice just off the end) associatedSliceIdx = len(self.slices) else: # find owning line (associatedSlice) foundIt: bool = False for associatedSliceIdx in range(len(self.slices) - 1, -1, -1): gridSlice: GridSlice = self.slices[associatedSliceIdx] if gridSlice is associatedSlice: foundIt = True break if not foundIt: # cannot find owning line (a.k.a. associatedSlice is not in this GridMeasure) return # see if the previous slice is a layout slice we can use prevIdx: int = associatedSliceIdx - 1 prevSlice: GridSlice = self.slices[prevIdx] if prevSlice.isLocalLayoutSlice: prevStaff: GridStaff = prevSlice.parts[partIndex].staves[staffIndex] prevVoice: GridVoice = self._getIndexedVoice_AppendingIfNecessary(prevStaff.voices, voiceIndex) if prevVoice.token is None or prevVoice.token.text == '!': prevVoice.token = HumdrumToken(locomment) return # if we get here, we couldn't use the previous slice, so we need to insert # a new Layout slice to use, just before the associated slice. insertPoint: int = associatedSliceIdx newSlice: GridSlice if associatedSlice is not None: newSlice = GridSlice(self, associatedSlice.timestamp, SliceType.Layouts) newSlice.initializeBySlice(associatedSlice) self.slices.insert(insertPoint, newSlice) else: newSlice = GridSlice(self, self.timestamp + self.duration, SliceType.Layouts) newSlice.initializeBySlice(self.slices[-1]) self.slices.append(newSlice) newStaff: GridStaff = newSlice.parts[partIndex].staves[staffIndex] newVoice: GridVoice = self._getIndexedVoice_AppendingIfNecessary(newStaff.voices, voiceIndex) newVoice.token = HumdrumToken(locomment)
def addVerseLabels(self, associatedSlice: GridSlice, partIndex: int, staffIndex: int, verseLabels: t.List[t.Optional[HumdrumToken]]) -> None: # add these verse labels just before this associatedSlice if len(self.slices) == 0: # something strange happened: expecting at least one item in measure. # associatedSlice is supposed to already be in the measure. return associatedSliceIdx: t.Optional[int] = None if associatedSlice is None: # place at end of measure (associate with imaginary slice just off the end) associatedSliceIdx = len(self.slices) else: # find owning line (associatedSlice) foundIt: bool = False for associatedSliceIdx in range(len(self.slices) - 1, -1, -1): gridSlice: GridSlice = self.slices[associatedSliceIdx] if gridSlice is associatedSlice: foundIt = True break if not foundIt: # cannot find owning line (a.k.a. associatedSlice is not in this GridMeasure) return # see if the previous slice is a VerseLabels slice we can use prevIdx: int = associatedSliceIdx - 1 prevSlice: GridSlice = self.slices[prevIdx] if prevSlice.isVerseLabelSlice: prevStaff: GridStaff = prevSlice.parts[partIndex].staves[staffIndex] if prevStaff.sides.verseCount == 0: for i, verseLabel in enumerate(verseLabels): if verseLabel is not None: prevStaff.sides.setVerse(i, verseLabel) return # if we get here, we couldn't use the previous slice, so we need to insert # a new Layout slice to use, just before the associated slice. insertPoint: int = associatedSliceIdx newSlice: GridSlice if associatedSlice is not None: newSlice = GridSlice(self, associatedSlice.timestamp, SliceType.VerseLabels) newSlice.initializeBySlice(associatedSlice) self.slices.insert(insertPoint, newSlice) else: newSlice = GridSlice(self, self.timestamp + self.duration, SliceType.VerseLabels) newSlice.initializeBySlice(self.slices[-1]) self.slices.append(newSlice) newStaff: GridStaff = newSlice.parts[partIndex].staves[staffIndex] for i, verseLabel in enumerate(verseLabels): if verseLabel is not None: newStaff.sides.setVerse(i, verseLabel)
def addDynamicsLayoutParameters(self, associatedSlice: GridSlice, partIndex: int, staffIndex: int, locomment: str): if len(self.slices) == 0: # something strange happened: expecting at least one item in measure. return # associatedSlice is supposed to already be in the measure # find owning line (associatedSlice) foundIt: bool = False associatedSliceIdx: int = None for associatedSliceIdx in range(len(self.slices) - 1, -1, -1): # loop in reverse index order gridSlice: GridSlice = self.slices[associatedSliceIdx] if gridSlice is associatedSlice: foundIt = True break if not foundIt: # cannot find owning line (a.k.a. associatedSlice is not in this GridMeasure) return # see if the previous slice is a layout slice we can use prevIdx: int = associatedSliceIdx - 1 prevSlice: GridSlice = self.slices[prevIdx] if prevSlice.isLocalLayoutSlice: prevStaff: GridStaff = prevSlice.parts[partIndex].staves[ staffIndex] if prevStaff.dynamics is None: prevStaff.dynamics = HumdrumToken(locomment) return # if we get here, we couldn't use the previous slice, so we need to insert # a new Layout slice to use, just before the associated slice. insertPoint: int = associatedSliceIdx newSlice: GridSlice = GridSlice(self, associatedSlice.timestamp, SliceType.Layouts) newSlice.initializeBySlice(associatedSlice) self.slices.insert(insertPoint, newSlice) newStaff: GridStaff = newSlice.parts[partIndex].staves[staffIndex] newStaff.dynamics = HumdrumToken(locomment)
def addGraceToken(self, tok: str, timestamp: HumNum, part: int, staff: int, voice: int, maxStaff: int, graceNumber: int) -> GridSlice: if graceNumber < 1: raise HumdrumInternalError( 'ERROR: graceNumber {} has to be larger than 0') gs: GridSlice = None if not self.slices: # add a new GridSlice to an empty list. gs = GridSlice(self, timestamp, SliceType.GraceNotes, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.append(gs) return gs if timestamp > self.slices[-1].timestamp: # Grace note needs to be added at the end of a measure. idx: int = len(self.slices) - 1 # pointing at last slice counter: int = 0 while idx >= 0: if self.slices[idx].isGraceSlice: counter += 1 if counter == graceNumber: # insert grace note into this slice self.slices[idx].addToken(tok, part, staff, voice) return self.slices[idx] elif self.slices[idx].isLocalLayoutSlice: # skip over any layout parameter lines idx -= 1 continue if self.slices[idx].isDataSlice: # insert grace note after this note gs = GridSlice(self, timestamp, SliceType.GraceNotes, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.insert(idx + 1, gs) return gs idx -= 1 return None # couldn't find anywhere to insert # search for existing line with same timestamp on a data slice: foundIndex: int = -1 for idx, gridSlice in enumerate(self.slices): if timestamp < gridSlice.timestamp: raise HumdrumInternalError( f'''STRANGE CASE 2 IN GRIDMEASURE::ADDGRACETOKEN \tGRACE TIMESTAMP: {timestamp} \tTEST TIMESTAMP: {gridSlice.timestamp}''') if gridSlice.isDataSlice: if gridSlice.timestamp == timestamp: foundIndex = idx break idx: int = foundIndex - 1 counter: int = 0 while idx >= 0: if self.slices[idx].isGraceSlice: counter += 1 if counter == graceNumber: # insert grace note into this slice self.slices[idx].addToken(tok, part, staff, voice) return self.slices[idx] elif self.slices[idx].isLocalLayoutSlice: # skip over any layout parameter lines idx -= 1 continue if self.slices[idx].isDataSlice: # insert grace note after this note gs = GridSlice(self, timestamp, SliceType.GraceNotes, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.insert(idx + 1, gs) return gs idx -= 1 # grace note should be added at start of measure gs = GridSlice(self, timestamp, SliceType.GraceNotes, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.insert(0, gs) return gs
def appendGlobalLayout(self, tok: str, timestamp: HumNum) -> GridSlice: gs: GridSlice = GridSlice(self, timestamp, SliceType.GlobalLayouts, 1) gs.addToken(tok, 0, 0, 0) gs.duration = HumNum(0) self.slices.append(gs) return gs
def addGlobalComment(self, tok: str, timestamp: HumNum) -> GridSlice: gs: GridSlice = None if not self.slices or self.slices[-1].timestamp < timestamp: # add a new GridSlice to an empty list or at end of list if timestamp # is after last entry in list. gs = GridSlice(self, timestamp, SliceType.GlobalComments, 1) gs.addToken(tok, 0, 0, 0) self.slices.append(gs) return gs # search for existing data line (of any type) with the same timestamp for idx, gridSlice in enumerate(self.slices): # does it need to be before data slice or any slice? # if (((*iterator)->getTimestamp() == timestamp) && (*iterator)->isDataSlice()) if gridSlice.timestamp == timestamp: # found the correct timestamp on a slice, so add the global comment # before the slice. But don't add if the slice we found is a # global comment with the same text. if gridSlice.isGlobalComment: if tok == gridSlice.parts[0].staves[0].voices[ 0].token.text: # do not insert duplicate global comments gs = gridSlice return gs gs = GridSlice(self, timestamp, SliceType.GlobalComments, 1) gs.addToken(tok, 0, 0, 0) self.slices.insert(idx, gs) return gs if gridSlice.timestamp > timestamp: # insert before this slice gs = GridSlice(self, timestamp, SliceType.GlobalComments, 1) gs.addToken(tok, 0, 0, 0) self.slices.insert(idx, gs) return gs return None # I think we should put it at the beginning in this case --gregc
def addTokenOfSliceType(self, tok: str, timestamp: HumNum, sliceType: SliceType, part: int, staff: int, voice: int, maxStaff: int) -> GridSlice: gs: GridSlice = None if not self.slices or self.slices[-1].timestamp < timestamp: # add a new GridSlice to an empty list or at end of list if timestamp # is after last entry in list. gs = GridSlice(self, timestamp, sliceType, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.append(gs) return gs # search for existing line with same timestamp and the same slice type for idx, gridSlice in enumerate(self.slices): if gridSlice.timestamp == timestamp and gridSlice.sliceType == sliceType: gridSlice.addToken(tok, part, staff, voice) gs = gridSlice return gs if gridSlice.timestamp == timestamp and gridSlice.isDataSlice: # found the correct timestamp, but no slice of the right type at the # timestamp, so add the new slice before the data slice (eventually # keeping track of the order in which the other non-data slices should # be placed). gs = GridSlice(self, timestamp, sliceType, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.insert(idx, gs) return gs if gridSlice.timestamp > timestamp: gs = GridSlice(self, timestamp, sliceType, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.insert(idx, gs) return gs # Couldn't find a place for the token, so place at end of measure gs = GridSlice(self, timestamp, sliceType, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.append(gs) return gs
def addDataToken(self, tok: str, timestamp: HumNum, part: int, staff: int, voice: int, maxStaff: int) -> GridSlice: gs: GridSlice = None if not self.slices or self.slices[-1].timestamp < timestamp: # add a new GridSlice to an empty list or at end of list if timestamp # is after last entry in list. gs = GridSlice(self, timestamp, SliceType.Notes, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.append(gs) return gs # search for existing line with same timestamp and the same slice type for idx, gridSlice in enumerate(self.slices): if timestamp == gridSlice.timestamp and gridSlice.isGraceSlice: # skip grace notes with the right timestamp continue if not gridSlice.isDataSlice: continue if gridSlice.timestamp == timestamp: gridSlice.addToken(tok, part, staff, voice) gs = gridSlice return gs if gridSlice.timestamp > timestamp: gs = GridSlice(self, timestamp, SliceType.Notes, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.insert(idx, gs) return gs # Couldn't find a place for it, so place at end of measure. gs = GridSlice(self, timestamp, SliceType.Notes, maxStaff) gs.addToken(tok, part, staff, voice) self.slices.append(gs) return gs