Browse Source

support for patroneo groups

master
Nils 3 years ago
parent
commit
9125a9a9fa
  1. 8
      template/engine/api.py
  2. 35
      template/engine/sequencer.py

8
template/engine/api.py

@ -78,7 +78,7 @@ class Callbacks(object):
def _dataChanged(self):
"""Only called from within the callbacks.
"""Only called from within the callbacks or template api.
This is about data the user cares about. In other words this is the indicator if you need
to save again.
@ -130,7 +130,8 @@ class Callbacks(object):
def _setPlaybackTicks(self):
"""This gets called very very often. Any connected function needs to watch closely
"""This gets called very very often (~60 times per second).
Any connected function needs to watch closely
for performance issues"""
ppqn = cbox.Transport.status().pos_ppqn
status = playbackStatus()
@ -237,12 +238,13 @@ class Callbacks(object):
"""New track, delete track, reorder
Sent the current track order as list of ids, combined with their structure.
This is also used when tracks get created or deleted, also on initial load.
This also includes the pattern.
"""
session.data.updateJackMetadataSorting()
lst = [track.export() for track in session.data.tracks]
for func in self.numberOfTracksChanged:
func(lst)
self._dataChanged() #includes _historyChanged
def _metronomeChanged(self):
"""returns a dictionary with meta data such as the mute-state and the track name"""

35
template/engine/sequencer.py

@ -88,6 +88,7 @@ class Score(Data):
#Tracks
def addTrack(self, name:str=""):
"""Create and add a new track. Not an existing one"""
track = Score.TrackClass(parentData=self, name=name)
assert track.sequencerInterface
self.tracks.append(track)
@ -96,6 +97,7 @@ class Score(Data):
def deleteTrack(self, track):
track.sequencerInterface.prepareForDeletion()
self.tracks.remove(track)
return track #for undo
def updateJackMetadataSorting(self):
"""Add this to you "tracksChanged" or "numberOfTracksChanged" callback.
@ -105,12 +107,16 @@ class Score(Data):
self.tracks changed and subsequent sorting. Multiple track changes in a row are common,
therefore the place to update jack order is in the API, where the new track order is also
sent to the UI.
We also check if the track is 'deactivated' by probing track.cboxMidiOutUuid.
Patroneo uses prepareForDeletion to deactive the tracks standalone track but keeps the
interface around for later use.
"""
order = {portName:index for index, portName in enumerate(track.sequencerInterface.cboxPortName() for track in self.tracks)}
order = {portName:index for index, portName in enumerate(track.sequencerInterface.cboxPortName() for track in self.tracks if track.sequencerInterface.cboxMidiOutUuid)}
try:
cbox.JackIO.Metadata.set_all_port_order(order)
except Exception as e: #No Jack Meta Data
except Exception as e: #No Jack Meta Data or Error with ports.
logger.error(e)
def trackById(self, trackId:int):
@ -195,6 +201,8 @@ class _Interface(object):
def _isNameAvailable(self, name:str):
"""Check if the name is free. If not increment"""
name = ''.join(ch for ch in name if ch.isalnum() or ch in (" ", "_", "-")) #sanitize
name = " ".join(name.split()) #remove double spaces
while name in [tr.sequencerInterface.name for tr in self.parentData.tracks]:
beforeLastChar = name[-2]
lastChar = name[-1]
@ -319,7 +327,7 @@ class SequencerInterface(_Interface): #Basically the midi part of a track.
def _processAfterInit(self):
#Create midi out and cbox track
logger.info("Creating empty SequencerInterface instance")
logger.info(f"Creating empty SequencerInterface instance for {self._name}")
super()._processAfterInit()
self.cboxMidiOutUuid = cbox.JackIO.create_midi_output(self._name)
self.calfboxTrack.set_external_output(self.cboxMidiOutUuid)
@ -346,7 +354,8 @@ class SequencerInterface(_Interface): #Basically the midi part of a track.
def name(self, value):
if not value in (track.sequencerInterface.name for track in self.parentData.tracks):
self._name = self._isNameAvailable(value)
cbox.JackIO.rename_midi_output(self.cboxMidiOutUuid, self._name)
if self.cboxMidiOutUuid: #we could be deactivated
cbox.JackIO.rename_midi_output(self.cboxMidiOutUuid, self._name)
def cboxPortName(self)->str:
"""Return the complete jack portname: OurName:PortName"""
@ -360,7 +369,14 @@ class SequencerInterface(_Interface): #Basically the midi part of a track.
undo. That is why we bother setting calfboxTrack to None
again.
"""
portlist = cbox.JackIO.get_connected_ports(self.cboxPortName())
if not self.calfboxTrack: #maybe non-template part deactivated it, like Patroneo groups
return
try:
portlist = cbox.JackIO.get_connected_ports(self.cboxPortName())
except: #port not found.
portlist = []
self._beforeDeleteThisJackMidiWasConnectedTo = portlist
self.calfboxTrack.set_external_output("")
@ -411,6 +427,15 @@ class SequencerInterface(_Interface): #Basically the midi part of a track.
self._subtracks[key].setSubtrack(blobs)
def deleteSubtrack(self, key):
"""Remove a subtrack.
Return for a potential undo"""
self._subtracks[key].prepareForDeletion()
toDelete = self._subtracks[key]
del self._subtracks[key]
return toDelete
#Save / Load / Export
def serialize(self)->dict:
"""Generate Data to save as json"""

Loading…
Cancel
Save