|
|
@ -32,11 +32,16 @@ from template.engine.input_midi import MidiInput |
|
|
|
#Our Modules |
|
|
|
import engine.api as api |
|
|
|
|
|
|
|
""" |
|
|
|
This file is used directly. It is a global part of the engine (see bottom of the file) |
|
|
|
that uses the api directly, which in turn triggers the GUI. |
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
class StepMidiInput(MidiInput): |
|
|
|
class StepMidiInput(MidiInput): |
|
|
|
"""We initialize with everything switched off. This makes it easier for a complex system |
|
|
|
of engine, GUI and midiinput to start up and get the order of operations right |
|
|
|
|
|
|
|
|
|
|
|
For chord entry we use the first note only as indicator. The indicator was a set() at one time, |
|
|
|
which means that as long as one of the chord notes would still be down the chord was still "on". |
|
|
|
That is not as robust and convenient as using the starting note, which is counter intuitive, |
|
|
@ -45,50 +50,50 @@ class StepMidiInput(MidiInput): |
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
#No super init in here! This is delayed until self.start |
|
|
|
self.firstActiveNote = None #for chord entry. |
|
|
|
self._currentlyActiveNotes = set() |
|
|
|
self.firstActiveNote = None #for chord entry. |
|
|
|
self._currentlyActiveNotes = set() |
|
|
|
|
|
|
|
def start(self): |
|
|
|
"""Call this manually after the engine and an event loop have started. |
|
|
|
For example from the GUI. It is currently started by mainwindow.py start() |
|
|
|
But it could be started from a simple command line interface as well.""" |
|
|
|
But it could be started from a simple command line interface as well.""" |
|
|
|
assert api.laborejoEngineStarted |
|
|
|
super().__init__(session=api.session, portName="in") |
|
|
|
self.midiProcessor.active = False #specific to Laborejo |
|
|
|
|
|
|
|
#Connect the template midi input with Laborejo api calls. |
|
|
|
self.midiProcessor.active = False #specific to Laborejo |
|
|
|
|
|
|
|
#Connect the template midi input with Laborejo api calls. |
|
|
|
#self.midiProcessor.notePrinter(True) |
|
|
|
self.midiProcessor.register_NoteOn(self._insertMusicItemFromMidi) |
|
|
|
self.midiProcessor.register_NoteOff(self._pop) |
|
|
|
|
|
|
|
|
|
|
|
api.callbacks.setCursor.append(self._setMidiThru) #When the track changes re-route cbox RT midi thru |
|
|
|
api.callbacks._setCursor(destroySelection = False) #Force once to trigger a cursor export which calls our midi thru setter |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
def midiInIsActive(self): |
|
|
|
try: |
|
|
|
return self.midiProcessor.active |
|
|
|
except AttributeError: #during startupt |
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
def _insertMusicItemFromMidi(self, timeStamp, channel, midipitch, velocity): |
|
|
|
if self._currentlyActiveNotes: #Chord |
|
|
|
api.left() |
|
|
|
keysig = api.session.data.currentTrack().state.keySignature() |
|
|
|
pitchToInsert = api.pitchmath.fromMidi(midipitch, keysig) |
|
|
|
api.addNoteToChord(pitchToInsert) |
|
|
|
api.right() |
|
|
|
api.right() |
|
|
|
else: #Single note |
|
|
|
baseDuration = api.session.data.cursor.prevailingBaseDuration |
|
|
|
keysig = api.session.data.currentTrack().state.keySignature() |
|
|
|
pitchToInsert = api.pitchmath.fromMidi(midipitch, keysig) |
|
|
|
api.insertChord(baseDuration, pitchToInsert) |
|
|
|
|
|
|
|
|
|
|
|
self._currentlyActiveNotes.add(midipitch) |
|
|
|
|
|
|
|
|
|
|
|
def _pop(self, timeStamp, channel, midipitch, velocity): |
|
|
|
self._currentlyActiveNotes.remove(midipitch) |
|
|
|
|
|
|
|
self._currentlyActiveNotes.remove(midipitch) |
|
|
|
|
|
|
|
def setMidiInputActive(self, state:bool): |
|
|
|
self.midiProcessor.active = state |
|
|
|
api.callbacks._prevailingBaseDurationChanged(api.session.data.cursor.prevailingBaseDuration) |
|
|
@ -98,9 +103,9 @@ class StepMidiInput(MidiInput): |
|
|
|
|
|
|
|
def _setMidiThru(self, cursorExport): |
|
|
|
"""We don't need to react to deleted tracks because that does reset the cursor. |
|
|
|
The template midi in does _not_ check if the routed output ports still exist. |
|
|
|
however, that is a low risk state that needs changes in the program""" |
|
|
|
self.setMidiThru(cursorExport["cboxMidiOutUuid"]) |
|
|
|
The template midi in does _not_ check if the routed output ports still exist. |
|
|
|
however, that is a low risk state that needs changes in the program""" |
|
|
|
self.setMidiThru(cursorExport["cboxMidiOutUuid"]) |
|
|
|
self.setMidiThruChannel(cursorExport["midiChannel"]+1) #cursor midi channel is 0 based |
|
|
|
|
|
|
|
stepMidiInput = StepMidiInput() #global to use in other parts of Laborejo |
|
|
|