class NoteSetting(SlotManager, Subject):
    __subject_events__ = ('setting_changed',)
    attribute_index = -1

    def __init__(self, grid_resolution = None, *a, **k):
        super(NoteSetting, self).__init__(*a, **k)
        self._encoder = None
        self._grid_resolution = grid_resolution
        self.value_source = DisplayDataSource()
        self.label_source = DisplayDataSource()
        self.label_source.set_display_string(self.get_label())

    def get_label(self):
        raise NotImplementedError

    def encoder_value_to_attribute(self, value):
        raise NotImplementedError

    def attribute_min_max_to_string(self, min_value, max_value):
        raise NotImplementedError

    @property
    def step_length(self):
        return self._grid_resolution.step_length if self._grid_resolution else 1.0

    def set_encoder(self, encoder):
        self._encoder = encoder
        self._on_value.subject = encoder

    def set_min_max(self, min_max_value):
        self.value_source.set_display_string(self.attribute_min_max_to_string(min_max_value[0], min_max_value[1]) if min_max_value else '-')

    @subject_slot('normalized_value')
    def _on_value(self, value):
        self.notify_setting_changed(self.attribute_index, self.encoder_value_to_attribute(value))
    def __init__(self, mixer_modes, device, encoders, page_buttons):
        raise isinstance(mixer_modes,
                         EncoderMixerModeSelector) or AssertionError
        raise isinstance(device, PageableDeviceComponent) or AssertionError
        raise isinstance(encoders, tuple) or AssertionError
        raise isinstance(page_buttons, tuple) or AssertionError
        ModeSelectorComponent.__init__(self)
        self._mixer_modes = mixer_modes
        self._device = device
        self._encoders = encoders
        self._page_buttons = page_buttons
        self._peek_button = None
        self._encoders_display = None
        self._value_display = None
        self._device_display = None
        self._page_displays = None
        self._device_dummy_source = DisplayDataSource()
        self._parameter_source = DisplayDataSource()
        self._device_dummy_source.set_display_string('Mixer')
        self._clean_value_display_in = -1
        self._must_update_encoder_display = False
        self._register_timer_callback(self._on_timer)
        identify_sender = True
        for encoder in self._encoders:
            encoder.add_value_listener(self._parameter_value, identify_sender)

        self.set_mode(0)
 def __init__(self, grid_resolution = None, *a, **k):
     super(NoteSetting, self).__init__(*a, **k)
     self._encoder = None
     self._grid_resolution = grid_resolution
     self.value_source = DisplayDataSource()
     self.label_source = DisplayDataSource()
     self.label_source.set_display_string(self.get_label())
예제 #4
0
 def __init__(self, num_options=8, num_labels=4, *a, **k):
     super(OptionsComponent, self).__init__(*a, **k)
     self._data_sources = [DisplayDataSource() for _ in xrange(num_options)]
     self._label_data_sources = [
         DisplayDataSource() for _ in xrange(num_labels)
     ]
     self._select_buttons = None
예제 #5
0
 def __init__(self, display_label = ' ', display_seg_start = 0, *a, **k):
     super(ValueDisplayComponentBase, self).__init__(*a, **k)
     self._label_data_source = DisplayDataSource(display_label)
     self._value_data_source = DisplayDataSource()
     self._graphic_data_source = DisplayDataSource()
     self._display_label = display_label
     self._display_seg_start = display_seg_start
예제 #6
0
 def __init__(self, *a, **k):
     super(ClipControlComponent, self).__init__(*a, **k)
     self._clip_param_sources = [DisplayDataSource() for _ in xrange(8)]
     self._clip_value_sources = [DisplayDataSource() for _ in xrange(8)]
     self._clip_name_data_sources = [
         DisplayDataSource() for _ in xrange(self.num_label_segments)
     ]
     self._clip_name_data_sources[0].set_display_string('Clip Selection:')
     self._no_settings = NoClipSettingsComponent(self._clip_param_sources,
                                                 self._clip_value_sources)
     self._midi_clip_settings = MidiClipSettingsComponent(
         self._clip_param_sources[4:], self._clip_value_sources[4:])
     self._midi_clip_settings.set_enabled(False)
     self._audio_clip_settings = AudioClipSettingsComponent(
         self._clip_param_sources[4:], self._clip_value_sources[4:])
     self._audio_clip_settings.set_enabled(False)
     self._loop_settings = LoopSettingsComponent(
         self._clip_param_sources[:4], self._clip_value_sources[:4])
     self._loop_settings.set_enabled(False)
     self._clip_name = ClipNameComponent(self._clip_name_data_sources[1])
     self._clip_name.set_enabled(False)
     self.register_components(self._no_settings, self._loop_settings,
                              self._midi_clip_settings,
                              self._audio_clip_settings, self._clip_name)
     self.add_mode('no_clip', (self._no_settings, self._clip_name))
     self.add_mode(
         'midi',
         (self._loop_settings, self._midi_clip_settings, self._clip_name))
     self.add_mode(
         'audio',
         (self._loop_settings, self._audio_clip_settings, self._clip_name))
     self.selected_mode = 'no_clip'
     self._update_clip()
     self._on_detail_clip_changed.subject = self.song().view
예제 #7
0
    def __init__(self, mixer_modes, device, encoders, page_buttons):
        raise isinstance(mixer_modes, EncoderMixerModeSelector) or AssertionError
        raise isinstance(device, PageableDeviceComponent) or AssertionError
        raise isinstance(encoders, tuple) or AssertionError
        raise isinstance(page_buttons, tuple) or AssertionError
        ModeSelectorComponent.__init__(self)
        self._mixer_modes = mixer_modes
        self._device = device
        self._encoders = encoders
        self._page_buttons = page_buttons
        self._peek_button = None
        self._encoders_display = None
        self._value_display = None
        self._device_display = None
        self._page_displays = None
        self._device_dummy_source = DisplayDataSource()
        self._parameter_source = DisplayDataSource()
        self._device_dummy_source.set_display_string('Mixer')
        self._clean_value_display_in = -1
        self._must_update_encoder_display = False
        self._register_timer_callback(self._on_timer)
        identify_sender = True
        for encoder in self._encoders:
            encoder.add_value_listener(self._parameter_value, identify_sender)

        self.set_mode(0)
        return
예제 #8
0
 def __init__(self, *a, **k):
     super(UserSettingsComponent, self).__init__(*a, **k)
     self._name_sources = [DisplayDataSource() for _ in xrange(4)]
     self._value_sources = [DisplayDataSource() for _ in xrange(4)]
     self._info_source = DisplayDataSource()
     self._settings = []
     self._encoders = []
 def _setup_displays(self):
     self._name_display = PhysicalDisplayElement(12, 1)
     self._name_display.name = "Name_Display"
     self._name_display.set_message_parts(SYSEX_START + (21,), (0, 247))
     self._name_display.set_clear_all_message(CLEAR_NAME)
     self._name_display_data_source = DisplayDataSource()
     self._name_display.segment(0).set_data_source(self._name_display_data_source)
     self._value_display = NumericalDisplayElement(3, 1)
     self._value_display.name = "Value_Display"
     self._value_display.set_message_parts(SYSEX_START + (20, 48), (0, 247))
     self._value_display.set_clear_all_message(CLEAR_VALUE)
     self._value_display_data_source = DisplayDataSource()
     self._value_display.segment(0).set_data_source(self._value_display_data_source)
     self._bank_display = NumericalDisplayElement(3, 1)
     self._bank_display.name = "Bank_Display"
     self._bank_display.set_message_parts(SYSEX_START + (19,), (0, 247))
     self._bank_display.set_clear_all_message(CLEAR_BANK)
     self._bank_display_data_source = DisplayDataSource()
     self._bank_display.segment(0).set_data_source(self._bank_display_data_source)
     self._pad_display = NumericalDisplayElement(2, 1)
     self._pad_display.name = "Pad_Display"
     self._pad_display.set_message_parts(SYSEX_START + (18,), (0, 247))
     self._pad_display.set_clear_all_message(CLEAR_PAD)
     self._pad_display_data_source = DisplayDataSource()
     self._pad_display.segment(0).set_data_source(self._pad_display_data_source)
예제 #10
0
 def __init__(self, num_options = 8, num_labels = 4, num_display_segments = None, *a, **k):
     super(OptionsComponent, self).__init__(*a, **k)
     num_display_segments = num_display_segments or num_options
     self._label_data_sources = [ DisplayDataSource() for _ in xrange(num_labels) ]
     self._data_sources = [ DisplayDataSource() for _ in xrange(num_display_segments) ]
     self._select_buttons = None
     self._option_names = []
예제 #11
0
 def __init__(self, grid_resolution = None, *a, **k):
     super(NoteSetting, self).__init__(*a, **k)
     self._encoder = None
     self._grid_resolution = grid_resolution
     self.value_source = DisplayDataSource()
     self.label_source = DisplayDataSource()
     self.label_source.set_display_string(self.get_label())
예제 #12
0
class NoteSetting(SlotManager, Subject):
    __subject_events__ = ('setting_changed',)
    attribute_index = -1

    def __init__(self, grid_resolution = None, *a, **k):
        super(NoteSetting, self).__init__(*a, **k)
        self._encoder = None
        self._grid_resolution = grid_resolution
        self.value_source = DisplayDataSource()
        self.label_source = DisplayDataSource()
        self.label_source.set_display_string(self.get_label())

    def get_label(self):
        raise NotImplementedError

    def encoder_value_to_attribute(self, value):
        raise NotImplementedError

    def attribute_min_max_to_string(self, min_value, max_value):
        raise NotImplementedError

    @property
    def step_length(self):
        return self._grid_resolution.step_length if self._grid_resolution else 1.0

    def set_encoder(self, encoder):
        self._encoder = encoder
        self._on_value.subject = encoder

    def set_min_max(self, min_max_value):
        self.value_source.set_display_string(self.attribute_min_max_to_string(min_max_value[0], min_max_value[1]) if min_max_value else '-')

    @subject_slot('normalized_value')
    def _on_value(self, value):
        self.notify_setting_changed(self.attribute_index, self.encoder_value_to_attribute(value))
예제 #13
0
 def _add_setting(self, setting):
     raise len(self._settings) < 8 or AssertionError, 'Cannot show more than 8 settings'
     self._settings.append(setting)
     self._update_encoders()
     self._top_data_sources = [ DisplayDataSource() for _ in xrange(8 - len(self._settings)) ] + [ s.label_source for s in self._settings ]
     self._bottom_data_sources = [ DisplayDataSource() for _ in xrange(8 - len(self._settings)) ] + [ s.value_source for s in self._settings ]
     self.register_disconnectable(setting)
     self.register_slot(setting, self.notify_setting_changed, 'setting_changed')
예제 #14
0
	def __init__(self, parent, *a, **k):
		super(MonoScaleDisplayComponent, self).__init__(*a, **k)
		self.num_segments = 4
		self._parent = parent
		self._name_display_line = None
		self._value_display_line = None
		self._name_data_sources = [ DisplayDataSource(DISPLAY_NAMES[index]) for index in xrange(4) ]
		self._value_data_sources = [ DisplayDataSource() for _ in range(self.num_segments) ]
예제 #15
0
class UserSettingsComponent(ControlSurfaceComponent):
    """ Component for changing a list of settings """
    def __init__(self, *a, **k):
        super(UserSettingsComponent, self).__init__(*a, **k)
        self._name_sources = [DisplayDataSource() for _ in xrange(4)]
        self._value_sources = [DisplayDataSource() for _ in xrange(4)]
        self._info_source = DisplayDataSource()
        self._settings = []
        self._encoders = []

    def set_display_line1(self, display):
        if display:
            display.set_data_sources(self._value_sources)

    def set_display_line2(self, display):
        if display:
            display.set_data_sources(self._name_sources)

    def set_display_line3(self, display):
        if display:
            display.reset()

    def set_display_line4(self, display):
        if display:
            display.set_data_sources([self._info_source])

    def set_encoders(self, encoders):
        self._encoders = encoders or []
        self._on_encoder_value.replace_subjects(self._encoders[::2], count())

    def _set_settings(self, settings):
        self._settings = settings.values()
        self._update_display()

    def _get_settings(self):
        return self._settings

    settings = property(_get_settings, _set_settings)

    def set_info_text(self, info_text):
        self._info_source.set_display_string(info_text)

    @subject_slot_group('normalized_value')
    def _on_encoder_value(self, value, index):
        if index >= 0 and index < len(
                self._settings) and self._settings[index].change_relative(
                    value):
            self._update_display()

    def _update_display(self):
        for index, setting in enumerate(self._settings):
            self._name_sources[index].set_display_string(setting.name)
            self._value_sources[index].set_display_string(str(setting))

    def update(self):
        super(UserSettingsComponent, self).update()
        if self.is_enabled():
            self._update_display()
class UserSettingsComponent(ControlSurfaceComponent):
    """ Component for changing a list of settings """

    def __init__(self, *a, **k):
        super(UserSettingsComponent, self).__init__(*a, **k)
        self._name_sources = [ DisplayDataSource() for _ in xrange(4) ]
        self._value_sources = [ DisplayDataSource() for _ in xrange(4) ]
        self._info_source = DisplayDataSource()
        self._settings = []
        self._encoders = []

    def set_display_line1(self, display):
        if display:
            display.set_data_sources(self._value_sources)

    def set_display_line2(self, display):
        if display:
            display.set_data_sources(self._name_sources)

    def set_display_line3(self, display):
        if display:
            display.reset()

    def set_display_line4(self, display):
        if display:
            display.set_data_sources([self._info_source])

    def set_encoders(self, encoders):
        self._encoders = encoders or []
        self._on_encoder_value.replace_subjects(self._encoders[::2], count())

    def _set_settings(self, settings):
        self._settings = settings.values()
        self._update_display()

    def _get_settings(self):
        return self._settings

    settings = property(_get_settings, _set_settings)

    def set_info_text(self, info_text):
        self._info_source.set_display_string(info_text)

    @subject_slot_group('normalized_value')
    def _on_encoder_value(self, value, index):
        if index >= 0 and index < len(self._settings) and self._settings[index].change_relative(value):
            self._update_display()

    def _update_display(self):
        for index, setting in enumerate(self._settings):
            self._name_sources[index].set_display_string(setting.name)
            self._value_sources[index].set_display_string(str(setting))

    def update(self):
        super(UserSettingsComponent, self).update()
        if self.is_enabled():
            self._update_display()
예제 #17
0
	def __init__(self, parent, display_strings, value_strings, *a, **k):
		assert len(display_strings) == len(value_strings)
		super(MonomodDisplayComponent, self).__init__(*a, **k)
		self.num_segments = len(display_strings)
		self._parent = parent
		self._name_display_line = None
		self._value_display_line = None
		self._name_data_sources = [ DisplayDataSource(string) for string in display_strings ]
		self._value_data_sources = [ DisplayDataSource(string) for string in value_strings ]
 def __init__(self, *a, **k):
     super(PageableDeviceComponent, self).__init__(*a, **k)
     self._parameter_value_data_source = DisplayDataSource()
     self._parameter_name_data_sources = []
     self._page_name_data_sources = []
     self._page_index = [0, 0, 0, 0]
     for new_index in range(8):
         self._parameter_name_data_sources.append(DisplayDataSource())
         self._page_name_data_sources.append(DisplayDataSource())
         self._parameter_name_data_sources[-1].set_display_string(' - ')
         self._page_name_data_sources[-1].set_display_string(' - ')
 def __init__(self, mixer):
     raise isinstance(mixer, NotifyingMixerComponent) or AssertionError
     ModeSelectorComponent.__init__(self)
     self._mixer = mixer
     self._controls = None
     self._page_names = ('Vol', 'Pan', 'SendA', 'SendB', 'SendC')
     self._page_name_sources = None
     self._current_page_data_source = DisplayDataSource()
     self._parameter_sources = [DisplayDataSource() for index in range(8)]
     self._show_volume_page = False
     self._mixer.set_update_callback(self._mixer_assignments_changed)
예제 #20
0
class ValueDisplayComponentBase(ControlSurfaceComponent):

    def __init__(self, display_label = ' ', display_seg_start = 0, *a, **k):
        super(ValueDisplayComponentBase, self).__init__(*a, **k)
        self._label_data_source = DisplayDataSource(display_label)
        self._value_data_source = DisplayDataSource()
        self._graphic_data_source = DisplayDataSource()
        self._display_label = display_label
        self._display_seg_start = display_seg_start

    def get_value_string(self):
        raise NotImplementedError

    def get_graphic_string(self):
        raise NotImplementedError

    def set_label_display(self, display):
        self._set_display(display, self._label_data_source)

    def set_value_display(self, display):
        self._set_display(display, self._value_data_source)

    def set_graphic_display(self, display):
        self._set_display(display, self._graphic_data_source)

    def set_clear_display1(self, display):
        self._clear_display(display)

    def set_clear_display2(self, display):
        self._clear_display(display)

    def set_clear_display3(self, display):
        self._clear_display(display)

    def set_clear_display4(self, display):
        self._clear_display(display)

    def _set_display(self, display, source):
        if display:
            display.set_data_sources((None,) * NUM_SEGMENTS)
            display.segment(self._display_seg_start).set_data_source(source)
        return None

    def _clear_display(self, display):
        if display:
            display.set_data_sources((None,))
            display.reset()
        return None

    def update(self):
        super(ValueDisplayComponentBase, self).update()
        if self.is_enabled():
            self._value_data_source.set_display_string(self.get_value_string())
            self._graphic_data_source.set_display_string(self.get_graphic_string())
예제 #21
0
 def __init__(self, grid_resolution = None, *a, **k):
     super(NoteSettingsComponent, self).__init__(*a, **k)
     self._top_data_sources = [ DisplayDataSource() for _ in xrange(8) ]
     self._bottom_data_sources = [ DisplayDataSource() for _ in xrange(8) ]
     self._info_data_source = DisplayDataSource()
     self._settings = []
     self._encoders = []
     self._add_setting(NoteNudgeSetting(grid_resolution=grid_resolution))
     self._add_setting(NoteLengthCoarseSetting(grid_resolution=grid_resolution))
     self._add_setting(NoteLengthFineSetting(grid_resolution=grid_resolution))
     self._add_setting(NoteVelocitySetting(grid_resolution=grid_resolution))
class InfoComponent(BackgroundComponent):
    """
    Component that will show an info text and grab all components that should be unusable.
    """
    def __init__(self, info_text='', *a, **k):
        super(InfoComponent, self).__init__(*a, **k)
        self._data_source = DisplayDataSource()
        self._data_source.set_display_string(info_text)

    def set_display(self, display):
        if display:
            display.set_data_sources([self._data_source])
예제 #23
0
 def __init__(self, *a, **k):
     super(LoopSettingsComponent, self).__init__(*a, **k)
     self._clip = None
     self._name_sources = [DisplayDataSource() for _ in xrange(4)]
     self._value_sources = [DisplayDataSource() for _ in xrange(4)]
     self._clip_is_looping = False
     self._clip_loop_start = None
     self._clip_loop_end = None
     self._clip_loop_length = None
     self._lowest_note_time = 0.0
     self._encoder_factor = 4.0
     self._shift_button = None
예제 #24
0
class InfoComponent(BackgroundComponent):
    """
    Component that will show an info text and grab all components that should be unusable.
    """

    def __init__(self, info_text = '', *a, **k):
        super(InfoComponent, self).__init__(*a, **k)
        self._data_source = DisplayDataSource()
        self._data_source.set_display_string(info_text)

    def set_display(self, display):
        if display:
            display.set_data_sources([self._data_source])
 def __init__(self):
     ShiftableDeviceComponent.__init__(self)
     self._main_lcds = None
     self._parameter_data_sources = []
     for index in range(8):
         self._parameter_data_sources.append(DisplayDataSource())
         self._parameter_data_sources[-1].set_display_string('---')
     self._device_name_lcd = None
     # Explicitly NAME the device_name_data_source
     # This is provided and controlled by DeviceComponent
     # I only need to assign it to a display
     self._device_name_data_source = DisplayDataSource()
     self._param_name_value_toggle = False
예제 #26
0
    def _create_display(self):
        self._display_line1, self._display_line2 = DisplayElement(16, 1), DisplayElement(16, 1)
        for index, display_line in enumerate((self._display_line1, self._display_line2)):
            display_line.set_message_parts(SETUP_MSG_PREFIX + (4, 0, 96), SETUP_MSG_SUFFIX)
            display_line.segment(0).set_position_identifier((index + 1,))

        def adjust_null_terminated_string(string, width):
            return string.ljust(width, ' ') + '\x00'

        self._display_line1_data_source, self._display_line2_data_source = DisplayDataSource(adjust_string_fn=adjust_null_terminated_string), DisplayDataSource(adjust_string_fn=adjust_null_terminated_string)
        self._display_line1.segment(0).set_data_source(self._display_line1_data_source)
        self._display_line2.segment(0).set_data_source(self._display_line2_data_source)
        self._display_line1_data_source.set_display_string('KeyLab')
        self._display_line2_data_source.set_display_string('Ableton Live')
예제 #27
0
 def __init__(self, *a, **k):
     super(DisplayingDeviceComponent, self).__init__(*a, **k)
     self._parameter_name_data_sources = [
         DisplayDataSource(' ') for _ in xrange(8)
     ]
     self._parameter_value_data_sources = [
         DisplayDataSource(' ') for _ in xrange(8)
     ]
     self._parameter_graphic_data_sources = [
         DisplayDataSource(' ') for _ in xrange(8)
     ]
     self._blank_data_sources = [DisplayDataSource(' ') for _ in xrange(8)]
     self._mapped_parameters = []
     self._alternating_display = None
     self._encoder_touch_buttons = []
 def __init__(self, *a, **k):
     super(UserSettingsComponent, self).__init__(*a, **k)
     self._name_sources = [ DisplayDataSource() for _ in xrange(4) ]
     self._value_sources = [ DisplayDataSource() for _ in xrange(4) ]
     self._info_source = DisplayDataSource()
     self._settings = []
     self._encoders = []
예제 #29
0
 def _setup_name_display(self):
     self._name_display = PhysicalDisplayElement(16, 1)
     self._name_display.name = b'Display'
     self._name_display.set_message_parts(SYSEX_START + (8, ), (247, ))
     self._name_display_data_source = DisplayDataSource()
     self._name_display.segment(0).set_data_source(
         self._name_display_data_source)
예제 #30
0
 def __init__(self, *a, **k):
     super(ClipNameComponent, self).__init__(*a, **k)
     self._clip = None
     self._name_data_sources = [
         DisplayDataSource() for _ in xrange(self.num_label_segments)
     ]
     self._name_data_sources[0].set_display_string('Clip Selection:')
예제 #31
0
 def __init__(self, *a, **k):
     super(SpecialChanStripComponent, self).__init__(*a, **k)
     self.empty_color = 'Option.Unused'
     self._invert_mute_feedback = True
     self._delete_button = None
     self._duplicate_button = None
     self._selector_button = None
     self._track_parameter_name_sources = [ DisplayDataSource(' ') for _ in xrange(14) ]
     self._track_parameter_data_sources = [ DisplayDataSource(' ') for _ in xrange(14) ]
     self._track_parameter_graphic_sources = [ DisplayDataSource(' ') for _ in xrange(14) ]
     self._on_return_tracks_changed.subject = self.song()
     self._on_selected_track_changed.subject = self.song().view
     self._fold_task = self._tasks.add(Task.sequence(Task.wait(TRACK_FOLD_DELAY), Task.run(self._do_fold_track))).kill()
     self._cue_volume_slot = self.register_disconnectable(ParameterSlot())
     self._track_state = self.register_disconnectable(TrackArmState())
     self._on_arm_state_changed.subject = self._track_state
 def _setup_displays(self):
     self._name_display = PhysicalDisplayElement(12, 1)
     self._name_display.name = 'Name_Display'
     self._name_display.set_message_parts(SYSEX_START + (21, ), (0, 247))
     self._name_display.set_clear_all_message(CLEAR_NAME)
     self._name_display_data_source = DisplayDataSource()
     self._name_display.segment(0).set_data_source(
         self._name_display_data_source)
     self._value_display = NumericalDisplayElement(3, 1)
     self._value_display.name = 'Value_Display'
     self._value_display.set_message_parts(SYSEX_START + (20, 48), (0, 247))
     self._value_display.set_clear_all_message(CLEAR_VALUE)
     self._value_display_data_source = DisplayDataSource()
     self._value_display.segment(0).set_data_source(
         self._value_display_data_source)
     self._bank_display = NumericalDisplayElement(3, 1)
     self._bank_display.name = 'Bank_Display'
     self._bank_display.set_message_parts(SYSEX_START + (19, ), (0, 247))
     self._bank_display.set_clear_all_message(CLEAR_BANK)
     self._bank_display_data_source = DisplayDataSource()
     self._bank_display.segment(0).set_data_source(
         self._bank_display_data_source)
     self._pad_display = NumericalDisplayElement(2, 1)
     self._pad_display.name = 'Pad_Display'
     self._pad_display.set_message_parts(SYSEX_START + (18, ), (0, 247))
     self._pad_display.set_clear_all_message(CLEAR_PAD)
     self._pad_display_data_source = DisplayDataSource()
     self._pad_display.segment(0).set_data_source(
         self._pad_display_data_source)
    def __init__(self, *a, **k):
        super(BestBankDeviceComponent, self).__init__(*a, **k)
        new_banks = {}
        new_bank_names = {}
        self._device_banks = DEVICE_DICT
        self._device_bank_names = BANK_NAME_DICT
        self._device_best_banks = DEVICE_BOB_DICT
        for device_name, current_banks in self._device_banks.iteritems():
            if len(current_banks) > 1:
                assert device_name in self._device_best_banks.keys(), b"Could not find best-of-banks for '%s'" % device_name
                assert device_name in self._device_bank_names.keys(), b"Could not find bank names for '%s'" % device_name
                current_banks = self._device_best_banks[device_name] + current_banks
                new_bank_names[device_name] = (BOP_BANK_NAME,) + self._device_bank_names[device_name]
            new_banks[device_name] = current_banks

        self._device_banks = new_banks
        self._device_bank_names = new_bank_names
        self._bank_name_data_source = DisplayDataSource()
예제 #34
0
 def __init__(self, *a, **k):
     super(ScrollableListComponent, self).__init__(*a, **k)
     self._data_sources = [ DisplayDataSource() for _ in range(self.num_segments) ]
     self._selected_option = None
     self._offset_index = 0
     self._option_names = []
     self._select_buttons = []
     self._select_button_slots = self.register_slot_manager()
     self.register_slot(self, self._set_selected_option, 'press_option')
    def __init__(self, clip_creator=None, playhead=None, *a, **k):
        super(NoteEditorComponent, self).__init__(*a, **k)
        self.loop_steps = False
        self._selected_page_point = 0
        self._page_index = 0
        self._clip_creator = clip_creator
        self._matrix = None
        self._sequencer_clip = None
        self._step_colors = ['NoteEditor.StepEmpty'] * STEP_SEQ_SIZE
        self._note_settings_layer = None
        self._top_data_sources = map(DisplayDataSource, STEP_PARAM_NAMES)
        self._bottom_data_sources = [DisplayDataSource() for _ in xrange(8)]
        self._show_settings_task = self._tasks.add(
            Task.sequence(Task.wait(Defaults.MOMENTARY_DELAY),
                          Task.run(self._show_settings)))
        self._show_settings_task.kill()
        self._mute_button = None
        self._velocity_offset = 0
        self._length_offset = 0
        self._nudge_offset = 0
        self._attribute_deltas = [None for _ in xrange(3)]
        self._full_velocity = False
        self._pressed_steps = []
        self._modified_steps = []
        self._pressed_step_callback = None
        self._quantization_buttons = []
        self._quantization_button_slots = self.register_slot_manager()
        self._modify_task = self._tasks.add(Task.run(self._do_modification))
        self._modify_task.kill()
        self._modify_all_notes_enabled = False
        self._step_tap_tasks = dict([
            ((x, y),
             self._tasks.add(
                 Task.sequence(
                     Task.wait(Defaults.MOMENTARY_DELAY),
                     Task.run(
                         partial(self._trigger_modification, (x, y),
                                 done=True)))))
            for x, y in product(xrange(STEP_SEQ_WIDTH), xrange(
                STEP_SEQ_HEIGHT))
        ])
        for task in self._step_tap_tasks.itervalues():
            task.kill()

        self._clip_notes = []
        self._note_index = 36
        self._triplet_factor = 1.0
        self._set_quantization_index(3)
        self._playhead = playhead
        self._playhead_notes = range(92, 100) + range(84, 92) + range(
            76, 84) + range(68, 76)
        self._playhead_triplet_notes = range(92, 98) + range(84, 90) + range(
            76, 82) + range(68, 74)
        with self._playhead_update_guard():
            self._update_full_playhead()
 def __init__(self, mixer):
     raise isinstance(mixer, NotifyingMixerComponent) or AssertionError
     ModeSelectorComponent.__init__(self)
     self._mixer = mixer
     self._controls = None
     self._page_names = ('Vol', 'Pan', 'SendA', 'SendB', 'SendC')
     self._page_name_sources = None
     self._current_page_data_source = DisplayDataSource()
     self._parameter_sources = [ DisplayDataSource() for index in range(8) ]
     self._show_volume_page = False
     self._mixer.set_update_callback(self._mixer_assignments_changed)
 def __init__(self, grid_resolution = None, *a, **k):
     super(NoteSettingsComponent, self).__init__(*a, **k)
     self._top_data_sources = [ DisplayDataSource() for _ in xrange(8) ]
     self._bottom_data_sources = [ DisplayDataSource() for _ in xrange(8) ]
     self._info_data_source = DisplayDataSource()
     self._settings = []
     self._encoders = []
     self._add_setting(NoteNudgeSetting(grid_resolution=grid_resolution))
     self._add_setting(NoteLengthCoarseSetting(grid_resolution=grid_resolution))
     self._add_setting(NoteLengthFineSetting(grid_resolution=grid_resolution))
     self._add_setting(NoteVelocitySetting(grid_resolution=grid_resolution))
    def page_name_data_source(self, index):
        assert index in range(4)
        if self._page_name_sources == None:
            self._page_name_sources = []
            offset = 0
            if not self._show_volume_page:
                offset = 1
            for idx in range(4):
                self._page_name_sources.append(DisplayDataSource())
                self._page_name_sources[idx].set_display_string(self._page_names[idx + offset])

        return self._page_name_sources[index]
예제 #39
0
    def page_name_data_source(self, index):
        if not index in range(4):
            raise AssertionError
            if self._page_name_sources == None:
                self._page_name_sources = []
                offset = 0
                offset = self._show_volume_page or 1
            for idx in range(4):
                self._page_name_sources.append(DisplayDataSource())
                self._page_name_sources[idx].set_display_string(self._page_names[(idx + offset)])

        return self._page_name_sources[index]
 def __init__(self):
     DeviceComponent.__init__(self)
     self._parameter_value_data_source = DisplayDataSource()
     self._parameter_name_data_sources = []
     self._page_name_data_sources = []
     self._page_index = [0,
      0,
      0,
      0]
     for new_index in range(8):
         self._parameter_name_data_sources.append(DisplayDataSource())
         self._page_name_data_sources.append(DisplayDataSource())
         self._parameter_name_data_sources[-1].set_display_string(' - ')
         self._page_name_data_sources[-1].set_display_string(' - ')
    def _create_display(self):
        self._display_line1, self._display_line2 = DisplayElement(16, 1), DisplayElement(16, 1)
        for index, display_line in enumerate((self._display_line1, self._display_line2)):
            display_line.set_message_parts(SETUP_MSG_PREFIX + (4, 0, 96), SETUP_MSG_SUFFIX)
            display_line.segment(0).set_position_identifier((index + 1,))

        def adjust_null_terminated_string(string, width):
            return string.ljust(width, ' ') + '\x00'

        self._display_line1_data_source, self._display_line2_data_source = DisplayDataSource(adjust_string_fn=adjust_null_terminated_string), DisplayDataSource(adjust_string_fn=adjust_null_terminated_string)
        self._display_line1.segment(0).set_data_source(self._display_line1_data_source)
        self._display_line2.segment(0).set_data_source(self._display_line2_data_source)
        self._display_line1_data_source.set_display_string('KeyLab')
        self._display_line2_data_source.set_display_string('Ableton Live')
예제 #42
0
    def __init__(self, *a, **k):
        super(BestBankDeviceComponent, self).__init__(*a, **k)
        new_banks = {}
        new_bank_names = {}
        self._device_banks = DEVICE_DICT
        self._device_bank_names = BANK_NAME_DICT
        self._device_best_banks = DEVICE_BOB_DICT
        for device_name, current_banks in self._device_banks.iteritems():
            if len(current_banks) > 1:
                raise device_name in self._device_best_banks.keys() or AssertionError("Could not find best-of-banks for '%s'" % device_name)
                raise device_name in self._device_bank_names.keys() or AssertionError("Could not find bank names for '%s'" % device_name)
                current_banks = self._device_best_banks[device_name] + current_banks
                new_bank_names[device_name] = (BOP_BANK_NAME,) + self._device_bank_names[device_name]
            new_banks[device_name] = current_banks

        self._device_banks = new_banks
        self._device_bank_names = new_bank_names
        self._bank_name_data_source = DisplayDataSource()
    def __init__(self):
        DeviceComponent.__init__(self)
        new_banks = {}
        new_bank_names = {}
        self._device_banks = DEVICE_DICT
        self._device_bank_names = BANK_NAME_DICT
        self._device_best_banks = DEVICE_BOB_DICT
        for device_name, current_banks in self._device_banks.iteritems():
            raise len(current_banks) > 1 and (device_name in self._device_best_banks.keys() or AssertionError), "Could not find best-of-banks for '%s'" % device_name
            if not device_name in self._device_bank_names.keys():
                raise AssertionError, "Could not find bank names for '%s'" % device_name
                current_banks = self._device_best_banks[device_name] + current_banks
                new_bank_names[device_name] = (BOP_BANK_NAME,) + self._device_bank_names[device_name]
            new_banks[device_name] = current_banks

        self._device_banks = new_banks
        self._device_bank_names = new_bank_names
        self._bank_name_data_source = DisplayDataSource()
class KeyLab(ArturiaControlSurface):

    def __init__(self, *a, **k):
        super(KeyLab, self).__init__(*a, **k)
        with self.component_guard():
            self._create_controls()
            self._create_display()
            self._create_device()
            self._create_drums()
            self._create_transport()
            self._create_session()
            self._create_session_recording()
            self._create_mixer()

    def _create_controls(self):
        self._device_encoders = ButtonMatrixElement(rows=[ [ EncoderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, identifier, Live.MidiMap.MapMode.relative_smooth_binary_offset, name='Device_Encoder_%d_%d' % (col_index, row_index)) for col_index, identifier in enumerate(row) ] for row_index, row in enumerate((ENCODER_MSG_IDS[:4], ENCODER_MSG_IDS[4:8])) ])
        self._horizontal_scroll_encoder = EncoderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, ENCODER_MSG_IDS[-2], Live.MidiMap.MapMode.relative_smooth_binary_offset, name='Horizontal_Scroll_Encoder')
        self._vertical_scroll_encoder = EncoderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, ENCODER_MSG_IDS[-1], Live.MidiMap.MapMode.relative_smooth_binary_offset, name='Vertical_Scroll_Encoder')
        self._volume_sliders = ButtonMatrixElement(rows=[[ SliderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, identifier) for identifier in SLIDER_MSG_IDS[:-1] ]])
        self._master_slider = SliderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, SLIDER_MSG_IDS[-1])

        def make_keylab_button(name):
            button = ButtonElement(True, MIDI_CC_TYPE, 0, get_button_identifier_by_name(name), name=name.title())
            return button

        for button_name in BUTTON_HARDWARE_AND_MESSAGE_IDS.keys():
            setattr(self, '_' + button_name, make_keylab_button(button_name))

        self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_CC_TYPE, PAD_CHANNEL, col_index + row_offset, name='Pad_%d_%d' % (col_index, row_index)) for col_index in xrange(4) ] for row_index, row_offset in enumerate(xrange(48, 35, -4)) ])

    def _create_display(self):
        self._display_line1, self._display_line2 = DisplayElement(16, 1), DisplayElement(16, 1)
        for index, display_line in enumerate((self._display_line1, self._display_line2)):
            display_line.set_message_parts(SETUP_MSG_PREFIX + (4, 0, 96), SETUP_MSG_SUFFIX)
            display_line.segment(0).set_position_identifier((index + 1,))

        def adjust_null_terminated_string(string, width):
            return string.ljust(width, ' ') + '\x00'

        self._display_line1_data_source, self._display_line2_data_source = DisplayDataSource(adjust_string_fn=adjust_null_terminated_string), DisplayDataSource(adjust_string_fn=adjust_null_terminated_string)
        self._display_line1.segment(0).set_data_source(self._display_line1_data_source)
        self._display_line2.segment(0).set_data_source(self._display_line2_data_source)
        self._display_line1_data_source.set_display_string('KeyLab')
        self._display_line2_data_source.set_display_string('Ableton Live')

    def _create_device(self):
        self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=self._device_encoders))
        self._device.set_enabled(True)
        self.set_device_component(self._device)
        self._device_selection_follows_track_selection = True
        self._device_navigation = DeviceNavigationComponent(name='Device_Navigation', is_enabled=False, layer=Layer(device_nav_left_button=self._device_left_button, device_nav_right_button=self._device_right_button))
        self._device_navigation.set_enabled(True)

    def _create_drums(self):
        self._drums = DrumRackComponent(name='Drums', is_enabled=False, layer=Layer(pads=self._pads))
        self._drums.set_enabled(True)

    def _create_transport(self):
        self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, record_button=self._record_button, loop_button=self._loop_button))
        self._transport.set_enabled(True)

    def _create_session(self):
        self._session = SessionComponent(num_tracks=8, num_scenes=1, name='Session', is_enabled=False, layer=Layer(select_next_button=self._scene_down_button, select_prev_button=self._scene_up_button, selected_scene_launch_button=self._scene_launch_button, stop_all_clips_button=self._stop_all_clips_button, scene_select_encoder=self._vertical_scroll_encoder))
        self._session.set_enabled(True)

    def _create_session_recording(self):
        self._session_recording = SessionRecordingComponent(ClipCreator(), ViewControlComponent(), name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._session_record_button))
        self._session_recording.set_enabled(True)

    def _create_mixer(self):
        self._mixer = MixerComponent(num_tracks=self._volume_sliders.width(), name='Mixer', is_enabled=False, layer=Layer(volume_controls=self._volume_sliders, track_select_encoder=self._horizontal_scroll_encoder))
        self._mixer.master_strip().layer = Layer(volume_control=self._master_slider)
        self._mixer.set_enabled(True)

    def _collect_setup_messages(self):
        for hardware_id, identifier in izip(ENCODER_HARDWARE_IDS, ENCODER_MSG_IDS):
            self._setup_hardware_encoder(hardware_id, identifier, ENCODER_CHANNEL)

        for hardware_id, identifier in izip(SLIDER_HARDWARE_IDS, SLIDER_MSG_IDS):
            self._setup_hardware_slider(hardware_id, identifier, ENCODER_CHANNEL)

        for hardware_id, identifier in BUTTON_HARDWARE_AND_MESSAGE_IDS.itervalues():
            self._setup_hardware_button(hardware_id, identifier)

        for hardware_id, identifier in izip(PAD_HARDWARE_IDS, PAD_MSG_IDS):
            self._setup_hardware_pad(hardware_id, identifier)

    def _setup_hardware_encoder(self, hardware_id, identifier, channel = 0):
        self._set_encoder_cc_msg_type(hardware_id, is_relative=True)
        self._set_identifier(hardware_id, identifier)
        self._set_channel(hardware_id, channel)

    def _setup_hardware_button(self, hardware_id, identifier, channel = 0, **k):
        self._set_encoder_cc_msg_type(hardware_id)
        self._set_identifier(hardware_id, identifier)
        self._set_channel(hardware_id, channel)
        self._set_value_minimum(hardware_id)
        self._set_value_maximum(hardware_id)

    def _setup_hardware_pad(self, hardware_id, identifier, channel = PAD_CHANNEL):
        self._set_pad_note_msg_type(hardware_id)
        self._set_identifier(hardware_id, identifier)
        self._set_channel(hardware_id, channel)

    def _set_pad_note_msg_type(self, hardware_id):
        self._collect_setup_message(MODE_PROPERTY, hardware_id, PAD_NOTE_MODE)
class EncoderMixerModeSelector(ModeSelectorComponent):
    """ Class that reassigns encoders on the AxiomPro to different mixer functions """

    def __init__(self, mixer):
        raise isinstance(mixer, NotifyingMixerComponent) or AssertionError
        ModeSelectorComponent.__init__(self)
        self._mixer = mixer
        self._controls = None
        self._page_names = ("Vol", "Pan", "SendA", "SendB", "SendC")
        self._page_name_sources = None
        self._current_page_data_source = DisplayDataSource()
        self._parameter_sources = [DisplayDataSource() for index in range(8)]
        self._show_volume_page = False
        self._mixer.set_update_callback(self._mixer_assignments_changed)
        return

    def disconnect(self):
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._mixer = None
        self._controls = None
        self._page_names = None
        self._page_name_sources = None
        self._current_page_data_source = None
        self._parameter_sources = None
        ModeSelectorComponent.disconnect(self)
        return

    def set_modes_buttons(self, buttons):
        raise buttons == None or isinstance(buttons, tuple) or len(buttons) == self.number_of_modes() or AssertionError
        identify_sender = True
        for button in self._modes_buttons:
            button.remove_value_listener(self._mode_value)

        self._modes_buttons = []
        if buttons != None:
            for button in buttons:
                raise isinstance(button, ButtonElement) or AssertionError
                self._modes_buttons.append(button)
                button.add_value_listener(self._mode_value, identify_sender)

        self.set_mode(0)
        self.update()
        return

    def set_controls(self, controls):
        raise controls == None or isinstance(controls, tuple) and len(controls) == 8 or AssertionError
        self._controls = controls
        self.set_mode(0)
        self.update()
        return

    def set_show_volume_page(self, show):
        if not isinstance(show, type(False)):
            raise AssertionError
            if show != self._show_volume_page:
                self._show_volume_page = show
                if self._page_name_sources != None:
                    offset = 0
                    offset = self._show_volume_page or 1
                for idx in range(4):
                    self._page_name_sources[idx].set_display_string(self._page_names[idx + offset])

            self.update()
        return

    def page_name_data_source(self, index):
        if not index in range(4):
            raise AssertionError
            if self._page_name_sources == None:
                self._page_name_sources = []
                offset = 0
                offset = self._show_volume_page or 1
            for idx in range(4):
                self._page_name_sources.append(DisplayDataSource())
                self._page_name_sources[idx].set_display_string(self._page_names[idx + offset])

        return self._page_name_sources[index]

    def parameter_data_source(self, index):
        raise self._controls != None or AssertionError
        raise index in range(len(self._controls)) or AssertionError
        return self._mixer.channel_strip(index).track_name_data_source()

    def current_page_data_source(self):
        return self._current_page_data_source

    def number_of_modes(self):
        return 4

    def update(self):
        super(EncoderMixerModeSelector, self).update()
        if not self._modes_buttons != None:
            raise AssertionError
            if self.is_enabled() and self._controls != None:
                mode = self._mode_index
                self._show_volume_page or mode += 1
            self._current_page_data_source.set_display_string(self._page_names[mode])
            for index in range(len(self._controls)):
                self._controls[index].release_parameter()
                self._mixer.channel_strip(index).track_name_data_source().update()
                self._mixer.channel_strip(index).set_pan_control(None)
                self._mixer.channel_strip(index).set_send_controls((None, None, None))
                if self._show_volume_page:
                    self._mixer.channel_strip(index).set_volume_control(None)
                if not (mode == 0 and self._show_volume_page):
                    raise AssertionError
                    self._mixer.channel_strip(index).set_volume_control(self._controls[index])
                elif mode == 1:
                    self._mixer.channel_strip(index).set_pan_control(self._controls[index])
                elif mode == 2:
                    self._mixer.channel_strip(index).set_send_controls((self._controls[index], None, None))
                elif mode == 3:
                    self._mixer.channel_strip(index).set_send_controls((None, self._controls[index], None))
                elif not (mode == 4 and not self._show_volume_page):
                    raise AssertionError
                    self._mixer.channel_strip(index).set_send_controls((None, None, self._controls[index]))
                else:
                    print "Invalid mode index"
                    raise False or AssertionError

        return

    def _mixer_assignments_changed(self):
        self.update()
class PageableDeviceComponent(DeviceComponent):
    """ Class representing a device on the AxiomPro """

    def __init__(self):
        DeviceComponent.__init__(self)
        self._parameter_value_data_source = DisplayDataSource()
        self._parameter_name_data_sources = []
        self._page_name_data_sources = []
        self._page_index = [0,
         0,
         0,
         0]
        for new_index in range(8):
            self._parameter_name_data_sources.append(DisplayDataSource())
            self._page_name_data_sources.append(DisplayDataSource())
            self._parameter_name_data_sources[-1].set_display_string(' - ')
            self._page_name_data_sources[-1].set_display_string(' - ')

    def disconnect(self):
        self._parameter_value_data_source = None
        self._parameter_name_data_sources = None
        self._page_name_data_sources = None
        DeviceComponent.disconnect(self)

    def set_device(self, device):
        DeviceComponent.set_device(self, device)
        if self._device == None:
            for source in self._parameter_name_data_sources:
                source.set_display_string(' - ')

            for source in self._page_name_data_sources:
                source.set_display_string(' - ')

    def set_bank_buttons(self, buttons):
        raise buttons == None or isinstance(buttons, tuple) and len(buttons) == 4 or AssertionError
        DeviceComponent.set_bank_buttons(self, buttons)

    def set_parameter_controls(self, controls):
        raise controls == None or isinstance(controls, tuple) and len(controls) == 8 or AssertionError
        if self._parameter_controls != None:
            for control in self._parameter_controls:
                if self._device != None:
                    control.release_parameter()

        self._parameter_controls = controls
        if self._parameter_controls != None:
            for control in self._parameter_controls:
                raise control != None or AssertionError
                raise isinstance(control, EncoderElement) or AssertionError

        self.update()

    def parameter_value_data_source(self):
        return self._parameter_value_data_source

    def parameter_name_data_source(self, index):
        raise index in range(8) or AssertionError
        return self._parameter_name_data_sources[index]

    def page_name_data_source(self, index):
        raise index in range(8) or AssertionError
        return self._page_name_data_sources[index]

    def _bank_value(self, value, button):
        if not self._bank_buttons != None:
            raise AssertionError
            raise value != None or AssertionError
            raise button != None or AssertionError
            raise isinstance(value, int) or AssertionError
            raise isinstance(button, ButtonElement) or AssertionError
            if not list(self._bank_buttons).count(button) == 1:
                raise AssertionError
                if self.is_enabled():
                    if not button.is_momentary() or value is not 0:
                        bank = list(self._bank_buttons).index(button)
                        self._bank_index = self._device != None and bank != self._bank_index and bank
                    else:
                        self._page_index[bank] += 1
                    self.update()

    def _assign_parameters(self):
        if not self.is_enabled():
            raise AssertionError
            raise self._device != None or AssertionError
            raise self._parameter_controls != None or AssertionError
            self._device.class_name in SPECIAL_DEVICE_DICT.keys() and self.__assign_parameters_special()
        elif self._device.class_name in DEVICE_DICT.keys():
            self.__assign_parameters_normal()
        else:
            self.__assign_parameters_plugin()
        self._parameter_value_data_source.set_display_string('')
        for index in range(len(self._parameter_controls)):
            if self._parameter_controls[index].mapped_parameter() != None:
                self._parameter_name_data_sources[index].set_display_string(self._parameter_controls[index].mapped_parameter().name)
            else:
                self._parameter_name_data_sources[index].set_display_string(' - ')

    def __assign_parameters_special(self):
        """ Assign the controls to the parameters of a device with more than 4 pages """
        banks = SPECIAL_DEVICE_DICT[self._device.class_name]
        bank_names = SPECIAL_NAME_DICT[self._device.class_name]
        pages = banks[self._bank_index]
        self._page_index[self._bank_index] %= len(pages)
        self._bank_name = bank_names[self._bank_index][self._page_index[self._bank_index]]
        page = pages[self._page_index[self._bank_index]]
        raise len(page) >= len(self._parameter_controls) or AssertionError
        for index in range(len(self._parameter_controls)):
            parameter = get_parameter_by_name(self._device, page[index])
            if parameter != None:
                self._parameter_controls[index].connect_to(parameter)
            else:
                self._parameter_controls[index].release_parameter()

        for index in range(len(self._page_name_data_sources)):
            if index < len(bank_names):
                page_names = bank_names[index]
                if index == self._bank_index:
                    self._page_name_data_sources[index].set_display_string(page_names[(self._page_index[index] + 1) % len(page_names)])
                else:
                    self._page_name_data_sources[index].set_display_string(page_names[self._page_index[index] % len(page_names)])
            else:
                self._page_name_data_sources[index].set_display_string(' - ')

    def __assign_parameters_normal(self):
        """ Assign the controls to the parameters of a device with 4 pages or less """
        if not self._device.class_name in DEVICE_BOB_DICT.keys():
            raise AssertionError
            self._page_index[self._bank_index] = 0
            banks = DEVICE_DICT[self._device.class_name]
            bank_names = []
            if len(banks) > self._bank_index:
                if self._device.class_name in BANK_NAME_DICT.keys() and len(BANK_NAME_DICT[self._device.class_name]) > 1:
                    bank_names = BANK_NAME_DICT[self._device.class_name]
                bank = banks[self._bank_index]
                self._bank_name = self._bank_index in range(len(bank_names)) and bank_names[self._bank_index]
            else:
                self._bank_name = 'Bank ' + str(self._bank_index + 1)
            raise len(bank) >= len(self._parameter_controls) or AssertionError
            for index in range(len(self._parameter_controls)):
                parameter = get_parameter_by_name(self._device, bank[index])
                if parameter != None:
                    self._parameter_controls[index].connect_to(parameter)
                else:
                    self._parameter_controls[index].release_parameter()

        for index in range(len(self._page_name_data_sources)):
            if index < len(bank_names):
                self._page_name_data_sources[index].set_display_string(bank_names[index])
            else:
                self._page_name_data_sources[index].set_display_string(' - ')

    def __assign_parameters_plugin(self):
        """ Assign the controls to the parameters of a plugin """
        num_controls = len(self._parameter_controls)
        num_banks = min(8, number_of_parameter_banks(self._device))
        num_double_pages = 0
        num_double_pages_before = 0
        parameters_to_use = self._device.parameters[1:]
        self._bank_name = 'Bank ' + str(self._bank_index + 1)
        if num_banks > 4:
            num_double_pages = num_banks - 4
        if self._bank_index < num_double_pages:
            self._page_index[self._bank_index] %= 2
            num_double_pages_before = self._bank_index
        else:
            self._page_index[self._bank_index] = 0
            num_double_pages_before = num_double_pages
        if self._bank_index + num_double_pages_before < num_banks:
            bank_offset = (self._bank_index + num_double_pages_before) * num_controls
            page_offset = bank_offset + self._page_index[self._bank_index] * num_controls
            for control in self._parameter_controls:
                if page_offset < len(parameters_to_use):
                    control.connect_to(parameters_to_use[page_offset])
                else:
                    control.release_parameter()
                page_offset += 1

            bank_names = []
            parameter_offset = 0
            for index in range(4):
                display_string = ' - '
                if index < num_banks:
                    if index < num_double_pages:
                        if not (index == self._bank_index and self._page_index[index] == 0):
                            if index != self._bank_index:
                                add_offset_before = self._page_index[index] != 0
                                add_offset_before and parameter_offset += num_controls
                            display_string = str(parameter_offset + 1).rjust(2) + '-' + str(parameter_offset + num_controls).rjust(2)
                            add_offset_before or parameter_offset += num_controls
                    else:
                        display_string = str(parameter_offset + 1).rjust(2) + '-' + str(parameter_offset + num_controls).rjust(2)
                self._page_name_data_sources[index].set_display_string(display_string)
                parameter_offset += num_controls
예제 #47
0
 def _setup_display(self):
     self._display = PhysicalDisplayElement(5, 1)
     self._display.name = "Display"
     self._display.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247,))
     self._display_data_source = DisplayDataSource()
     self._display.segment(0).set_data_source(self._display_data_source)
class Axiom_AIR_25_49_61(ControlSurface):
    """ Script for the M-Audio Axiom A.I.R. 25, 49 and 61 """

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        self._alt_device_component = None
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = "HyperControl"
            self._suggested_output_port = "HyperControl"
            self._single_fader_button_modes = None
            self._has_faders = True
            self._display_reset_delay = -1
            self._hc_byte = HC_BYTE
            self._waiting_for_first_response = True
            self._setup_controls()
            self._setup_displays()
            self._setup_mixer()
            self._setup_session()
            self._setup_transport()
            self._setup_device()
            self._setup_modes()
            self._drum_group_midi_button = None
            self._drum_group_hyper_button = None
            for component in self.components:
                component.set_enabled(False)

    def disconnect(self):
        self._scheduled_messages = []
        for encoder in self._encoders:
            encoder.remove_value_listener(self._encoder_value)

        for fader in self._faders:
            fader.remove_value_listener(self._fader_value)

        for fader_button in self._fader_buttons:
            fader_button.remove_value_listener(self._fader_button_value)

        self._master_fader.remove_value_listener(self._fader_value)
        self._master_fader_button.remove_value_listener(self._fader_button_value)
        self._select_button.remove_value_listener(self._select_button_value)
        self._identify_button.remove_value_listener(self._identify_value)
        self._fader_group_midi_button.remove_value_listener(self._midi_button_value)
        self._fader_group_mix_button.remove_value_listener(self._hyper_button_value)
        self._fader_group_fx_button.remove_value_listener(self._hyper_button_value)
        self._encoder_group_midi_button.remove_value_listener(self._midi_button_value)
        self._encoder_group_mix_button.remove_value_listener(self._hyper_button_value)
        self._encoder_group_fx_button.remove_value_listener(self._hyper_button_value)
        if self._drum_group_midi_button != None:
            self._drum_group_midi_button.remove_value_listener(self._midi_button_value)
        if self._drum_group_hyper_button != None:
            self._drum_group_hyper_button.remove_value_listener(self._hyper_button_value)
        self._alt_device_component = None
        self._name_display = None
        self._value_display = None
        self._bank_display = None
        self._pad_display = None
        self._name_display_data_source = None
        self._value_display_data_source = None
        self._bank_display_data_source = None
        self._pad_display_data_source = None
        self._select_button = None
        self._left_button = None
        self._right_button = None
        self._up_button = None
        self._down_button = None
        self._loop_button = None
        self._ffwd_button = None
        self._rwd_button = None
        self._play_button = None
        self._stop_button = None
        self._rec_button = None
        self._master_fader_button = None
        self._fader_buttons = None
        self._faders = None
        self._encoders = None
        self._drum_pads = None
        self._identify_button = None
        self._main_group_hyper_button = None
        self._main_group_track_button = None
        self._main_group_fx_button = None
        self._encoder_group_midi_button = None
        self._encoder_group_mix_button = None
        self._encoder_group_fx_button = None
        self._fader_group_mode_button = None
        self._fader_group_midi_button = None
        self._fader_group_mix_button = None
        self._fader_group_fx_button = None
        self._drum_group_midi_button = None
        self._drum_group_roll_button = None
        self._drum_group_hyper_button = None
        self._mixer_for_encoders = None
        self._mixer_for_faders = None
        self._device_for_encoders = None
        self._device_for_faders = None
        self._transport = None
        self._session = None
        ControlSurface.disconnect(self)
        self._send_midi(SYSEX_START + DISABLE_HYPERCONTROL)

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self.schedule_message(5, self._send_midi, IDENTITY_REQUEST)

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:10] == AXIOM_AIR_RESPONSE:
            if midi_bytes[12:15] < AXIOM_REV4_RESPONSE:
                self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL)
                self.schedule_message(2, self._send_midi, SYSEX_START + CLEAR_ALL)
                self.schedule_message(3, self._name_display.display_message, "Firmware")
                self.schedule_message(13, self._name_display.display_message, "Update")
                self.schedule_message(23, self._name_display.display_message, "Required")
                self.schedule_message(33, self._send_midi, SYSEX_START + DISABLE_HYPERCONTROL)
            elif midi_bytes[12:15] >= AXIOM_REV4_RESPONSE:
                if self._waiting_for_first_response == True:
                    self._waiting_for_first_response = False
                    self._has_faders = midi_bytes[10] != 50
                    self.schedule_message(1, self._send_midi, SYSEX_START + ENGAGE_HYPERCONTROL)
                    self.schedule_message(2, self._send_midi, SYSEX_START + SPECIAL_HYPERCONTROL)
                    self.schedule_message(3, self._complete_setup)
                else:
                    self._display_reset_delay = 0
        elif midi_bytes[0:8] == REQUEST_HYPERCONTROL:
            self.schedule_message(5, self._send_midi, IDENTITY_REQUEST)

    def update_display(self):
        ControlSurface.update_display(self)
        if self._display_reset_delay >= 0:
            self._display_reset_delay -= 1
            if self._display_reset_delay == -1:
                self._set_displays_to_default()

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._display_reset_delay = 0

    def restore_bank(self, bank_index):
        ControlSurface.restore_bank(self, bank_index)
        if self._alt_device_component != None:
            self._alt_device_component.restore_bank(bank_index)

    def set_appointed_device(self, device):
        ControlSurface.set_appointed_device(self, device)
        with self.component_guard():
            if self._alt_device_component != None:
                self._alt_device_component.set_device(device)

    def set_alt_device_component(self, device_component):
        self._alt_device_component = device_component

    def _update_device_selection(self):
        track = self.song().view.selected_track
        device_to_select = track.view.selected_device
        if device_to_select == None and len(track.devices) > 0:
            device_to_select = track.devices[0]
        if device_to_select != None:
            self.song().view.select_device(device_to_select)
        self._device_component.set_device(device_to_select)
        if self._alt_device_component != None:
            self._alt_device_component.set_device(device_to_select)

    def _setup_controls(self):
        self._left_button = create_button(99, "Left_Button")
        self._right_button = create_button(100, "Right_Button")
        self._up_button = create_button(101, "Up_Button")
        self._down_button = create_button(102, "Down_Button")
        self._loop_button = create_button(113, "Loop_Button")
        self._rwd_button = create_button(114, "Rwd_Button")
        self._ffwd_button = create_button(115, "FFwd_Button")
        self._stop_button = create_button(116, "Stop_Button")
        self._play_button = create_button(117, "Play_Button")
        self._rec_button = create_button(118, "Record_Button")
        self._select_button = ConfigurableButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, GLOBAL_CHANNEL, 98)
        self._select_button.name = "Select_Button"
        self._select_button.add_value_listener(self._select_button_value)
        self._main_group_hyper_button = create_configurable_button(104, "Fader_Group_HyperControl_Button", 2, 14)
        self._main_group_track_button = create_configurable_button(105, "Main_Group_Track_Button", 2, 11)
        self._main_group_fx_button = create_configurable_button(106, "Main_Group_Inst_FX_Button", 2, 11)
        self._identify_button = create_configurable_button(97, "Identify_Button", 2, 16)
        self._identify_button.add_value_listener(self._identify_value)
        self._fader_buttons = []
        for index in range(8):
            self._fader_buttons.append(create_configurable_button(49 + index, "Fader_Button_%d" % index))
            self._fader_buttons[-1].add_value_listener(self._fader_button_value, identify_sender=True)

        self._faders = []
        for index in range(8):
            self._faders.append(create_slider(33 + index, "Fader_%d" % index))
            self._faders[-1].add_value_listener(self._fader_value, identify_sender=True)

        self._master_fader_button = create_configurable_button(57, "Master_Fader_Button")
        self._master_fader_button.add_value_listener(self._fader_button_value, identify_sender=True)
        self._master_fader = create_slider(41, "Master_Fader")
        self._master_fader.add_value_listener(self._fader_value, identify_sender=True)
        self._fader_group_mode_button = create_configurable_button(61, "Fader_Group_Mode_Button")
        self._fader_group_midi_button = create_configurable_button(60, "Fader_Group_MIDI_Button")
        self._fader_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True)
        self._fader_group_mix_button = create_configurable_button(58, "Fader_Group_Mix_Button", 0, 1)
        self._fader_group_mix_button.add_value_listener(self._hyper_button_value, identify_sender=True)
        self._fader_group_fx_button = create_configurable_button(59, "Fader_Group_Inst_FX_Button", 0, -1)
        self._fader_group_fx_button.add_value_listener(self._hyper_button_value, identify_sender=True)
        self._encoders = []
        for index in range(8):
            self._encoders.append(create_encoder(17 + index, "Encoder_%d" % index))
            self._encoders[-1].add_value_listener(self._encoder_value, identify_sender=True)

        self._encoder_group_midi_button = create_configurable_button(27, "Encoder_Group_MIDI_Button", 0, 72)
        self._encoder_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True)
        self._encoder_group_mix_button = create_configurable_button(25, "Encoder_Group_Mix_Button", 0, 72)
        self._encoder_group_mix_button.add_value_listener(self._hyper_button_value, identify_sender=True)
        self._encoder_group_fx_button = create_configurable_button(26, "Encoder_Group_Inst_FX_Button", 0, 72)
        self._encoder_group_fx_button.add_value_listener(self._hyper_button_value, identify_sender=True)

    def _setup_drum_pads(self):
        self._drum_pads = []
        num_pads = 12 if self._has_faders else 16
        for index in range(8):
            self._drum_pads.append(create_configurable_button(81 + index, "Pad_%d" % index, 0, 0, MIDI_CC_TYPE))

        for index in range(num_pads - 8):
            self._drum_pads.append(
                ConfigurableButtonElement(
                    IS_MOMENTARY, MIDI_NOTE_TYPE, GLOBAL_CHANNEL - 1, 81 + index, GLOBAL_SEND_CHANNEL, 8, MIDI_CC_TYPE
                )
            )
            self._drum_pads[-1].name = "Pad_" + str(index + 8)

        self._drum_group_midi_button = create_configurable_button(91, "Drum_Group_MIDI_Button", 2, -2)
        self._drum_group_midi_button.add_value_listener(self._midi_button_value, identify_sender=True)
        self._drum_group_roll_button = create_configurable_button(90, "Drum_Group_Roll_Button", -1)
        self._drum_group_hyper_button = create_configurable_button(89, "Drum_Group_HyperControl_Button", 2, 2)
        self._drum_group_hyper_button.add_value_listener(self._hyper_button_value, identify_sender=True)

    def _setup_displays(self):
        self._name_display = PhysicalDisplayElement(12, 1)
        self._name_display.name = "Name_Display"
        self._name_display.set_message_parts(SYSEX_START + (21,), (0, 247))
        self._name_display.set_clear_all_message(CLEAR_NAME)
        self._name_display_data_source = DisplayDataSource()
        self._name_display.segment(0).set_data_source(self._name_display_data_source)
        self._value_display = NumericalDisplayElement(3, 1)
        self._value_display.name = "Value_Display"
        self._value_display.set_message_parts(SYSEX_START + (20, 48), (0, 247))
        self._value_display.set_clear_all_message(CLEAR_VALUE)
        self._value_display_data_source = DisplayDataSource()
        self._value_display.segment(0).set_data_source(self._value_display_data_source)
        self._bank_display = NumericalDisplayElement(3, 1)
        self._bank_display.name = "Bank_Display"
        self._bank_display.set_message_parts(SYSEX_START + (19,), (0, 247))
        self._bank_display.set_clear_all_message(CLEAR_BANK)
        self._bank_display_data_source = DisplayDataSource()
        self._bank_display.segment(0).set_data_source(self._bank_display_data_source)
        self._pad_display = NumericalDisplayElement(2, 1)
        self._pad_display.name = "Pad_Display"
        self._pad_display.set_message_parts(SYSEX_START + (18,), (0, 247))
        self._pad_display.set_clear_all_message(CLEAR_PAD)
        self._pad_display_data_source = DisplayDataSource()
        self._pad_display.segment(0).set_data_source(self._pad_display_data_source)

    def _setup_mixer(self):
        self._mixer_for_encoders = SpecialMixerComponent(self._name_display, self._value_display, 8)
        self._mixer_for_encoders.name = "Mixer_for_encoders"
        self._mixer_for_faders = SpecialMixerComponent(self._name_display, self._value_display, 8)
        self._mixer_for_faders.name = "Mixer_for_faders"

    def _setup_session(self):
        self._session = SpecialSessionComponent(8, 0)
        self._session.name = "Session_Control"
        self._session.selected_scene().name = "Selected_Scene"
        self._session.set_mixer(self._mixer_for_encoders)
        self._session.set_alt_mixer(self._mixer_for_faders)
        self._session.add_offset_listener(self._update_bank_value)

    def _setup_transport(self):
        self._transport = TransportComponent()
        self._transport.name = "Transport"
        self._transport.set_stop_button(self._stop_button)
        self._transport.set_play_button(self._play_button)
        self._transport.set_record_button(self._rec_button)
        transport_view_modes = TransportViewModeSelector(
            self._transport, self._session, self._ffwd_button, self._rwd_button, self._loop_button
        )
        transport_view_modes.name = "Transport_View_Modes"

    def _setup_device(self):
        self._device_for_encoders = BestBankDeviceComponent()
        self._device_for_encoders.name = "Device_Component_for_encoders"
        self._device_for_faders = BestBankDeviceComponent()
        self._device_for_faders.name = "Device_Component_for_faders"
        self.set_device_component(self._device_for_encoders)
        self.set_alt_device_component(self._device_for_faders)
        self._device_nav = DeviceNavComponent()
        self._device_nav.name = "Device_Nav_Component"

    def _setup_modes(self):
        self._fader_button_modes = FaderButtonModeSelector(self._mixer_for_faders, tuple(self._fader_buttons))
        self._fader_button_modes.name = "Fader_Button_Modes"
        self._fader_button_modes.set_mode_toggle(self._fader_group_mode_button)
        self._fader_modes = FaderModeSelector(
            self._mixer_for_faders,
            self._device_for_faders,
            tuple(self._faders),
            self._fader_button_modes,
            self._master_fader_button,
        )
        self._fader_modes.name = "Fader_Modes"
        self._fader_modes.set_mode_buttons((self._fader_group_mix_button, self._fader_group_fx_button))
        self._encoder_modes = EncoderModeSelector(
            self._mixer_for_encoders, self._device_for_encoders, tuple(self._encoders)
        )
        self._encoder_modes.name = "Encoder_Modes"
        self._encoder_modes.set_mode_buttons((self._encoder_group_mix_button, self._encoder_group_fx_button))
        main_modes = MainModeSelector(
            self._device_for_encoders,
            self._device_for_faders,
            self._session,
            self._mixer_for_faders,
            self._device_nav,
            self._up_button,
            self._down_button,
            self._left_button,
            self._right_button,
            self._select_button,
        )
        main_modes.name = "Main_Modes"
        main_modes.set_mode_buttons((self._main_group_track_button, self._main_group_fx_button))

    def _setup_master_fader(self):
        if self._has_faders:
            self._mixer_for_encoders.master_strip().set_volume_control(self._master_fader)
        else:
            self._mixer_for_encoders.selected_strip().set_volume_control(self._master_fader)

    def _setup_single_fader_button_modes(self):
        self._single_fader_button_modes = SingleFaderButtonModeSelector(
            self._mixer_for_encoders, self._fader_group_midi_button
        )
        self._single_fader_button_modes.name = "Single_Fader_Button_Modes"
        self._single_fader_button_modes.set_mode_toggle(self._fader_group_mode_button)

    def _complete_setup(self):
        self._setup_drum_pads()
        self._set_drum_pads_to_hc()
        self._setup_master_fader()
        if not self._has_faders:
            self._setup_single_fader_button_modes()
        for control in self.controls:
            if isinstance(control, InputControlElement):
                control.clear_send_cache()

        for component in self.components:
            component.set_enabled(True)

        self._fader_group_midi_button.send_value(LED_OFF, True)
        self._encoder_group_midi_button.send_value(LED_OFF, True)
        self._main_group_hyper_button.send_value(AMB_FULL, True)
        self.request_rebuild_midi_map()
        self._on_selected_track_changed()
        self.schedule_message(1, self._show_startup_message)

    def _show_startup_message(self):
        self._send_midi(SYSEX_START + CLEAR_ALL)
        self._name_display.display_message("Ableton Live")
        self._display_reset_delay = INITIAL_DISPLAY_DELAY

    def _select_button_value(self, value):
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _identify_value(self, value):
        for encoder in self._encoders:
            encoder.set_identify_mode(value > 0)

        for fader in self._faders:
            fader.set_identify_mode(value > 0)

        self._master_fader.set_identify_mode(value > 0)
        self._display_reset_delay = 0
        self._identify_button.turn_on() if value > 0 else self._identify_button.turn_off()

    def _midi_button_value(self, value, sender):
        if value > 0:
            if sender is self._drum_group_midi_button:
                hc_byte = self._hc_byte ^ PADS
                if hc_byte != self._hc_byte:
                    self._hc_byte = hc_byte
                    self._drum_group_hyper_button.send_value(LED_OFF, True)
                    self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247))
            elif sender is self._encoder_group_midi_button:
                hc_byte = self._hc_byte ^ ENCODERS
                if hc_byte != self._hc_byte:
                    self._hc_byte = hc_byte
                    self._encoder_group_mix_button.send_value(LED_OFF, True)
                    self._encoder_group_fx_button.send_value(LED_OFF, True)
                    if self._encoder_modes.mode_index < 3:
                        self._encoder_modes.set_enabled(False)
                    self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247))
            elif sender is self._fader_group_midi_button:
                if self._has_faders:
                    hc_byte = self._hc_byte ^ FADERS
                    if hc_byte != self._hc_byte:
                        self._hc_byte = hc_byte
                        self._fader_group_mix_button.send_value(LED_OFF, True)
                        self._fader_group_fx_button.send_value(LED_OFF, True)
                        self._fader_group_mode_button.send_value(LED_OFF, True)
                        if self._fader_modes.mode_index < 2:
                            self._fader_modes.set_enabled(False)
                            self._fader_button_modes.set_enabled(False)
                        self.schedule_message(1, self._send_midi, SYSEX_START + (32, self._hc_byte, 247))
                else:
                    self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _hyper_button_value(self, value, sender):
        if value > 0:
            if sender is self._drum_group_hyper_button:
                if self._hc_byte | PADS != self._hc_byte:
                    self._hc_byte = self._hc_byte | PADS
                    self._send_midi(SYSEX_START + (32, self._hc_byte, 247))
                    self.schedule_message(1, self._set_drum_pads_to_hc)
            elif sender is self._encoder_group_fx_button or sender is self._encoder_group_mix_button:
                if self._hc_byte | ENCODERS != self._hc_byte:
                    self._hc_byte = self._hc_byte | ENCODERS
                    self._send_midi(SYSEX_START + (32, self._hc_byte, 247))
                    self._encoder_group_midi_button.turn_off()
                    if sender is self._encoder_group_fx_button:
                        self._encoder_modes.set_enabled(True)
                        self._display_reset_delay = 0
                        return
                    else:
                        self.schedule_message(1, self._encoder_modes.set_enabled, True)
                        self.schedule_message(1, self._encoder_modes.update)
                        self._display_reset_delay = 2
                        return
            elif sender is self._fader_group_fx_button or sender is self._fader_group_mix_button:
                if self._hc_byte | FADERS != self._hc_byte:
                    self._hc_byte = self._hc_byte | FADERS
                    self._send_midi(SYSEX_START + (32, self._hc_byte, 247))
                    self._fader_group_midi_button.turn_off()
                    self._fader_button_modes.set_enabled(True)
                    if sender is self._fader_group_fx_button:
                        self._fader_modes.set_enabled(True)
                        self._fader_button_modes.set_enabled(True)
                        self._display_reset_delay = 0
                        return
                    else:
                        self.schedule_message(1, self._fader_modes.set_enabled, True)
                        self.schedule_message(1, self._fader_modes.update)
                        self.schedule_message(1, self._fader_button_modes.set_enabled, True)
                        self.schedule_message(1, self._fader_button_modes.update)
                        self._display_reset_delay = 2
                        return
            self._display_reset_delay = 0

    def _set_drum_pads_to_hc(self):
        self._drum_group_midi_button.send_value(LED_OFF, True)
        self._drum_group_hyper_button.send_value(RED_FULL, True)
        for index in range(len(self._drum_pads)):
            self._drum_pads[index].send_value(RED_LOW, True)

    def _fader_button_value(self, value, sender):
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _fader_value(self, value, sender):
        param = sender.mapped_parameter()
        if param != None:
            param_range = param.max - param.min
            if param.name == "Track Volume":
                if sender == self._master_fader:
                    if self._has_faders:
                        name_string = "Master  Vol"
                    else:
                        name_string = (
                            self._mixer_for_faders.selected_strip().track_name_data_source().display_string() + "   Vol"
                        )
                else:
                    name_string = (
                        self._mixer_for_faders.channel_strip(self._faders.index(sender))
                        .track_name_data_source()
                        .display_string()
                        + "   Vol"
                    )
            else:
                name_string = param.name
                value = int((param.value - param.min) / param_range * 127)
            value_string = str(value)
        else:
            name_string = "<unmapped>"
            value_string = None
            self.schedule_message(1, self._set_value_string)
        self._set_name_string(name_string)
        self._set_value_string(value_string)

    def _encoder_value(self, value, sender):
        param = sender.mapped_parameter()
        if param != None:
            param_range = param.max - param.min
            if param.name == "Track Volume":
                name_string = (
                    self._mixer_for_encoders.channel_strip(self._encoders.index(sender))
                    .track_name_data_source()
                    .display_string()
                    + "   Vol"
                )
                value = int((param.value - param.min) / param_range * 127)
            elif param.name == "Track Panning":
                name_string = (
                    self._mixer_for_encoders.channel_strip(self._encoders.index(sender))
                    .track_name_data_source()
                    .display_string()
                    + "   Pan"
                )
                value = int(param.value / param_range * 127)
                if value < 0:
                    name_string += "  L"
                elif value > 0:
                    name_string += "  R"
                else:
                    name_string += "  C"
            else:
                name_string = param.name
                value = int((param.value - param.min) / param_range * 127)
            value_string = str(value)
        else:
            name_string = "<unmapped>"
            value_string = None
            self.schedule_message(1, self._set_value_string)
        self._set_name_string(name_string)
        self._set_value_string(value_string)

    def _set_displays_to_default(self):
        self._name_display.segment(0).set_data_source(
            self._mixer_for_encoders.selected_strip().track_name_data_source()
        )
        self._name_display.update()
        self._update_bank_value()
        self._set_value_string(None)
        self._send_midi(SYSEX_START + LCD_HC_DEFAULT)

    def _set_name_string(self, name_string):
        self._name_display.segment(0).set_data_source(self._name_display_data_source)
        self._name_display_data_source.set_display_string(name_string)
        self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _set_value_string(self, value_string=None):
        if value_string != None:
            self._value_display_data_source.set_display_string(value_string)
        else:
            self._value_display.reset()

    def _set_bank_string(self, bank_string=None):
        if bank_string != None:
            self._bank_display_data_source.set_display_string(bank_string)
        else:
            self._bank_display.reset()

    def _update_bank_value(self):
        bank = (self._session.track_offset() + 1) / self._session.width() + 1
        self._set_bank_string(str(bank))

    def _install_mapping(self, midi_map_handle, control, parameter, feedback_delay, feedback_map):
        if not self._in_build_midi_map:
            raise AssertionError
            raise midi_map_handle != None or AssertionError
            raise control != None and parameter != None or AssertionError
            raise isinstance(parameter, Live.DeviceParameter.DeviceParameter) or AssertionError
            raise isinstance(control, InputControlElement) or AssertionError
            raise isinstance(feedback_delay, int) or AssertionError
            if not isinstance(feedback_map, tuple):
                raise AssertionError
                success = False
                feedback_rule = None
                feedback_rule = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.NoteFeedbackRule()
                feedback_rule.note_no = 0
                feedback_rule.vel_map = (0,)
            elif control.message_type() is MIDI_CC_TYPE:
                feedback_rule = Live.MidiMap.CCFeedbackRule()
                feedback_rule.cc_no = 0
                feedback_rule.cc_value_map = (0,)
            elif control.message_type() is MIDI_PB_TYPE:
                feedback_rule = Live.MidiMap.PitchBendFeedbackRule()
                feedback_rule.value_pair_map = feedback_map
            raise feedback_rule != None or AssertionError
            feedback_rule.channel = control.message_channel()
            feedback_rule.delay_in_ms = feedback_delay
            success = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.map_midi_note_with_feedback_map(
                midi_map_handle, parameter, control.message_channel(), control.message_identifier(), feedback_rule
            )
        elif control.message_type() is MIDI_CC_TYPE:
            success = Live.MidiMap.map_midi_cc_with_feedback_map(
                midi_map_handle,
                parameter,
                control.message_channel(),
                control.message_identifier(),
                control.message_map_mode(),
                feedback_rule,
                not control.needs_takeover(),
            )
        elif control.message_type() is MIDI_PB_TYPE:
            success = Live.MidiMap.map_midi_pitchbend_with_feedback_map(
                midi_map_handle, parameter, control.message_channel(), feedback_rule, not control.needs_takeover()
            )
        return success
예제 #49
0
 def __init__(self, info_text = '', *a, **k):
     super(InfoComponent, self).__init__(*a, **k)
     self._data_source = DisplayDataSource()
     self._data_source.set_display_string(info_text)
	def device_name_data_source(self):
		if self._device_name_data_source == None:
			self._device_name_data_source = DisplayDataSource()
			self._on_device_name_changed()
		return self._device_name_data_source
class NoteSettingsComponent(ControlSurfaceComponent):
    __subject_events__ = ('setting_changed',)

    def __init__(self, grid_resolution = None, *a, **k):
        super(NoteSettingsComponent, self).__init__(*a, **k)
        self._top_data_sources = [ DisplayDataSource() for _ in xrange(8) ]
        self._bottom_data_sources = [ DisplayDataSource() for _ in xrange(8) ]
        self._info_data_source = DisplayDataSource()
        self._settings = []
        self._encoders = []
        self._add_setting(NoteNudgeSetting(grid_resolution=grid_resolution))
        self._add_setting(NoteLengthCoarseSetting(grid_resolution=grid_resolution))
        self._add_setting(NoteLengthFineSetting(grid_resolution=grid_resolution))
        self._add_setting(NoteVelocitySetting(grid_resolution=grid_resolution))

    def _add_setting(self, setting):
        raise len(self._settings) < 8 or AssertionError, 'Cannot show more than 8 settings'
        self._settings.append(setting)
        self._update_encoders()
        self._top_data_sources = [ DisplayDataSource() for _ in xrange(8 - len(self._settings)) ] + [ s.label_source for s in self._settings ]
        self._bottom_data_sources = [ DisplayDataSource() for _ in xrange(8 - len(self._settings)) ] + [ s.value_source for s in self._settings ]
        self.register_disconnectable(setting)
        self.register_slot(setting, self.notify_setting_changed, 'setting_changed')

    def set_encoder_controls(self, encoders):
        self._encoders = encoders or []
        self._update_encoders()

    def set_top_display_line(self, display):
        if self.is_enabled() and display:
            display.set_data_sources(self._top_data_sources)

    def set_bottom_display_line(self, display):
        if self.is_enabled() and display:
            display.set_data_sources(self._bottom_data_sources)

    def set_info_display_line(self, display):
        if self.is_enabled() and display:
            display.set_data_sources([self._info_data_source])

    def set_clear_display_line(self, display):
        if self.is_enabled() and display:
            display.reset()

    def set_full_velocity_button(self, button):
        self._on_full_velocity.subject = button

    @subject_slot('value')
    def _on_full_velocity(self, value):
        if self.is_enabled():
            self.notify_setting_changed(3, 127)

    def set_min_max(self, index, min_max_value):
        setting_for_index = [ i for i in self._settings if i.attribute_index == index ]
        for setting in setting_for_index:
            setting.set_min_max(min_max_value)

    def set_info_message(self, message):
        self._info_data_source.set_display_string(message.rjust(62))

    def _update_encoders(self):
        if self.is_enabled() and self._encoders:
            for encoder, setting in map(None, self._encoders[-len(self._settings):], self._settings):
                setting.set_encoder(encoder)

        else:
            map(lambda setting: setting.set_encoder(None), self._settings)

    def update(self):
        super(NoteSettingsComponent, self).update()
        self._update_encoders()
예제 #52
0
class Axiom_DirectLink(ControlSurface):
    """ Script for the M-Audio Axiom DirectLink """

    def __init__(self, c_instance):
        ControlSurface.__init__(self, c_instance)
        with self.component_guard():
            self.set_pad_translations(PAD_TRANSLATIONS)
            self._device_selection_follows_track_selection = True
            self._suggested_input_port = "DirectLink"
            self._suggested_output_port = "DirectLink"
            self._waiting_for_first_response = True
            self._has_sliders = True
            self._current_midi_map = None
            self._display_reset_delay = -1
            self._shift_pressed = False
            self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 13)
            self._master_slider = SliderElement(MIDI_CC_TYPE, 15, 41)
            self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 111)
            self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 110)
            self._device_bank_buttons = None
            self._device_navigation = None
            self._shift_button.name = "Shift_Button"
            self._master_slider.name = "Master_Volume_Control"
            self._next_nav_button.name = "Next_Track_Button"
            self._prev_nav_button.name = "Prev_Track_Button"
            self._master_slider.add_value_listener(self._slider_value, identify_sender=True)
            self._shift_button.add_value_listener(self._shift_value)
            self._setup_mixer()
            self._setup_transport_and_session()
            self._setup_device()
            self._setup_display()
            for component in self.components:
                component.set_enabled(False)

        return

    def refresh_state(self):
        ControlSurface.refresh_state(self)
        self._waiting_for_first_response = True
        self.schedule_message(3, self._send_midi, SYSEX_START + (32, 46, 247))

    def handle_sysex(self, midi_bytes):
        if midi_bytes[0:-2] == SYSEX_START + (32,) and midi_bytes[-2] != 0:
            self._has_sliders = midi_bytes[-2] & 8 != 0
            if self._waiting_for_first_response:
                self._waiting_for_first_response = False
                self.schedule_message(1, self._show_startup_message)
                for component in self.components:
                    component.set_enabled(True)

            if self._has_sliders:
                self._mixer.master_strip().set_volume_control(self._master_slider)
                self._mixer.update()
            else:
                self._mixer.master_strip().set_volume_control(None)
                self._mixer.selected_strip().set_volume_control(self._master_slider)
            self.request_rebuild_midi_map()
        return

    def disconnect(self):
        self._display_data_source.set_display_string("  ")
        self._shift_button.remove_value_listener(self._shift_value)
        self._inst_button.remove_value_listener(self._inst_value)
        for encoder in self._encoders:
            encoder.remove_value_listener(self._encoder_value)

        for slider in tuple(self._sliders) + (self._master_slider,):
            slider.remove_value_listener(self._slider_value)

        for button in tuple(self._strip_buttons) + (self._selected_mute_solo_button,):
            button.remove_value_listener(self._mixer_button_value)

        for button in self._device_bank_buttons:
            button.remove_value_listener(self._device_bank_value)

        self._encoders = None
        self._sliders = None
        self._strip_buttons = None
        self._master_slider = None
        self._current_midi_map = None
        self._selected_mute_solo_button = None
        self._inst_button = None
        self._shift_button = None
        self._device_navigation = None
        self._display = None
        ControlSurface.disconnect(self)
        self._send_midi(SYSEX_START + (32, 0, 247))
        return

    def build_midi_map(self, midi_map_handle):
        self._current_midi_map = midi_map_handle
        ControlSurface.build_midi_map(self, midi_map_handle)

    def update_display(self):
        ControlSurface.update_display(self)
        if self._display_reset_delay >= 0:
            self._display_reset_delay -= 1
            if self._display_reset_delay == -1:
                self._show_current_track_name()

    def _setup_mixer(self):
        self._selected_mute_solo_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 12)
        mute_solo_flip_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 57)
        self._strip_buttons = []
        self._selected_mute_solo_button.name = "Selected_Mute_Button"
        mute_solo_flip_button.name = "Mute_Solo_Flip_Button"
        self._selected_mute_solo_button.add_value_listener(self._mixer_button_value, identify_sender=True)
        self._mixer = ShiftableMixerComponent(8)
        self._mixer.name = "Mixer"
        self._mixer.set_shift_button(self._shift_button)
        self._mixer.set_selected_mute_solo_button(self._selected_mute_solo_button)
        self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button)
        self._mixer.selected_strip().name = "Selected_Channel_Strip"
        self._mixer.master_strip().name = "Master_Channel_Strip"
        self._mixer.master_strip().set_volume_control(self._master_slider)
        self._sliders = []
        for index in range(8):
            strip = self._mixer.channel_strip(index)
            strip.name = "Channel_Strip_" + str(index)
            strip.set_invert_mute_feedback(True)
            self._sliders.append(SliderElement(MIDI_CC_TYPE, 15, 33 + index))
            self._sliders[-1].name = str(index) + "_Volume_Control"
            self._sliders[-1].set_feedback_delay(-1)
            self._sliders[-1].add_value_listener(self._slider_value, identify_sender=True)
            strip.set_volume_control(self._sliders[-1])
            self._strip_buttons.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 49 + index))
            self._strip_buttons[-1].name = str(index) + "_Mute_Button"
            self._strip_buttons[-1].add_value_listener(self._mixer_button_value, identify_sender=True)

        self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button)

    def _setup_transport_and_session(self):
        ffwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 115)
        rwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 114)
        loop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 113)
        play_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 117)
        stop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 116)
        rec_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 118)
        ffwd_button.name = "FFwd_Button"
        rwd_button.name = "Rwd_Button"
        loop_button.name = "Loop_Button"
        play_button.name = "Play_Button"
        stop_button.name = "Stop_Button"
        rec_button.name = "Record_Button"
        transport = ShiftableTransportComponent()
        transport.name = "Transport"
        transport.set_shift_button(self._shift_button)
        transport.set_stop_button(stop_button)
        transport.set_play_button(play_button)
        transport.set_record_button(rec_button)
        pads = []
        for index in range(len(PAD_TRANSLATIONS)):
            pads.append(ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 15, PAD_TRANSLATIONS[index][2]))
            pads[-1].name = "Pad_" + str(index)

        self._session = ShiftableSessionComponent(8, 0)
        self._session.name = "Session_Control"
        self._session.selected_scene().name = "Selected_Scene"
        self._session.set_mixer(self._mixer)
        self._session.set_shift_button(self._shift_button)
        self._session.set_clip_slot_buttons(tuple(pads))
        transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button, loop_button)
        transport_view_modes.name = "Transport_View_Modes"

    def _setup_device(self):
        self._encoders = []
        for offset in range(8):
            self._encoders.append(
                PeekableEncoderElement(
                    MIDI_CC_TYPE, 15, 17 + offset, Live.MidiMap.MapMode.relative_smooth_two_compliment
                )
            )
            self._encoders[-1].set_feedback_delay(-1)
            self._encoders[-1].add_value_listener(self._encoder_value, identify_sender=True)
            self._encoders[-1].name = "Device_Control_" + str(offset)

        prev_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 14)
        next_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 15)
        prev_bank_button.name = "Device_Bank_Down_Button"
        next_bank_button.name = "Device_Bank_Up_Button"
        device = BestBankDeviceComponent()
        device.name = "Device_Component"
        self.set_device_component(device)
        device.set_parameter_controls(tuple(self._encoders))
        device.set_bank_nav_buttons(prev_bank_button, next_bank_button)
        self._device_bank_buttons = (prev_bank_button, next_bank_button)
        prev_bank_button.add_value_listener(self._device_bank_value)
        next_bank_button.add_value_listener(self._device_bank_value)
        self._inst_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 15, 109)
        self._inst_button.name = "Inst_Button"
        self._inst_button.add_value_listener(self._inst_value)
        self._device_navigation = DetailViewCntrlComponent()
        self._device_navigation.name = "Device_Navigation_Component"

    def _setup_display(self):
        self._display = PhysicalDisplayElement(5, 1)
        self._display.name = "Display"
        self._display.set_message_parts(SYSEX_START + (17, 1, 0, 0), (247,))
        self._display_data_source = DisplayDataSource()
        self._display.segment(0).set_data_source(self._display_data_source)

    def _on_selected_track_changed(self):
        ControlSurface._on_selected_track_changed(self)
        self._show_current_track_name()

    def _shift_value(self, value):
        if not value in range(128):
            raise AssertionError
            self._shift_pressed = value > 0
            for encoder in self._encoders:
                encoder.set_peek_mode(self._shift_pressed)

            self._shift_pressed and self._mixer.set_select_buttons(None, None)
            self._session.set_track_bank_buttons(self._next_nav_button, self._prev_nav_button)
            self._device_component.set_bank_nav_buttons(None, None)
            self._device_navigation.set_device_nav_buttons(self._device_bank_buttons[0], self._device_bank_buttons[1])
        else:
            self._session.set_track_bank_buttons(None, None)
            self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button)
            self._device_navigation.set_device_nav_buttons(None, None)
            self._device_component.set_bank_nav_buttons(self._device_bank_buttons[0], self._device_bank_buttons[1])
        self.request_rebuild_midi_map()
        return

    def _encoder_value(self, value, sender):
        if not sender in self._encoders:
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                display_string = self._device_component.is_enabled() and " - "
                display_string = sender.mapped_parameter() != None and sender.mapped_parameter().name
            self._display_data_source.set_display_string(display_string)
            self._set_display_data_source(self._display_data_source)
            self._display_reset_delay = STANDARD_DISPLAY_DELAY
        return

    def _slider_value(self, value, sender):
        if not sender in tuple(self._sliders) + (self._master_slider,):
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                if self._mixer.is_enabled():
                    display_string = " - "
                    if sender.mapped_parameter() != None:
                        master = self.song().master_track
                        tracks = self.song().tracks
                        returns = self.song().return_tracks
                        track = None
                        if sender == self._master_slider:
                            track = self._has_sliders and master
                        else:
                            track = self.song().view.selected_track
                    else:
                        track = self._mixer.channel_strip(self._sliders.index(sender))._track
                    display_string = track == master and "Ma"
                elif track in tracks:
                    display_string = str(list(tracks).index(track) + 1)
                elif track in returns:
                    display_string = str(chr(ord("A") + list(returns).index(track)))
                else:
                    raise False or AssertionError
                display_string += " Vol"
            self._display_data_source.set_display_string(display_string)
            self._set_display_data_source(self._display_data_source)
            self._display_reset_delay = STANDARD_DISPLAY_DELAY
        return

    def _mixer_button_value(self, value, sender):
        if not sender in tuple(self._strip_buttons) + (self._selected_mute_solo_button,):
            raise AssertionError
            if not value in range(128):
                raise AssertionError
                if self._mixer.is_enabled() and value > 0:
                    strip = None
                    strip = sender == self._selected_mute_solo_button and self._mixer.selected_strip()
                else:
                    strip = self._mixer.channel_strip(self._strip_buttons.index(sender))
                strip != None and self._set_display_data_source(strip.track_name_data_source())
            else:
                self._display_data_source.set_display_string(" - ")
                self._set_display_data_source(self._display_data_source)
            self._display_reset_delay = STANDARD_DISPLAY_DELAY
        return

    def _device_bank_value(self, value):
        if not value in range(128):
            raise AssertionError
            if self._device_component.is_enabled() and value > 0:
                data_source = self._device_component.bank_name_data_source()
                data_source = self._shift_pressed and self._device_component.device_name_data_source()
            self._set_display_data_source(data_source)
            self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _inst_value(self, value):
        if not value in range(128):
            raise AssertionError
            value > 0 and self._device_component.is_enabled() and self.song().view.selected_track.view.select_instrument() and self._set_display_data_source(
                self._device_component.device_name_data_source()
            )
            self._display_reset_delay = STANDARD_DISPLAY_DELAY

    def _show_current_track_name(self):
        if self._display != None and self._mixer != None:
            self._set_display_data_source(self._mixer.selected_strip().track_name_data_source())
        return

    def _show_startup_message(self):
        self._display.display_message("LIVE")
        self._display_reset_delay = INITIAL_DISPLAY_DELAY

    def _set_display_data_source(self, data_source):
        raise isinstance(data_source, DisplayDataSource) or AssertionError
        self._display.segment(0).set_data_source(data_source)
        data_source.update()
예제 #53
0
class MixerOrDeviceModeSelector(ModeSelectorComponent):
    """ Class that toggles between mixer and device modes """

    def __init__(self, mixer_modes, device, encoders, page_buttons):
        raise isinstance(mixer_modes, EncoderMixerModeSelector) or AssertionError
        raise isinstance(device, PageableDeviceComponent) or AssertionError
        raise isinstance(encoders, tuple) or AssertionError
        raise isinstance(page_buttons, tuple) or AssertionError
        ModeSelectorComponent.__init__(self)
        self._mixer_modes = mixer_modes
        self._device = device
        self._encoders = encoders
        self._page_buttons = page_buttons
        self._peek_button = None
        self._encoders_display = None
        self._value_display = None
        self._device_display = None
        self._page_displays = None
        self._device_dummy_source = DisplayDataSource()
        self._parameter_source = DisplayDataSource()
        self._device_dummy_source.set_display_string('Mixer')
        self._clean_value_display_in = -1
        self._must_update_encoder_display = False
        self._register_timer_callback(self._on_timer)
        identify_sender = True
        for encoder in self._encoders:
            encoder.add_value_listener(self._parameter_value, identify_sender)

        self.set_mode(0)
        return

    def disconnect(self):
        self._unregister_timer_callback(self._on_timer)
        self._mixer_modes = None
        self._device = None
        self._encoders = None
        self._page_buttons = None
        self._encoders_display = None
        self._value_display = None
        self._device_display = None
        self._page_displays = None
        self._device_dummy_source = None
        self._parameter_source = None
        ModeSelectorComponent.disconnect(self)
        return

    def set_displays(self, encoders_display, value_display, device_display, page_displays):
        if not isinstance(encoders_display, PhysicalDisplayElement):
            raise AssertionError
            raise isinstance(value_display, PhysicalDisplayElement) or AssertionError
            raise isinstance(device_display, PhysicalDisplayElement) or AssertionError
            raise isinstance(page_displays, tuple) or AssertionError
            self._encoders_display = encoders_display
            self._value_display = value_display
            self._device_display = device_display
            self._page_displays = page_displays
            self._value_display != None and self._value_display.segment(0).set_data_source(self._parameter_source)
        self.update()
        return

    def set_peek_button(self, button):
        if not (button == None or isinstance(button, ButtonElement)):
            raise AssertionError
            if self._peek_button != button:
                if self._peek_button != None:
                    self._peek_button.remove_value_listener(self._peek_value)
                self._peek_button = button
                self._peek_button != None and self._peek_button.add_value_listener(self._peek_value)
            self.update()
        return

    def number_of_modes(self):
        return 2

    def update(self):
        super(MixerOrDeviceModeSelector, self).update()
        if self.is_enabled():
            if self._mode_index == 0:
                self._device.set_parameter_controls(None)
                self._device.set_bank_buttons(None)
                self._mixer_modes.set_controls(self._encoders)
                self._mixer_modes.set_modes_buttons(self._page_buttons)
                if self._device_display != None:
                    self._device_display.segment(0).set_data_source(self._mixer_modes.current_page_data_source())
                    self._device_display.update()
                if self._encoders_display != None:
                    for index in range(len(self._encoders)):
                        self._encoders_display.segment(index).set_data_source(self._mixer_modes.parameter_data_source(index))

                    self._encoders_display.update()
                if self._page_displays != None:
                    for index in range(len(self._page_displays)):
                        self._page_displays[index].segment(0).set_data_source(self._mixer_modes.page_name_data_source(index))
                        self._page_displays[index].update()

            elif self._mode_index == 1:
                self._mixer_modes.set_controls(None)
                self._mixer_modes.set_modes_buttons(None)
                self._device.set_parameter_controls(self._encoders)
                self._device.set_bank_buttons(self._page_buttons)
                if self._device_display != None:
                    self._device_display.segment(0).set_data_source(self._device.device_name_data_source())
                    self._device_display.update()
                if self._encoders_display != None:
                    for index in range(len(self._encoders)):
                        self._encoders_display.segment(index).set_data_source(self._device.parameter_name_data_source(index))

                    self._encoders_display.update()
                if self._page_displays != None:
                    for index in range(len(self._page_displays)):
                        self._page_displays[index].segment(0).set_data_source(self._device.page_name_data_source(index))
                        self._page_displays[index].update()

            else:
                print 'Invalid mode index'
                raise False or AssertionError
        return

    def _parameter_value(self, value, control):
        if not control in self._encoders:
            raise AssertionError
            if self.is_enabled():
                parameter = control.mapped_parameter()
                parameter != None and self._parameter_source.set_display_string(parameter.name + ': ' + parameter.__str__())
            else:
                self._parameter_source.set_display_string('<unmapped>')
            self._clean_value_display_in = 20
        return

    def _on_timer(self):
        if self._clean_value_display_in > 0:
            self._clean_value_display_in -= 1
            if self._clean_value_display_in == 0:
                self._parameter_source.set_display_string('')
                self._clean_value_display_in = -1
        if self._must_update_encoder_display:
            self._encoders_display.update()
            self._must_update_encoder_display = False

    def _peek_value(self, value):
        if not self._peek_button != None:
            raise AssertionError
            raise value in range(128) or AssertionError
            new_peek_mode = value != 0
            peek_changed = False
            for encoder in self._encoders:
                if new_peek_mode != encoder.get_peek_mode():
                    encoder.set_peek_mode(new_peek_mode)
                    peek_changed = True

            self._must_update_encoder_display = peek_changed and self._encoders_display != None and True
        return
class Live8DeviceComponent(ControlSurfaceComponent):
	
	__doc__ = ' Class representing a device in Live '
	def __init__(self):
		ControlSurfaceComponent.__init__(self)
		self._device_banks = DEVICE_DICT
		self._device_best_banks = DEVICE_BOB_DICT
		self._device_bank_names = BANK_NAME_DICT
		self._device = None
		self._parameter_controls = None
		self._bank_up_button = None
		self._bank_down_button = None
		self._bank_buttons = None
		self._on_off_button = None
		self._lock_button = None
		self._lock_callback = None
		self._device_name_data_source = None
		self._device_bank_registry = {}
		self._bank_index = 0
		self._bank_name = '<No Bank>'
		self._locked_to_device = False
		return None
	
	def disconnect(self):
		self._lock_callback = None
		self._device_bank_registry = None
		if self._parameter_controls != None:
			for control in self._parameter_controls:
				control.release_parameter()
			self._parameter_controls = None
		if self._bank_up_button != None:
			self._bank_up_button.remove_value_listener(self._bank_up_value)
			self._bank_up_button = None
		if self._bank_down_button != None:
			self._bank_down_button.remove_value_listener(self._bank_down_value)
			self._bank_down_button = None
		if self._bank_buttons != None:
			for button in self._bank_buttons:
				button.remove_value_listener(self._bank_value)
		self._bank_buttons = None
		if self._on_off_button != None:
			self._on_off_button.remove_value_listener(self._on_off_value)
			self._on_off_button = None
		if self._lock_button != None:
			self._lock_button.remove_value_listener(self._lock_value)
			self._lock_button = None
		if self._device != None:
			parameter = self._on_off_parameter()
			if parameter != None:
				parameter.remove_value_listener(self._on_on_off_changed)
			self._device.remove_name_listener(self._on_device_name_changed)
			self._device.remove_parameters_listener(self._on_parameters_changed)
			self._device = None
		return None
	
	def on_enabled_changed(self):
		self.update()
	

	def set_device(self, device):
		assert ((device == None) or isinstance(device, Live.Device.Device))
		if ((not self._locked_to_device) and (device != self._device)):
			if (self._device != None):
				self._device.remove_name_listener(self._on_device_name_changed)
				self._device.remove_parameters_listener(self._on_parameters_changed)
				parameter = self._on_off_parameter()
				if (parameter != None):
					parameter.remove_value_listener(self._on_on_off_changed)
				if (self._parameter_controls != None):
					for control in self._parameter_controls:
						control.release_parameter()
			self._device = device
			if (self._device != None):
				self._bank_index = 0
				self._device.add_name_listener(self._on_device_name_changed)
				self._device.add_parameters_listener(self._on_parameters_changed)
				parameter = self._on_off_parameter()
				if (parameter != None):
					parameter.add_value_listener(self._on_on_off_changed)
			for key in self._device_bank_registry.keys():
				if (key == self._device):
					self._bank_index = self._device_bank_registry.get(key, 0)
					del self._device_bank_registry[key]
					break
			self._bank_name = '<No Bank>' #added
			self._on_device_name_changed()
			self.update()		 
		
	def set_bank_nav_buttons(self, down_button, up_button):
		assert ((down_button != None) or (up_button == None))
		assert ((up_button == None) or isinstance(up_button, ButtonElement))
		assert ((down_button == None) or isinstance(down_button, ButtonElement))
		do_update = False
		if up_button != self._bank_up_button:
			do_update = True
			if self._bank_up_button != None:
				self._bank_up_button.remove_value_listener(self._bank_up_value)
			self._bank_up_button = up_button
			if self._bank_up_button != None:
				self._bank_up_button.add_value_listener(self._bank_up_value)
		if down_button != self._bank_down_button:
			do_update = True
			if self._bank_down_button != None:
				self._bank_down_button.remove_value_listener(self._bank_down_value)
			self._bank_down_button = down_button
			if self._bank_down_button != None:
				self._bank_down_button.add_value_listener(self._bank_down_value)
		if do_update:
			self.update()
		return None
	
	def set_bank_buttons(self, buttons):
		assert ((buttons == None) or isinstance(buttons, tuple))
		if self._bank_buttons != None:
			for button in self._bank_buttons:
				button.remove_value_listener(self._bank_value)
		self._bank_buttons = buttons
		if self._bank_buttons != None:
			identify_sender = True
			for button in self._bank_buttons:
				button.add_value_listener(self._bank_value, identify_sender)
		self.update()
		return None
	
	def set_parameter_controls(self, controls):
		assert (controls != None)
		assert isinstance(controls, tuple)
		if self._device != None and self._parameter_controls != None:
			for control in self._parameter_controls:
				control.release_parameter()
		for control in controls:
			assert (control != None)
			assert isinstance(control, EncoderElement)
		self._parameter_controls = controls
		self.update()
		return None
	

	def set_lock_to_device(self, lock, device):
		assert isinstance(lock, type(False))
		assert (lock is not self._locked_to_device)
		if lock:
			self.set_device(device)
		else:
			assert (device == self._device)
		self._locked_to_device = lock
		if self.is_enabled():
			if (self._lock_button != None):
				if self._locked_to_device:
					self._lock_button.turn_on()
				else:
					self._lock_button.turn_off()		

					
	def set_lock_button(self, button):
		assert ((button == None) or isinstance(button, ButtonElement))
		if self._lock_button != None:
			self._lock_button.remove_value_listener(self._lock_value)
			self._lock_button = None
		self._lock_button = button
		if self._lock_button != None:
			self._lock_button.add_value_listener(self._lock_value)
		self.update()
		return None

	
	def set_on_off_button(self, button):
		assert ((button == None) or isinstance(button, ButtonElement))
		if self._on_off_button != None:
			self._on_off_button.remove_value_listener(self._on_off_value)
			self._on_off_button = None
		self._on_off_button = button
		if self._on_off_button != None:
			self._on_off_button.add_value_listener(self._on_off_value)
		self.update()
		return None
	
	def set_lock_callback(self, callback):
		assert (self._lock_callback == None)
		assert (callback != None)
		assert (dir(callback).count('im_func') is 1)
		self._lock_callback = callback
		return None
	
	def restore_bank(self, bank_index):
		if self._device != None and self._is_banking_enabled() and self._locked_to_device and self._number_of_parameter_banks() > bank_index and self._bank_index != bank_index:
			self._bank_index = bank_index
			self.update()
		return None
	
	def device_name_data_source(self):
		if self._device_name_data_source == None:
			self._device_name_data_source = DisplayDataSource()
			self._on_device_name_changed()
		return self._device_name_data_source
	

	def update(self):
		if (self.is_enabled() and (self._device != None)):
			self._device_bank_registry[self._device] = self._bank_index
			if (self._parameter_controls != None):
				old_bank_name = self._bank_name #added
				self._assign_parameters()
				if self._bank_name != old_bank_name: #added
					self._show_msg_callback(self._device.name + ' Bank: ' + self._bank_name) #added
			if ((self._bank_up_button != None) and (self._bank_down_button != None)):
				if (self.number_of_parameter_banks()) > (self._bank_index + 1):
					self._bank_up_button.turn_on()
				else:
					self._bank_up_button.turn_off()
				if (self._bank_index > 0):
					self._bank_down_button.turn_on()
				else:
					self._bank_down_button.turn_off()
			if (self._bank_buttons != None):
				for index in range(len(self._bank_buttons)):
					if (index == self._bank_index):
						self._bank_buttons[index].turn_on()
					else:
						self._bank_buttons[index].turn_off()
		else:
			if (self._lock_button != None):
				self._lock_button.turn_off()
			if (self._bank_up_button != None):
				self._bank_up_button.turn_off()
			if (self._bank_down_button != None):
				self._bank_down_button.turn_off()
			if (self._bank_buttons != None):
				for button in self._bank_buttons:
					button.turn_off()
			if (self._parameter_controls != None):
				for control in self._parameter_controls:
					control.release_parameter()
		#self._rebuild_callback()		
		

	def _bank_up_value(self, value):
		assert (self._bank_up_button != None)
		assert (value != None)
		assert isinstance(value, int)
		if self.is_enabled():
			if ((not self._bank_up_button.is_momentary()) or (value is not 0)):
				if (self._device != None):
					num_banks = self._number_of_parameter_banks()
					if (self._bank_down_button == None):
						self._bank_name = ''
						self._bank_index = ((self._bank_index + 1) % num_banks)
						self.update()
					elif (num_banks > (self._bank_index + 1)):
						self._bank_name = ''
						self._bank_index += 1
						self.update()
						

	def _bank_down_value(self, value):
		assert (self._bank_down_button != None)
		assert (value != None)
		assert isinstance(value, int)
		if self.is_enabled():
			if ((not self._bank_down_button.is_momentary()) or (value is not 0)):
				if ((self._device != None) and (self._bank_index > 0)):
					self._bank_name = ''
					self._bank_index -= 1
					self.update()
					
					
	def _lock_value(self, value):
		assert (self._lock_button != None)
		assert (self._lock_callback != None)
		assert (value != None)
		assert isinstance(value, int)
		if not self._lock_button.is_momentary() or value is not 0:
			self._lock_callback()
		return None
	
	def _on_off_value(self, value):
		assert (self._on_off_button != None)
		assert (value in range(128))
		if not self._on_off_button.is_momentary() or value is not 0:
			parameter = self._on_off_parameter()
			if parameter != None and parameter.is_enabled:
				parameter.value = float(int(parameter.value == 0.0))
		return None
	

	def _bank_value(self, value, button):
		assert (self._bank_buttons != None)
		assert (value != None)
		assert (button != None)
		assert isinstance(value, int)
		assert isinstance(button, ButtonElement)
		assert (list(self._bank_buttons).count(button) == 1)
		if self.is_enabled() and self._device != None: #added
			if ((not button.is_momentary()) or (value is not 0)):
				bank = list(self._bank_buttons).index(button)
				if (bank != self._bank_index):
					if (self._number_of_parameter_banks() > bank):
						self._bank_name = '' #added
						self._bank_index = bank
						self.update()
				else:
					self._show_msg_callback(self._device.name + ' Bank: ' + self._bank_name)


	def _is_banking_enabled(self):
		direct_banking = (self._bank_buttons != None)
		roundtrip_banking = (self._bank_up_button != None)
		increment_banking = ((self._bank_up_button != None) and (self._bank_down_button != None))
		return (direct_banking or (roundtrip_banking or increment_banking))


	def _assign_parameters(self):
		assert self.is_enabled()
		assert (self._device != None)
		assert (self._parameter_controls != None)
		self._bank_name = ('Bank ' + str(self._bank_index + 1)) #added
		if (self._device.class_name in self._device_banks.keys()): #modified
			assert (self._device.class_name in self._device_best_banks.keys())
			banks = self._device_banks[self._device.class_name]
			bank = None
			#if (not self._is_banking_enabled()):
			#	 banks = self._device_best_banks[self._device.class_name]
			#	 self._bank_name = 'Best of Parameters' #added
			if (len(banks) > self._bank_index):
				bank = banks[self._bank_index]
				if self._is_banking_enabled(): #added
					if self._device.class_name in self._device_bank_names.keys(): #added
						self._bank_name[self._bank_index] = self._device_bank_names[self._device.class_name] #added *recheck
			assert ((bank == None) or (len(bank) >= len(self._parameter_controls)))
			for index in range(len(self._parameter_controls)):
				parameter = None
				if (bank != None):
					parameter = get_parameter_by_name(self._device, bank[index])
				if (parameter != None):
					self._parameter_controls[index].connect_to(parameter)
				else:
					self._parameter_controls[index].release_parameter()
		else:
			parameters = self._device_parameters_to_map()
			num_controls = len(self._parameter_controls)
			index = (self._bank_index * num_controls)
			for control in self._parameter_controls:
				if (index < len(parameters)):
					control.connect_to(parameters[index])
				else:
					control.release_parameter()
				index += 1


	def _on_device_name_changed(self):
		if (self._device_name_data_source != None):
			if (self.is_enabled() and (self._device != None)):
				self._device_name_data_source.set_display_string(self._device.name)
			else:
				self._device_name_data_source.set_display_string('No Device')


	def _on_parameters_changed(self):
		self.update()


	def _on_off_parameter(self):
		result = None
		if (self._device != None):
			for parameter in self._device.parameters:
				if str(parameter.name).startswith('Device On'):
					result = parameter
					break
		return result


	def _on_on_off_changed(self):
		if (self.is_enabled() and (self._on_off_button != None)):
			turn_on = False
			if (self._device != None):
				parameter = self._on_off_parameter()
				turn_on = ((parameter != None) and (parameter.value > 0.0))
			if turn_on:
				self._on_off_button.turn_on()
			else:
				self._on_off_button.turn_off()


	def _device_parameters_to_map(self):
		assert self.is_enabled()
		assert (self._device != None)
		assert (self._parameter_controls != None)
		return self._device.parameters[1:] #check this...


	def _number_of_parameter_banks(self):
		return number_of_parameter_banks(self._device) #added
class BestBankDeviceComponent(DeviceComponent):
    """ Special Device component that uses the best of bank of a device as default """

    def __init__(self):
        DeviceComponent.__init__(self)
        new_banks = {}
        new_bank_names = {}
        self._device_banks = DEVICE_DICT
        self._device_bank_names = BANK_NAME_DICT
        self._device_best_banks = DEVICE_BOB_DICT
        for device_name, current_banks in self._device_banks.iteritems():
            raise len(current_banks) > 1 and (device_name in self._device_best_banks.keys() or AssertionError), "Could not find best-of-banks for '%s'" % device_name
            if not device_name in self._device_bank_names.keys():
                raise AssertionError, "Could not find bank names for '%s'" % device_name
                current_banks = self._device_best_banks[device_name] + current_banks
                new_bank_names[device_name] = (BOP_BANK_NAME,) + self._device_bank_names[device_name]
            new_banks[device_name] = current_banks

        self._device_banks = new_banks
        self._device_bank_names = new_bank_names
        self._bank_name_data_source = DisplayDataSource()

    def disconnect(self):
        self._bank_name_data_source = None
        DeviceComponent.disconnect(self)

    def bank_name_data_source(self):
        return self._bank_name_data_source

    def _bank_up_value(self, value):
        DeviceComponent._bank_up_value(self, value)
        self._update_bank_display()

    def _bank_down_value(self, value):
        DeviceComponent._bank_down_value(self, value)
        self._update_bank_display()

    def _update_bank_display(self):
        if self.is_enabled():
            bank_name = ''
            if self._device != None and self._bank_name != '<No Bank>':
                bank_name = self._bank_name
                if bank_name in (BOP_BANK_NAME, 'Bank 1'):
                    bank_name = 'Home'
            self._bank_name_data_source.set_display_string(bank_name)

    def _is_banking_enabled(self):
        return True

    def _number_of_parameter_banks(self):
        result = 0
        if self._device != None:
            if self._device.class_name in self._device_banks.keys():
                result = len(self._device_banks[self._device.class_name])
            else:
                result = DeviceComponent._number_of_parameter_banks(self)
        return result

    def _parameter_banks(self):
        return parameter_banks(self._device, self._device_banks)

    def _parameter_bank_names(self):
        return parameter_bank_names(self._device, self._device_bank_names)