| Home | Trees | Indices | Help |
|---|
|
|
1 #Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/_Framework/InputControlElement.py 2 from __future__ import with_statement 3 import contextlib 4 from Dependency import depends 5 from SubjectSlot import SubjectEvent 6 from Signal import Signal 7 from NotifyingControlElement import NotifyingControlElement 8 from Util import in_range, const, nop 9 from Debug import debug_print 10 from Disconnectable import Disconnectable 11 import Task 12 MIDI_NOTE_TYPE = 0 13 MIDI_CC_TYPE = 1 14 MIDI_PB_TYPE = 2 15 MIDI_SYSEX_TYPE = 3 16 MIDI_INVALID_TYPE = 4 17 MIDI_MSG_TYPES = (MIDI_NOTE_TYPE, 18 MIDI_CC_TYPE, 19 MIDI_PB_TYPE, 20 MIDI_SYSEX_TYPE, 21 MIDI_INVALID_TYPE) 22 MIDI_NOTE_ON_STATUS = 144 23 MIDI_NOTE_OFF_STATUS = 128 24 MIDI_CC_STATUS = 176 25 MIDI_PB_STATUS = 22428 """ 29 Maintains the connection between a parameter and 30 InputControlElement. Keeps the invariant that whenever both 31 parameter and control are set, the parameter is connected to the 32 control. Whenever any of them is changed, they are disconnected 33 and reconnected to the new one, in a similar fashion to a 34 SubjectSlot. 35 """ 36 _parameter = None 37 _control = None 387840 super(ParameterSlot, self).__init__(*a, **k) 41 self.parameter = parameter 42 self.control = control4345 return self._control4648 if control != self._control: 49 self.soft_disconnect() 50 self._control = control 51 self.connect()52 53 control = property(_get_control, _set_control) 5456 return self._parameter5759 if parameter != self._parameter: 60 self.soft_disconnect() 61 self._parameter = parameter 62 self.connect()63 64 parameter = property(_get_parameter, _set_parameter) 6567 if self._control != None and self._parameter != None: 68 self._control.connect_to(self._parameter)69 7381 """ 82 Special signal type that makes sure that interaction with input 83 works properly. Special input control elements that define 84 value-dependent properties should use this kind of signal. 85 """ 86 90 91 @contextlib.contextmanager11593 try: 94 control = self._input_control 95 old_count = self.count 96 old_wants_forwarding = control.script_wants_forwarding() 97 yield 98 finally: 99 diff_count = self.count - old_count 100 control._input_signal_listener_count += diff_count 101 if old_wants_forwarding != control.script_wants_forwarding(): 102 self._input_control._request_rebuild()103 107 111118 """ 119 Base class for all classes representing control elements on a controller 120 """ 121 __subject_events__ = (SubjectEvent(name='value', signal=InputSignal, override=True),) 122 _input_signal_listener_count = 0 123 num_delayed_messages = 1 124 send_depends_on_forwarding = True 125 126 @depends(request_rebuild_midi_map=const(nop))396127 - def __init__(self, msg_type = None, channel = None, identifier = None, sysex_identifier = None, request_rebuild_midi_map = None, *a, **k):128 raise msg_type in MIDI_MSG_TYPES or AssertionError 129 raise in_range(channel, 0, 16) or channel is None or AssertionError 130 raise in_range(identifier, 0, 128) or identifier is None or AssertionError 131 raise msg_type != MIDI_SYSEX_TYPE or channel == None or AssertionError 132 raise msg_type != MIDI_SYSEX_TYPE or identifier == None or AssertionError 133 raise msg_type == MIDI_SYSEX_TYPE or sysex_identifier == None or AssertionError 134 super(InputControlElement, self).__init__(*a, **k) 135 self._request_rebuild = request_rebuild_midi_map 136 self._msg_type = msg_type 137 self._msg_channel = channel 138 self._msg_identifier = identifier 139 self._msg_sysex_identifier = sysex_identifier 140 self._original_channel = channel 141 self._original_identifier = identifier 142 self._needs_takeover = True 143 self._is_mapped = True 144 self._is_being_forwarded = True 145 self._delayed_messages = [] 146 self._force_next_send = False 147 self._mapping_feedback_delay = 0 148 self._mapping_sensitivity = 1.0 149 self._send_delayed_messages_task = self._tasks.add(Task.run(self._send_delayed_messages)) 150 self._send_delayed_messages_task.kill() 151 self._parameter_to_map_to = None 152 self._in_parameter_gesture = False 153 self._last_sent_message = None 154 self._report_input = False 155 self._report_output = False156 159 162 165 168 171 174 177 178 mapping_sensitivity = property(_get_mapping_sensitivity, _set_mapping_sensitivity) 179181 """ 182 Enforces sending the next value regardless of wether the 183 control is mapped to the script. 184 """ 185 self._force_next_send = True186188 if not self._msg_type != MIDI_SYSEX_TYPE: 189 raise AssertionError 190 raise in_range(channel, 0, 16) or channel == None or AssertionError 191 self._msg_channel = self._msg_channel != channel and channel 192 self._request_rebuild()193195 if not self._msg_type != MIDI_SYSEX_TYPE: 196 raise AssertionError 197 raise in_range(identifier, 0, 128) or identifier == None or AssertionError 198 self._msg_identifier = self._msg_identifier != identifier and identifier 199 self._request_rebuild()200202 raise self.message_type() != MIDI_NOTE_TYPE or AssertionError 203 self._needs_takeover = needs_takeover204 208 212214 if (self._msg_channel, self._msg_identifier) != (self._original_channel, self._original_identifier): 215 self._msg_channel = self._original_channel 216 self._msg_identifier = self._original_identifier 217 self._request_rebuild()218220 value_map = tuple() 221 if self._mapping_feedback_delay != 0: 222 if self._msg_type != MIDI_PB_TYPE: 223 value_map = tuple(range(128)) 224 else: 225 value_pairs = [] 226 for value in xrange(16384): 227 value_pairs.append((value >> 7 & 127, value & 127)) 228 229 value_map = tuple(value_pairs) 230 return value_map231233 self._send_delayed_messages_task.kill() 234 self._is_mapped = False 235 self._is_being_forwarded = False 236 if self._msg_channel != self._original_channel or self._msg_identifier != self._original_identifier: 237 install_translation(self._msg_type, self._original_identifier, self._original_channel, self._msg_identifier, self._msg_channel) 238 if self._parameter_to_map_to != None: 239 self._is_mapped = install_mapping(self, self._parameter_to_map_to, self._mapping_feedback_delay, self._mapping_feedback_values()) 240 if self.script_wants_forwarding(): 241 self._is_being_forwarded = install_forwarding(self) 242 if self._is_being_forwarded and self.send_depends_on_forwarding: 243 self._send_delayed_messages_task.restart()244246 """ 247 Returns wether the script wants to receive receive the values, 248 otherwise, the control will be mapped to the track. 249 250 Subclasses that overload this should _request_rebuild() 251 whenever the property changes. 252 """ 253 return self._input_signal_listener_count > 0 or self._report_input254256 """ 257 Begins a modification on the input control element, 258 meaning that we should consider the next flow of input data as 259 a consistent gesture from the user. 260 """ 261 if self._parameter_to_map_to and not self._in_parameter_gesture: 262 self._in_parameter_gesture = True 263 self._parameter_to_map_to.begin_gesture()264266 """ 267 Ends a modification of the input control element. See 268 begin_gesture. 269 """ 270 if self._parameter_to_map_to and self._in_parameter_gesture: 271 self._in_parameter_gesture = False 272 self._parameter_to_map_to.end_gesture()273275 """ parameter is a Live.Device.DeviceParameter """ 276 if not parameter != None: 277 raise AssertionError 278 self._parameter_to_map_to = self._parameter_to_map_to != parameter and parameter 279 self._request_rebuild()280282 if self._parameter_to_map_to != None: 283 self.end_gesture() 284 self._parameter_to_map_to = None 285 self._request_rebuild()286 289291 status_byte = channel 292 if self._msg_type == MIDI_NOTE_TYPE: 293 status_byte += MIDI_NOTE_ON_STATUS 294 elif self._msg_type == MIDI_CC_TYPE: 295 status_byte += MIDI_CC_STATUS 296 elif self._msg_type == MIDI_PB_TYPE: 297 status_byte += MIDI_PB_STATUS 298 else: 299 raise NotImplementedError 300 return status_byte301303 """ 304 Returns a list with all the MIDI message prefixes that 305 identify this control element. 306 """ 307 if self._msg_type == MIDI_PB_TYPE: 308 return ((self._status_byte(self._msg_channel),),) 309 elif self._msg_type == MIDI_SYSEX_TYPE: 310 return (self.message_sysex_identifier(),) 311 elif self._msg_type == MIDI_NOTE_TYPE: 312 return ((self._status_byte(self._msg_channel), self.message_identifier()), (self._status_byte(self._msg_channel) - 16, self.message_identifier())) 313 else: 314 return ((self._status_byte(self._msg_channel), self.message_identifier()),)315317 self.clear_send_cache() 318 for value, channel in self._delayed_messages: 319 self._do_send_value(value, channel=channel) 320 321 self._delayed_messages[:] = []322324 value = int(value) 325 self._verify_value(value) 326 if force_send or self._force_next_send: 327 self._do_send_value(value, channel) 328 elif self.send_depends_on_forwarding and not self._is_being_forwarded or self._send_delayed_messages_task.is_running: 329 first = 1 - self.num_delayed_messages 330 self._delayed_messages = self._delayed_messages[first:] + [(value, channel)] 331 elif (value, channel) != self._last_sent_message: 332 self._do_send_value(value, channel) 333 self._force_next_send = False334336 data_byte1 = self._original_identifier 337 data_byte2 = value 338 status_byte = self._status_byte(channel or self._original_channel) 339 if self._msg_type == MIDI_PB_TYPE: 340 data_byte1 = value & 127 341 data_byte2 = value >> 7 & 127 342 if self.send_midi((status_byte, data_byte1, data_byte2)): 343 self._last_sent_message = (value, channel) 344 if self._report_output: 345 is_input = True 346 self._report_value(value, not is_input) 347 self._delayed_value_to_send = None 348 self._delayed_channel = None349 352 356358 self._verify_value(value) 359 self._last_sent_message = None 360 self.notify_value(value) 361 if self._report_input: 362 is_input = True 363 self._report_value(value, is_input)364366 """ 367 Set boolean values report_input and report_output enabling 368 debug information. 369 """ 370 self._report_input = report_input 371 self._report_output = report_output372374 upper_bound = self._msg_type < MIDI_SYSEX_TYPE and (16384 if self._msg_type == MIDI_PB_TYPE else 128) 375 if not in_range(value, 0, upper_bound): 376 raise AssertionError377379 self._verify_value(value) 380 message = str(self.__class__.__name__) + ' (' 381 if self._msg_type == MIDI_NOTE_TYPE: 382 message += 'Note ' + str(self._msg_identifier) + ', ' 383 elif self._msg_type == MIDI_CC_TYPE: 384 message += 'CC ' + str(self._msg_identifier) + ', ' 385 else: 386 message += 'PB ' 387 message += 'Chan. ' + str(self._msg_channel) 388 message += ') ' 389 message += 'received value ' if is_input else 'sent value ' 390 message += str(value) 391 debug_print(message)392 393 @property
| Home | Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 on Wed Mar 6 18:53:34 2013 | http://epydoc.sourceforge.net |