From 351e83c1efc813f0325e586c716cc56e9cbef50d Mon Sep 17 00:00:00 2001 From: evgenyslab Date: Wed, 24 Apr 2019 19:22:31 -0400 Subject: [PATCH] added merge to reserve only midi notes and cc's on the channels defined in settings (or default channel) this frees up the same notes on different channels to be passed to Ableton - this allows controllers to have notes controlling Live functions on reserved channels, while same notes on different channels will be played by the instrument --- SelectedTrackControl.py | 64 ++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/SelectedTrackControl.py b/SelectedTrackControl.py index 3ce8217..56a7706 100755 --- a/SelectedTrackControl.py +++ b/SelectedTrackControl.py @@ -39,6 +39,7 @@ def __init__(self, c_instance): self._device_control, QuantizationControl(c_instance, self), ) + self.prevMsg = None def mapping_parse_recursive(self, mapping): tuple_type = type((1,2)); @@ -75,32 +76,62 @@ def update_display(self): def connect_script_instances(self, instanciated_scripts): pass - + + + def recursive_forward_midi(self,script_handle,midi_map_handle, data): + # need to check if tuple, or not: + if type(data)==tuple: + # Live.Base.log("tuple detected") + for i in data: + self.recursive_forward_midi(script_handle, midi_map_handle,i) + elif isinstance(data,MIDI.Note) or isinstance(data,MIDI.NoteOff): + # Live.Base.log("recusrive_forward_midi logging Note: channel %d, key %d" % (data.channel, data.key)) + Live.MidiMap.forward_midi_note(script_handle, midi_map_handle, data.channel, data.key) + elif isinstance(data,MIDI.CC): + # Live.Base.log("recusrive_forward_midi logging CC: channel %d, key %d" % (data.channel, data.key)) + Live.MidiMap.forward_midi_cc(script_handle, midi_map_handle, data.channel, data.key) + else: + # Live.Base.log("Type didn't work...") + # Live.Base.log(type(data).__name__) + pass + + # called from Live to build the MIDI bindings def build_midi_map(self, midi_map_handle): #log("SelectedTrackControl::build_midi_map") script_handle = self.c_instance.handle() - - for channel in range(16): - callbacks = self.midi_callbacks.get(channel, {}) - - for note in callbacks.get(MIDI.NOTEON_STATUS,{}).keys(): - Live.MidiMap.forward_midi_note(script_handle, midi_map_handle, channel, note) - - for cc in callbacks.get(MIDI.CC_STATUS,{}).keys(): - Live.MidiMap.forward_midi_cc(script_handle, midi_map_handle, channel, cc) - - + """ + EN: this needs to only capture the notes and cc's from the settings.py list + """ + + Live.Base.log("STC_EN: Starting mapping") + for item in settings.midi_mapping: + # item -> key + #MIDI.midi_mapping[item] -> values + # Live.Base.log("STC_EN: mapping Item: %s" % (item)) + self.recursive_forward_midi(script_handle,midi_map_handle, settings.midi_mapping[item]) + # called from Live when MIDI messages are received def receive_midi(self, midi_bytes): + """ + There seems to be a doubling up of messages, may need to filter if two messages are too close together; + but this may affect other functinality. + :param midi_bytes: + :return: + """ + # Dirty filter: + if self.prevMsg is not None and midi_bytes==self.prevMsg: + return + self.prevMsg = midi_bytes + channel = (midi_bytes[0] & MIDI.CHAN_MASK) status = (midi_bytes[0] & MIDI.STATUS_MASK) key = midi_bytes[1] value = midi_bytes[2] - #log("receive_midi on channel %d, status %d, key %d, value %d" % (channel, status, key, value)) + # Live.Base.log("receive_midi on channel %d, status %d, key %d, value %d" % (channel, status, key, value)) # execute callbacks that are registered for this event callbacks = self.midi_callbacks.get(channel,{}).get(status,{}).get(key,[]) @@ -151,4 +182,11 @@ def register_midi_callback(self, callback, key, mode, status, channel): self.midi_callbacks[channel][status][key].append(callback) else: self.midi_callbacks[channel][status][key] = [callback, ] + + def send_midi(self, midi_event_bytes): + u"""Script -> Live + Use this function to send MIDI events through Live to the _real_ MIDI devices + that this script is assigned to. + """ + self.c_instance.send_midi(midi_event_bytes) \ No newline at end of file