def_template_processAfterInit(self):#needs a different name because there is an inherited class with the same method.
"""Call this after either init or instanceFromSerializedData"""
@ -119,11 +120,21 @@ class Score(Data):
exceptExceptionase:#No Jack Meta Data or Error with ports.
logger.error(e)
deftrackById(self,trackId:int):
"""Returns a track or None, if not found"""
fortrackinself.tracks:
iftrackId==id(track):
returntrack
raiseValueError(f"Track {trackId} not found. Current Tracks: {[id(tr)fortrinself.tracks]}")
else:
#Previously this crashed with a ValueError. However, after a rare bug that a gui widget focussed out because a track was deleted and then tried to send its value to the engine we realize that this lookup can gracefully return None.
#Nothing will break: Functions that are not aware yet, that None is an option will crash when they try to access None as a track object. For this case we present the following logger error:
ifnottrackIdinself._tracksFailedLookup:
logger.error(f"Track {trackId} not found. Current Tracks: {[id(tr)fortrinself.tracks]}")
self._tracksFailedLookup.append(trackId)#prevent multiple error messages for the same track in a row.
returnNone
#raise ValueError(f"Track {trackId} not found. Current Tracks: {[id(tr) for tr in self.tracks]}")