You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
4.3 KiB
103 lines
4.3 KiB
#! /usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Copyright 2019, Nils Hilbricht, Germany ( https://www.hilbricht.net )
|
|
|
|
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
|
|
more specifically its template base application.
|
|
|
|
The Template Base Application is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
import logging; logging.info("import {}".format(__file__))
|
|
|
|
#Python Standard Library
|
|
|
|
#Third Party Modules
|
|
|
|
#Template Modules
|
|
from template.engine.input_midi import MidiInput
|
|
|
|
#Our Modules
|
|
import engine.api as api
|
|
|
|
|
|
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,
|
|
therefore documented here.
|
|
"""
|
|
|
|
def __init__(self):
|
|
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."""
|
|
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.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
|
|
|
|
@property
|
|
def midiInIsActive(self):
|
|
try:
|
|
return self.midiProcessor.active
|
|
except AttributeError: #during startupt
|
|
return False
|
|
|
|
def _insertMusicItemFromMidi(self, 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()
|
|
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, channel, midipitch, velocity):
|
|
self._currentlyActiveNotes.remove(midipitch)
|
|
|
|
def setMidiInputActive(self, state:bool):
|
|
self.midiProcessor.active = state
|
|
api.callbacks._prevailingBaseDurationChanged(api.session.data.cursor.prevailingBaseDuration)
|
|
|
|
def toggleMidiIn(self):
|
|
self.setMidiInputActive(not self.midiInIsActive)
|
|
|
|
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"])
|
|
|
|
stepMidiInput = StepMidiInput() #global to use in other parts of Laborejo
|
|
|