"""Move the oldItems parentBlocks to the new item"""
#self.parentBlocks = oldItem.parentBlocks #TODO. We took that out when pasting after deleting a track and recreating failed. Why do we to copy the parentBlocks when a parentBlock is added during block.insert anyway? Wild guess: we don't.
"""Move the oldItems parentBlocks to the new item"""
#self.parentBlocks = oldItem.parentBlocks #TODO. We took that out when pasting after deleting a track and recreating failed. Why do we to copy the parentBlocks when a parentBlock is added during block.insert anyway? Wild guess: we don't.
deflogicalDuration(self):
return0
@ -1347,8 +1347,8 @@ class Chord(Item):
fornoteinself.notelist:
oldValues.append(note.duration.copy())#we don't actually need a copy since we create a new one. But better safe than sorry. This matches also the behaviour of the other duration change functions.
schemepairs="".join(schemepairs.split())# split and join again to reduce all whitespaces to single ones.
subtextRoot="\\once \\override Staff.KeySignature #'stencil = #(lambda (grob) (ly:stencil-combine-at-edge (ly:key-signature-interface::print grob) Y DOWN (grob-interpret-markup grob (markup #:small \""+pitchmath.pitch2ly[self.root].strip(",").title()+"\")) 3)) "#3 is the space between keysig and text
schemepairs="".join(schemepairs.split())# split and join again to reduce all whitespaces to single ones.
subtextRoot="\\once \\override Staff.KeySignature #'stencil = #(lambda (grob) (ly:stencil-combine-at-edge (ly:key-signature-interface::print grob) Y DOWN (grob-interpret-markup grob (markup #:small \""+pitchmath.pitch2ly[self.root].strip(",").title()+"\")) 3)) "#3 is the space between keysig and text
cbox.Pattern.serialize_event(tickPosition,0xB0+trackState.midiChannel(),0,self.msb),#position, status byte+channel, controller number, controller value
cbox.Pattern.serialize_event(tickPosition,0xB0+trackState.midiChannel(),32,self.lsb),#position, status byte+channel, controller number, controller value
],
],
"shortInstrumentName":self.shortInstrumentName,
"UIstring":"{}[pr{}{}{}]".format(_nameStr,self.program,_msbStr,_lsbStr),#this is for a UI, possibly a text UI, maybe for simple items of a GUI. Make it as short and unambigious as possible.
}
}
def_lilypond(self):
"""called by block.lilypond(), returns a string.
Don't create white-spaces yourself, this is done by the structures.
self.ccGraphTracks={}#cc number, graphTrackCC. Every CC is its own SequencerTrack that routes to this tracks jack midi out
self.ccChannels=tuple()#unsorted numbers from 0-15 which represent the midi channels all CCs are sent to. Only replaced by a new tuple by the user directly. From json this becomes a list, so don't test for type. If empty then CC uses the initial midi channel.
self.blocks=[Block(track=self)]
self.blocks=[Block(track=self)]
self.durationSettingsSignature=DurationSettingsSignature()#only one per track
self.dynamicSettingsSignature=DynamicSettingsSignature()#only one per track
self.upbeatInTicks=0#playback does not care about upbeats. But exporting does. for example barlines.
self.dynamicSettingsSignature=DynamicSettingsSignature()#only one per track
self.upbeatInTicks=0#playback does not care about upbeats. But exporting does. for example barlines.
self.double=False#if true add 5 stafflines extra below. Clef will always stay in the upper staff. This is a representation-hint. E.g. a gui can offer a bigger staff system for the user.
#A set of starting values. They are user editable and represent the tracks playback state on head(). Therefore they get saved.
self.initialMidiChannel=0# 0-15
self.initialMidiProgram=-1# 0-127. -1 is "don't send"
self.initialMidiBankMsb=0# 0-127. Depends on program >= 0
self.initialMidiBankLsb=0# 0-127. Depends on program >= 0
self.initialMidiBankLsb=0# 0-127. Depends on program >= 0
self.midiTranspose=0# -127 to +127 but the result is never outside of 0-127.1 Cannot change during the track.
#The instrument names are also handled by the trackState so that the cursor knows about instrument changes
self.initialInstrumentName=""#different than the track name. e.g. "Violin"
self.initialShortInstrumentName=""# e.g. "vl"
self.asMetronomeData=None#This track as metronome version. Is always up to date through export.
self._processAfterInit()
def_processAfterInit(self):
@ -417,8 +417,8 @@ class Track(object):
returnself.sequencerInterface.name
@name.setter
defname(self,newValue):
self.sequencerInterface.name=newValue
defname(self,newValue):
self.sequencerInterface.name=newValue
defduration(self):
"""Return the duration of the whole track, in ticks"""
@ -569,7 +569,7 @@ class Track(object):
"""We don't use goToTickIndex for this because that
#TODO: However, it is even less elegant to put this call in all rhythm editing methods and functions. inserts, block duplicate, content links, augment, tuplets undo etc.
#Taken out an placed in tempo Export. #self.score.tempoTrack.expandLastBlockToScoreDuration() #we guarantee that the tempo track is always at least as long as the music tracks.
midiNotesBinaryCboxData=bytes()# Create a binary blob that contains the MIDI events
midiNotesBinaryCboxData=bytes()# Create a binary blob that contains the MIDI events
instrumentChangesBinaryCboxData=bytes()# same as above, but only for instrument changes.
originalPosition=self.state.position()
self.getPreliminaryData()
barlines=OrderedDict()#tick:metricalInstruction . We do not use selft.state.barlines, which is simply barlines for the live cursor. This is to send Barlines to a UI and also to generate the Metronome by associating a metricalInstruction with each barline.
@ -1026,14 +1026,14 @@ class Track(object):
resultAppend(expObj)
dur=expObj["completeDuration"]
ifexpObj["type"]!="InstrumentChange":
forblobinexpObj["midiBytes"]:#a list of
forblobinexpObj["midiBytes"]:#a list of
midiNotesBinaryCboxData+=blob
ifexpObj["type"]=="Chord"orexpObj["type"]=="Rest":#save for later when we create Beams. No other use.
_allExportedChordsAppend(expObj)
else:
_allExportedChordsAppend(expObj)
else:
forblobinexpObj["midiBytes"]:#a list of
instrumentChangesBinaryCboxData+=blob
elifr==2:#block end. Again, this is already the previous state. right now we are in the next block already.
lastBlock=self.blocks[self.state.blockindex-1]#why -1? see comment above
dur=lastBlock.staticExportEndMarkerDuration()
@ -1076,8 +1076,8 @@ class Track(object):
#Metronome start
#The metronome cannot be calculated by simply looking at metricalInstructions.
#We need to look at the barlines. Two instructions in a row at the same tick are wrong,
#but technically possible. These are not two full measures of metronome
#Metronome end. Nothing below is connected with the metronome subtrack.
#Calculate the beam positions for the static groups.
@ -1120,14 +1120,14 @@ class Track(object):
ifsum(s[2]forsinstems)>=0:#beam upwards direction
direction=1
length=-5
beamPosition=minimum+length
startDotOnLineKeyword="highestPitchAsDotOnLine"
beamPosition=minimum+length-1#if not -1 it will be the same as the highest note, in wide intervals
startDotOnLineKeyword="lowestPitchAsDotOnLine"
#assert beamPosition <= 0
else:#beam down direction
length=5
beamPosition=maximum+length
beamPosition=maximum+length+2#if not +2 it will be in the position of lowest note, in wide intervals
direction=-1
startDotOnLineKeyword="lowestPitchAsDotOnLine"
startDotOnLineKeyword="highestPitchAsDotOnLine"
#assert beamPosition > 0
#beams have the same syntax and structure as a stem.
@ -1144,7 +1144,6 @@ class Track(object):
currentSubGroupFlag=obj["flag"]
subBeamGroups[-1].append(obj)
forsubBeamGroupinsubBeamGroups:
forobjinsubBeamGroup:
startStaffLine=obj[startDotOnLineKeyword]
@ -1158,15 +1157,15 @@ class Track(object):
resultAppend(metaData)
metaData["barlines"]=barlines.keys()
metaData["duration"]=self.state.tickindex#tickindex is now at the end, so this is the end duration. This includes Blocks minimumDuration as well since it is included in left/right
self.sequencerInterface.setTrack([t])#(bytes-blob, position, length) #tickindex is still on the last position, which means the second parameter is the length