def _on_loop_properties_changed(self): """ Updates loop button LEDs to reflect current state and position of the clip's loop. """ if self.is_enabled() and self._loop_buttons: if self._clip: if self._clip.looping: seg_len = self._clip.end_marker / len(self._loop_buttons) adjusted_end = self._clip.loop_end - seg_len for index, button in enumerate(self._loop_buttons): if button: btn_pos = seg_len * index end_diff = abs(adjusted_end - btn_pos) start_diff = abs(self._clip.loop_start - btn_pos) if btn_pos >= self._clip.loop_start and ( btn_pos <= adjusted_end or floats_equal(btn_pos, adjusted_end)): button.set_light(self._in_range_value) elif btn_pos >= self._clip.loop_start and end_diff < seg_len: button.set_light( self._partially_in_range_value) elif btn_pos < self._clip.loop_start and start_diff < seg_len: button.set_light( self._partially_in_range_value) else: button.set_light(self._out_of_range_value) else: set_group_button_lights(self._loop_buttons, self._out_of_range_value) else: set_group_button_lights(self._loop_buttons, 'Clip.NoClip')
def _update_midi_meter_buttons(self): if self.is_enabled() and self._meter_buttons: if self._track: self._update_meter_button_leds(self._track.output_meter_level) else: set_group_button_lights(self._meter_buttons, 'DefaultButton.Off')
def _update_mapping_type(self): """ Updates the type of mapping to use based on the type of parameter being controlled. """ self._last_sent_value = -1 self._mapping_type = SLIDER self._smoother.stop_smoothing() if self._parameter_to_map_to is not None: param = self._parameter_to_map_to if self._is_fine_tuning: self._mapping_type = INC_DEC self._inc_dec_factor = (param.max - param.min) / 127.0 elif param.max == abs(param.min): self._mapping_type = BIPOLAR else: parent = param.canonical_parent if isinstance(parent, Live.Device.Device): parent = parent.class_name if parameter_is_quantized(param): self._mapping_type = INC_DEC if param.max - param.min == 1.0: self._mapping_type = ON_OFF self._inc_dec_factor = 1 self._strategy = STRATEGIES[self._mapping_type] self._on_parameter_changed() else: set_group_button_lights(self._buttons, 'DefaultButton.Off') self.notify_parameter_value(self.parameter_value) self.notify_parameter_name(self.parameter_name) return
def send_value(self, value, **k): """ Overrides standard to interpret parameter values differently and use different LED colors depending on the type of parameter being controlled. Also handles clearing LEDs if no parameter assigned. """ assert value is not None assert isinstance(value, int) assert value in range(128) if self._buttons and value != self._last_sent_value: buttons_len = len(self._buttons) led_color = 'DefaultButton.Off' param = self._parameter_to_map_to if param: param_value = int((param.value - param.min) / (param.max - param.min) * buttons_len) offsets = self._strategy['offsets'](param, param_value, value, buttons_len) if offsets == (-1, -1): set_group_button_lights(self._buttons, 'DefaultButton.Off') else: for index, button in enumerate(self._buttons): led_color = self._strategy['send_value'](self, param, index, offsets, buttons_len) if button: button.set_light(led_color or 'DefaultButton.Off') else: set_group_button_lights(self._buttons, 'DefaultButton.Off') self._last_sent_value = value return
def _on_playing_position_changed(self): """ Updates button LEDs to reflect playhead position. """ if self.is_enabled() and self._position_buttons: if self._clip: num_buttons = len(self._position_buttons) if ( self._clip.is_playing or self._clip.is_triggered ) and self._clip.loop_start <= self._clip.playing_position <= self._clip.loop_end: start_offset = 0.0 + int( self._clip.looping) * self._clip.loop_start position = int( (self._clip.playing_position - start_offset) / ((self._clip.loop_end - start_offset) / num_buttons)) if position in xrange( num_buttons ) and position != self._last_playing_position: set_group_button_light(self._position_buttons, self._last_playing_position, 'DefaultButton.Off') set_group_button_light(self._position_buttons, position, self._playhead_value) self._last_playing_position = position else: set_group_button_light(self._position_buttons, self._last_playing_position, 'DefaultButton.Off') else: set_group_button_lights(self._position_buttons, 'Clip.NoClip')
def _update_pitch_buttons(name, buttons, predicate, pitch): if buttons: set_group_button_lights(buttons, 'Clip.Pitch.%s' % name) if predicate: if pitch in xrange(len(buttons)): buttons[pitch].set_light('Clip.Pitch.Selected') else: buttons[(-1)].set_light('Clip.Pitch.Selected')
def _update_audio_meter_buttons(self): if self.is_enabled() and self._meter_buttons: if self._track: self._update_meter_button_leds( (self._track.output_meter_left + self._track.output_meter_right) / 2.0) else: set_group_button_lights(self._meter_buttons, 'DefaultButton.Off')
def _update_page_buttons(self): if self.is_enabled() and self._page_buttons: if self._clip: for i in xrange(self._num_page_buttons): self._update_page_button(i) else: set_group_button_lights(self._page_buttons, 'Sequence.Page.OutOfRange')
def set_visual_metro_buttons(self, buttons): """ Sets the list of buttons to use for displaying the visual metronome. Needs to be at least 4 buttons. The first button can be used for toggling playback state. """ assert buttons is None or len(buttons) >= 4 self._buttons = list(buttons) if buttons else None self._on_visual_metro_button_value.replace_subjects(buttons or []) self._last_visual_metro_led = None set_group_button_lights(self._buttons, 'VisualMetronome.Off') return
def _update_swing_buttons(self): if self.is_enabled() and self._swing_buttons: if self._repeat.enabled: swing_val = self.song().swing_amount step = 0.5 / self._num_swing_buttons for i, button in enumerate(self._swing_buttons): button.set_light('NoteRepeat.Swing.On' if i * step <= swing_val else 'NoteRepeat.Swing.Off') else: set_group_button_lights(self._swing_buttons, 'NoteRepeat.Inactive')
def set_meter_buttons(self, buttons): """ Sets the buttons to use for displaying the track's meter. """ self._last_meter_value = -1 if self._should_invert_buttons: self._meter_buttons = list(buttons)[::-1] if buttons else [] else: self._meter_buttons = list(buttons) if buttons else [] if buttons and self.is_enabled(): set_group_button_lights(buttons, 'DefaultButton.Off') self._dummy_listener.replace_subjects(self._meter_buttons)
def _update_button_leds(self): if self.is_enabled() and self._buttons: if self._cx_instance and self._cx_settings: for index, button in enumerate(self._buttons): if button: setting = self._cx_settings.get(index) button.set_light(setting['color'] if setting else 'DefaultButton.Off') else: set_group_button_lights(self._buttons, 'DefaultButton.Off')
def disconnect(self): set_group_button_lights(self._buttons, 'DefaultButton.Off') super(SpecialButtonSliderElement, self).disconnect() self._smoother.disconnect() self._parameter_to_map_to = None self._parameter_value_slot = None self._buttons = None self._inc_dec_colors = None self._off_on_colors = None self._automat_clear_colors = None self._strategy = None return
def _update_volume_buttons(self): if self.is_enabled() and self._volume_buttons: if self._track: param = self._track.mixer_device.volume param_value = int(param.value / self._volume_max * self._num_buttons) for index, button in enumerate(self._volume_buttons): button.set_light('Meters.Volume' if index <= param_value else 'DefaultButton.Off') else: set_group_button_lights(self._volume_buttons, 'DefaultButton.Off')
def _update_sequence_buttons(self): if self.is_enabled(): if self._sequence_buttons: if self._clip and self._current_lane: for index, button in enumerate(self._sequence_buttons): self._update_sequence_button(index, button) else: set_group_button_lights( self._sequence_buttons, 'Sequence.Step.%s' % ('Unusable' if self._note == -1 else 'Off')) if self._unused_sequence_buttons: set_group_button_lights(self._unused_sequence_buttons, 'Sequence.Step.Unusable')
def _update_selection_buttons(self): if self.is_enabled() and self._selection_buttons: if self._device and self._num_presets: for index, button in enumerate(self._selection_buttons): preset_index = index + self._page_offset if preset_index == self._device.selected_preset_index: button.set_light('Preset.Selected') elif preset_index < self._num_presets: button.set_light('Preset.NotSelected') else: button.set_light('DefaultButton.Off') else: set_group_button_lights(self._selection_buttons, 'DefaultButton.Off')
def _update_cue_buttons(self): if self.is_enabled() and self._cue_buttons: if self._cue_times: num_cues = len(self._cue_times) for index, button in enumerate(self._cue_buttons): if button: if index < num_cues: self._update_cue_button(button, self._cue_times[index]) else: button.set_light('DefaultButton.Off') else: set_group_button_lights(self._cue_buttons, 'DefaultButton.Off')
def _on_playing_position_changed(self): if self.is_enabled() and self._page_buttons: if self._clip: position = int(self._clip.playing_position / self._page_length) if position in xrange( self._num_page_buttons ) and position != self._last_playing_page: self._clear_last_playing_page_button() if self._is_following: self._handle_page_follow(position) self._page_buttons[position].set_light( 'Sequence.Page.Playing') self._last_playing_page = position else: set_group_button_lights(self._page_buttons, 'Sequence.Page.OutOfRange')
def _update_load_buttons(self): if self.is_enabled() and self._load_buttons: if self._load_button_colors and self._plugin_list: for index, button in enumerate(self._load_buttons): if button: color = None item = None if index < len( self._load_button_colors) and index < len( self._plugin_list): color = self._load_button_colors[index] item = self._plugin_list[index] button.set_light( color if color and item else 'DefaultButton.Off') else: set_group_button_lights(self._load_buttons, 'DefaultButton.Off') return
def _update_matrix(self, update_x=False, update_y=False): if self._is_enabled and self._matrix: if live_object_is_valid(self._x_parameter) or live_object_is_valid( self._y_parameter): should_update = False x_value = self._last_x_value y_value = self._last_y_value if live_object_is_valid(self._x_parameter) and update_x: x_value = self._get_scaled_parameter_value( self._x_parameter, self._width) if x_value != self._last_x_value: self._last_x_value = x_value should_update = True if live_object_is_valid(self._y_parameter) and update_y: y_value = self._height - 1 - self._get_scaled_parameter_value( self._y_parameter, self._height) if y_value != self._last_y_value: self._last_y_value = y_value should_update = True if should_update: self._handle_matrix_update(x_value, y_value) else: set_group_button_lights(self._matrix, 'DefaultButton.Off')
def _update_meter_button_leds(self, value): scaled = int(value / 1.0 * self._scale_factor) if self._last_meter_value != scaled: if scaled is 0: set_group_button_lights(self._meter_buttons, 'DefaultButton.Off') else: high_btn_index = (scaled - 1) / 3 high_value_full = scaled % 3 == 0 high_value_half = scaled % 2 == 0 for index, button in enumerate(self._meter_buttons): if button: if index < high_btn_index: button.set_light(self._full_values[index]) elif index > high_btn_index: button.set_light('DefaultButton.Off') elif high_value_full: button.set_light(self._full_values[index]) else: button.set_light( self._half_values[index] if high_value_half else self._dim_values[index]) self._last_meter_value = scaled
def update(self): super(VisualMetroComponent, self).update() if self.is_enabled(): set_group_button_lights(self._buttons, 'VisualMetronome.Off')
def _clear_position_buttons(self): if self.is_enabled() and self._position_buttons: set_group_button_lights(self._position_buttons, 'DefaultButton.Off')