From bc8a646eac17d1863f9bbe7af05e7a5dae39c9f1 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sat, 12 Oct 2013 03:06:32 +1100 Subject: [PATCH 01/45] added tofo --- Novation_Impulse2/readme.txt | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 800d551b..2a92b4f2 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -6,10 +6,37 @@ Mixer button 9 - arm selected track Shift changes mixer buttons to be arm the specific track button. -Known issues -1) After moving track with Shift+Track buttons are not returned to inital condition. +Known issues (todo:) +1) impulse does not disconnect properly and does not send disconnection message. +1.5) refactor shift - move it to main class. +2) After moving track with Shift+Track buttons are not returned to inital condition. Also happens sometimes in other cases (like bank switching with Shift). Workaround - press and release Shit again. -2) Pressin shift + (mutes/solos) flip button leds to unpredictable results. +3) when track goes down, the bank is not changed. +4) Pressin shift + (mutes/solos) flip button leds to unpredictable results. Workaround - do not do that, if you have done that, just press and release shift. + + +Future things to implement. + +1) mixer9 - overdub +2) Shift + Mixer 9 - automation arm +3) Shift + Stop - stop all clips. + + +4) Shift+Rec - metronome on/off (as metronome has much to do with recording) +5) Shift + Loop switch session/arrangement (as loop is the button that also changes in this case) +6) Shift + play Undo (as play is like backspace but turned opposite) + +another parallel feature - Shift + drum pad in clip mode - stop the selected clip. + +7) display messages, when + metronome on/off + undo + switch session/arrangement + overdub + automation arm + + + From c6513ef4a64f0f8359093d209127dedf644bf3a4 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 13 Oct 2013 03:15:55 +1100 Subject: [PATCH 02/45] fixed disconnect --- Novation_Impulse2/EncoderModeSelector.py | 6 ++++-- Novation_Impulse2/Novation_Impulse2.py | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Novation_Impulse2/EncoderModeSelector.py b/Novation_Impulse2/EncoderModeSelector.py index 15f933bc..6bd98afb 100644 --- a/Novation_Impulse2/EncoderModeSelector.py +++ b/Novation_Impulse2/EncoderModeSelector.py @@ -43,8 +43,10 @@ def set_device_mixer_buttons(self, device_button, mixer_button): self._device_button = device_button self._mixer_button = mixer_button #raise self._device_button != None and (self._mixer_button != None or AssertionError) - self._device_button.add_value_listener(self._device_value) - self._mixer_button.add_value_listener(self._mixer_value) + if self._device_button != None: + self._device_button.add_value_listener(self._device_value) + if self._mixer_button!= None: + self._mixer_button.add_value_listener(self._mixer_value) def set_provide_volume_mode(self, provide_volume_mode): self._number_of_modes = 6 if provide_volume_mode else 5 diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index e0f34eea..db5d50aa 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -102,6 +102,7 @@ def handle_sysex(self, midi_bytes): self.request_rebuild_midi_map() def disconnect(self): + self.log('starting disconnect 1') self._name_display_data_source.set_display_string(' ') for encoder in self._encoders: encoder.remove_value_listener(self._encoder_value) @@ -115,7 +116,9 @@ def disconnect(self): button.remove_value_listener(self._mixer_button_value) self._preview_button.remove_value_listener(self._preview_value) + self.log('starting disconnect 3') ControlSurface.disconnect(self) + self.log('starting disconnect 3') self._encoders = None self._sliders = None self._strip_buttons = None @@ -127,7 +130,9 @@ def disconnect(self): self._next_bank_button = None self._encoder_modes = None self._transport_view_modes = None + self.log('starting disconnect 4') self._send_midi(SYSEX_START + (6, 0, 0, 0, 247)) + self.log('starting disconnect 5') def build_midi_map(self, midi_map_handle): self._current_midi_map = midi_map_handle From 56cb24cf1b2ee203c70499b8aff9d8199a118d97 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 13 Oct 2013 03:45:10 +1100 Subject: [PATCH 03/45] moved overdub to mixer9 button + fixed disconnect issue --- Novation_Impulse2/Novation_Impulse2.py | 2 +- .../ShiftableTransportComponent.py | 26 +++++++++++++------ Novation_Impulse2/SpecialMixerComponent.py | 11 -------- Novation_Impulse2/changelog.txt | 0 Novation_Impulse2/readme.txt | 23 +++++++++------- add.pyproj | 1 + 6 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 Novation_Impulse2/changelog.txt diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index db5d50aa..89a21a84 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -181,7 +181,6 @@ def _setup_mixer(self): self._mixer.set_shift_button(self._shift_button) self._button9 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + 8) - self._mixer.set_selected_mute_solo_button(self._button9) def _setup_session(self): num_pads = len(PAD_TRANSLATIONS) @@ -223,6 +222,7 @@ def _setup_transport(self): transport.set_play_button(play_button) transport.set_record_buttonOnInit(rec_button) transport.set_shift_button(self._shift_button) + transport.set_mixer9_button(self._button9) self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button, loop_button) self._transport_view_modes.name = 'Transport_View_Modes' diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index bdeb0862..e6258aa9 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -10,6 +10,7 @@ def __init__(self, c_instance): self.c_instance = c_instance self._shift_button = None self._shift_pressed = False + self._mixer9_button = None TransportComponent.__init__(self) def disconnect(self): @@ -38,6 +39,13 @@ def set_record_buttonOnInit(self, button): self.set_record_button(self.record_button) self.log("set_record_buttonOnInit 2") + def set_mixer9_button(self, button): + self.log("set_mixer9_button 1") + self._mixer9_button = button + self.set_overdub_button(self._mixer9_button) + self.log("set_mixer9_button 2") + + def _shift_value(self, value): self.log("shift handler") if not self._shift_button != None: @@ -47,14 +55,16 @@ def _shift_value(self, value): self.log("shift handler 2") self._shift_pressed = self.is_enabled() and value > 0 self.log("shift handler 3") - if self._shift_pressed: - self.log("shift handler pressed") - self.set_overdub_button(self.record_button) - self.set_record_button(None) - else: - self.log("shift handler unpressed") - self.set_overdub_button(None) - self.set_record_button(self.record_button) +# if self._shift_pressed: +# self.log("shift handler pressed") +# self.set_overdub_button(None) +# self.set_record_button(None) +# self.set_session_overdub_button(self._mixer9_button) +# else: +# self.log("shift handler unpressed") +# self.set_overdub_button(None) +# self.set_record_button(self.record_button) +# self.set_arrangement_overdub_button(self._mixer9_button) diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index 3f3b6a3b..8206297e 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -40,17 +40,6 @@ def set_shift_button(self, shift_button): self._shift_button = shift_button self._shift_button != None and self._shift_button.add_value_listener(self._shift_value) - def set_selected_mute_solo_button(self, button): - if not isinstance(button, (type(None), ButtonElement)): - raise AssertionError - self._selected_mute_solo_button = button - #self.selected_strip().set_mute_button(self._selected_mute_solo_button) - #self.selected_strip().set_solo_button(None) - #self.selected_strip().set_arm_button(None) - self.selected_strip().set_mute_button(None) - self.selected_strip().set_solo_button(None) - self.selected_strip().set_arm_button(self._selected_mute_solo_button) - def set_strip_mute_solo_buttons(self, buttons, flip_button): self.log("set_strip_mute_solo_buttons") if not (buttons is None or isinstance(buttons, tuple) and len(buttons) == len(self._channel_strips)): diff --git a/Novation_Impulse2/changelog.txt b/Novation_Impulse2/changelog.txt new file mode 100644 index 00000000..e69de29b diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 2a92b4f2..2416e44b 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -2,26 +2,30 @@ Features Shift + Rec = Overdub -Mixer button 9 - arm selected track +Mixer button 9 = OverDub Shift changes mixer buttons to be arm the specific track button. -Known issues (todo:) -1) impulse does not disconnect properly and does not send disconnection message. -1.5) refactor shift - move it to main class. -2) After moving track with Shift+Track buttons are not returned to inital condition. +Known issues that cannot be fixed +1) After moving track with Shift+Track buttons are not returned to inital condition. Also happens sometimes in other cases (like bank switching with Shift). Workaround - press and release Shit again. -3) when track goes down, the bank is not changed. -4) Pressin shift + (mutes/solos) flip button leds to unpredictable results. +2) Pressin shift + (mutes/solos) flip button leds to unpredictable results. Workaround - do not do that, if you have done that, just press and release shift. +The reason for these problems is that when you use shift+track or shift+bank, the message "shift off" is not sent. +This is out of the scope of what I can do + +Known issues (todo:) +FIXED: 1) impulse does not disconnect properly and does not send disconnection message. +1.5) refactor shift - move it to main class. +3) when track goes down, the bank is not changed. + Future things to implement. -1) mixer9 - overdub -2) Shift + Mixer 9 - automation arm +DONE 1) mixer9 - overdub 3) Shift + Stop - stop all clips. @@ -38,5 +42,6 @@ another parallel feature - Shift + drum pad in clip mode - stop the selected cli overdub automation arm +2) Shift + Mixer 9 - automation arm (seems to be rather hard - not sure there is API for that) diff --git a/add.pyproj b/add.pyproj index 544dce6e..f0dc00db 100644 --- a/add.pyproj +++ b/add.pyproj @@ -59,6 +59,7 @@ + From 28887172cbe41dd90c47ca36d806abfa7bbe06a8 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 13 Oct 2013 04:28:08 +1100 Subject: [PATCH 04/45] fixed bank operations --- Novation_Impulse2/Novation_Impulse2.py | 6 +++++- Novation_Impulse2/SpecialMixerComponent.py | 6 +++++- Novation_Impulse2/readme.txt | 6 ++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 89a21a84..285d0c7a 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -179,6 +179,7 @@ def _setup_mixer(self): self._mixer.master_strip().set_mute_button(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17)) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button) self._mixer.set_shift_button(self._shift_button) + self._mixer.updateMixerButtons() self._button9 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + 8) @@ -337,15 +338,18 @@ def _set_string_to_display(self, string_to_display): self._display_reset_delay = STANDARD_DISPLAY_DELAY def _on_selected_track_changed(self): + self.log('_on_selected_track_changed') ControlSurface._on_selected_track_changed(self) self._show_current_track_name() #all_tracks = self._has_sliders or self._session.tracks_to_use() all_tracks2 = self._session.tracks_to_use() selected_track = self.song().view.selected_track num_strips = self._session.width() - for selected_track in all_tracks2: + if selected_track in all_tracks2: track_index = list(all_tracks2).index(selected_track) + self.log('track_index '+ str(track_index)) new_offset = track_index - track_index % num_strips + self.log('new_offset '+ str(new_offset)) if not new_offset / num_strips == int(new_offset / num_strips): raise AssertionError self._session.set_offsets(new_offset, self._session.scene_offset()) diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index 8206297e..e7ade61e 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -96,6 +96,7 @@ def _mute_solo_flip_value(self, value): def updateMixerButtons(self): + self.log("updateMixerButtons") if self._strip_mute_solo_buttons != None: for index in range(len(self._strip_mute_solo_buttons)): strip = self.channel_strip(index) @@ -115,6 +116,7 @@ def updateMixerButtons(self): strip.set_arm_button(None) def _on_timer(self): +# self.log("_on_timer") sel_track = None while len(self._selected_tracks) > 0: track = self._selected_tracks[-1] @@ -150,14 +152,16 @@ def _on_timer(self): sel_track.arm = True sel_track.view.select_instrument() self._selected_tracks = [] - self.updateMixerButtons() +# self.updateMixerButtons() def _next_track_value(self, value): + self.log("_next_track_value "+ str(value)) MixerComponent._next_track_value(self, value) self._selected_tracks.append(self.song().view.selected_track) self.updateMixerButtons() def _prev_track_value(self, value): + self.log("_prev_track_value " + str(value)) MixerComponent._prev_track_value(self, value) self._selected_tracks.append(self.song().view.selected_track) self.updateMixerButtons() diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 2416e44b..42c0811a 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -16,10 +16,12 @@ Known issues that cannot be fixed The reason for these problems is that when you use shift+track or shift+bank, the message "shift off" is not sent. This is out of the scope of what I can do -Known issues (todo:) +Known issues and todo: FIXED: 1) impulse does not disconnect properly and does not send disconnection message. 1.5) refactor shift - move it to main class. -3) when track goes down, the bank is not changed. +FIXED: 2)when track goes down, the bank is not changed. +3) on initialize mute/solo buttons do not light + workaround - press shift button. From 92d1c59a9154a0e39985e501e994684871e29c16 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 13 Oct 2013 04:44:26 +1100 Subject: [PATCH 05/45] stop clips on shift + clip --- Novation_Impulse2/Novation_Impulse2.py | 38 ++++++++++++++++++- .../ShiftableTransportComponent.py | 3 +- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 285d0c7a..8bd69541 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -67,6 +67,10 @@ def __init__(self, c_instance): self._encoder_modes = EncoderModeSelector(self._device_component, self._mixer, self._next_bank_button, self._prev_bank_button, self._encoders) self._encoder_modes.set_device_mixer_buttons(device_button, mixer_button) self._string_to_display = None + self._shift_pressed = False + self._shift_button.add_value_listener(self._shift_value) + + for component in self.components: component.set_enabled(False) @@ -124,7 +128,6 @@ def disconnect(self): self._strip_buttons = None self._master_slider = None self._current_midi_map = None - self._shift_button = None self._name_display = None self._prev_bank_button = None self._next_bank_button = None @@ -134,6 +137,11 @@ def disconnect(self): self._send_midi(SYSEX_START + (6, 0, 0, 0, 247)) self.log('starting disconnect 5') + if self._shift_button != None: + self._shift_button.remove_value_listener(self._shift_value) + self._shift_button = None + self.log('starting disconnect 6') + def build_midi_map(self, midi_map_handle): self._current_midi_map = midi_map_handle ControlSurface.build_midi_map(self, midi_map_handle) @@ -354,6 +362,34 @@ def _on_selected_track_changed(self): raise AssertionError self._session.set_offsets(new_offset, self._session.scene_offset()) + + def _shift_value(self, value): + self.log("root shift handler") + if not self._shift_button != None: + raise AssertionError + if not value in range(128): + raise AssertionError + self.log("root shift handler 2") + self._shift_pressed = value > 0 + self.log("root shift handler 3") +#clip stop + num_pads = len(PAD_TRANSLATIONS) + pads = [] + for index in range(num_pads): + pads.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index)) + pads[-1].name = 'Pad_' + str(index) + clip_slot = self._session.selected_scene().clip_slot(index) + if self._shift_pressed: + clip_slot.set_launch_button(None) + else: + clip_slot.set_launch_button(pads[index]) + if self._shift_pressed: + self._session.set_stop_track_clip_buttons(tuple(pads)) + else: + self._session.set_stop_track_clip_buttons(None) + + self.log("root shift handler 3") + def log(self, message): pass # self.c_instance.log_message(message) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index e6258aa9..b77ed277 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -30,7 +30,8 @@ def set_shift_button(self, button): self._shift_pressed = False self._shift_button = button self.log("set_shift_button 3 (transport)") - self._shift_button != None and self._shift_button.add_value_listener(self._shift_value) + if self._shift_button != None: + self._shift_button.add_value_listener(self._shift_value) self.log("set_shift_button 4 (transport)") def set_record_buttonOnInit(self, button): From 41447ce7b4a3eeb3f89cff6e6baad535721236de Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 13 Oct 2013 04:51:03 +1100 Subject: [PATCH 06/45] readme --- Novation_Impulse2/changelog.txt | 0 Novation_Impulse2/readme.txt | 4 +++- add.pyproj | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) delete mode 100644 Novation_Impulse2/changelog.txt diff --git a/Novation_Impulse2/changelog.txt b/Novation_Impulse2/changelog.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 42c0811a..b81a1eed 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -6,6 +6,8 @@ Mixer button 9 = OverDub Shift changes mixer buttons to be arm the specific track button. +Shift + Clip buttons are now clip stop. + Known issues that cannot be fixed 1) After moving track with Shift+Track buttons are not returned to inital condition. Also happens sometimes in other cases (like bank switching with Shift). @@ -35,7 +37,7 @@ DONE 1) mixer9 - overdub 5) Shift + Loop switch session/arrangement (as loop is the button that also changes in this case) 6) Shift + play Undo (as play is like backspace but turned opposite) -another parallel feature - Shift + drum pad in clip mode - stop the selected clip. +DONE: another parallel feature - Shift + drum pad in clip mode - stop the selected clip. 7) display messages, when metronome on/off diff --git a/add.pyproj b/add.pyproj index f0dc00db..544dce6e 100644 --- a/add.pyproj +++ b/add.pyproj @@ -59,7 +59,6 @@ - From 165f2ba418bf21717bcdb93dcd3675631d70d443 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 13 Oct 2013 14:59:33 +1100 Subject: [PATCH 07/45] added todo --- Novation_Impulse2/readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index b81a1eed..d289929c 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -24,7 +24,7 @@ FIXED: 1) impulse does not disconnect properly and does not send disconnection FIXED: 2)when track goes down, the bank is not changed. 3) on initialize mute/solo buttons do not light workaround - press shift button. - +4) when arming a single track make the track selected Future things to implement. From 2de540dc7a74dacd96884197236f8262959cabdb Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Mon, 14 Oct 2013 01:59:23 +1100 Subject: [PATCH 08/45] added somethoughts --- Novation_Impulse2/readme.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index d289929c..1fc950e6 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -39,6 +39,8 @@ DONE 1) mixer9 - overdub DONE: another parallel feature - Shift + drum pad in clip mode - stop the selected clip. +think of re-mapping drum pads for another notes. + 7) display messages, when metronome on/off undo From e52c14742c53b26bba2dfef1e7f2482de5d543d2 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Wed, 11 Dec 2013 02:30:15 +1100 Subject: [PATCH 09/45] rename --- add.pyproj => AbletonRemoteScripts.pyproj | 1 + add.sln => AbletonRemoteScripts.sln | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) rename add.pyproj => AbletonRemoteScripts.pyproj (98%) rename add.sln => AbletonRemoteScripts.sln (81%) diff --git a/add.pyproj b/AbletonRemoteScripts.pyproj similarity index 98% rename from add.pyproj rename to AbletonRemoteScripts.pyproj index 544dce6e..034478c4 100644 --- a/add.pyproj +++ b/AbletonRemoteScripts.pyproj @@ -11,6 +11,7 @@ . 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + AbletonRemoteScripts diff --git a/add.sln b/AbletonRemoteScripts.sln similarity index 81% rename from add.sln rename to AbletonRemoteScripts.sln index 4be9b948..2173f144 100644 --- a/add.sln +++ b/AbletonRemoteScripts.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.20827.3 +VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "add", "add.pyproj", "{ED5FBFBF-4BE8-482D-B574-58DB3CD35247}" +Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "AbletonRemoteScripts", "AbletonRemoteScripts.pyproj", "{ED5FBFBF-4BE8-482D-B574-58DB3CD35247}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From bd6c3968eb3790990d1e441276e631d46cf8eaee Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Wed, 11 Dec 2013 02:36:11 +1100 Subject: [PATCH 10/45] added bat file --- AbletonRemoteScripts.pyproj | 1 + Novation_Impulse2/deploy.bat | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 Novation_Impulse2/deploy.bat diff --git a/AbletonRemoteScripts.pyproj b/AbletonRemoteScripts.pyproj index 034478c4..2cc2b6c0 100644 --- a/AbletonRemoteScripts.pyproj +++ b/AbletonRemoteScripts.pyproj @@ -60,6 +60,7 @@ + diff --git a/Novation_Impulse2/deploy.bat b/Novation_Impulse2/deploy.bat new file mode 100644 index 00000000..54adce24 --- /dev/null +++ b/Novation_Impulse2/deploy.bat @@ -0,0 +1,2 @@ +del /Q "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse\*.*" +xcopy *.py "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse\*.*" \ No newline at end of file From f704e0dc815688452036f46d1d419c42d1f38fd1 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Wed, 11 Dec 2013 02:56:10 +1100 Subject: [PATCH 11/45] added some files --- AbletonRemoteScripts.pyproj | 8 +++ Nocturn2/._.DS_Store | Bin 0 -> 70 bytes Nocturn2/._MixerController.py | Bin 0 -> 70 bytes Nocturn2/._Nocturn.py | Bin 0 -> 70 bytes Nocturn2/._NocturnComponent.py | Bin 0 -> 70 bytes Nocturn2/._PlayingController.py | Bin 0 -> 70 bytes Nocturn2/._SceneController.py | Bin 0 -> 70 bytes Nocturn2/.___init__.py | Bin 0 -> 70 bytes Nocturn2/.___init__.py2.py | Bin 0 -> 70 bytes Nocturn2/._apihelper.py | Bin 0 -> 70 bytes Nocturn2/._consts.py | Bin 0 -> 70 bytes Nocturn2/Automap/._.DS_Store | Bin 0 -> 70 bytes Nocturn2/Automap/._User.automap | Bin 0 -> 1420 bytes Nocturn2/Automap/Fx.automap | 101 ++++++++++++++++++++++++++++++++ Nocturn2/Automap/Inst.automap | 55 +++++++++++++++++ Nocturn2/Automap/Mixer.automap | 78 ++++++++++++++++++++++++ Nocturn2/Automap/User.automap | 78 ++++++++++++++++++++++++ Nocturn2/readme.txt | 3 + Novation_Impulse2/deploy.bat | 4 +- 19 files changed, 325 insertions(+), 2 deletions(-) create mode 100644 Nocturn2/._.DS_Store create mode 100644 Nocturn2/._MixerController.py create mode 100644 Nocturn2/._Nocturn.py create mode 100644 Nocturn2/._NocturnComponent.py create mode 100644 Nocturn2/._PlayingController.py create mode 100644 Nocturn2/._SceneController.py create mode 100644 Nocturn2/.___init__.py create mode 100644 Nocturn2/.___init__.py2.py create mode 100644 Nocturn2/._apihelper.py create mode 100644 Nocturn2/._consts.py create mode 100644 Nocturn2/Automap/._.DS_Store create mode 100644 Nocturn2/Automap/._User.automap create mode 100644 Nocturn2/Automap/Fx.automap create mode 100644 Nocturn2/Automap/Inst.automap create mode 100644 Nocturn2/Automap/Mixer.automap create mode 100644 Nocturn2/Automap/User.automap create mode 100644 Nocturn2/readme.txt diff --git a/AbletonRemoteScripts.pyproj b/AbletonRemoteScripts.pyproj index 2cc2b6c0..8efdc262 100644 --- a/AbletonRemoteScripts.pyproj +++ b/AbletonRemoteScripts.pyproj @@ -43,11 +43,19 @@ + + + + + + + + diff --git a/Nocturn2/._.DS_Store b/Nocturn2/._.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c7f79192aee6ac507a19da4a75e58297e9d261ac GIT binary patch literal 70 gcmZQz6=P>$V!#B9Kp{>bRs&)MAO-^mD2+}502>MbwEzGB literal 0 HcmV?d00001 diff --git a/Nocturn2/._MixerController.py b/Nocturn2/._MixerController.py new file mode 100644 index 0000000000000000000000000000000000000000..269384c43104819c9534799b605cf173aedfb010 GIT binary patch literal 70 kcmZQz6=P>$V!#B9Kp{>bRs&*%5Z8zh#h~O2Ol1%e09-Kw_y7O^ literal 0 HcmV?d00001 diff --git a/Nocturn2/._Nocturn.py b/Nocturn2/._Nocturn.py new file mode 100644 index 0000000000000000000000000000000000000000..eed6c1d66263875824168c6e2c3cfa39aa68a2eb GIT binary patch literal 70 gcmZQz6=P>$V!#B9Kp{>bRs&*%5Z8zhOeF{r06Vz>x&QzG literal 0 HcmV?d00001 diff --git a/Nocturn2/._NocturnComponent.py b/Nocturn2/._NocturnComponent.py new file mode 100644 index 0000000000000000000000000000000000000000..269384c43104819c9534799b605cf173aedfb010 GIT binary patch literal 70 kcmZQz6=P>$V!#B9Kp{>bRs&*%5Z8zh#h~O2Ol1%e09-Kw_y7O^ literal 0 HcmV?d00001 diff --git a/Nocturn2/._PlayingController.py b/Nocturn2/._PlayingController.py new file mode 100644 index 0000000000000000000000000000000000000000..269384c43104819c9534799b605cf173aedfb010 GIT binary patch literal 70 kcmZQz6=P>$V!#B9Kp{>bRs&*%5Z8zh#h~O2Ol1%e09-Kw_y7O^ literal 0 HcmV?d00001 diff --git a/Nocturn2/._SceneController.py b/Nocturn2/._SceneController.py new file mode 100644 index 0000000000000000000000000000000000000000..269384c43104819c9534799b605cf173aedfb010 GIT binary patch literal 70 kcmZQz6=P>$V!#B9Kp{>bRs&*%5Z8zh#h~O2Ol1%e09-Kw_y7O^ literal 0 HcmV?d00001 diff --git a/Nocturn2/.___init__.py b/Nocturn2/.___init__.py new file mode 100644 index 0000000000000000000000000000000000000000..eed6c1d66263875824168c6e2c3cfa39aa68a2eb GIT binary patch literal 70 gcmZQz6=P>$V!#B9Kp{>bRs&*%5Z8zhOeF{r06Vz>x&QzG literal 0 HcmV?d00001 diff --git a/Nocturn2/.___init__.py2.py b/Nocturn2/.___init__.py2.py new file mode 100644 index 0000000000000000000000000000000000000000..cd271bc303993fd75db27e48544f8867889ff70f GIT binary patch literal 70 jcmZQz6=P>$V!#B9Kp{>bRs&*%5Z8zhuo3|$V!#B9Kp{>bRs&*%5Z8zhOeF{r06Vz>x&QzG literal 0 HcmV?d00001 diff --git a/Nocturn2/._consts.py b/Nocturn2/._consts.py new file mode 100644 index 0000000000000000000000000000000000000000..eed6c1d66263875824168c6e2c3cfa39aa68a2eb GIT binary patch literal 70 gcmZQz6=P>$V!#B9Kp{>bRs&*%5Z8zhOeF{r06Vz>x&QzG literal 0 HcmV?d00001 diff --git a/Nocturn2/Automap/._.DS_Store b/Nocturn2/Automap/._.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c7f79192aee6ac507a19da4a75e58297e9d261ac GIT binary patch literal 70 gcmZQz6=P>$V!#B9Kp{>bRs&)MAO-^mD2+}502>MbwEzGB literal 0 HcmV?d00001 diff --git a/Nocturn2/Automap/._User.automap b/Nocturn2/Automap/._User.automap new file mode 100644 index 0000000000000000000000000000000000000000..6d0d8d287302e94cea7de860d3b87d3bf25799e0 GIT binary patch literal 1420 zcmZQz6=P>$V!#9-F-{;h0%8Rq2JwR!7+9@BTq8n&Y&?JwD96gdz`z2;VEuU14o4{# z7ND;b^c@Qdax#+>OEUBGiuD~!OY(CQ3xZRN%2JE;5(^53qsK@6G#Ub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Nocturn2/Automap/Inst.automap b/Nocturn2/Automap/Inst.automap new file mode 100644 index 00000000..6c0a372b --- /dev/null +++ b/Nocturn2/Automap/Inst.automap @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Nocturn2/Automap/Mixer.automap b/Nocturn2/Automap/Mixer.automap new file mode 100644 index 00000000..b6c95411 --- /dev/null +++ b/Nocturn2/Automap/Mixer.automap @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Nocturn2/Automap/User.automap b/Nocturn2/Automap/User.automap new file mode 100644 index 00000000..daec8d1b --- /dev/null +++ b/Nocturn2/Automap/User.automap @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Nocturn2/readme.txt b/Nocturn2/readme.txt new file mode 100644 index 00000000..f6016d6c --- /dev/null +++ b/Nocturn2/readme.txt @@ -0,0 +1,3 @@ +This is so-called "Gulie Script" +all relevant files and instruction can be found here +http://www.macableton.com/hardware-reviews-tutorials/guille-script-for-automapno.html diff --git a/Novation_Impulse2/deploy.bat b/Novation_Impulse2/deploy.bat index 54adce24..9041931a 100644 --- a/Novation_Impulse2/deploy.bat +++ b/Novation_Impulse2/deploy.bat @@ -1,2 +1,2 @@ -del /Q "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse\*.*" -xcopy *.py "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse\*.*" \ No newline at end of file +del /Q "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" +xcopy *.py "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" \ No newline at end of file From fcea4a0fb69d20141d0d6a8f997b97cea6d36a07 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 03:30:21 +1100 Subject: [PATCH 12/45] refactoring for shift handler in the mixer --- AbletonRemoteScripts.pyproj | 1 + Novation_Impulse2/Novation_Impulse2.py | 11 ++++--- .../ShiftableTransportComponent.py | 6 ++-- Novation_Impulse2/SpecialMixerComponent.py | 33 ++++++++++--------- Novation_Impulse2/debug.bat | 2 ++ Novation_Impulse2/readme.txt | 2 +- 6 files changed, 31 insertions(+), 24 deletions(-) create mode 100644 Novation_Impulse2/debug.bat diff --git a/AbletonRemoteScripts.pyproj b/AbletonRemoteScripts.pyproj index 8efdc262..97229c17 100644 --- a/AbletonRemoteScripts.pyproj +++ b/AbletonRemoteScripts.pyproj @@ -68,6 +68,7 @@ + diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 8bd69541..874d048d 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -186,7 +186,7 @@ def _setup_mixer(self): self._mixer.master_strip().set_mute_button(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17)) self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button) - self._mixer.set_shift_button(self._shift_button) + #self._mixer.set_shift_button(self._shift_button) self._mixer.updateMixerButtons() self._button9 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + 8) @@ -372,6 +372,9 @@ def _shift_value(self, value): self.log("root shift handler 2") self._shift_pressed = value > 0 self.log("root shift handler 3") +# calling other handlers + self._mixer._shift_value(value) + #clip stop num_pads = len(PAD_TRANSLATIONS) pads = [] @@ -388,8 +391,8 @@ def _shift_value(self, value): else: self._session.set_stop_track_clip_buttons(None) - self.log("root shift handler 3") + self.log("root shift handler 4") def log(self, message): - pass -# self.c_instance.log_message(message) +# pass + self.c_instance.log_message(message) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index b77ed277..6b020279 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -48,7 +48,7 @@ def set_mixer9_button(self, button): def _shift_value(self, value): - self.log("shift handler") + self.log("shift handler transport component") if not self._shift_button != None: raise AssertionError if not value in range(128): @@ -98,5 +98,5 @@ def _rwd_value(self, value): TransportComponent._rwd_value(self, value) def log(self, message): - pass -# self.c_instance.log_message(message) +# pass + self.c_instance.log_message(message) diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index e7ade61e..5f7b0cd8 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -7,7 +7,7 @@ class SpecialMixerComponent(MixerComponent): def __init__(self, num_tracks, c_instance): self.c_instance = c_instance - self._shift_button = None + #self._shift_button = None self._selected_mute_solo_button = None self._strip_mute_solo_buttons = None self._mute_solo_flip_button = None @@ -22,23 +22,23 @@ def disconnect(self): self._unregister_timer_callback(self._on_timer) self._selected_tracks = None MixerComponent.disconnect(self) - if self._shift_button != None: - self._shift_button.remove_value_listener(self._shift_value) - self._shift_button = None + #if self._shift_button != None: + # self._shift_button.remove_value_listener(self._shift_value) + # self._shift_button = None if self._mute_solo_flip_button != None: self._mute_solo_flip_button.remove_value_listener(self._mute_solo_flip_value) self._mute_solo_flip_button = None self._selected_mute_solo_button = None self._strip_mute_solo_buttons = None - def set_shift_button(self, shift_button): - self.log("set_shift_button - mixer") - if not (shift_button == None or shift_button.is_momentary()): - raise AssertionError - if self._shift_button != None: - self._shift_button.remove_value_listener(self._shift_value) - self._shift_button = shift_button - self._shift_button != None and self._shift_button.add_value_listener(self._shift_value) + #def set_shift_button(self, shift_button): + # self.log("set_shift_button - mixer") + # if not (shift_button == None or shift_button.is_momentary()): + # raise AssertionError + # if self._shift_button != None: + # self._shift_button.remove_value_listener(self._shift_value) + # self._shift_button = shift_button + # self._shift_button != None and self._shift_button.add_value_listener(self._shift_value) def set_strip_mute_solo_buttons(self, buttons, flip_button): self.log("set_strip_mute_solo_buttons") @@ -64,6 +64,7 @@ def tracks_to_use(self): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) def _shift_value(self, value): + self.log("calling mixer shift value" + str(value)) if (value > 0): self._shift_pressed = True else: @@ -72,8 +73,8 @@ def _shift_value(self, value): pass return self.log("_shift_value " + str(value)) - if not self._shift_button != None: - raise AssertionError + #if not self._shift_button != None: + # raise AssertionError if not value in range(128): raise AssertionError if value > 0: @@ -167,5 +168,5 @@ def _prev_track_value(self, value): self.updateMixerButtons() def log(self, message): - pass -# self.c_instance.log_message(message) +# pass + self.c_instance.log_message(message) diff --git a/Novation_Impulse2/debug.bat b/Novation_Impulse2/debug.bat new file mode 100644 index 00000000..32c4d6c7 --- /dev/null +++ b/Novation_Impulse2/debug.bat @@ -0,0 +1,2 @@ +rem C:\Documents and Settings\%username%\Application Data\Ableton\Live 8.x.x\Preferences\Log.txt +cd "C:\Documents and Settings\%username%\Application Data\Ableton\Live 9.1\Preferences\" diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 1fc950e6..69271dcb 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -16,7 +16,7 @@ Known issues that cannot be fixed Workaround - do not do that, if you have done that, just press and release shift. The reason for these problems is that when you use shift+track or shift+bank, the message "shift off" is not sent. -This is out of the scope of what I can do +This is out of the scope of what I can do. The bug report is sent to Novation. Known issues and todo: FIXED: 1) impulse does not disconnect properly and does not send disconnection message. From 7189ad9476c6228c29b82eab3b8374791274138c Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 03:47:45 +1100 Subject: [PATCH 13/45] REQFACTORING DONE --- AbletonRemoteScripts.pyproj | 54 +++++++++++++++++++ Novation_Impulse2/Novation_Impulse2.py | 19 +++---- .../ShiftableTransportComponent.py | 36 +------------ Novation_Impulse2/SpecialMixerComponent.py | 27 +--------- Novation_Impulse2/readme.txt | 4 +- 5 files changed, 69 insertions(+), 71 deletions(-) diff --git a/AbletonRemoteScripts.pyproj b/AbletonRemoteScripts.pyproj index 97229c17..c9b1d6b1 100644 --- a/AbletonRemoteScripts.pyproj +++ b/AbletonRemoteScripts.pyproj @@ -50,12 +50,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 874d048d..70d035c9 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -225,14 +225,14 @@ def _setup_transport(self): play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' rec_button.name = 'Record_Button' - transport = ShiftableTransportComponent(self.c_instance) - transport.name = 'Transport' - transport.set_stop_button(stop_button) - transport.set_play_button(play_button) - transport.set_record_buttonOnInit(rec_button) - transport.set_shift_button(self._shift_button) - transport.set_mixer9_button(self._button9) - self._transport_view_modes = TransportViewModeSelector(transport, self._session, ffwd_button, rwd_button, loop_button) + self._transport = ShiftableTransportComponent(self.c_instance) + self._transport.name = 'Transport' + self._transport.set_stop_button(stop_button) + self._transport.set_play_button(play_button) + self._transport.set_record_buttonOnInit(rec_button) +# self._transport.set_shift_button(self._shift_button) + self._transport.set_mixer9_button(self._button9) + self._transport_view_modes = TransportViewModeSelector(self._transport, self._session, ffwd_button, rwd_button, loop_button) self._transport_view_modes.name = 'Transport_View_Modes' def _setup_device(self): @@ -371,11 +371,12 @@ def _shift_value(self, value): raise AssertionError self.log("root shift handler 2") self._shift_pressed = value > 0 - self.log("root shift handler 3") # calling other handlers self._mixer._shift_value(value) + self._transport._shift_value(value) #clip stop + self.log("root shift handler 3") num_pads = len(PAD_TRANSLATIONS) pads = [] for index in range(num_pads): diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index 6b020279..27c8f253 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -8,32 +8,13 @@ class ShiftableTransportComponent(TransportComponent): def __init__(self, c_instance): self.c_instance = c_instance - self._shift_button = None self._shift_pressed = False self._mixer9_button = None TransportComponent.__init__(self) def disconnect(self): - if self._shift_button != None: - self._shift_button.remove_value_listener(self._shift_value) - self._shift_button = None TransportComponent.disconnect(self) - def set_shift_button(self, button): - self.log("set_shift_button (transport)") - if not (button == None or isinstance(button, ButtonElement) and button.is_momentary()): - raise AssertionError - self.log("set_shift_button 2 (transport)") - if self._shift_button != button: - if self._shift_button != None: - self._shift_button.remove_value_listener(self._shift_value) - self._shift_pressed = False - self._shift_button = button - self.log("set_shift_button 3 (transport)") - if self._shift_button != None: - self._shift_button.add_value_listener(self._shift_value) - self.log("set_shift_button 4 (transport)") - def set_record_buttonOnInit(self, button): self.log("set_record_buttonOnInit 1") self.record_button = button @@ -48,25 +29,12 @@ def set_mixer9_button(self, button): def _shift_value(self, value): - self.log("shift handler transport component") - if not self._shift_button != None: - raise AssertionError + self.log("shift handler transport component " + str(value)) if not value in range(128): raise AssertionError self.log("shift handler 2") self._shift_pressed = self.is_enabled() and value > 0 self.log("shift handler 3") -# if self._shift_pressed: -# self.log("shift handler pressed") -# self.set_overdub_button(None) -# self.set_record_button(None) -# self.set_session_overdub_button(self._mixer9_button) -# else: -# self.log("shift handler unpressed") -# self.set_overdub_button(None) -# self.set_record_button(self.record_button) -# self.set_arrangement_overdub_button(self._mixer9_button) - def _ffwd_value(self, value): @@ -99,4 +67,4 @@ def _rwd_value(self, value): def log(self, message): # pass - self.c_instance.log_message(message) + self.c_instance.log_message(message) diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index 5f7b0cd8..f345d2b3 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -7,7 +7,6 @@ class SpecialMixerComponent(MixerComponent): def __init__(self, num_tracks, c_instance): self.c_instance = c_instance - #self._shift_button = None self._selected_mute_solo_button = None self._strip_mute_solo_buttons = None self._mute_solo_flip_button = None @@ -31,15 +30,6 @@ def disconnect(self): self._selected_mute_solo_button = None self._strip_mute_solo_buttons = None - #def set_shift_button(self, shift_button): - # self.log("set_shift_button - mixer") - # if not (shift_button == None or shift_button.is_momentary()): - # raise AssertionError - # if self._shift_button != None: - # self._shift_button.remove_value_listener(self._shift_value) - # self._shift_button = shift_button - # self._shift_button != None and self._shift_button.add_value_listener(self._shift_value) - def set_strip_mute_solo_buttons(self, buttons, flip_button): self.log("set_strip_mute_solo_buttons") if not (buttons is None or isinstance(buttons, tuple) and len(buttons) == len(self._channel_strips)): @@ -64,7 +54,7 @@ def tracks_to_use(self): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) def _shift_value(self, value): - self.log("calling mixer shift value" + str(value)) + self.log("calling mixer shift value " + str(value)) if (value > 0): self._shift_pressed = True else: @@ -72,20 +62,7 @@ def _shift_value(self, value): self.updateMixerButtons() pass return - self.log("_shift_value " + str(value)) - #if not self._shift_button != None: - # raise AssertionError - if not value in range(128): - raise AssertionError - if value > 0: - self.selected_strip().set_mute_button(None) -# self.selected_strip().set_solo_button(self._selected_mute_solo_button) - self.selected_strip().set_arm_button(self._selected_mute_solo_button) - else: -# self.selected_strip().set_solo_button(None) - self.selected_strip().set_arm_button(None) - self.selected_strip().set_mute_button(self._selected_mute_solo_button) - + def _mute_solo_flip_value(self, value): #self.log(value) if not self._mute_solo_flip_button != None: diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 69271dcb..1ddfcb61 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -1,7 +1,5 @@ Features -Shift + Rec = Overdub - Mixer button 9 = OverDub Shift changes mixer buttons to be arm the specific track button. @@ -20,7 +18,7 @@ This is out of the scope of what I can do. The bug report is sent to Novation. Known issues and todo: FIXED: 1) impulse does not disconnect properly and does not send disconnection message. -1.5) refactor shift - move it to main class. +FIXED 1.5) refactor shift - move it to main class. FIXED: 2)when track goes down, the bank is not changed. 3) on initialize mute/solo buttons do not light workaround - press shift button. From d35d65b67f6f98fa0d1e4be3bd430a59d4c4de4f Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 03:58:46 +1100 Subject: [PATCH 14/45] workign on play --- Novation_Impulse2/Novation_Impulse2.py | 4 +-- .../ShiftableTransportComponent.py | 25 +++++++++++++++++++ Novation_Impulse2/SpecialMixerComponent.py | 4 +-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 70d035c9..073b3a71 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -395,5 +395,5 @@ def _shift_value(self, value): self.log("root shift handler 4") def log(self, message): -# pass - self.c_instance.log_message(message) + pass +# self.c_instance.log_message(message) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index 27c8f253..f1e5ff49 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -10,6 +10,7 @@ def __init__(self, c_instance): self.c_instance = c_instance self._shift_pressed = False self._mixer9_button = None + self._play_button = None TransportComponent.__init__(self) def disconnect(self): @@ -28,6 +29,10 @@ def set_mixer9_button(self, button): self.log("set_mixer9_button 2") + def set_play_button(self, button): + self._play_button = button + self._play_toggle.set_toggle_button(button) + def _shift_value(self, value): self.log("shift handler transport component " + str(value)) if not value in range(128): @@ -35,6 +40,12 @@ def _shift_value(self, value): self.log("shift handler 2") self._shift_pressed = self.is_enabled() and value > 0 self.log("shift handler 3") + if self._shift_pressed: + self._play_toggle.set_toggle_button(None) + else: + self._play_toggle.set_toggle_button(self._play_button) + self.log("shift handler 4") + def _ffwd_value(self, value): @@ -65,6 +76,20 @@ def _rwd_value(self, value): self.log("rwd normal handler") TransportComponent._rwd_value(self, value) + def _play_toggle_value(self, value): + self.log("play toggle " + str(value)) + if not self._play_toggle != None: + raise AssertionError + if not value in range(128): + raise AssertionError + else: + if self._shift_pressed: + self.log("play shifted handler") + TransportComponent._play_toggle_value(self, value) + else: + self.log("play normal handler") + TransportComponent._play_toggle_value(self, value) + def log(self, message): # pass self.c_instance.log_message(message) diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index f345d2b3..5364732b 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -145,5 +145,5 @@ def _prev_track_value(self, value): self.updateMixerButtons() def log(self, message): -# pass - self.c_instance.log_message(message) + pass +# self.c_instance.log_message(message) From 623d6e41bbde3c174e09a97b9af6dc23a9814c73 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 04:22:27 +1100 Subject: [PATCH 15/45] shift+play done --- .../ShiftableTransportComponent.py | 34 ++++++++++--------- Novation_Impulse2/readme.txt | 6 +++- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index f1e5ff49..f0d8b288 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -14,6 +14,10 @@ def __init__(self, c_instance): TransportComponent.__init__(self) def disconnect(self): + if self._play_button != None: + self._play_button.remove_value_listener(self._play_pressed) + self._play_button = None + TransportComponent.disconnect(self) def set_record_buttonOnInit(self, button): @@ -31,8 +35,20 @@ def set_mixer9_button(self, button): def set_play_button(self, button): self._play_button = button + self._play_button.add_value_listener(self._play_pressed) self._play_toggle.set_toggle_button(button) + def _play_pressed(self, value): + self.log("_play_pressed " + str(value)) + if not value in range(128): + raise AssertionError + if self._shift_pressed: + if value != 0: + if self.song().can_undo: + self.song().undo() + self.log("undoing") + + def _shift_value(self, value): self.log("shift handler transport component " + str(value)) if not value in range(128): @@ -76,20 +92,6 @@ def _rwd_value(self, value): self.log("rwd normal handler") TransportComponent._rwd_value(self, value) - def _play_toggle_value(self, value): - self.log("play toggle " + str(value)) - if not self._play_toggle != None: - raise AssertionError - if not value in range(128): - raise AssertionError - else: - if self._shift_pressed: - self.log("play shifted handler") - TransportComponent._play_toggle_value(self, value) - else: - self.log("play normal handler") - TransportComponent._play_toggle_value(self, value) - def log(self, message): -# pass - self.c_instance.log_message(message) + pass +# self.c_instance.log_message(message) diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 1ddfcb61..bbb4b830 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -2,10 +2,14 @@ Features Mixer button 9 = OverDub +Shift + PLay = Undo + Shift changes mixer buttons to be arm the specific track button. Shift + Clip buttons are now clip stop. + + Known issues that cannot be fixed 1) After moving track with Shift+Track buttons are not returned to inital condition. Also happens sometimes in other cases (like bank switching with Shift). @@ -33,7 +37,7 @@ DONE 1) mixer9 - overdub 4) Shift+Rec - metronome on/off (as metronome has much to do with recording) 5) Shift + Loop switch session/arrangement (as loop is the button that also changes in this case) -6) Shift + play Undo (as play is like backspace but turned opposite) +FIXED: 6) Shift + play Undo (as play is like backspace but turned opposite) DONE: another parallel feature - Shift + drum pad in clip mode - stop the selected clip. From 8375b064fe38e6f7f917f21392a49bb47ea47c5a Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 04:40:49 +1100 Subject: [PATCH 16/45] done with shift+stop = stop all clips --- Novation_Impulse2/Novation_Impulse2.py | 4 ++-- .../ShiftableTransportComponent.py | 20 ++++++++++++++++--- Novation_Impulse2/readme.txt | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 073b3a71..2aa1bc91 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -225,9 +225,9 @@ def _setup_transport(self): play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' rec_button.name = 'Record_Button' - self._transport = ShiftableTransportComponent(self.c_instance) + self._transport = ShiftableTransportComponent(self.c_instance,self._session) self._transport.name = 'Transport' - self._transport.set_stop_button(stop_button) + self._transport.set_stop_buttonOnInit(stop_button) self._transport.set_play_button(play_button) self._transport.set_record_buttonOnInit(rec_button) # self._transport.set_shift_button(self._shift_button) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index f0d8b288..6d22ff25 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -6,11 +6,13 @@ class ShiftableTransportComponent(TransportComponent): """ Special transport class handling the seek buttons differently based on a shift button""" - def __init__(self, c_instance): + def __init__(self, c_instance, session): self.c_instance = c_instance self._shift_pressed = False self._mixer9_button = None self._play_button = None + self._record_button = None + self._session = session TransportComponent.__init__(self) def disconnect(self): @@ -20,10 +22,17 @@ def disconnect(self): TransportComponent.disconnect(self) + def set_stop_buttonOnInit(self, button): + self.log("set_stop_buttonOnInit 1") + self._stop_button = button + self.set_stop_button(self._stop_button) + self.log("set_stopbuttonOnInit 2") + + def set_record_buttonOnInit(self, button): self.log("set_record_buttonOnInit 1") - self.record_button = button - self.set_record_button(self.record_button) + self._record_button = button + self.set_record_button(self._record_button) self.log("set_record_buttonOnInit 2") def set_mixer9_button(self, button): @@ -58,8 +67,12 @@ def _shift_value(self, value): self.log("shift handler 3") if self._shift_pressed: self._play_toggle.set_toggle_button(None) + self._session.set_stop_all_clips_button(self._stop_button) + self.set_stop_button(None) else: self._play_toggle.set_toggle_button(self._play_button) + self._session.set_stop_all_clips_button(None) + self.set_stop_button(self._stop_button) self.log("shift handler 4") @@ -95,3 +108,4 @@ def _rwd_value(self, value): def log(self, message): pass # self.c_instance.log_message(message) + diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index bbb4b830..117a119e 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -32,7 +32,7 @@ FIXED: 2)when track goes down, the bank is not changed. Future things to implement. DONE 1) mixer9 - overdub -3) Shift + Stop - stop all clips. +DONE 3) Shift + Stop - stop all clips. 4) Shift+Rec - metronome on/off (as metronome has much to do with recording) From 923cb44da694701ca9a752752aa9515506def8e4 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 04:46:37 +1100 Subject: [PATCH 17/45] comments --- Novation_Impulse2/ShiftableTransportComponent.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index 6d22ff25..b4706027 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -54,8 +54,12 @@ def _play_pressed(self, value): if self._shift_pressed: if value != 0: if self.song().can_undo: + #todo: add message self.song().undo() self.log("undoing") + else: + #todo: add message + pass def _shift_value(self, value): From a99fdbd8dcdabc54429d541d1e05f646ef83b38d Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 04:48:31 +1100 Subject: [PATCH 18/45] comment --- Novation_Impulse2/readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 117a119e..2f8e64df 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -3,6 +3,7 @@ Features Mixer button 9 = OverDub Shift + PLay = Undo +Shift + Stop = Stop all clips Shift changes mixer buttons to be arm the specific track button. From 0f581257271e1adb2aa288811d2defe65d9e3966 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 05:09:08 +1100 Subject: [PATCH 19/45] metronome on shift + mixer 9 --- Novation_Impulse2/ShiftableTransportComponent.py | 4 ++++ Novation_Impulse2/debug.bat | 3 +++ Novation_Impulse2/readme.txt | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index b4706027..985d0cfd 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -73,10 +73,14 @@ def _shift_value(self, value): self._play_toggle.set_toggle_button(None) self._session.set_stop_all_clips_button(self._stop_button) self.set_stop_button(None) + self.set_overdub_button(None) + self.set_metronome_button(self._mixer9_button) else: self._play_toggle.set_toggle_button(self._play_button) self._session.set_stop_all_clips_button(None) self.set_stop_button(self._stop_button) + self.set_overdub_button(self._mixer9_button) + self.set_metronome_button(None) self.log("shift handler 4") diff --git a/Novation_Impulse2/debug.bat b/Novation_Impulse2/debug.bat index 32c4d6c7..455b6f53 100644 --- a/Novation_Impulse2/debug.bat +++ b/Novation_Impulse2/debug.bat @@ -1,2 +1,5 @@ rem C:\Documents and Settings\%username%\Application Data\Ableton\Live 8.x.x\Preferences\Log.txt cd "C:\Documents and Settings\%username%\Application Data\Ableton\Live 9.1\Preferences\" + + +rem http://remotescripts.blogspot.com.au/2010_03_01_archive.html \ No newline at end of file diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 2f8e64df..a524a1ad 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -1,6 +1,7 @@ Features Mixer button 9 = OverDub +Shift + Mixer button 9 = Metronome on/off Shift + PLay = Undo Shift + Stop = Stop all clips @@ -36,7 +37,7 @@ DONE 1) mixer9 - overdub DONE 3) Shift + Stop - stop all clips. -4) Shift+Rec - metronome on/off (as metronome has much to do with recording) +FIXED:4) Shift+Mixer9 - metronome on/off 5) Shift + Loop switch session/arrangement (as loop is the button that also changes in this case) FIXED: 6) Shift + play Undo (as play is like backspace but turned opposite) From 1d94d1c8accc50f094999fb024d145352a7f5b31 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 23:13:07 +1100 Subject: [PATCH 20/45] Shift + Mixer button 9 = Automation record on/off Shift + Rec = Metronome on/off --- Novation_Impulse2/ShiftableTransportComponent.py | 15 +++++++++++++-- Novation_Impulse2/readme.txt | 3 ++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index 985d0cfd..db4683c6 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -2,18 +2,24 @@ import Live from _Framework.ButtonElement import ButtonElement from _Framework.TransportComponent import TransportComponent +from _Framework.ToggleComponent import ToggleComponent class ShiftableTransportComponent(TransportComponent): """ Special transport class handling the seek buttons differently based on a shift button""" def __init__(self, c_instance, session): + TransportComponent.__init__(self) self.c_instance = c_instance self._shift_pressed = False self._mixer9_button = None self._play_button = None self._record_button = None self._session = session - TransportComponent.__init__(self) + song = self.song() +# self._automation_toggle= self.register_component(ToggleComponent('session_automation_record', song)) + self._automation_toggle, self._re_enable_automation_toggle, self._delete_automation = self.register_components(ToggleComponent('session_automation_record', song), ToggleComponent('re_enable_automation_enabled', song, read_only=True), ToggleComponent('has_envelopes', None, read_only=True)) + + def disconnect(self): if self._play_button != None: @@ -39,6 +45,7 @@ def set_mixer9_button(self, button): self.log("set_mixer9_button 1") self._mixer9_button = button self.set_overdub_button(self._mixer9_button) + #self._automation_toggle.set_toggle_button(self._mixer9_button) self.log("set_mixer9_button 2") @@ -74,13 +81,17 @@ def _shift_value(self, value): self._session.set_stop_all_clips_button(self._stop_button) self.set_stop_button(None) self.set_overdub_button(None) - self.set_metronome_button(self._mixer9_button) + self._automation_toggle.set_toggle_button(self._mixer9_button) + self.set_metronome_button(self._record_button) + self.set_record_button(None) else: self._play_toggle.set_toggle_button(self._play_button) self._session.set_stop_all_clips_button(None) self.set_stop_button(self._stop_button) self.set_overdub_button(self._mixer9_button) + self._automation_toggle.set_toggle_button(None) self.set_metronome_button(None) + self.set_record_button(self._record_button) self.log("shift handler 4") diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index a524a1ad..4c0a5d29 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -1,7 +1,8 @@ Features Mixer button 9 = OverDub -Shift + Mixer button 9 = Metronome on/off +Shift + Mixer button 9 = Automation record on/off +Shift + Rec = Metronome on/off Shift + PLay = Undo Shift + Stop = Stop all clips From 464b627aaa86959fe4fcf7ca8b30b1efce4364f9 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 23:16:03 +1100 Subject: [PATCH 21/45] fiixed readme --- Novation_Impulse2/readme.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 4c0a5d29..6a1c9ae6 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -7,7 +7,7 @@ Shift + Rec = Metronome on/off Shift + PLay = Undo Shift + Stop = Stop all clips -Shift changes mixer buttons to be arm the specific track button. +Shift + track mixer button = rec this track.. Shift + Clip buttons are now clip stop. @@ -38,7 +38,8 @@ DONE 1) mixer9 - overdub DONE 3) Shift + Stop - stop all clips. -FIXED:4) Shift+Mixer9 - metronome on/off +FIXED:4) Shift+Mixer9 - Automation record on/off +4.5) Shift + Rec = metronome 5) Shift + Loop switch session/arrangement (as loop is the button that also changes in this case) FIXED: 6) Shift + play Undo (as play is like backspace but turned opposite) From da780ea4ed8b973f59f6fc8ad6aa4c3f80bf91eb Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 23:26:36 +1100 Subject: [PATCH 22/45] polishing --- Novation_Impulse2/Novation_Impulse2.py | 6 +++--- Novation_Impulse2/ShiftableTransportComponent.py | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 2aa1bc91..73b8eda6 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -14,8 +14,8 @@ from ShiftableTransportComponent import ShiftableTransportComponent from PeekableEncoderElement import PeekableEncoderElement from EncoderModeSelector import EncoderModeSelector -INITIAL_DISPLAY_DELAY = 30 -STANDARD_DISPLAY_DELAY = 20 +INITIAL_DISPLAY_DELAY = 20 +STANDARD_DISPLAY_DELAY = 15 IS_MOMENTARY = True SYSEX_START = (240, 0, 32, 41, 103) PAD_TRANSLATIONS = ((0, 3, 60, 0), @@ -225,7 +225,7 @@ def _setup_transport(self): play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' rec_button.name = 'Record_Button' - self._transport = ShiftableTransportComponent(self.c_instance,self._session) + self._transport = ShiftableTransportComponent(self.c_instance,self._session, self) self._transport.name = 'Transport' self._transport.set_stop_buttonOnInit(stop_button) self._transport.set_play_button(play_button) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index db4683c6..c12bd282 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -7,7 +7,7 @@ class ShiftableTransportComponent(TransportComponent): """ Special transport class handling the seek buttons differently based on a shift button""" - def __init__(self, c_instance, session): + def __init__(self, c_instance, session, parent): TransportComponent.__init__(self) self.c_instance = c_instance self._shift_pressed = False @@ -15,6 +15,7 @@ def __init__(self, c_instance, session): self._play_button = None self._record_button = None self._session = session + self._parent = parent song = self.song() # self._automation_toggle= self.register_component(ToggleComponent('session_automation_record', song)) self._automation_toggle, self._re_enable_automation_toggle, self._delete_automation = self.register_components(ToggleComponent('session_automation_record', song), ToggleComponent('re_enable_automation_enabled', song, read_only=True), ToggleComponent('has_envelopes', None, read_only=True)) @@ -64,9 +65,11 @@ def _play_pressed(self, value): #todo: add message self.song().undo() self.log("undoing") + self._parent._set_string_to_display('undoing') + else: #todo: add message - pass + self._parent._set_string_to_display('cannot undo') def _shift_value(self, value): From 9fc2d088733f213bf5427b646b868d8a890dd0fb Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sun, 15 Dec 2013 23:50:38 +1100 Subject: [PATCH 23/45] fixes to make impulse 25 work --- Novation_Impulse2/Novation_Impulse2.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 73b8eda6..393e2249 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -280,6 +280,7 @@ def _encoder_value(self, value, sender): self._set_string_to_display(display_string) def _slider_value(self, value, sender): + self.log ('_slider_value ' + str(value) + ' ' +str(sender)) if not sender in tuple(self._sliders) + (self._master_slider,): raise AssertionError if not value in range(128): @@ -291,12 +292,22 @@ def _slider_value(self, value, sender): returns = self.song().return_tracks track = None if sender.mapped_parameter() != None: + self.log ('1') if sender == self._master_slider: - track = self._has_sliders and master + self.log ('2') +# track = self._has_sliders and master + if self._has_sliders: + track = master + else: + self.log ('2.1') + track = self.song().view.selected_track else: + self.log ('3') track = self._mixer.channel_strip(self._sliders.index(sender))._track else: + self.log ('4') track = self.song().view.selected_track + self.log('track='+str(track)) if track == master: display_string = 'Master' elif track in tracks: From 9d22d4d8fbd5070d140ab8badd8993e921756163 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sat, 12 Apr 2014 01:40:40 +1000 Subject: [PATCH 24/45] fixed to make work under ableton 9.1.2 --- AbletonRemoteScripts.pyproj | 11 + Novation_Impulse2/Novation_Impulse2.py | 11 +- Novation_Impulse2/debug.bat | 4 +- Novation_Impulse2/readme.txt | 8 + Novation_Impulse2_9_1/EncoderModeSelector.py | 119 +++++ Novation_Impulse2_9_1/Novation_Impulse2.py | 410 ++++++++++++++++++ .../PeekableEncoderElement.py | 27 ++ .../ShiftableTransportComponent.py | 133 ++++++ .../SpecialMixerComponent.py | 149 +++++++ .../TransportViewModeSelector.py | 58 +++ Novation_Impulse2_9_1/__init__.py | 12 + Novation_Impulse2_9_1/debug.bat | 7 + Novation_Impulse2_9_1/deploy.bat | 2 + Novation_Impulse2_9_1/readme.txt | 59 +++ 14 files changed, 1007 insertions(+), 3 deletions(-) create mode 100644 Novation_Impulse2_9_1/EncoderModeSelector.py create mode 100644 Novation_Impulse2_9_1/Novation_Impulse2.py create mode 100644 Novation_Impulse2_9_1/PeekableEncoderElement.py create mode 100644 Novation_Impulse2_9_1/ShiftableTransportComponent.py create mode 100644 Novation_Impulse2_9_1/SpecialMixerComponent.py create mode 100644 Novation_Impulse2_9_1/TransportViewModeSelector.py create mode 100644 Novation_Impulse2_9_1/__init__.py create mode 100644 Novation_Impulse2_9_1/debug.bat create mode 100644 Novation_Impulse2_9_1/deploy.bat create mode 100644 Novation_Impulse2_9_1/readme.txt diff --git a/AbletonRemoteScripts.pyproj b/AbletonRemoteScripts.pyproj index c9b1d6b1..6011b275 100644 --- a/AbletonRemoteScripts.pyproj +++ b/AbletonRemoteScripts.pyproj @@ -36,6 +36,13 @@ + + + + + + + @@ -107,6 +114,7 @@ + @@ -122,6 +130,9 @@ + + + diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 393e2249..f1fdb39f 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -197,8 +197,15 @@ def _setup_session(self): self._session.name = 'Session_Control' self._session.selected_scene().name = 'Selected_Scene' self._session.set_mixer(self._mixer) - self._session.set_track_banking_increment(num_pads) - self._session.set_track_bank_buttons(ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35), ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36)) + # for ableton 9.1.1 and lower + #self._session.set_track_banking_increment(num_pads) + #self._session.set_track_bank_buttons(ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35), ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36)) + # for ableton 9.1.1 and higher + self._track_left_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36) + self._track_right_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35) + self._session.set_page_left_button(self._track_left_button) + self._session.set_page_right_button(self._track_right_button) + pads = [] for index in range(num_pads): pads.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index)) diff --git a/Novation_Impulse2/debug.bat b/Novation_Impulse2/debug.bat index 455b6f53..4eaa6b3f 100644 --- a/Novation_Impulse2/debug.bat +++ b/Novation_Impulse2/debug.bat @@ -1,5 +1,7 @@ rem C:\Documents and Settings\%username%\Application Data\Ableton\Live 8.x.x\Preferences\Log.txt -cd "C:\Documents and Settings\%username%\Application Data\Ableton\Live 9.1\Preferences\" +em cd "C:\Documents and Settings\%username%\Application Data\Ableton\Live 9.1\Preferences\" + +cd "C:\Documents and Settings\mbakirov\Application Data\Ableton\Live 9.1.2\Preferences\" rem http://remotescripts.blogspot.com.au/2010_03_01_archive.html \ No newline at end of file diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 6a1c9ae6..4da731d3 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -1,3 +1,11 @@ +IMPORTANT! + +since Ableton 9.1.2 some API has been changed + +the new version is for Ableton 9.1.2 and higher + +for old version please use version from a folder Novation_Impulse2_9_1 + Features Mixer button 9 = OverDub diff --git a/Novation_Impulse2_9_1/EncoderModeSelector.py b/Novation_Impulse2_9_1/EncoderModeSelector.py new file mode 100644 index 00000000..6bd98afb --- /dev/null +++ b/Novation_Impulse2_9_1/EncoderModeSelector.py @@ -0,0 +1,119 @@ +#Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/Novation_Impulse/EncoderModeSelector.py +import Live +from _Framework.ModeSelectorComponent import ModeSelectorComponent + +class EncoderModeSelector(ModeSelectorComponent): + """ Class that reassigns the given encoders to either device- or mixer control """ + + def __init__(self, device, mixer, bank_up_button, bank_down_button, encoders): + ModeSelectorComponent.__init__(self) + self._mixer = mixer + self._device = device + self._bank_up_button = bank_up_button + self._bank_down_button = bank_down_button + self._encoders = encoders + self._device_button = None + self._mixer_button = None + self._device_mode = True + self._mode_index = 0 + self._number_of_modes = 5 + self._bank_down_button.add_value_listener(self._bank_down_value) + self._bank_up_button.add_value_listener(self._bank_up_value) + self.update() + + def disconnect(self): + self._bank_down_button.remove_value_listener(self._bank_down_value) + self._bank_up_button.remove_value_listener(self._bank_up_value) + self.set_device_mixer_buttons(None, None) + ModeSelectorComponent.disconnect(self) + self._mixer = None + self._device = None + self._bank_up_button = None + self._bank_down_button = None + self._encoders = None + + def set_device_mixer_buttons(self, device_button, mixer_button): + #if not self._device_button != None: + # if not self._mixer_button != None: + # raise AssertionError + if self._device_button != None: + self._device_button.remove_value_listener(self._device_value) + if self._mixer_button!= None: + self._mixer_button.remove_value_listener(self._mixer_value) + self._device_button = device_button + self._mixer_button = mixer_button + #raise self._device_button != None and (self._mixer_button != None or AssertionError) + if self._device_button != None: + self._device_button.add_value_listener(self._device_value) + if self._mixer_button!= None: + self._mixer_button.add_value_listener(self._mixer_value) + + def set_provide_volume_mode(self, provide_volume_mode): + self._number_of_modes = 6 if provide_volume_mode else 5 + + def number_of_modes(self): + return self._number_of_modes + + def update(self): + if not self._mode_index in range(self.number_of_modes()): + raise AssertionError + if self.is_enabled(): + self._device.set_allow_update(False) + self._mixer.set_allow_update(False) + self._device.set_bank_nav_buttons(None, None) + self._device.set_parameter_controls(()) + for index in range(len(self._encoders)): + strip = self._mixer.channel_strip(index) + strip.set_pan_control(None) + strip.set_send_controls(None) + if self.number_of_modes() > 5: + strip.set_volume_control(None) + + if self._device_mode: + self._device.set_bank_nav_buttons(self._bank_down_button, self._bank_up_button) + self._device.set_parameter_controls(self._encoders) + else: + for index in range(len(self._encoders)): + strip = self._mixer.channel_strip(index) + if self._mode_index == 0: + strip.set_pan_control(self._encoders[index]) + elif self._mode_index < 5: + sends = [None, + None, + None, + None] + sends[self._mode_index - 1] = self._encoders[index] + strip.set_send_controls(tuple(sends)) + else: + strip.set_volume_control(self._encoders[index]) + + self._device.set_allow_update(True) + self._mixer.set_allow_update(True) + + def _bank_down_value(self, value): + if not value in range(128): + raise AssertionError + if self.is_enabled() and not self._device_mode: + new_mode = (value > 0 or not self._bank_down_button.is_momentary()) and max(self._mode_index - 1, 0) + self.set_mode(new_mode) + + def _bank_up_value(self, value): + if not value in range(128): + raise AssertionError + if self.is_enabled() and not self._device_mode: + new_mode = (value > 0 or not self._bank_up_button.is_momentary()) and min(self._mode_index + 1, self.number_of_modes() - 1) + self.set_mode(new_mode) + + def _device_value(self, value): + if not value in range(128): + raise AssertionError + if self.is_enabled() and not self._device_mode: + self._device_mode = (value > 0 or not self._device_button.is_momentary()) and True + self.update() + + def _mixer_value(self, value): + if not value in range(128): + raise AssertionError + if self.is_enabled() and self._device_mode: + self._device_mode = (value > 0 or not self._mixer_button.is_momentary()) and False + self.update() \ No newline at end of file diff --git a/Novation_Impulse2_9_1/Novation_Impulse2.py b/Novation_Impulse2_9_1/Novation_Impulse2.py new file mode 100644 index 00000000..393e2249 --- /dev/null +++ b/Novation_Impulse2_9_1/Novation_Impulse2.py @@ -0,0 +1,410 @@ +#Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/Novation_Impulse/Novation_Impulse.py +from __future__ import with_statement +import Live +from _Framework.ControlSurface import ControlSurface +from _Framework.InputControlElement import * +from _Framework.SliderElement import SliderElement +from _Framework.ButtonElement import ButtonElement +from _Framework.PhysicalDisplayElement import PhysicalDisplayElement +from _Framework.DisplayDataSource import DisplayDataSource +from _Framework.SessionComponent import SessionComponent +from _Framework.DeviceComponent import DeviceComponent +from TransportViewModeSelector import TransportViewModeSelector +from SpecialMixerComponent import SpecialMixerComponent +from ShiftableTransportComponent import ShiftableTransportComponent +from PeekableEncoderElement import PeekableEncoderElement +from EncoderModeSelector import EncoderModeSelector +INITIAL_DISPLAY_DELAY = 20 +STANDARD_DISPLAY_DELAY = 15 +IS_MOMENTARY = True +SYSEX_START = (240, 0, 32, 41, 103) +PAD_TRANSLATIONS = ((0, 3, 60, 0), + (1, 3, 62, 0), + (2, 3, 64, 0), + (3, 3, 65, 0), + (0, 2, 67, 0), + (1, 2, 69, 0), + (2, 2, 71, 0), + (3, 2, 72, 0)) +LED_OFF = 4 +RED_FULL = 7 +RED_BLINK = 11 +GREEN_FULL = 52 +GREEN_BLINK = 56 +AMBER_FULL = RED_FULL + GREEN_FULL - 4 +AMBER_BLINK = AMBER_FULL - 4 + 8 + +class Novation_Impulse2(ControlSurface): + """ Script for Novation's Impulse keyboards """ + + def __init__(self, c_instance): + ControlSurface.__init__(self, c_instance) + self.c_instance = c_instance + with self.component_guard(): + self.set_pad_translations(PAD_TRANSLATIONS) + self._device_selection_follows_track_selection = True + self._suggested_input_port = 'Impulse' + self._suggested_output_port = 'Impulse' + self._has_sliders = True + self._current_midi_map = None + self._display_reset_delay = -1 + self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 39) + self._preview_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 41) + self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 8) + self._shift_button.name = 'Shift_Button' + self._master_slider.name = 'Master_Volume_Control' + self._master_slider.add_value_listener(self._slider_value, identify_sender=True) + self._preview_button.add_value_listener(self._preview_value) + self._setup_mixer() + self._setup_session() + self._setup_transport() + self._setup_device() + self._setup_name_display() + device_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 10) + mixer_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 1, 9) + device_button.name = 'Encoder_Device_Mode' + mixer_button.name = 'Encoder_Mixer_Mode' + self._encoder_modes = EncoderModeSelector(self._device_component, self._mixer, self._next_bank_button, self._prev_bank_button, self._encoders) + self._encoder_modes.set_device_mixer_buttons(device_button, mixer_button) + self._string_to_display = None + self._shift_pressed = False + self._shift_button.add_value_listener(self._shift_value) + + + for component in self.components: + component.set_enabled(False) + + def refresh_state(self): + ControlSurface.refresh_state(self) + self.schedule_message(3, self._send_midi, SYSEX_START + (6, 1, 1, 1, 247)) + + def handle_sysex(self, midi_bytes): + if midi_bytes[0:-2] == SYSEX_START + (7,) and midi_bytes[-2] != 0: + self._has_sliders = midi_bytes[-2] != 25 + self.schedule_message(1, self._show_startup_message) + for control in self.controls: + if isinstance(control, InputControlElement): + control.clear_send_cache() + + 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) + for index in range(len(self._sliders)): + self._mixer.channel_strip(index).set_volume_control(None) + slider = self._sliders[index] + slider.release_parameter() + if slider.value_has_listener(self._slider_value): + slider.remove_value_listener(self._slider_value) + + self._encoder_modes.set_provide_volume_mode(not self._has_sliders) + self.request_rebuild_midi_map() + + def disconnect(self): + self.log('starting disconnect 1') + self._name_display_data_source.set_display_string(' ') + for encoder in self._encoders: + encoder.remove_value_listener(self._encoder_value) + + self._master_slider.remove_value_listener(self._slider_value) + if self._has_sliders: + for slider in tuple(self._sliders): + slider.remove_value_listener(self._slider_value) + + for button in self._strip_buttons: + button.remove_value_listener(self._mixer_button_value) + + self._preview_button.remove_value_listener(self._preview_value) + self.log('starting disconnect 3') + ControlSurface.disconnect(self) + self.log('starting disconnect 3') + self._encoders = None + self._sliders = None + self._strip_buttons = None + self._master_slider = None + self._current_midi_map = None + self._name_display = None + self._prev_bank_button = None + self._next_bank_button = None + self._encoder_modes = None + self._transport_view_modes = None + self.log('starting disconnect 4') + self._send_midi(SYSEX_START + (6, 0, 0, 0, 247)) + self.log('starting disconnect 5') + + if self._shift_button != None: + self._shift_button.remove_value_listener(self._shift_value) + self._shift_button = None + self.log('starting disconnect 6') + + 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._string_to_display != None: + self._name_display_data_source.set_display_string(self._string_to_display) + self._string_to_display = None + 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): + mute_solo_flip_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 34) + self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 37) + self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 38) + self._strip_buttons = [] + mute_solo_flip_button.name = 'Mute_Solo_Flip_Button' + self._next_nav_button.name = 'Next_Track_Button' + self._prev_nav_button.name = 'Prev_Track_Button' + self._mixer = SpecialMixerComponent(8, self.c_instance) + self._mixer.name = 'Mixer' + 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, 0, 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, 0, 9 + 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.master_strip().set_mute_button(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 17)) + self._mixer.set_strip_mute_solo_buttons(tuple(self._strip_buttons), mute_solo_flip_button) + #self._mixer.set_shift_button(self._shift_button) + self._mixer.updateMixerButtons() + + self._button9 = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 9 + 8) + + def _setup_session(self): + num_pads = len(PAD_TRANSLATIONS) + self._session = SessionComponent(8, 0) + self._session.name = 'Session_Control' + self._session.selected_scene().name = 'Selected_Scene' + self._session.set_mixer(self._mixer) + self._session.set_track_banking_increment(num_pads) + self._session.set_track_bank_buttons(ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 35), ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 36)) + pads = [] + for index in range(num_pads): + pads.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index)) + pads[-1].name = 'Pad_' + str(index) + clip_slot = self._session.selected_scene().clip_slot(index) + clip_slot.set_triggered_to_play_value(GREEN_BLINK) + clip_slot.set_triggered_to_record_value(RED_BLINK) + clip_slot.set_stopped_value(AMBER_FULL) + clip_slot.set_started_value(GREEN_FULL) + clip_slot.set_recording_value(RED_FULL) + clip_slot.set_launch_button(pads[-1]) + clip_slot.name = str(index) + '_Selected_Clip_Slot' + + def _setup_transport(self): + rwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 27) + ffwd_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 28) + stop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 29) + play_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 30) + loop_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 31) + rec_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 32) + 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' + self._transport = ShiftableTransportComponent(self.c_instance,self._session, self) + self._transport.name = 'Transport' + self._transport.set_stop_buttonOnInit(stop_button) + self._transport.set_play_button(play_button) + self._transport.set_record_buttonOnInit(rec_button) +# self._transport.set_shift_button(self._shift_button) + self._transport.set_mixer9_button(self._button9) + self._transport_view_modes = TransportViewModeSelector(self._transport, self._session, ffwd_button, rwd_button, loop_button) + self._transport_view_modes.name = 'Transport_View_Modes' + + def _setup_device(self): + encoders = [] + for index in range(8): + encoders.append(PeekableEncoderElement(MIDI_CC_TYPE, 1, index, Live.MidiMap.MapMode.relative_binary_offset)) + encoders[-1].set_feedback_delay(-1) + encoders[-1].add_value_listener(self._encoder_value, identify_sender=True) + encoders[-1].name = 'Device_Control_' + str(index) + + self._encoders = tuple(encoders) + self._prev_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 12) + self._next_bank_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 1, 11) + self._prev_bank_button.name = 'Device_Bank_Down_Button' + self._next_bank_button.name = 'Device_Bank_Up_Button' + device = DeviceComponent() + device.name = 'Device_Component' + self.set_device_component(device) + device.set_parameter_controls(self._encoders) + device.set_bank_nav_buttons(self._prev_bank_button, self._next_bank_button) + + def _setup_name_display(self): + self._name_display = PhysicalDisplayElement(16, 1) + self._name_display.name = '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) + + 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 + display_string = '' + if self._device_component.is_enabled(): +# display_string = sender.name +# track = self.song().view.selected_track +# display_string = str(list(tracks).index(track) + 1) + pass + if (sender.mapped_parameter() != None): +# display_string = display_string + '-' + display_string = display_string + sender.mapped_parameter().name + self._set_string_to_display(display_string) + + def _slider_value(self, value, sender): + self.log ('_slider_value ' + str(value) + ' ' +str(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 = ' - ' + master = self.song().master_track + tracks = self.song().tracks + returns = self.song().return_tracks + track = None + if sender.mapped_parameter() != None: + self.log ('1') + if sender == self._master_slider: + self.log ('2') +# track = self._has_sliders and master + if self._has_sliders: + track = master + else: + self.log ('2.1') + track = self.song().view.selected_track + else: + self.log ('3') + track = self._mixer.channel_strip(self._sliders.index(sender))._track + else: + self.log ('4') + track = self.song().view.selected_track + self.log('track='+str(track)) + if track == master: + display_string = 'Master' + 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 + raise AssertionError + display_string += ' Volume' + self._set_string_to_display(display_string) + + def _mixer_button_value(self, value, sender): + if not value in range(128): + raise AssertionError + #if self._mixer.is_enabled() and value > 0: + if self._mixer.is_enabled(): + strip = self._mixer.channel_strip(self._strip_buttons.index(sender)) + #self._string_to_display = strip != None and None + self._name_display.segment(0).set_data_source(strip.track_name_data_source()) + self._name_display.update() + self._display_reset_delay = STANDARD_DISPLAY_DELAY + else: + self._set_string_to_display(' - ') + + def _preview_value(self, value): + if not value in range(128): + raise AssertionError + for encoder in self._encoders: + encoder.set_peek_mode(value > 0) + + def _show_current_track_name(self): + if self._name_display != None and self._mixer != None: + self._string_to_display = None + self._name_display.segment(0).set_data_source(self._mixer.selected_strip().track_name_data_source()) + self._name_display.update() + + def _show_startup_message(self): + self._name_display.display_message('LIVE') + self._display_reset_delay = INITIAL_DISPLAY_DELAY + + def _set_string_to_display(self, string_to_display): + if not isinstance(string_to_display, (str, unicode)): + raise AssertionError + self._name_display.segment(0).set_data_source(self._name_display_data_source) + self._string_to_display = string_to_display + self._display_reset_delay = STANDARD_DISPLAY_DELAY + + def _on_selected_track_changed(self): + self.log('_on_selected_track_changed') + ControlSurface._on_selected_track_changed(self) + self._show_current_track_name() + #all_tracks = self._has_sliders or self._session.tracks_to_use() + all_tracks2 = self._session.tracks_to_use() + selected_track = self.song().view.selected_track + num_strips = self._session.width() + if selected_track in all_tracks2: + track_index = list(all_tracks2).index(selected_track) + self.log('track_index '+ str(track_index)) + new_offset = track_index - track_index % num_strips + self.log('new_offset '+ str(new_offset)) + if not new_offset / num_strips == int(new_offset / num_strips): + raise AssertionError + self._session.set_offsets(new_offset, self._session.scene_offset()) + + + def _shift_value(self, value): + self.log("root shift handler") + if not self._shift_button != None: + raise AssertionError + if not value in range(128): + raise AssertionError + self.log("root shift handler 2") + self._shift_pressed = value > 0 +# calling other handlers + self._mixer._shift_value(value) + self._transport._shift_value(value) + +#clip stop + self.log("root shift handler 3") + num_pads = len(PAD_TRANSLATIONS) + pads = [] + for index in range(num_pads): + pads.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index)) + pads[-1].name = 'Pad_' + str(index) + clip_slot = self._session.selected_scene().clip_slot(index) + if self._shift_pressed: + clip_slot.set_launch_button(None) + else: + clip_slot.set_launch_button(pads[index]) + if self._shift_pressed: + self._session.set_stop_track_clip_buttons(tuple(pads)) + else: + self._session.set_stop_track_clip_buttons(None) + + self.log("root shift handler 4") + + def log(self, message): + pass +# self.c_instance.log_message(message) diff --git a/Novation_Impulse2_9_1/PeekableEncoderElement.py b/Novation_Impulse2_9_1/PeekableEncoderElement.py new file mode 100644 index 00000000..14569cf1 --- /dev/null +++ b/Novation_Impulse2_9_1/PeekableEncoderElement.py @@ -0,0 +1,27 @@ +#Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/Novation_Impulse/PeekableEncoderElement.py +import Live +from _Framework.EncoderElement import EncoderElement +from _Framework.InputControlElement import * + +class PeekableEncoderElement(EncoderElement): + """ Encoder that can be connected and disconnected to a specific parameter """ + + def __init__(self, msg_type, channel, identifier, map_mode): + EncoderElement.__init__(self, msg_type, channel, identifier, map_mode) + self._peek_mode = False + + def set_peek_mode(self, peek_mode): + if not isinstance(peek_mode, type(False)): + raise AssertionError + self._peek_mode = self._peek_mode != peek_mode and peek_mode + self._request_rebuild() + + def get_peek_mode(self): + return self._peek_mode + + def install_connections(self, install_translation_callback, install_mapping_callback, install_forwarding_callback): + current_parameter = self._parameter_to_map_to + if self._peek_mode: + self._parameter_to_map_to = None + InputControlElement.install_connections(self, install_translation_callback, install_mapping_callback, install_forwarding_callback) + self._parameter_to_map_to = current_parameter \ No newline at end of file diff --git a/Novation_Impulse2_9_1/ShiftableTransportComponent.py b/Novation_Impulse2_9_1/ShiftableTransportComponent.py new file mode 100644 index 00000000..c12bd282 --- /dev/null +++ b/Novation_Impulse2_9_1/ShiftableTransportComponent.py @@ -0,0 +1,133 @@ +#Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/Novation_Impulse/ShiftableTransportComponent.py +import Live +from _Framework.ButtonElement import ButtonElement +from _Framework.TransportComponent import TransportComponent +from _Framework.ToggleComponent import ToggleComponent + +class ShiftableTransportComponent(TransportComponent): + """ Special transport class handling the seek buttons differently based on a shift button""" + + def __init__(self, c_instance, session, parent): + TransportComponent.__init__(self) + self.c_instance = c_instance + self._shift_pressed = False + self._mixer9_button = None + self._play_button = None + self._record_button = None + self._session = session + self._parent = parent + song = self.song() +# self._automation_toggle= self.register_component(ToggleComponent('session_automation_record', song)) + self._automation_toggle, self._re_enable_automation_toggle, self._delete_automation = self.register_components(ToggleComponent('session_automation_record', song), ToggleComponent('re_enable_automation_enabled', song, read_only=True), ToggleComponent('has_envelopes', None, read_only=True)) + + + + def disconnect(self): + if self._play_button != None: + self._play_button.remove_value_listener(self._play_pressed) + self._play_button = None + + TransportComponent.disconnect(self) + + def set_stop_buttonOnInit(self, button): + self.log("set_stop_buttonOnInit 1") + self._stop_button = button + self.set_stop_button(self._stop_button) + self.log("set_stopbuttonOnInit 2") + + + def set_record_buttonOnInit(self, button): + self.log("set_record_buttonOnInit 1") + self._record_button = button + self.set_record_button(self._record_button) + self.log("set_record_buttonOnInit 2") + + def set_mixer9_button(self, button): + self.log("set_mixer9_button 1") + self._mixer9_button = button + self.set_overdub_button(self._mixer9_button) + #self._automation_toggle.set_toggle_button(self._mixer9_button) + self.log("set_mixer9_button 2") + + + def set_play_button(self, button): + self._play_button = button + self._play_button.add_value_listener(self._play_pressed) + self._play_toggle.set_toggle_button(button) + + def _play_pressed(self, value): + self.log("_play_pressed " + str(value)) + if not value in range(128): + raise AssertionError + if self._shift_pressed: + if value != 0: + if self.song().can_undo: + #todo: add message + self.song().undo() + self.log("undoing") + self._parent._set_string_to_display('undoing') + + else: + #todo: add message + self._parent._set_string_to_display('cannot undo') + + + def _shift_value(self, value): + self.log("shift handler transport component " + str(value)) + if not value in range(128): + raise AssertionError + self.log("shift handler 2") + self._shift_pressed = self.is_enabled() and value > 0 + self.log("shift handler 3") + if self._shift_pressed: + self._play_toggle.set_toggle_button(None) + self._session.set_stop_all_clips_button(self._stop_button) + self.set_stop_button(None) + self.set_overdub_button(None) + self._automation_toggle.set_toggle_button(self._mixer9_button) + self.set_metronome_button(self._record_button) + self.set_record_button(None) + else: + self._play_toggle.set_toggle_button(self._play_button) + self._session.set_stop_all_clips_button(None) + self.set_stop_button(self._stop_button) + self.set_overdub_button(self._mixer9_button) + self._automation_toggle.set_toggle_button(None) + self.set_metronome_button(None) + self.set_record_button(self._record_button) + self.log("shift handler 4") + + + + def _ffwd_value(self, value): + self.log("ffwd handler main") + if not self._ffwd_button != None: + raise AssertionError + if not value in range(128): + raise AssertionError + else: + if self._shift_pressed: + self.log("ffwd shifted handler") + self.song().current_song_time = self._shift_pressed and self.song().last_event_time + else: + self.log("ffwd normal handler") + TransportComponent._ffwd_value(self, value) + + def _rwd_value(self, value): + self.log("rwd handler main") + if not self._rwd_button != None: + raise AssertionError + if not value in range(128): + raise AssertionError + else: + if self._shift_pressed: + self.song().current_song_time = self._shift_pressed and 0.0 + self.log("rwd shifted handler") + else: + self.log("rwd normal handler") + TransportComponent._rwd_value(self, value) + + def log(self, message): + pass +# self.c_instance.log_message(message) + diff --git a/Novation_Impulse2_9_1/SpecialMixerComponent.py b/Novation_Impulse2_9_1/SpecialMixerComponent.py new file mode 100644 index 00000000..5364732b --- /dev/null +++ b/Novation_Impulse2_9_1/SpecialMixerComponent.py @@ -0,0 +1,149 @@ +#Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/Novation_Impulse/SpecialMixerComponent.py +from _Framework.MixerComponent import MixerComponent +from _Framework.ButtonElement import ButtonElement + +class SpecialMixerComponent(MixerComponent): + """ Special mixer class that reassigns buttons to mute or solo based on a toggle """ + + def __init__(self, num_tracks, c_instance): + self.c_instance = c_instance + self._selected_mute_solo_button = None + self._strip_mute_solo_buttons = None + self._mute_solo_flip_button = None + MixerComponent.__init__(self, num_tracks) + self._selected_tracks = [] + self._register_timer_callback(self._on_timer) + self._shift_pressed = False + self._mute_solo_raw_value = 127 + + + def disconnect(self): + self._unregister_timer_callback(self._on_timer) + self._selected_tracks = None + MixerComponent.disconnect(self) + #if self._shift_button != None: + # self._shift_button.remove_value_listener(self._shift_value) + # self._shift_button = None + if self._mute_solo_flip_button != None: + self._mute_solo_flip_button.remove_value_listener(self._mute_solo_flip_value) + self._mute_solo_flip_button = None + self._selected_mute_solo_button = None + self._strip_mute_solo_buttons = None + + def set_strip_mute_solo_buttons(self, buttons, flip_button): + self.log("set_strip_mute_solo_buttons") + if not (buttons is None or isinstance(buttons, tuple) and len(buttons) == len(self._channel_strips)): + raise AssertionError + if not isinstance(flip_button, (type(None), ButtonElement)): + raise AssertionError + self._mute_solo_flip_button = flip_button + self._strip_mute_solo_buttons = buttons + if self._mute_solo_flip_button != None: + self._mute_solo_flip_button.remove_value_listener(self._mute_solo_flip_value) + if self._mute_solo_flip_button != None: + self._mute_solo_flip_button.add_value_listener(self._mute_solo_flip_value) + for index in range(len(self._channel_strips)): + strip = self.channel_strip(index) + button = None + if self._strip_mute_solo_buttons != None: + button = self._strip_mute_solo_buttons[index] + strip.set_mute_button(button) + strip.set_solo_button(None) + + def tracks_to_use(self): + return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) + + def _shift_value(self, value): + self.log("calling mixer shift value " + str(value)) + if (value > 0): + self._shift_pressed = True + else: + self._shift_pressed = False + self.updateMixerButtons() + pass + return + + def _mute_solo_flip_value(self, value): + #self.log(value) + if not self._mute_solo_flip_button != None: + raise AssertionError + if not value in range(128): + raise AssertionError + self._mute_solo_raw_value = value + self.updateMixerButtons() + + + def updateMixerButtons(self): + self.log("updateMixerButtons") + if self._strip_mute_solo_buttons != None: + for index in range(len(self._strip_mute_solo_buttons)): + strip = self.channel_strip(index) + self.log("setting strip") + if self._shift_pressed: + strip.set_mute_button(None) + strip.set_solo_button(None) + strip.set_arm_button(self._strip_mute_solo_buttons[index]) + else: + if self._mute_solo_raw_value == 0: + strip.set_mute_button(None) + strip.set_solo_button(self._strip_mute_solo_buttons[index]) + strip.set_arm_button(None) + else: + strip.set_solo_button(None) + strip.set_mute_button(self._strip_mute_solo_buttons[index]) + strip.set_arm_button(None) + + def _on_timer(self): +# self.log("_on_timer") + sel_track = None + while len(self._selected_tracks) > 0: + track = self._selected_tracks[-1] + if track != None and track.has_midi_input and track.can_be_armed and not track.arm: + sel_track = track + break + del self._selected_tracks[-1] + + if sel_track != None: + found_recording_clip = False + song = self.song() + tracks = song.tracks + if song.is_playing: + check_arrangement = song.record_mode + for track in tracks: + if track.can_be_armed and track.arm: + if check_arrangement: + found_recording_clip = True + break + else: + playing_slot_index = track.playing_slot_index + if playing_slot_index in range(len(track.clip_slots)): + slot = track.clip_slots[playing_slot_index] + if slot.has_clip and slot.clip.is_recording: + found_recording_clip = True + break + + if found_recording_clip or song.exclusive_arm: + for track in tracks: + if track.can_be_armed and track.arm and track != sel_track: + track.arm = False + + sel_track.arm = True + sel_track.view.select_instrument() + self._selected_tracks = [] +# self.updateMixerButtons() + + def _next_track_value(self, value): + self.log("_next_track_value "+ str(value)) + MixerComponent._next_track_value(self, value) + self._selected_tracks.append(self.song().view.selected_track) + self.updateMixerButtons() + + def _prev_track_value(self, value): + self.log("_prev_track_value " + str(value)) + MixerComponent._prev_track_value(self, value) + self._selected_tracks.append(self.song().view.selected_track) + self.updateMixerButtons() + + def log(self, message): + pass +# self.c_instance.log_message(message) diff --git a/Novation_Impulse2_9_1/TransportViewModeSelector.py b/Novation_Impulse2_9_1/TransportViewModeSelector.py new file mode 100644 index 00000000..63db9307 --- /dev/null +++ b/Novation_Impulse2_9_1/TransportViewModeSelector.py @@ -0,0 +1,58 @@ +#Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/Novation_Impulse/TransportViewModeSelector.py +import Live +from _Framework.ModeSelectorComponent import ModeSelectorComponent +from _Framework.ButtonElement import ButtonElement +from _Framework.TransportComponent import TransportComponent +from _Framework.SessionComponent import SessionComponent + +class TransportViewModeSelector(ModeSelectorComponent): + """ Class that reassigns specific buttons based on the views visible in Live """ + + def __init__(self, transport, session, ffwd_button, rwd_button, loop_button): + if not isinstance(transport, TransportComponent): + raise AssertionError + if not isinstance(session, SessionComponent): + raise AssertionError + if not isinstance(ffwd_button, ButtonElement): + raise AssertionError + if not isinstance(rwd_button, ButtonElement): + raise AssertionError + if not isinstance(loop_button, ButtonElement): + raise AssertionError + ModeSelectorComponent.__init__(self) + self._transport = transport + self._session = session + self._ffwd_button = ffwd_button + self._rwd_button = rwd_button + self._loop_button = loop_button + self.application().view.add_is_view_visible_listener('Session', self._on_view_changed) + self.update() + + def disconnect(self): + ModeSelectorComponent.disconnect(self) + self._transport = None + self._session = None + self._ffwd_button = None + self._rwd_button = None + self._loop_button = None + self.application().view.remove_is_view_visible_listener('Session', self._on_view_changed) + + def update(self): + if self.is_enabled(): + if self._mode_index == 0: + self._transport.set_seek_buttons(self._ffwd_button, self._rwd_button) + self._transport.set_loop_button(self._loop_button) + self._session.set_select_buttons(None, None) + self._session.selected_scene().set_launch_button(None) + else: + self._transport.set_seek_buttons(None, None) + self._transport.set_loop_button(None) + self._session.set_select_buttons(self._ffwd_button, self._rwd_button) + self._session.selected_scene().set_launch_button(self._loop_button) + + def _on_view_changed(self): + if self.application().view.is_view_visible('Session'): + self._mode_index = 1 + else: + self._mode_index = 0 + self.update() \ No newline at end of file diff --git a/Novation_Impulse2_9_1/__init__.py b/Novation_Impulse2_9_1/__init__.py new file mode 100644 index 00000000..2ff28270 --- /dev/null +++ b/Novation_Impulse2_9_1/__init__.py @@ -0,0 +1,12 @@ +#Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/Novation_Impulse/__init__.py +from Novation_Impulse2 import Novation_Impulse2 + +def create_instance(c_instance): + return Novation_Impulse2(c_instance) + + +from _Framework.Capabilities import * + +def get_capabilities(): + return {CONTROLLER_ID_KEY: controller_id(vendor_id=4661, product_ids=[25], model_name='Impulse 25'), + PORTS_KEY: [inport(props=[NOTES_CC, REMOTE, SCRIPT]), inport(props=[NOTES_CC, REMOTE]), outport(props=[NOTES_CC, REMOTE, SCRIPT])]} \ No newline at end of file diff --git a/Novation_Impulse2_9_1/debug.bat b/Novation_Impulse2_9_1/debug.bat new file mode 100644 index 00000000..c95dcf34 --- /dev/null +++ b/Novation_Impulse2_9_1/debug.bat @@ -0,0 +1,7 @@ +rem C:\Documents and Settings\%username%\Application Data\Ableton\Live 8.x.x\Preferences\Log.txt +rem cd "C:\Documents and Settings\%username%\Application Data\Ableton\Live 9.1\Preferences\" + +cd "C:\Documents and Settings\mbakirov\Application Data\Ableton\Live 9.1.2\Preferences\" + + +rem http://remotescripts.blogspot.com.au/2010_03_01_archive.html \ No newline at end of file diff --git a/Novation_Impulse2_9_1/deploy.bat b/Novation_Impulse2_9_1/deploy.bat new file mode 100644 index 00000000..9041931a --- /dev/null +++ b/Novation_Impulse2_9_1/deploy.bat @@ -0,0 +1,2 @@ +del /Q "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" +xcopy *.py "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" \ No newline at end of file diff --git a/Novation_Impulse2_9_1/readme.txt b/Novation_Impulse2_9_1/readme.txt new file mode 100644 index 00000000..6a1c9ae6 --- /dev/null +++ b/Novation_Impulse2_9_1/readme.txt @@ -0,0 +1,59 @@ +Features + +Mixer button 9 = OverDub +Shift + Mixer button 9 = Automation record on/off +Shift + Rec = Metronome on/off + +Shift + PLay = Undo +Shift + Stop = Stop all clips + +Shift + track mixer button = rec this track.. + +Shift + Clip buttons are now clip stop. + + + +Known issues that cannot be fixed +1) After moving track with Shift+Track buttons are not returned to inital condition. + Also happens sometimes in other cases (like bank switching with Shift). + Workaround - press and release Shit again. +2) Pressin shift + (mutes/solos) flip button leds to unpredictable results. + Workaround - do not do that, if you have done that, just press and release shift. + +The reason for these problems is that when you use shift+track or shift+bank, the message "shift off" is not sent. +This is out of the scope of what I can do. The bug report is sent to Novation. + +Known issues and todo: +FIXED: 1) impulse does not disconnect properly and does not send disconnection message. +FIXED 1.5) refactor shift - move it to main class. +FIXED: 2)when track goes down, the bank is not changed. +3) on initialize mute/solo buttons do not light + workaround - press shift button. +4) when arming a single track make the track selected + + +Future things to implement. + +DONE 1) mixer9 - overdub +DONE 3) Shift + Stop - stop all clips. + + +FIXED:4) Shift+Mixer9 - Automation record on/off +4.5) Shift + Rec = metronome +5) Shift + Loop switch session/arrangement (as loop is the button that also changes in this case) +FIXED: 6) Shift + play Undo (as play is like backspace but turned opposite) + +DONE: another parallel feature - Shift + drum pad in clip mode - stop the selected clip. + +think of re-mapping drum pads for another notes. + +7) display messages, when + metronome on/off + undo + switch session/arrangement + overdub + automation arm + +2) Shift + Mixer 9 - automation arm (seems to be rather hard - not sure there is API for that) + + From 9bf5bcb4aa5f08f774e6c4944660e50e0bf7349b Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sat, 12 Apr 2014 03:01:40 +1000 Subject: [PATCH 25/45] device bavigation buttons --- Novation_Impulse2/Novation_Impulse2.py | 2 +- .../ShiftableTransportComponent.py | 35 ++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index f1fdb39f..285405ba 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -232,7 +232,7 @@ def _setup_transport(self): play_button.name = 'Play_Button' stop_button.name = 'Stop_Button' rec_button.name = 'Record_Button' - self._transport = ShiftableTransportComponent(self.c_instance,self._session, self) + self._transport = ShiftableTransportComponent(self.c_instance,self._session, self, ffwd_button, rwd_button) self._transport.name = 'Transport' self._transport.set_stop_buttonOnInit(stop_button) self._transport.set_play_button(play_button) diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index c12bd282..c808e933 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -1,5 +1,6 @@ #Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/Novation_Impulse/ShiftableTransportComponent.py import Live +NavDirection = Live.Application.Application.View.NavDirection from _Framework.ButtonElement import ButtonElement from _Framework.TransportComponent import TransportComponent from _Framework.ToggleComponent import ToggleComponent @@ -7,7 +8,7 @@ class ShiftableTransportComponent(TransportComponent): """ Special transport class handling the seek buttons differently based on a shift button""" - def __init__(self, c_instance, session, parent): + def __init__(self, c_instance, session, parent, ffwd_button, rwd_button): TransportComponent.__init__(self) self.c_instance = c_instance self._shift_pressed = False @@ -16,6 +17,8 @@ def __init__(self, c_instance, session, parent): self._record_button = None self._session = session self._parent = parent + self._ffwd_button = ffwd_button + self._rwd_button = rwd_button song = self.song() # self._automation_toggle= self.register_component(ToggleComponent('session_automation_record', song)) self._automation_toggle, self._re_enable_automation_toggle, self._delete_automation = self.register_components(ToggleComponent('session_automation_record', song), ToggleComponent('re_enable_automation_enabled', song, read_only=True), ToggleComponent('has_envelopes', None, read_only=True)) @@ -87,6 +90,7 @@ def _shift_value(self, value): self._automation_toggle.set_toggle_button(self._mixer9_button) self.set_metronome_button(self._record_button) self.set_record_button(None) + else: self._play_toggle.set_toggle_button(self._play_button) self._session.set_stop_all_clips_button(None) @@ -95,12 +99,12 @@ def _shift_value(self, value): self._automation_toggle.set_toggle_button(None) self.set_metronome_button(None) self.set_record_button(self._record_button) + self.log("shift handler 4") - def _ffwd_value(self, value): - self.log("ffwd handler main") + self.log("ffwd handler main" + str(value)) if not self._ffwd_button != None: raise AssertionError if not value in range(128): @@ -108,26 +112,41 @@ def _ffwd_value(self, value): else: if self._shift_pressed: self.log("ffwd shifted handler") - self.song().current_song_time = self._shift_pressed and self.song().last_event_time +# self.song().current_song_time = self.song().last_event_time + if value == 1: + self._scroll_device_chain(NavDirection.right) else: self.log("ffwd normal handler") TransportComponent._ffwd_value(self, value) def _rwd_value(self, value): - self.log("rwd handler main") + self.log("rwd handler main" + str(value)) if not self._rwd_button != None: raise AssertionError if not value in range(128): raise AssertionError else: if self._shift_pressed: - self.song().current_song_time = self._shift_pressed and 0.0 self.log("rwd shifted handler") +# self.song().current_song_time = 0.0 + if value == 1: + self._scroll_device_chain(NavDirection.left) else: self.log("rwd normal handler") TransportComponent._rwd_value(self, value) + + def _scroll_device_chain(self, direction): + self.log("_scroll_device_chain 1") + view = self._parent.application().view + self.log("_scroll_device_chain 2") + if not view.is_view_visible('Detail') or not view.is_view_visible('Detail/DeviceChain'): + view.show_view('Detail') + view.show_view('Detail/DeviceChain') + else: + view.scroll_view(direction, 'Detail/DeviceChain', False) + def log(self, message): - pass -# self.c_instance.log_message(message) +# pass + self.c_instance.log_message(message) From 99e8d19fc948c4e58c38615b699d84cc5b945ccf Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sat, 12 Apr 2014 03:36:25 +1000 Subject: [PATCH 26/45] shift + fwf/ back buttons - device selector --- Novation_Impulse2/Novation_Impulse2.py | 3 +- .../ShiftableTransportComponent.py | 4 +-- .../TransportViewModeSelector.py | 34 +++++++++++++++---- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 285405ba..91937e31 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -239,7 +239,7 @@ def _setup_transport(self): self._transport.set_record_buttonOnInit(rec_button) # self._transport.set_shift_button(self._shift_button) self._transport.set_mixer9_button(self._button9) - self._transport_view_modes = TransportViewModeSelector(self._transport, self._session, ffwd_button, rwd_button, loop_button) + self._transport_view_modes = TransportViewModeSelector(self.c_instance,self._transport, self._session, ffwd_button, rwd_button, loop_button) self._transport_view_modes.name = 'Transport_View_Modes' def _setup_device(self): @@ -392,6 +392,7 @@ def _shift_value(self, value): # calling other handlers self._mixer._shift_value(value) self._transport._shift_value(value) + self._transport_view_modes._shift_value(value) #clip stop self.log("root shift handler 3") diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index c808e933..463f15d4 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -147,6 +147,6 @@ def _scroll_device_chain(self, direction): view.scroll_view(direction, 'Detail/DeviceChain', False) def log(self, message): -# pass - self.c_instance.log_message(message) + pass +# self.c_instance.log_message(message) diff --git a/Novation_Impulse2/TransportViewModeSelector.py b/Novation_Impulse2/TransportViewModeSelector.py index 63db9307..98ba871b 100644 --- a/Novation_Impulse2/TransportViewModeSelector.py +++ b/Novation_Impulse2/TransportViewModeSelector.py @@ -8,7 +8,7 @@ class TransportViewModeSelector(ModeSelectorComponent): """ Class that reassigns specific buttons based on the views visible in Live """ - def __init__(self, transport, session, ffwd_button, rwd_button, loop_button): + def __init__(self, c_instance, transport, session, ffwd_button, rwd_button, loop_button): if not isinstance(transport, TransportComponent): raise AssertionError if not isinstance(session, SessionComponent): @@ -20,11 +20,13 @@ def __init__(self, transport, session, ffwd_button, rwd_button, loop_button): if not isinstance(loop_button, ButtonElement): raise AssertionError ModeSelectorComponent.__init__(self) + self.c_instance = c_instance self._transport = transport self._session = session self._ffwd_button = ffwd_button self._rwd_button = rwd_button self._loop_button = loop_button + self._shift_pressed = False self.application().view.add_is_view_visible_listener('Session', self._on_view_changed) self.update() @@ -39,20 +41,40 @@ def disconnect(self): def update(self): if self.is_enabled(): + self.log("transportviewselctor_update ") if self._mode_index == 0: - self._transport.set_seek_buttons(self._ffwd_button, self._rwd_button) self._transport.set_loop_button(self._loop_button) - self._session.set_select_buttons(None, None) self._session.selected_scene().set_launch_button(None) else: - self._transport.set_seek_buttons(None, None) self._transport.set_loop_button(None) - self._session.set_select_buttons(self._ffwd_button, self._rwd_button) self._session.selected_scene().set_launch_button(self._loop_button) + # hack as we have nadler for fwd that changes devices + if self._mode_index == 0 or self._shift_pressed: + self._transport.set_seek_buttons(self._ffwd_button, self._rwd_button) + self._session.set_select_buttons(None, None) + else: + self._transport.set_seek_buttons(None, None) + self._session.set_select_buttons(self._ffwd_button, self._rwd_button) def _on_view_changed(self): if self.application().view.is_view_visible('Session'): self._mode_index = 1 else: self._mode_index = 0 - self.update() \ No newline at end of file + self.update() + + + def _shift_value(self, value): + self.log("shift handler transport component " + str(value)) + if not value in range(128): + raise AssertionError + self.log("shift handler 2") + self._shift_pressed = self.is_enabled() and value > 0 + self.update() + self.log("shift handler 3") + + + def log(self, message): + pass +# self.c_instance.log_message(message) + From 65d08fd4ccdadd8366eca6f3c0fa7932516147bf Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Sat, 12 Apr 2014 03:37:22 +1000 Subject: [PATCH 27/45] readme --- Novation_Impulse2/readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 4da731d3..bc076d42 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -19,6 +19,7 @@ Shift + track mixer button = rec this track.. Shift + Clip buttons are now clip stop. +Shift + Ffwd/Back - next/previous device Known issues that cannot be fixed From 1897b68b65cd7d0702c1b6a5d7831f6c6f7baa8a Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 2 Oct 2016 22:31:30 +0800 Subject: [PATCH 28/45] updated to visual studio 2015 --- .vs/AbletonRemoteScripts/v14/.suo | Bin 0 -> 22016 bytes AbletonRemoteScripts.pyproj | 8 ++++++-- AbletonRemoteScripts.sln | 4 ++-- Backup/AbletonRemoteScripts.sln | 22 ++++++++++++++++++++++ UpgradeLog.htm | Bin 0 -> 35552 bytes 5 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 .vs/AbletonRemoteScripts/v14/.suo create mode 100644 Backup/AbletonRemoteScripts.sln create mode 100644 UpgradeLog.htm diff --git a/.vs/AbletonRemoteScripts/v14/.suo b/.vs/AbletonRemoteScripts/v14/.suo new file mode 100644 index 0000000000000000000000000000000000000000..9706accf40955b5291ce9b3ec60c43a73f32249d GIT binary patch literal 22016 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 literal 0 HcmV?d00001 diff --git a/AbletonRemoteScripts.pyproj b/AbletonRemoteScripts.pyproj index 6011b275..b75d2111 100644 --- a/AbletonRemoteScripts.pyproj +++ b/AbletonRemoteScripts.pyproj @@ -1,5 +1,5 @@  - + Debug 2.0 @@ -15,6 +15,9 @@ + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets + @@ -137,5 +140,6 @@ - + + \ No newline at end of file diff --git a/AbletonRemoteScripts.sln b/AbletonRemoteScripts.sln index 2173f144..7177b599 100644 --- a/AbletonRemoteScripts.sln +++ b/AbletonRemoteScripts.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "AbletonRemoteScripts", "AbletonRemoteScripts.pyproj", "{ED5FBFBF-4BE8-482D-B574-58DB3CD35247}" EndProject diff --git a/Backup/AbletonRemoteScripts.sln b/Backup/AbletonRemoteScripts.sln new file mode 100644 index 00000000..2173f144 --- /dev/null +++ b/Backup/AbletonRemoteScripts.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "AbletonRemoteScripts", "AbletonRemoteScripts.pyproj", "{ED5FBFBF-4BE8-482D-B574-58DB3CD35247}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ED5FBFBF-4BE8-482D-B574-58DB3CD35247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED5FBFBF-4BE8-482D-B574-58DB3CD35247}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED5FBFBF-4BE8-482D-B574-58DB3CD35247}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED5FBFBF-4BE8-482D-B574-58DB3CD35247}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/UpgradeLog.htm b/UpgradeLog.htm new file mode 100644 index 0000000000000000000000000000000000000000..712e88b5c2c3df59be49110ebd3f0562b9561cd8 GIT binary patch literal 35552 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 Dc-w?S literal 0 HcmV?d00001 From fceceb67e49d6ee04b01c46718ecc18587b6342f Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 2 Oct 2016 23:51:52 +0800 Subject: [PATCH 29/45] added selection of the armed track --- .vs/AbletonRemoteScripts/v14/.suo | Bin 22016 -> 50176 bytes Novation_Impulse2/Novation_Impulse2.py | 23 +++++++++++++++++++++ Novation_Impulse2/SpecialMixerComponent.py | 2 ++ Novation_Impulse2/debug.bat | 5 ++--- Novation_Impulse2/deploy.bat | 4 ++-- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/.vs/AbletonRemoteScripts/v14/.suo b/.vs/AbletonRemoteScripts/v14/.suo index 9706accf40955b5291ce9b3ec60c43a73f32249d..e6bcac88bb4581f49e25ea6addaeafc32e7144e5 100644 GIT binary patch delta 6880 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 AWB>pF delta 634 zcmZ8eO-LJ25YD`;B*xusG}RhSaVraoKeVA96IjrehzAqfQ)|Uzpn?ZOD}u0shf)I7 z9fbBI?AcP2J$VbnV-KaLf*^Pjdg`Uni`s7zx2+xcn3-?pee>o$_f6D2pq(6Pwfuc$ z9)5rE?kMw>Vv$J1(Rf2`P?CSDd7VILz!i+U)1$l|o#Up;awDf1rznWUfs5Tzs`nCI z2_)jhx+JcZKGE*7?Wq;hIa&J6BJ8PcS~-@c9wcoVnz}HL_oLET}A1iCx=b%eHl4M{ZP~&PR>b z;|%>ncP%1W0APHz`bfWn;4bi2^;wnb{nOO?`$=@-t^HZf6drPZ-wfV9eq{uW1Bd?XWTma&gf-sE diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 91937e31..9ce121bd 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -157,6 +157,7 @@ def update_display(self): self._show_current_track_name() def _setup_mixer(self): + self.log('setup mixer') mute_solo_flip_button = ButtonElement(not IS_MOMENTARY, MIDI_CC_TYPE, 0, 34) self._next_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 37) self._prev_nav_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 38) @@ -339,6 +340,28 @@ def _mixer_button_value(self, value, sender): self._display_reset_delay = STANDARD_DISPLAY_DELAY else: self._set_string_to_display(' - ') + if self._shift_pressed: + self.log_message("_mixer_button_value") + self.log_message(value) + if (value == 0): + self.select_armed_track_if_only_one() + + def select_armed_track_if_only_one(self): + self.log_message("select_armed_track_if_only_one") + song = self.song() + armed_tracks = [] + tracks = song.tracks + for track in tracks: + if track.can_be_armed and track.arm: + armed_tracks.append(track) + self.log_message(len(armed_tracks)) + if (len(armed_tracks) == 1): + self.log_message("selecting the track") + sel_track = armed_tracks[0] + self.song().view.selected_track = sel_track + self._mixer._selected_tracks = [] + self._mixer._selected_tracks.append(sel_track) + self._mixer.on_selected_track_changed() def _preview_value(self, value): if not value in range(128): diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index 5364732b..3fb8b1e4 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -7,6 +7,7 @@ class SpecialMixerComponent(MixerComponent): def __init__(self, num_tracks, c_instance): self.c_instance = c_instance + self.log("mixer.init") self._selected_mute_solo_button = None self._strip_mute_solo_buttons = None self._mute_solo_flip_button = None @@ -93,6 +94,7 @@ def updateMixerButtons(self): strip.set_mute_button(self._strip_mute_solo_buttons[index]) strip.set_arm_button(None) + def _on_timer(self): # self.log("_on_timer") sel_track = None diff --git a/Novation_Impulse2/debug.bat b/Novation_Impulse2/debug.bat index 4eaa6b3f..8b9035f0 100644 --- a/Novation_Impulse2/debug.bat +++ b/Novation_Impulse2/debug.bat @@ -1,7 +1,6 @@ rem C:\Documents and Settings\%username%\Application Data\Ableton\Live 8.x.x\Preferences\Log.txt -em cd "C:\Documents and Settings\%username%\Application Data\Ableton\Live 9.1\Preferences\" - -cd "C:\Documents and Settings\mbakirov\Application Data\Ableton\Live 9.1.2\Preferences\" +rem cd "C:\Documents and Settings\%username%\Application Data\Ableton\Live 9.1\Preferences\" +cd "C:\Documents and Settings\mbakirov\Application Data\Ableton\Live 9.5\Preferences" rem http://remotescripts.blogspot.com.au/2010_03_01_archive.html \ No newline at end of file diff --git a/Novation_Impulse2/deploy.bat b/Novation_Impulse2/deploy.bat index 9041931a..0261bea0 100644 --- a/Novation_Impulse2/deploy.bat +++ b/Novation_Impulse2/deploy.bat @@ -1,2 +1,2 @@ -del /Q "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" -xcopy *.py "D:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" \ No newline at end of file +del /Q "C:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" +xcopy *.py "C:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" \ No newline at end of file From 3de8c8469100e0cae81e637df1ddd77e9db1aa99 Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 16 Oct 2016 22:27:52 +0800 Subject: [PATCH 30/45] updated to the newer version of track select logic --- .vs/AbletonRemoteScripts/v14/.suo | Bin 50176 -> 59392 bytes Novation_Impulse2/SpecialMixerComponent.py | 36 ++++++++++----------- Novation_Impulse2/deploy.bat | 6 ++-- Novation_Impulse2/readme.txt | 8 ++++- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/.vs/AbletonRemoteScripts/v14/.suo b/.vs/AbletonRemoteScripts/v14/.suo index e6bcac88bb4581f49e25ea6addaeafc32e7144e5..d94e3127ad2399f59dbfb7f1283419c271493e42 100644 GIT binary patch delta 4408 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 CnUd!K diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index 3fb8b1e4..ca9111d9 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -63,7 +63,7 @@ def _shift_value(self, value): self.updateMixerButtons() pass return - + def _mute_solo_flip_value(self, value): #self.log(value) if not self._mute_solo_flip_button != None: @@ -96,7 +96,6 @@ def updateMixerButtons(self): def _on_timer(self): -# self.log("_on_timer") sel_track = None while len(self._selected_tracks) > 0: track = self._selected_tracks[-1] @@ -109,22 +108,22 @@ def _on_timer(self): found_recording_clip = False song = self.song() tracks = song.tracks - if song.is_playing: - check_arrangement = song.record_mode - for track in tracks: - if track.can_be_armed and track.arm: - if check_arrangement: - found_recording_clip = True - break - else: - playing_slot_index = track.playing_slot_index - if playing_slot_index in range(len(track.clip_slots)): - slot = track.clip_slots[playing_slot_index] - if slot.has_clip and slot.clip.is_recording: - found_recording_clip = True - break - - if found_recording_clip or song.exclusive_arm: + check_arrangement = song.is_playing and song.record_mode + for track in tracks: + if track.can_be_armed and track.arm: + if check_arrangement: + found_recording_clip = True + break + else: + playing_slot_index = track.playing_slot_index + if playing_slot_index in range(len(track.clip_slots)): + slot = track.clip_slots[playing_slot_index] + if slot.has_clip and slot.clip.is_recording: + found_recording_clip = True + break + + if not found_recording_clip: + if song.exclusive_arm: for track in tracks: if track.can_be_armed and track.arm and track != sel_track: track.arm = False @@ -132,7 +131,6 @@ def _on_timer(self): sel_track.arm = True sel_track.view.select_instrument() self._selected_tracks = [] -# self.updateMixerButtons() def _next_track_value(self, value): self.log("_next_track_value "+ str(value)) diff --git a/Novation_Impulse2/deploy.bat b/Novation_Impulse2/deploy.bat index 0261bea0..39e6a2ab 100644 --- a/Novation_Impulse2/deploy.bat +++ b/Novation_Impulse2/deploy.bat @@ -1,2 +1,4 @@ -del /Q "C:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" -xcopy *.py "C:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" \ No newline at end of file +del /Q "C:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" +xcopy *.py "C:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" +del /Q "C:\ProgramData\Ableton\Live 9 Suite 64\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" +xcopy *.py "C:\ProgramData\Ableton\Live 9 Suite 64\Resources\MIDI Remote Scripts\Novation_Impulse2\*.*" \ No newline at end of file diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index bc076d42..6a5f2deb 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -1,3 +1,8 @@ +Created by Marat Bakirov 2013-2016 +Marat branch is here: +https://github.com/maratbakirov/AbletonLive9_RemoteScripts + + IMPORTANT! since Ableton 9.1.2 some API has been changed @@ -26,6 +31,7 @@ Known issues that cannot be fixed 1) After moving track with Shift+Track buttons are not returned to inital condition. Also happens sometimes in other cases (like bank switching with Shift). Workaround - press and release Shit again. + update : seems to work fine with Nocation Firmware 695 and higher 2) Pressin shift + (mutes/solos) flip button leds to unpredictable results. Workaround - do not do that, if you have done that, just press and release shift. @@ -38,7 +44,7 @@ FIXED 1.5) refactor shift - move it to main class. FIXED: 2)when track goes down, the bank is not changed. 3) on initialize mute/solo buttons do not light workaround - press shift button. -4) when arming a single track make the track selected +FIXED: 4) when arming a single track make the track selected Future things to implement. From 94c2f28683a4634e1e76930dec5efa85fbffd0b8 Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 16 Oct 2016 23:56:10 +0800 Subject: [PATCH 31/45] added an "alternative" mode - for now it only features permanent arm mode --- .vs/AbletonRemoteScripts/v14/.suo | Bin 59392 -> 70144 bytes AbletonRemoteScripts.pyproj.user | 6 ++++ Novation_Impulse2/Novation_Impulse2.py | 23 +++++++++++-- Novation_Impulse2/SpecialMixerComponent.py | 7 ++-- .../TransportViewModeSelector.py | 27 +++++++++++---- Novation_Impulse2/readme.txt | 32 ++++++++++-------- 6 files changed, 68 insertions(+), 27 deletions(-) create mode 100644 AbletonRemoteScripts.pyproj.user diff --git a/.vs/AbletonRemoteScripts/v14/.suo b/.vs/AbletonRemoteScripts/v14/.suo index d94e3127ad2399f59dbfb7f1283419c271493e42..6607448c24de33ee12ab13efb5c85c98a513e743 100644 GIT binary patch delta 5349 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 H|4#c4>aX+v delta 3371 zcmc&%eNa@_6@T~fc6qz3xXOo!Aj?W%(FGO|#I3>t8)}fRC=z2GD<&AyF+#`+1qr)| zNz;rqu*aHdQWX}=Ok>5cFH^8JxG9#BX7B^kB!6V4aZKC%;i$yb7E-0>?DBLqb?kq+ zJHL77+;iS}@BZ#N=e~9H36AqYoyK^^aU75E4K2q-p%8?)Gcz+ob3p@7o?u<|f|K77 z+WptYqeDp(ESL<1(4uVNLm1rR%fxv&u?zt^y$(#g27Vg!8dCxj!t5AlMujFd0^@TF z5s3(zr`rTX!mJ*O*LcJNMBMBg`DsuV5pxiW5N1RyA{sFt5rd!?rXgQRj^sEymx0D4 zgaJ{2Sc)(r79&y+sfaX$36YM-M9^BY5ELXEuPbL|(pRIrEkMsjd3}IRKFN3Wu1#ju zhFR^gt|v29&!F-wA`H3|nXCaWsM5OXHAF9$-g1{-kDuPqhtV6{X;)&9+w?FTv}l=R z(q)n((1%D?Ac$m{oVh3y$vOlPNW>G#A&5Yd!%-)aDJGFj*Vz~llB=>K!QUspT~Dq4 zzsOa`sC^7!va1=~S$%e(Uc;Q~7=dO%r;Y+4cdVzLITO!_l-#uCv#BhCr$T^#Csqiw z*1MCoq;eIblq6QO%-=T7ZgXy$sJ{S|z zv`)wiFoP`}AE``NhadwzXuvz~1B6CLk z_vHA90o%%b&J3$ag-6}%UhIqtk+OsmL!Okp85-t}_Au}$#PFBUVnfh=HR832JikyR zIE$=e7|K+`@}2As>?*P=zrm?g2Gd1PsC;Fs3vh8>75HC;Ld%9?kvhbZ08JcX`#8>v0)HnMK#~K&wxZya~8EvsI+tNxejVwqh45SD@LvR;2bsElD=9 z2I;0bgt^z~nbtC$zwF4{OAfAWeJA!GIbXUkW+be6V#vAq(abBhV$gJ$D&4C+^m^b}wc+3;7yC%Ce<1fd6b4#mRtb~R!#Ot#0ya8^7ai||DC zBZXUz^5a|%o~i4h{cs*Q_JqTM!^U3Eo=5J7UY#N zgWYA6zU@&k*EZg1E>!v21l7PjlFj~Nq_UDH6%D9VNmFKQdjo%43g-r*a08^D^d4lc zMqaK`7+Yjg*wNDgx7RnZ>sW^6A~mPL?g!q=N*D_=D%;S&&4rd97K^mW@d){Gnt&SQ zpy%RFF=O++*JmOe{m8_uFxh7hSe07scS+q=4O`#IR^6xFv)Lg1f&t1dCn@MFFGIR= zsf*1iNLgQLHsNpgGuty$U9HJT#-E1CAE2MuZEgE;V$-KX_zE;2{*{H$zjwa7qmhr;U6ZrTl)XJGGlg0UZG(dQ046WB z`Dwoldw^h?zaX|9sd)kMqhyaUxYwyae5AtU3&4olPq#i!1SB5vh}1dyyrx? zRCZ!Mi|C_Rz9D*sQ1*q!ZQ1~J7xn%ZI)!(%LUI2>e*rIqkB?GTKjqQv}c%Ywv$NiR5p9l`g1D8J65#vxg zPzwJXcuIQt@@fW8XD30!>DT72;_A41u7=ym<>CjU8lPGNtt)1(uF`;N7!j nZ#F7fE$GJ8;P|?1@K!L3WP=kb_6-l7zgxg_rC?C0Wy9>hgBT&$ diff --git a/AbletonRemoteScripts.pyproj.user b/AbletonRemoteScripts.pyproj.user new file mode 100644 index 00000000..76fe5a55 --- /dev/null +++ b/AbletonRemoteScripts.pyproj.user @@ -0,0 +1,6 @@ + + + + ProjectFiles + + \ No newline at end of file diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 9ce121bd..d291d3e7 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -68,12 +68,21 @@ def __init__(self, c_instance): self._encoder_modes.set_device_mixer_buttons(device_button, mixer_button) self._string_to_display = None self._shift_pressed = False + # special alternative buttons mode. for now only mixer buttons become record buttons. later we will add something more + self.alternative_buttons_mode = False self._shift_button.add_value_listener(self._shift_value) for component in self.components: component.set_enabled(False) + def alternative_buttons_mode(self): + return self.alternative_buttons_mode + + def alternative_buttons_mode(self,value): + self.log ('alternative_buttons_mode_value ' + str(value)) + self.alternative_buttons_mode = value + def refresh_state(self): ControlSurface.refresh_state(self) self.schedule_message(3, self._send_midi, SYSEX_START + (6, 1, 1, 1, 247)) @@ -165,7 +174,7 @@ def _setup_mixer(self): mute_solo_flip_button.name = 'Mute_Solo_Flip_Button' self._next_nav_button.name = 'Next_Track_Button' self._prev_nav_button.name = 'Prev_Track_Button' - self._mixer = SpecialMixerComponent(8, self.c_instance) + self._mixer = SpecialMixerComponent(self, 8, self.c_instance) self._mixer.name = 'Mixer' self._mixer.set_select_buttons(self._next_nav_button, self._prev_nav_button) self._mixer.selected_strip().name = 'Selected_Channel_Strip' @@ -240,7 +249,7 @@ def _setup_transport(self): self._transport.set_record_buttonOnInit(rec_button) # self._transport.set_shift_button(self._shift_button) self._transport.set_mixer9_button(self._button9) - self._transport_view_modes = TransportViewModeSelector(self.c_instance,self._transport, self._session, ffwd_button, rwd_button, loop_button) + self._transport_view_modes = TransportViewModeSelector(self,self.c_instance,self._transport, self._session, ffwd_button, rwd_button, loop_button) self._transport_view_modes.name = 'Transport_View_Modes' def _setup_device(self): @@ -340,7 +349,7 @@ def _mixer_button_value(self, value, sender): self._display_reset_delay = STANDARD_DISPLAY_DELAY else: self._set_string_to_display(' - ') - if self._shift_pressed: + if self._shift_pressed or self.alternative_buttons_mode: self.log_message("_mixer_button_value") self.log_message(value) if (value == 0): @@ -436,6 +445,14 @@ def _shift_value(self, value): self.log("root shift handler 4") + def flipAlternativeButtonMode(self): + self.alternative_buttons_mode = not self.alternative_buttons_mode + self.updateAlternativeButtonMode() + + def updateAlternativeButtonMode(self): + self._mixer.updateMixerButtons() + self._transport_view_modes.update() + def log(self, message): pass # self.c_instance.log_message(message) diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index ca9111d9..688acc46 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -5,7 +5,8 @@ class SpecialMixerComponent(MixerComponent): """ Special mixer class that reassigns buttons to mute or solo based on a toggle """ - def __init__(self, num_tracks, c_instance): + def __init__(self, parent, num_tracks, c_instance): + self.parent = parent self.c_instance = c_instance self.log("mixer.init") self._selected_mute_solo_button = None @@ -75,12 +76,12 @@ def _mute_solo_flip_value(self, value): def updateMixerButtons(self): - self.log("updateMixerButtons") + self.log("updateMixerButtons" + str(self._shift_pressed) + " " +str(self.parent.alternative_buttons_mode)) if self._strip_mute_solo_buttons != None: for index in range(len(self._strip_mute_solo_buttons)): strip = self.channel_strip(index) self.log("setting strip") - if self._shift_pressed: + if self._shift_pressed or self.parent.alternative_buttons_mode: strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(self._strip_mute_solo_buttons[index]) diff --git a/Novation_Impulse2/TransportViewModeSelector.py b/Novation_Impulse2/TransportViewModeSelector.py index 98ba871b..96909a9b 100644 --- a/Novation_Impulse2/TransportViewModeSelector.py +++ b/Novation_Impulse2/TransportViewModeSelector.py @@ -8,18 +8,19 @@ class TransportViewModeSelector(ModeSelectorComponent): """ Class that reassigns specific buttons based on the views visible in Live """ - def __init__(self, c_instance, transport, session, ffwd_button, rwd_button, loop_button): + def __init__(self, parent, c_instance, transport, session, ffwd_button, rwd_button, loop_button): if not isinstance(transport, TransportComponent): raise AssertionError if not isinstance(session, SessionComponent): raise AssertionError if not isinstance(ffwd_button, ButtonElement): raise AssertionError - if not isinstance(rwd_button, ButtonElement): + if not isinstance(rwd_button, ButtonElement): raise AssertionError - if not isinstance(loop_button, ButtonElement): + if not isinstance(loop_button, ButtonElement): raise AssertionError ModeSelectorComponent.__init__(self) + self._parent = parent self.c_instance = c_instance self._transport = transport self._session = session @@ -28,6 +29,7 @@ def __init__(self, c_instance, transport, session, ffwd_button, rwd_button, loop self._loop_button = loop_button self._shift_pressed = False self.application().view.add_is_view_visible_listener('Session', self._on_view_changed) + self._loop_button.add_value_listener(self._loop_value) self.update() def disconnect(self): @@ -37,17 +39,23 @@ def disconnect(self): self._ffwd_button = None self._rwd_button = None self._loop_button = None + self._loop_button.remove_value_listener(self._loop_pressed) self.application().view.remove_is_view_visible_listener('Session', self._on_view_changed) def update(self): if self.is_enabled(): self.log("transportviewselctor_update ") - if self._mode_index == 0: - self._transport.set_loop_button(self._loop_button) + if self._shift_pressed: + #shift plus loop will make an alternative control mode for everything self._session.selected_scene().set_launch_button(None) - else: self._transport.set_loop_button(None) - self._session.selected_scene().set_launch_button(self._loop_button) + else: + if self._mode_index == 0: + self._transport.set_loop_button(self._loop_button) + self._session.selected_scene().set_launch_button(None) + else: + self._transport.set_loop_button(None) + self._session.selected_scene().set_launch_button(self._loop_button) # hack as we have nadler for fwd that changes devices if self._mode_index == 0 or self._shift_pressed: self._transport.set_seek_buttons(self._ffwd_button, self._rwd_button) @@ -73,6 +81,11 @@ def _shift_value(self, value): self.update() self.log("shift handler 3") + def _loop_value(self, value): + self.log("loop handler transport component " + str(value)) + if value == 1: + self._parent.flipAlternativeButtonMode() + def log(self, message): pass diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 6a5f2deb..52050e1a 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -15,21 +15,24 @@ Features Mixer button 9 = OverDub Shift + Mixer button 9 = Automation record on/off -Shift + Rec = Metronome on/off -Shift + PLay = Undo +Shift + Rec = Metronome on/off +Shift + Play = Undo Shift + Stop = Stop all clips +Shift + Ffwd/Back - next/previous device + +Shift + Loop now enters "alternative assignments" mode. +For now the only difference is that mixer buttons are permanently armed (like the shift is pressed) -Shift + track mixer button = rec this track.. +It is very good for perfomance when you need to quickly switch instruments and only have one left hand or right hand available as the other is ready to play Shift + Clip buttons are now clip stop. -Shift + Ffwd/Back - next/previous device -Known issues that cannot be fixed -1) After moving track with Shift+Track buttons are not returned to inital condition. - Also happens sometimes in other cases (like bank switching with Shift). +Known issues that cannot be fixed +1) After moving track with Shift+Track buttons are not returned to inital condition. + Also happens sometimes in other cases (like bank switching with Shift). Workaround - press and release Shit again. update : seems to work fine with Nocation Firmware 695 and higher 2) Pressin shift + (mutes/solos) flip button leds to unpredictable results. @@ -39,26 +42,27 @@ The reason for these problems is that when you use shift+track or shift+bank, th This is out of the scope of what I can do. The bug report is sent to Novation. Known issues and todo: -FIXED: 1) impulse does not disconnect properly and does not send disconnection message. +FIXED: 1) impulse does not disconnect properly and does not send disconnection message. FIXED 1.5) refactor shift - move it to main class. -FIXED: 2)when track goes down, the bank is not changed. +FIXED: 2)when track goes down, the bank is not changed. 3) on initialize mute/solo buttons do not light workaround - press shift button. -FIXED: 4) when arming a single track make the track selected +FIXED: 4) when arming a single track make the track selected -Future things to implement. +Future things to implement. DONE 1) mixer9 - overdub DONE 3) Shift + Stop - stop all clips. - - + + FIXED:4) Shift+Mixer9 - Automation record on/off 4.5) Shift + Rec = metronome 5) Shift + Loop switch session/arrangement (as loop is the button that also changes in this case) + replanned as shift+loop now behave totally differently FIXED: 6) Shift + play Undo (as play is like backspace but turned opposite) -DONE: another parallel feature - Shift + drum pad in clip mode - stop the selected clip. +DONE: another parallel feature - Shift + drum pad in clip mode - stop the selected clip. think of re-mapping drum pads for another notes. From 891d9da6aba868d03bea579ef6b31a67d6ee1d7e Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 16 Oct 2016 23:56:43 +0800 Subject: [PATCH 32/45] updated readme --- Novation_Impulse2/readme.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index 52050e1a..cb98754e 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -2,6 +2,8 @@ Created by Marat Bakirov 2013-2016 Marat branch is here: https://github.com/maratbakirov/AbletonLive9_RemoteScripts +Discussion +https://forum.ableton.com/viewtopic.php?f=1&t=197828 IMPORTANT! From 1a6e696384dc3181a008bb324609bfc3d8b5fdbb Mon Sep 17 00:00:00 2001 From: mbakirov Date: Mon, 17 Oct 2016 00:26:21 +0800 Subject: [PATCH 33/45] refactoring --- .vs/AbletonRemoteScripts/v14/.suo | Bin 70144 -> 85504 bytes Novation_Impulse2/Novation_Impulse2.py | 45 +++++++++++------- .../ShiftableTransportComponent.py | 12 ++--- Novation_Impulse2/SpecialMixerComponent.py | 14 ++---- .../TransportViewModeSelector.py | 10 ++-- Novation_Impulse2/readme.txt | 4 +- 6 files changed, 43 insertions(+), 42 deletions(-) diff --git a/.vs/AbletonRemoteScripts/v14/.suo b/.vs/AbletonRemoteScripts/v14/.suo index 6607448c24de33ee12ab13efb5c85c98a513e743..0ef980069adaa6f3514d8974031438fd63a70120 100644 GIT binary patch delta 5286 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 self.alternative_buttons_mode: + self.log("_mixer_button_value") + self.log(value) if (value == 0): self.select_armed_track_if_only_one() def select_armed_track_if_only_one(self): - self.log_message("select_armed_track_if_only_one") + self.log("select_armed_track_if_only_one") song = self.song() armed_tracks = [] tracks = song.tracks for track in tracks: if track.can_be_armed and track.arm: armed_tracks.append(track) - self.log_message(len(armed_tracks)) + self.log(len(armed_tracks)) if (len(armed_tracks) == 1): - self.log_message("selecting the track") + self.log("selecting the track") sel_track = armed_tracks[0] self.song().view.selected_track = sel_track self._mixer._selected_tracks = [] @@ -413,18 +422,18 @@ def _on_selected_track_changed(self): self._session.set_offsets(new_offset, self._session.scene_offset()) - def _shift_value(self, value): + def _shift_button_handler(self, value): self.log("root shift handler") if not self._shift_button != None: raise AssertionError if not value in range(128): raise AssertionError self.log("root shift handler 2") - self._shift_pressed = value > 0 + self.shift_pressed = value > 0 # calling other handlers - self._mixer._shift_value(value) - self._transport._shift_value(value) - self._transport_view_modes._shift_value(value) + self._mixer._shift_button_handler(value) + self._transport._shift_button_handler(value) + self._transport_view_modes._shift_button_handler(value) #clip stop self.log("root shift handler 3") @@ -434,11 +443,11 @@ def _shift_value(self, value): pads.append(ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 60 + index)) pads[-1].name = 'Pad_' + str(index) clip_slot = self._session.selected_scene().clip_slot(index) - if self._shift_pressed: + if self.shift_pressed: clip_slot.set_launch_button(None) else: clip_slot.set_launch_button(pads[index]) - if self._shift_pressed: + if self.shift_pressed: self._session.set_stop_track_clip_buttons(tuple(pads)) else: self._session.set_stop_track_clip_buttons(None) @@ -446,7 +455,7 @@ def _shift_value(self, value): self.log("root shift handler 4") def flipAlternativeButtonMode(self): - self.alternative_buttons_mode = not self.alternative_buttons_mode + self.alternative_buttons_mode = not self.alternative_buttons_mode self.updateAlternativeButtonMode() def updateAlternativeButtonMode(self): diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index 463f15d4..f6dbbe13 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -11,7 +11,6 @@ class ShiftableTransportComponent(TransportComponent): def __init__(self, c_instance, session, parent, ffwd_button, rwd_button): TransportComponent.__init__(self) self.c_instance = c_instance - self._shift_pressed = False self._mixer9_button = None self._play_button = None self._record_button = None @@ -62,7 +61,7 @@ def _play_pressed(self, value): self.log("_play_pressed " + str(value)) if not value in range(128): raise AssertionError - if self._shift_pressed: + if self._parent.shift_pressed: if value != 0: if self.song().can_undo: #todo: add message @@ -75,14 +74,13 @@ def _play_pressed(self, value): self._parent._set_string_to_display('cannot undo') - def _shift_value(self, value): + def _shift_button_handler(self, value): self.log("shift handler transport component " + str(value)) if not value in range(128): raise AssertionError self.log("shift handler 2") - self._shift_pressed = self.is_enabled() and value > 0 self.log("shift handler 3") - if self._shift_pressed: + if self._parent.shift_pressed: self._play_toggle.set_toggle_button(None) self._session.set_stop_all_clips_button(self._stop_button) self.set_stop_button(None) @@ -110,7 +108,7 @@ def _ffwd_value(self, value): if not value in range(128): raise AssertionError else: - if self._shift_pressed: + if self._parent.shift_pressed: self.log("ffwd shifted handler") # self.song().current_song_time = self.song().last_event_time if value == 1: @@ -126,7 +124,7 @@ def _rwd_value(self, value): if not value in range(128): raise AssertionError else: - if self._shift_pressed: + if self._parent.shift_pressed: self.log("rwd shifted handler") # self.song().current_song_time = 0.0 if value == 1: diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index 688acc46..960b8188 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -15,7 +15,6 @@ def __init__(self, parent, num_tracks, c_instance): MixerComponent.__init__(self, num_tracks) self._selected_tracks = [] self._register_timer_callback(self._on_timer) - self._shift_pressed = False self._mute_solo_raw_value = 127 @@ -23,9 +22,6 @@ def disconnect(self): self._unregister_timer_callback(self._on_timer) self._selected_tracks = None MixerComponent.disconnect(self) - #if self._shift_button != None: - # self._shift_button.remove_value_listener(self._shift_value) - # self._shift_button = None if self._mute_solo_flip_button != None: self._mute_solo_flip_button.remove_value_listener(self._mute_solo_flip_value) self._mute_solo_flip_button = None @@ -55,12 +51,8 @@ def set_strip_mute_solo_buttons(self, buttons, flip_button): def tracks_to_use(self): return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) - def _shift_value(self, value): + def _shift_button_handler(self, value): self.log("calling mixer shift value " + str(value)) - if (value > 0): - self._shift_pressed = True - else: - self._shift_pressed = False self.updateMixerButtons() pass return @@ -76,12 +68,12 @@ def _mute_solo_flip_value(self, value): def updateMixerButtons(self): - self.log("updateMixerButtons" + str(self._shift_pressed) + " " +str(self.parent.alternative_buttons_mode)) + self.log("updateMixerButtons" + str(self.parent.shift_pressed) + " " +str(self.parent.alternative_buttons_mode)) if self._strip_mute_solo_buttons != None: for index in range(len(self._strip_mute_solo_buttons)): strip = self.channel_strip(index) self.log("setting strip") - if self._shift_pressed or self.parent.alternative_buttons_mode: + if self.parent.shift_pressed or self.parent.alternative_buttons_mode: strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(self._strip_mute_solo_buttons[index]) diff --git a/Novation_Impulse2/TransportViewModeSelector.py b/Novation_Impulse2/TransportViewModeSelector.py index 96909a9b..74f18bf7 100644 --- a/Novation_Impulse2/TransportViewModeSelector.py +++ b/Novation_Impulse2/TransportViewModeSelector.py @@ -29,7 +29,7 @@ def __init__(self, parent, c_instance, transport, session, ffwd_button, rwd_butt self._loop_button = loop_button self._shift_pressed = False self.application().view.add_is_view_visible_listener('Session', self._on_view_changed) - self._loop_button.add_value_listener(self._loop_value) + self._loop_button.add_value_listener(self._loop_pressed) self.update() def disconnect(self): @@ -38,8 +38,8 @@ def disconnect(self): self._session = None self._ffwd_button = None self._rwd_button = None - self._loop_button = None self._loop_button.remove_value_listener(self._loop_pressed) + self._loop_button = None self.application().view.remove_is_view_visible_listener('Session', self._on_view_changed) def update(self): @@ -72,16 +72,16 @@ def _on_view_changed(self): self.update() - def _shift_value(self, value): + def _shift_button_handler(self, value): self.log("shift handler transport component " + str(value)) if not value in range(128): raise AssertionError self.log("shift handler 2") - self._shift_pressed = self.is_enabled() and value > 0 + self._shift_pressed = self.is_enabled() and self._parent.shift_pressed self.update() self.log("shift handler 3") - def _loop_value(self, value): + def _loop_pressed(self, value): self.log("loop handler transport component " + str(value)) if value == 1: self._parent.flipAlternativeButtonMode() diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index cb98754e..d80e2694 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -24,7 +24,9 @@ Shift + Stop = Stop all clips Shift + Ffwd/Back - next/previous device Shift + Loop now enters "alternative assignments" mode. -For now the only difference is that mixer buttons are permanently armed (like the shift is pressed) +Differences: + is that mixer buttons are permanently armed (like the shift is pressed) + if you press Shift and arm the track, it will NOT me selected automatically It is very good for perfomance when you need to quickly switch instruments and only have one left hand or right hand available as the other is ready to play From e2480a83eba0545df9544dd0e413cd8ca4a0fb66 Mon Sep 17 00:00:00 2001 From: maratbakirov Date: Tue, 25 Oct 2016 01:20:10 +0800 Subject: [PATCH 34/45] Delete .suo --- .vs/AbletonRemoteScripts/v14/.suo | Bin 85504 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .vs/AbletonRemoteScripts/v14/.suo diff --git a/.vs/AbletonRemoteScripts/v14/.suo b/.vs/AbletonRemoteScripts/v14/.suo deleted file mode 100644 index 0ef980069adaa6f3514d8974031438fd63a70120..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85504 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 From b1dd6fc1c95689377a977ed174a0c44d1304d40f Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sat, 11 Mar 2017 20:55:28 +0800 Subject: [PATCH 35/45] bugfixes --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..fed0bf8f --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +################################################################################ +# This .gitignore file was automatically created by Microsoft(R) Visual Studio. +################################################################################ + +/.vs/AbletonRemoteScripts/v14/.suo From 050fc2272e7c5cc8a4bd0c8a62df55b98370b934 Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sat, 11 Mar 2017 21:08:40 +0800 Subject: [PATCH 36/45] bugfixing --- Novation_Impulse2/Novation_Impulse2.py | 16 +++++++++------- Novation_Impulse2/ShiftableTransportComponent.py | 7 +++---- Novation_Impulse2/SpecialMixerComponent.py | 9 +++++++-- Novation_Impulse2/TransportViewModeSelector.py | 3 ++- Novation_Impulse2/readme.txt | 2 +- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Novation_Impulse2/Novation_Impulse2.py b/Novation_Impulse2/Novation_Impulse2.py index 545f46bd..5b948193 100644 --- a/Novation_Impulse2/Novation_Impulse2.py +++ b/Novation_Impulse2/Novation_Impulse2.py @@ -49,6 +49,10 @@ def __init__(self, c_instance): self._has_sliders = True self._current_midi_map = None self._display_reset_delay = -1 + self._string_to_display = None + self.shift_pressed = False + # special alternative buttons mode. for now only mixer buttons become record buttons. later we will add something more + self.alternative_buttons_mode = False self._shift_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 39) self._preview_button = ButtonElement(IS_MOMENTARY, MIDI_CC_TYPE, 0, 41) self._master_slider = SliderElement(MIDI_CC_TYPE, 0, 8) @@ -67,10 +71,6 @@ def __init__(self, c_instance): mixer_button.name = 'Encoder_Mixer_Mode' self._encoder_modes = EncoderModeSelector(self._device_component, self._mixer, self._next_bank_button, self._prev_bank_button, self._encoders) self._encoder_modes.set_device_mixer_buttons(device_button, mixer_button) - self._string_to_display = None - self.shift_pressed = False - # special alternative buttons mode. for now only mixer buttons become record buttons. later we will add something more - self.alternative_buttons_mode = False self._shift_button.add_value_listener(self._shift_button_handler) for component in self.components: @@ -346,6 +346,7 @@ def _slider_value(self, value, sender): self._set_string_to_display(display_string) def _mixer_button_value(self, value, sender): + self.log ('__mixer_button_value ' + str(value) + ' ' +str(sender)) if not value in range(128): raise AssertionError #if self._mixer.is_enabled() and value > 0: @@ -360,7 +361,7 @@ def _mixer_button_value(self, value, sender): # if shift_pressed XOR alternative_mode if self.shift_pressed <> self.alternative_buttons_mode: self.log("_mixer_button_value") - self.log(value) + self.log(str(value)) if (value == 0): self.select_armed_track_if_only_one() @@ -369,10 +370,11 @@ def select_armed_track_if_only_one(self): song = self.song() armed_tracks = [] tracks = song.tracks + self.log("select_armed_track_if_only_one 2") for track in tracks: if track.can_be_armed and track.arm: armed_tracks.append(track) - self.log(len(armed_tracks)) + self.log(str(len(armed_tracks))) if (len(armed_tracks) == 1): self.log("selecting the track") sel_track = armed_tracks[0] @@ -423,7 +425,7 @@ def _on_selected_track_changed(self): def _shift_button_handler(self, value): - self.log("root shift handler") + self.log("root shift handler : "+ str(value)) if not self._shift_button != None: raise AssertionError if not value in range(128): diff --git a/Novation_Impulse2/ShiftableTransportComponent.py b/Novation_Impulse2/ShiftableTransportComponent.py index f6dbbe13..12555f2f 100644 --- a/Novation_Impulse2/ShiftableTransportComponent.py +++ b/Novation_Impulse2/ShiftableTransportComponent.py @@ -75,11 +75,10 @@ def _play_pressed(self, value): def _shift_button_handler(self, value): - self.log("shift handler transport component " + str(value)) + self.log("shift handler transport component : " + str(value)) if not value in range(128): raise AssertionError - self.log("shift handler 2") - self.log("shift handler 3") + self.log("shift handler transport component 2") if self._parent.shift_pressed: self._play_toggle.set_toggle_button(None) self._session.set_stop_all_clips_button(self._stop_button) @@ -98,7 +97,7 @@ def _shift_button_handler(self, value): self.set_metronome_button(None) self.set_record_button(self._record_button) - self.log("shift handler 4") + self.log("shift handler transport component 3") def _ffwd_value(self, value): diff --git a/Novation_Impulse2/SpecialMixerComponent.py b/Novation_Impulse2/SpecialMixerComponent.py index 960b8188..487c1808 100644 --- a/Novation_Impulse2/SpecialMixerComponent.py +++ b/Novation_Impulse2/SpecialMixerComponent.py @@ -58,7 +58,7 @@ def _shift_button_handler(self, value): return def _mute_solo_flip_value(self, value): - #self.log(value) + self.log("_mute_solo_flip_value" + str(value)) if not self._mute_solo_flip_button != None: raise AssertionError if not value in range(128): @@ -68,21 +68,26 @@ def _mute_solo_flip_value(self, value): def updateMixerButtons(self): - self.log("updateMixerButtons" + str(self.parent.shift_pressed) + " " +str(self.parent.alternative_buttons_mode)) + parent_shift_pressed = self.parent.shift_pressed + parent_alternative_buttons_mode = self.parent.alternative_buttons_mode + self.log("updateMixerButtons " + str(parent_shift_pressed) + " " +str(parent_alternative_buttons_mode)) if self._strip_mute_solo_buttons != None: for index in range(len(self._strip_mute_solo_buttons)): strip = self.channel_strip(index) self.log("setting strip") if self.parent.shift_pressed or self.parent.alternative_buttons_mode: + self.log("setting strip to arm") strip.set_mute_button(None) strip.set_solo_button(None) strip.set_arm_button(self._strip_mute_solo_buttons[index]) else: if self._mute_solo_raw_value == 0: + self.log("setting strip to solo") strip.set_mute_button(None) strip.set_solo_button(self._strip_mute_solo_buttons[index]) strip.set_arm_button(None) else: + self.log("setting strip to mute") strip.set_solo_button(None) strip.set_mute_button(self._strip_mute_solo_buttons[index]) strip.set_arm_button(None) diff --git a/Novation_Impulse2/TransportViewModeSelector.py b/Novation_Impulse2/TransportViewModeSelector.py index 74f18bf7..ee4b6172 100644 --- a/Novation_Impulse2/TransportViewModeSelector.py +++ b/Novation_Impulse2/TransportViewModeSelector.py @@ -83,7 +83,8 @@ def _shift_button_handler(self, value): def _loop_pressed(self, value): self.log("loop handler transport component " + str(value)) - if value == 1: + + if (value == 1) and (self._shift_pressed): self._parent.flipAlternativeButtonMode() diff --git a/Novation_Impulse2/readme.txt b/Novation_Impulse2/readme.txt index d80e2694..20ca11ae 100644 --- a/Novation_Impulse2/readme.txt +++ b/Novation_Impulse2/readme.txt @@ -1,4 +1,4 @@ -Created by Marat Bakirov 2013-2016 +Created by Marat Bakirov 2013-2017 Marat branch is here: https://github.com/maratbakirov/AbletonLive9_RemoteScripts From 0e50ecdf19c007c94c678bd757fc2ed043061ff2 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Mon, 19 Aug 2019 21:01:00 +0800 Subject: [PATCH 37/45] Vs upgrade to 2019 --- .vs/AbletonRemoteScripts/v14/.suo | Bin 0 -> 142848 bytes .vs/AbletonRemoteScripts/v16/.suo | Bin 0 -> 142848 bytes AbletonRemoteScripts.pyproj | 7 ++----- AbletonRemoteScripts.sln | 7 +++++-- Backup1/AbletonRemoteScripts.sln | 22 ++++++++++++++++++++++ UpgradeLog2.htm | Bin 0 -> 36576 bytes 6 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 .vs/AbletonRemoteScripts/v14/.suo create mode 100644 .vs/AbletonRemoteScripts/v16/.suo create mode 100644 Backup1/AbletonRemoteScripts.sln create mode 100644 UpgradeLog2.htm diff --git a/.vs/AbletonRemoteScripts/v14/.suo b/.vs/AbletonRemoteScripts/v14/.suo new file mode 100644 index 0000000000000000000000000000000000000000..2a87edd921ce196e4a82aab799591d5df2eae40d GIT binary patch literal 142848 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

Vf|cTT~rs literal 0 HcmV?d00001 diff --git a/.vs/AbletonRemoteScripts/v16/.suo b/.vs/AbletonRemoteScripts/v16/.suo new file mode 100644 index 0000000000000000000000000000000000000000..f9879a198e20028b0592019d99a2087ad3f6773c GIT binary patch literal 142848 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 bk48G?YfS)0l#fZ&jmE4XB0M|h>Vf|c7UQUX literal 0 HcmV?d00001 diff --git a/AbletonRemoteScripts.pyproj b/AbletonRemoteScripts.pyproj index b75d2111..d7d18c23 100644 --- a/AbletonRemoteScripts.pyproj +++ b/AbletonRemoteScripts.pyproj @@ -15,9 +15,7 @@ - - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets - + @@ -140,6 +138,5 @@ - - + \ No newline at end of file diff --git a/AbletonRemoteScripts.sln b/AbletonRemoteScripts.sln index 7177b599..ce577c9f 100644 --- a/AbletonRemoteScripts.sln +++ b/AbletonRemoteScripts.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29201.188 MinimumVisualStudioVersion = 10.0.40219.1 Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "AbletonRemoteScripts", "AbletonRemoteScripts.pyproj", "{ED5FBFBF-4BE8-482D-B574-58DB3CD35247}" EndProject @@ -19,4 +19,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {043C1B30-6E87-4123-8E53-DA1C1379F802} + EndGlobalSection EndGlobal diff --git a/Backup1/AbletonRemoteScripts.sln b/Backup1/AbletonRemoteScripts.sln new file mode 100644 index 00000000..7177b599 --- /dev/null +++ b/Backup1/AbletonRemoteScripts.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "AbletonRemoteScripts", "AbletonRemoteScripts.pyproj", "{ED5FBFBF-4BE8-482D-B574-58DB3CD35247}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ED5FBFBF-4BE8-482D-B574-58DB3CD35247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED5FBFBF-4BE8-482D-B574-58DB3CD35247}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED5FBFBF-4BE8-482D-B574-58DB3CD35247}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED5FBFBF-4BE8-482D-B574-58DB3CD35247}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/UpgradeLog2.htm b/UpgradeLog2.htm new file mode 100644 index 0000000000000000000000000000000000000000..ae87587e3c1169d7206f8826c7e05bfd0d739719 GIT binary patch literal 36576 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 Nr#aOr(!Ni<{{v;RK~4Yw literal 0 HcmV?d00001 From 7a31a2ab0e221089a049afac6cec7dab835dec04 Mon Sep 17 00:00:00 2001 From: Marat Bakirov Date: Mon, 19 Aug 2019 21:09:06 +0800 Subject: [PATCH 38/45] added releases fodler --- _releases/Novation_Impulse2.zip | Bin 0 -> 13452 bytes _releases/Novation_Impulse2_9_1.zip | Bin 0 -> 11967 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 _releases/Novation_Impulse2.zip create mode 100644 _releases/Novation_Impulse2_9_1.zip diff --git a/_releases/Novation_Impulse2.zip b/_releases/Novation_Impulse2.zip new file mode 100644 index 0000000000000000000000000000000000000000..61e535c782fa2e93d362b2d40538badbcaed55dd GIT binary patch literal 13452 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 GuKouv+#J0C literal 0 HcmV?d00001 diff --git a/_releases/Novation_Impulse2_9_1.zip b/_releases/Novation_Impulse2_9_1.zip new file mode 100644 index 0000000000000000000000000000000000000000..b2818b59a59ac9b45f66c11e91ecc1d08e2a10fd GIT binary patch literal 11967 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 a``aqYLcN?rU| Date: Mon, 19 Aug 2019 21:10:25 +0800 Subject: [PATCH 39/45] added reasme --- README.md | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a78c7006..b2f8c91a 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,5 @@ -Ableton Live 9.6 Remote Scripts -============================= +please download from the folder -This is the unofficial repository of Ableton Live 9.6 MIDI Remote Scripts. +https://github.com/maratbakirov/AbletonLive9_RemoteScripts/tree/master/_releases -You can find more informations on -[this page](http://julienbayle.net/ableton-live-9-midi-remote-scripts "this page") - - -**UPDATED on 31th March 2016 with Lemur Live Control v2.1.31 (just in case)** - -(all files marked with older references didn't have changed since previous versions) - - -===> NO support given, ONLY source files ! - -Please, enjoy. From 4fd44fb2f400a19b3ab237263a8fd6d415e9767f Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 9 May 2021 16:27:36 +0800 Subject: [PATCH 40/45] added readme and changed releases location --- README.md | 12 +++++++++++- _releases/README.md | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 _releases/README.md diff --git a/README.md b/README.md index b2f8c91a..b9df97be 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,15 @@ please download from the folder -https://github.com/maratbakirov/AbletonLive9_RemoteScripts/tree/master/_releases +https://github.com/maratbakirov/AbletonLive9_RemoteScripts/releases/ + +Novation_Impulse2.zip + main release for ableton version higher than 9.1 + + +Novation_Impulse2_9_1.zip + for ableton before 9.1 + + + diff --git a/_releases/README.md b/_releases/README.md new file mode 100644 index 00000000..c33cd317 --- /dev/null +++ b/_releases/README.md @@ -0,0 +1,13 @@ +please download from the folder + +https://github.com/maratbakirov/AbletonLive9_RemoteScripts/releases/ + +Novation_Impulse2.zip + main release for ableton version higher than 9.1 + + +Novation_Impulse2_9_1.zip + for ableton before 9.1 + + + From 571ebaaec57ba2980954d9547cb0c03d2aafb9a8 Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 9 May 2021 16:28:06 +0800 Subject: [PATCH 41/45] added readme --- README.md | 5 ++++- _releases/README.md | 11 +---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b9df97be..9d4860f3 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ Novation_Impulse2_9_1.zip for ableton before 9.1 - +extract the zip to the + +"C:\ProgramData\Ableton\Live 9 [here it could sat Suite 64]\Resources\MIDI Remote Scripts" + diff --git a/_releases/README.md b/_releases/README.md index c33cd317..7688fac2 100644 --- a/_releases/README.md +++ b/_releases/README.md @@ -1,13 +1,4 @@ -please download from the folder +please download from the releases https://github.com/maratbakirov/AbletonLive9_RemoteScripts/releases/ -Novation_Impulse2.zip - main release for ableton version higher than 9.1 - - -Novation_Impulse2_9_1.zip - for ableton before 9.1 - - - From 5041d46c8358ecf6ed083f3129cc0c8a125901df Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 9 May 2021 16:35:00 +0800 Subject: [PATCH 42/45] fixing misprint --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d4860f3..8fa7d5be 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Novation_Impulse2_9_1.zip extract the zip to the -"C:\ProgramData\Ableton\Live 9 [here it could sat Suite 64]\Resources\MIDI Remote Scripts" +"C:\ProgramData\Ableton\Live 9 [here it could have said Suite 64]\Resources\MIDI Remote Scripts" From 3ee01c06fa3923a1b1abbabfb7fd0f6fa8b5be2d Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 9 May 2021 19:41:33 +0800 Subject: [PATCH 43/45] Update README.md --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 8fa7d5be..6572e91d 100644 --- a/README.md +++ b/README.md @@ -16,3 +16,15 @@ extract the zip to the + +# All related projects: +https://github.com/maratbakirov/AbletonLive9_RemoteScripts +https://github.com/maratbakirov/AbletonLive9_RemoteScripts/releases + +https://github.com/maratbakirov/AbletonLive10_MIDIRemoteScripts +https://github.com/maratbakirov/AbletonLive10_MIDIRemoteScripts/releases + +https://github.com/maratbakirov/AbletonLive11_MIDIRemoteScripts +https://github.com/maratbakirov/AbletonLive11_MIDIRemoteScripts/releases + + From 0cd6e700919349a1a458dcb92eff6f4b442f670e Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 9 May 2021 19:41:58 +0800 Subject: [PATCH 44/45] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6572e91d..950f64ad 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,13 @@ extract the zip to the # All related projects: -https://github.com/maratbakirov/AbletonLive9_RemoteScripts +https://github.com/maratbakirov/AbletonLive9_RemoteScripts https://github.com/maratbakirov/AbletonLive9_RemoteScripts/releases -https://github.com/maratbakirov/AbletonLive10_MIDIRemoteScripts +https://github.com/maratbakirov/AbletonLive10_MIDIRemoteScripts https://github.com/maratbakirov/AbletonLive10_MIDIRemoteScripts/releases -https://github.com/maratbakirov/AbletonLive11_MIDIRemoteScripts +https://github.com/maratbakirov/AbletonLive11_MIDIRemoteScripts https://github.com/maratbakirov/AbletonLive11_MIDIRemoteScripts/releases From 4a1517c206353409542e8276ebab7f36f9bbd4ef Mon Sep 17 00:00:00 2001 From: mbakirov Date: Sun, 9 May 2021 19:42:10 +0800 Subject: [PATCH 45/45] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 950f64ad..bc71668a 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ extract the zip to the # All related projects: https://github.com/maratbakirov/AbletonLive9_RemoteScripts + https://github.com/maratbakirov/AbletonLive9_RemoteScripts/releases https://github.com/maratbakirov/AbletonLive10_MIDIRemoteScripts