forked from wiffbi/Selected_Track_Control
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SelectedTrackControl.py
executable file
·154 lines (115 loc) · 4.39 KB
/
SelectedTrackControl.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import Live
import MIDI
import settings
#from Logging import log
from SessionControl import SessionControl
from MixerControl import MixerControl
from GlobalControl import GlobalControl
from ViewControl import ViewControl
from DeviceControl import DeviceControl
from QuantizationControl import QuantizationControl
class SelectedTrackControl:
__module__ = __name__
__doc__ = 'MIDI Remote Script to control the selected track'
__name__ = "SelectedTrackControl MIDI Remote Script"
def __init__(self, c_instance):
#log("SelectedTrackControl::__init__")
self.c_instance = c_instance
# mappings for registered MIDI notes/CCs
self.midi_callbacks = {}
# lookup object for fast lookup of cc to mode
self.midi_cc_to_mode = {}
# parse midi_mapping recursive for MIDI.CC
self.mapping_parse_recursive(settings.midi_mapping.values())
self._device_control = DeviceControl(c_instance, self)
self.components = (
SessionControl(c_instance, self),
MixerControl(c_instance, self),
GlobalControl(c_instance, self),
ViewControl(c_instance, self),
self._device_control,
QuantizationControl(c_instance, self),
)
def mapping_parse_recursive(self, mapping):
tuple_type = type((1,2));
for command in mapping:
if type(command) == tuple_type:
self.mapping_parse_recursive(command)
elif isinstance(command, MIDI.CC):
#log("MIDI CC %d is %s" % (command.key, command.mode))
self.midi_cc_to_mode[command.key] = command.mode
def suggest_map_mode(self, cc_no):
#log("suggest_map_mode")
if cc_no in self.midi_cc_to_mode:
return self.midi_cc_to_mode[cc_no]
return MIDI.ABSOLUTE # see MIDI.py for definitions of modes
def disconnect(self):
for c in self.components:
c.disconnect()
def refresh_state(self):
#log("refresh_state")
#for c in self.components:
# c.refresh_state()
pass
def update_display(self):
#log("update_display")
#for c in self.components:
# c.update_display()
pass
def connect_script_instances(self, instanciated_scripts):
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)
# called from Live when MIDI messages are received
def receive_midi(self, 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))
# execute callbacks that are registered for this event
callbacks = self.midi_callbacks.get(channel,{}).get(status,{}).get(key,[])
mode = MIDI.ABSOLUTE
if status == MIDI.CC_STATUS:
# get mode and calculate signed int for MIDI value
mode = self.suggest_map_mode(key)
value = MIDI.relative_to_signed_int[mode](value)
for callback in callbacks:
callback(value, mode, status)
def suggest_input_port(self):
return str('Kimidi Input')
def suggest_output_port(self):
return str('Kimidi Output')
def can_lock_to_devices(self):
return True
def lock_to_device(self, device):
assert (self._device_control != None)
self._device_control.set_lock_to_device(True, device)
def unlock_from_device(self, device):
assert (self._device_control != None)
self._device_control.set_lock_to_device(False, device)
def set_appointed_device(self, device):
assert ((device == None) or isinstance(device, Live.Device.Device))
assert (self._device_control != None)
self._device_control.set_device(device)
# internal method to register callbacks from different controls
def register_midi_callback(self, callback, key, mode, status, channel):
if not channel in self.midi_callbacks:
self.midi_callbacks[channel] = {}
if not status in self.midi_callbacks[channel]:
self.midi_callbacks[channel][status] = {
key: [callback,]
}
else:
if key in self.midi_callbacks[channel][status]:
self.midi_callbacks[channel][status][key].append(callback)
else:
self.midi_callbacks[channel][status][key] = [callback, ]