def check_translation(translation): raise len(translation) == 4 or AssertionError raise in_range(translation[0], 0, 4) or AssertionError raise in_range(translation[1], 0, 4) or AssertionError raise in_range(translation[2], 0, 128) or AssertionError raise in_range(translation[3], 0, 16) or AssertionError return True
def set_light(self, column, row, value): if not in_range(column, 0, self.width()): raise AssertionError if not in_range(row, 0, self.height()): raise AssertionError button = len(self._buttons[row]) > column and self._buttons[row][column] button and button.set_light(value)
def __init__(self, msg_type = None, channel = None, identifier = None, sysex_identifier = None, request_rebuild_midi_map = None, *a, **k): raise msg_type in MIDI_MSG_TYPES or AssertionError raise in_range(channel, 0, 16) or channel is None or AssertionError raise in_range(identifier, 0, 128) or identifier is None or AssertionError raise msg_type != MIDI_SYSEX_TYPE or channel == None or AssertionError raise msg_type != MIDI_SYSEX_TYPE or identifier == None or AssertionError raise msg_type == MIDI_SYSEX_TYPE or sysex_identifier == None or AssertionError super(InputControlElement, self).__init__(*a, **k) self._request_rebuild = request_rebuild_midi_map self._msg_type = msg_type self._msg_channel = channel self._msg_identifier = identifier self._msg_sysex_identifier = sysex_identifier self._original_channel = channel self._original_identifier = identifier self._needs_takeover = True self._is_mapped = True self._is_being_forwarded = True self._delayed_messages = [] self._force_next_send = False self._mapping_feedback_delay = 0 self._mapping_sensitivity = 1.0 self._send_delayed_messages_task = self._tasks.add(Task.run(self._send_delayed_messages)) self._send_delayed_messages_task.kill() self._parameter_to_map_to = None self._in_parameter_gesture = False self._last_sent_message = None self._report_input = False self._report_output = False
def send_value(self, column, row, value, force = False): if not in_range(value, 0, 128): raise AssertionError raise in_range(column, 0, self.width()) or AssertionError if not in_range(row, 0, self.height()): raise AssertionError button = len(self._buttons[row]) > column and self._buttons[row][column] button and button.send_value(value, force)
def send_value(self, column, row, value, force = False): if not in_range(value, 0, 128): raise AssertionError raise in_range(column, 0, self.width()) or AssertionError if not in_range(row, 0, self.height()): raise AssertionError button = len(self._buttons[row]) > column and self._buttons[row][column] button and button.send_value(value, force=force)
def suggest_needs_takeover(self, cc_no, channel): """ Live -> Script: Live can ask whether a given CC needs takeover """ raise in_range(cc_no, 0, 128) or AssertionError raise in_range(channel, 0, 16) or AssertionError needs_takeover = True for control in self._controls: if isinstance(control, InputControlElement) and control.message_type() == MIDI_CC_TYPE and control.message_identifier() == cc_no and control.message_channel() == channel: needs_takeover = control.needs_takeover() break return needs_takeover
def suggest_map_mode(self, cc_no, channel): """ Live -> Script: Live can ask for a suitable mapping mode for a given CC""" raise in_range(cc_no, 0, 128) or AssertionError raise in_range(channel, 0, 16) or AssertionError suggested_map_mode = -1 for control in self.controls: if isinstance(control, InputControlElement) and control.message_type() == MIDI_CC_TYPE and control.message_identifier() == cc_no and control.message_channel() == channel: suggested_map_mode = control.message_map_mode() break return suggested_map_mode
def _tempo_fine_value(self, value): if self.is_enabled(): if self._fine_tempo_needs_pickup: if in_range(self._prior_fine_tempo_value, 0, 128): range_max = max(value, self._prior_fine_tempo_value) range_min = min(value, self._prior_fine_tempo_value) if in_range(64, range_min, range_max + 1): self._fine_tempo_needs_pickup = False else: raise in_range(self._prior_fine_tempo_value, 0, 128) or AssertionError difference = value - self._prior_fine_tempo_value ratio = 127.0 / TEMPO_FINE_RANGE new_tempo = clamp(self.song().tempo + difference / ratio, TEMPO_BOTTOM, TEMPO_TOP) self.song().tempo = new_tempo self._prior_fine_tempo_value = value
def _on_stop_track_value(self, value, sender): if self.is_enabled(): if value is not 0 or not sender.is_momentary(): tracks = self.tracks_to_use() track_index = list(self._stop_track_clip_buttons).index(sender) + self.track_offset() if in_range(track_index, 0, len(tracks)) and tracks[track_index] in self.song().tracks: tracks[track_index].stop_all_clips()
def set_identifier(self, identifier): if not self._msg_type != MIDI_SYSEX_TYPE: raise AssertionError raise in_range(identifier, 0, 128) or identifier == None or AssertionError self._msg_identifier = self._msg_identifier != identifier and identifier self._request_rebuild()
def set_channel(self, channel): if not self._msg_type != MIDI_SYSEX_TYPE: raise AssertionError raise in_range(channel, 0, 16) or channel == None or AssertionError self._msg_channel = self._msg_channel != channel and channel self._request_rebuild() return
def set_identifier(self, identifier): if not self._msg_type != MIDI_SYSEX_TYPE: raise AssertionError raise in_range(identifier, 0, 128) or identifier == None or AssertionError self._msg_identifier = self._msg_identifier != identifier and identifier self._request_rebuild() return
def set_num_segments(self, num_segments): width = self._width if not in_range(num_segments, 1, width) or width % num_segments != 0: raise DisplaySegmentationError, 'Can not split display of size %d into %d segments' % (self.width, num_segments) if num_segments != len(self._logical_segments): self._disconnect_segments() self._width_per_segment = width / num_segments self._logical_segments = [ LogicalDisplaySegment(self._width_per_segment, self.update) for _ in xrange(num_segments) ]
def update(self): super(SessionZoomingComponent, self).update() if self._allow_updates: self._session_set_enabled(not self._is_zoomed_out) if self.is_enabled(): if self._is_zoomed_out and self._buttons != None: tracks = self._session.tracks_to_use() scenes = self.song().scenes slots_registry = [None for index in range(len(scenes))] width = self._session.width() height = self._session.height() for x in range(self._buttons.width()): for y in range(self._buttons.height()): value_to_send = self._empty_value scene_bank_offset = self._scene_bank_index * self._buttons.height() * height track_offset = x * width scene_offset = y * height + scene_bank_offset if track_offset in range(len(tracks)) and scene_offset in range(len(scenes)): value_to_send = self._stopped_value if self._session.track_offset() in range( width * (x - 1) + 1, width * (x + 1) ) and self._session.scene_offset() - scene_bank_offset in range( height * (y - 1) + 1, height * (y + 1) ): value_to_send = self._selected_value else: playing = False for track in range(track_offset, track_offset + width): for scene in range(scene_offset, scene_offset + height): if track in range(len(tracks)) and scene in range(len(scenes)): if slots_registry[scene] == None: slots_registry[scene] = scenes[scene].clip_slots slot = ( slots_registry[scene][track] if len(slots_registry[scene]) > track else None ) if slot != None and slot.has_clip and slot.clip.is_playing: value_to_send = self._playing_value playing = True break if playing: break if in_range(value_to_send, 0, 128): self._buttons.send_value(x, y, value_to_send) else: self._buttons.set_light(x, y, value_to_send) if self._scene_bank_buttons != None: for index, button in enumerate(self._scene_bank_buttons): if button: button.set_light(self._is_zoomed_out and index == self._scene_bank_index) else: self._update_requests += 1 return
def set_num_segments(self, num_segments, use_delimiters = True): if not in_range(num_segments, 1, self._width - num_segments + 1): raise AssertionError if num_segments != len(self._logical_segments): self._disconnect_segments() width_without_delimiters = use_delimiters and self._width - num_segments + 1 else: width_without_delimiters = self._width width_per_segment = int(width_without_delimiters / num_segments) self._logical_segments = [ LogicalDisplaySegment(width_per_segment, self.update) for _ in xrange(num_segments) ]
def set_num_segments(self, num_segments, use_delimiters=True): if not in_range(num_segments, 1, self._width - num_segments + 1): raise AssertionError if num_segments != len(self._logical_segments): self._disconnect_segments() width_without_delimiters = use_delimiters and self._width - num_segments + 1 else: width_without_delimiters = self._width width_per_segment = int(width_without_delimiters / num_segments) self._logical_segments = [ LogicalDisplaySegment(width_per_segment, self.update) for _ in xrange(num_segments) ]
def _update_matrix_buttons(self): if self._buttons != None: tracks = self._session.tracks_to_use() scenes = self.song().scenes slots_registry = [None for index in xrange(len(scenes))] width = self._session.width() height = self._session.height() for x in xrange(self._buttons.width()): for y in xrange(self._buttons.height()): value_to_send = self._empty_value scene_bank_offset = self._scene_bank_index * self._buttons.height( ) * height track_offset = x * width scene_offset = y * height + scene_bank_offset if track_offset in xrange( len(tracks)) and scene_offset in xrange( len(scenes)): value_to_send = self._stopped_value if self._session.track_offset() in xrange( width * (x - 1) + 1, width * (x + 1)) and self._session.scene_offset( ) - scene_bank_offset in xrange( height * (y - 1) + 1, height * (y + 1)): value_to_send = self._selected_value else: playing = False for track in xrange(track_offset, track_offset + width): for scene in xrange(scene_offset, scene_offset + height): if track in xrange( len(tracks)) and scene in xrange( len(scenes)): if slots_registry[scene] == None: slots_registry[scene] = scenes[ scene].clip_slots slot = slots_registry[scene][ track] if len(slots_registry[scene] ) > track else None if slot != None and slot.has_clip and slot.clip.is_playing: value_to_send = self._playing_value playing = True break if playing: break if in_range(value_to_send, 0, 128): self._buttons.send_value(x, y, value_to_send) else: self._buttons.set_light(x, y, value_to_send)
def update(self): self._has_fired_slot = False button = self._launch_button_value.subject if self._allow_updates: if self.is_enabled() and button != None: value_to_send = self._feedback_value() if value_to_send in (None, -1): button.turn_off() elif in_range(value_to_send, 0, 128): button.send_value(value_to_send) else: button.set_light(value_to_send) else: self._update_requests += 1
def update(self): super(SessionZoomingComponent, self).update() if self._allow_updates: self._session_set_enabled(not self._is_zoomed_out) if self.is_enabled(): if self._is_zoomed_out and self._buttons != None: tracks = self._session.tracks_to_use() scenes = self.song().scenes slots_registry = [ None for index in range(len(scenes)) ] width = self._session.width() height = self._session.height() for x in range(self._buttons.width()): for y in range(self._buttons.height()): value_to_send = self._empty_value scene_bank_offset = self._scene_bank_index * self._buttons.height() * height track_offset = x * width scene_offset = y * height + scene_bank_offset if track_offset in range(len(tracks)) and scene_offset in range(len(scenes)): value_to_send = self._stopped_value if self._session.track_offset() in range(width * (x - 1) + 1, width * (x + 1)) and self._session.scene_offset() - scene_bank_offset in range(height * (y - 1) + 1, height * (y + 1)): value_to_send = self._selected_value else: playing = False for track in range(track_offset, track_offset + width): for scene in range(scene_offset, scene_offset + height): if track in range(len(tracks)) and scene in range(len(scenes)): if slots_registry[scene] == None: slots_registry[scene] = scenes[scene].clip_slots slot = slots_registry[scene][track] if len(slots_registry[scene]) > track else None if slot != None and slot.has_clip and slot.clip.is_playing: value_to_send = self._playing_value playing = True break if playing: break if in_range(value_to_send, 0, 128): self._buttons.send_value(x, y, value_to_send) else: self._buttons.set_light(x, y, value_to_send) if self._scene_bank_buttons != None: for index, button in enumerate(self._scene_bank_buttons): if button: button.set_light(self._is_zoomed_out and index == self._scene_bank_index) else: self._update_requests += 1 return
def _update_launch_button(self): if self.is_enabled() and self._launch_button != None: value_to_send = self._no_scene_value if self._scene: if self._scene.is_triggered: value_to_send = self._triggered_value elif self._scene_value is not None: value_to_send = self._scene_value else: value_to_send = self._color_value(self._scene.color) if value_to_send is None: self._launch_button.turn_off() elif in_range(value_to_send, 0, 128): self._launch_button.send_value(value_to_send) else: self._launch_button.set_light(value_to_send)
def _update_stop_clips_led(self, index): tracks_to_use = self.tracks_to_use() track_index = index + self.track_offset() button = self.is_enabled() and self._stop_track_clip_buttons != None and index < len(self._stop_track_clip_buttons) and self._stop_track_clip_buttons[index] if button != None: value_to_send = None if track_index < len(tracks_to_use): if tracks_to_use[track_index].clip_slots: track = tracks_to_use[track_index] if track.fired_slot_index == -2: value_to_send = self._stop_clip_triggered_value elif track.playing_slot_index >= 0: value_to_send = self._stop_clip_value if value_to_send == None: button.turn_off() elif in_range(value_to_send, 0, 128): button.send_value(value_to_send) else: button.set_light(value_to_send)
def _update_stop_clips_led(self, index): tracks_to_use = self.tracks_to_use() track_index = index + self.track_offset() button = self.is_enabled( ) and self._stop_track_clip_buttons != None and index < len( self._stop_track_clip_buttons ) and self._stop_track_clip_buttons[index] if button != None: value_to_send = None if track_index < len(tracks_to_use): if tracks_to_use[track_index].clip_slots: track = tracks_to_use[track_index] if track.fired_slot_index == -2: value_to_send = self._stop_clip_triggered_value elif track.playing_slot_index >= 0: value_to_send = self._stop_clip_value if value_to_send == None: button.turn_off() elif in_range(value_to_send, 0, 128): button.send_value(value_to_send) else: button.set_light(value_to_send)
def _update_matrix_buttons(self): if self._buttons != None: tracks = self._session.tracks_to_use() scenes = self.song().scenes slots_registry = [ None for index in xrange(len(scenes)) ] width = self._session.width() height = self._session.height() for x in xrange(self._buttons.width()): for y in xrange(self._buttons.height()): value_to_send = self._empty_value scene_bank_offset = self._scene_bank_index * self._buttons.height() * height track_offset = x * width scene_offset = y * height + scene_bank_offset if track_offset in xrange(len(tracks)) and scene_offset in xrange(len(scenes)): value_to_send = self._stopped_value if self._session.track_offset() in xrange(width * (x - 1) + 1, width * (x + 1)) and self._session.scene_offset() - scene_bank_offset in xrange(height * (y - 1) + 1, height * (y + 1)): value_to_send = self._selected_value else: playing = False for track in xrange(track_offset, track_offset + width): for scene in xrange(scene_offset, scene_offset + height): if track in xrange(len(tracks)) and scene in xrange(len(scenes)): if slots_registry[scene] == None: slots_registry[scene] = scenes[scene].clip_slots slot = slots_registry[scene][track] if len(slots_registry[scene]) > track else None if slot != None and slot.has_clip and slot.clip.is_playing: value_to_send = self._playing_value playing = True break if playing: break if in_range(value_to_send, 0, 128): self._buttons.send_value(x, y, value_to_send) else: self._buttons.set_light(x, y, value_to_send)
def get_button(self, column, row): if not in_range(column, 0, self.width()): raise AssertionError raise in_range(row, 0, self.height()) or AssertionError return len(self._buttons[row]) > column and self._buttons[row][column]
def set_stopped_value(self, value): raise in_range(value, -1, 128) or AssertionError self._stopped_value = value self._clip_palette = []
def set_triggered_value(self, value): value = int(value) raise in_range(value, 0, 128) or AssertionError self._triggered_value = value
def _verify_value(self, value): upper_bound = self._msg_type < MIDI_SYSEX_TYPE and (16384 if self._msg_type == MIDI_PB_TYPE else 128) if not in_range(value, 0, upper_bound): raise AssertionError
def scene(self, index): raise in_range(index, 0, len(self._scenes)) or AssertionError return self._scenes[index]
def _do_get_item(self, index): raise in_range(index, 0, len(self)) or AssertionError, 'Index out of range' row, col = divmod(index, self.width()) return self.get_button(col, row)
def set_playing_value(self, value): value = int(value) raise in_range(value, 0, 128) or AssertionError self._playing_value = value
def set_stop_track_clip_value(self, value): raise in_range(value, 0, 128) or AssertionError self._stop_track_clip_value = value