diff --git a/ADVANCE/Advance.py b/ADVANCE/Advance.py index a212423a..93eee2e7 100644 --- a/ADVANCE/Advance.py +++ b/ADVANCE/Advance.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ADVANCE/Advance.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ADVANCE/Advance.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/ADVANCE/__init__.py b/ADVANCE/__init__.py index daf320ed..ae227f27 100644 --- a/ADVANCE/__init__.py +++ b/ADVANCE/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ADVANCE/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ADVANCE/__init__.py import _Framework.Capabilities as caps from .Advance import Advance diff --git a/AIRA_MX_1/Colors.py b/AIRA_MX_1/Colors.py index a4f96bff..d8454053 100644 --- a/AIRA_MX_1/Colors.py +++ b/AIRA_MX_1/Colors.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AIRA_MX_1/Colors.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AIRA_MX_1/Colors.py from _Framework.ButtonElement import Color BLINK_LED_CHANNEL = 14 diff --git a/AIRA_MX_1/ControlElementUtils.py b/AIRA_MX_1/ControlElementUtils.py index ab015970..b2af1053 100644 --- a/AIRA_MX_1/ControlElementUtils.py +++ b/AIRA_MX_1/ControlElementUtils.py @@ -1,13 +1,15 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AIRA_MX_1/ControlElementUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AIRA_MX_1/ControlElementUtils.py import Live from _Framework.Resource import PrioritizedResource +from _Framework.Dependency import depends from _Framework.InputControlElement import MIDI_NOTE_TYPE, MIDI_CC_TYPE from _Framework.ComboElement import ComboElement from _Framework.ButtonElement import ButtonElement from _Framework.EncoderElement import EncoderElement -def make_button(name, identifier, channel = 0, msg_type = MIDI_NOTE_TYPE, is_momentary = True, is_modifier = False): - return ButtonElement(is_momentary, msg_type, channel, identifier, name=name, resource_type=PrioritizedResource if is_modifier else None) +@depends(skin=None) +def make_button(name, identifier, channel = 0, msg_type = MIDI_NOTE_TYPE, is_momentary = True, is_modifier = False, skin = None): + return ButtonElement(is_momentary, msg_type, channel, identifier, name=name, resource_type=PrioritizedResource if is_modifier else None, skin=skin) def make_encoder(name, identifier, channel = 0): diff --git a/AIRA_MX_1/NotifyingMixerComponent.py b/AIRA_MX_1/NotifyingMixerComponent.py index 31a9288e..3a736386 100644 --- a/AIRA_MX_1/NotifyingMixerComponent.py +++ b/AIRA_MX_1/NotifyingMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AIRA_MX_1/NotifyingMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AIRA_MX_1/NotifyingMixerComponent.py from _Framework.MixerComponent import MixerComponent from _Framework.Control import ButtonControl diff --git a/AIRA_MX_1/NotifyingSessionComponent.py b/AIRA_MX_1/NotifyingSessionComponent.py index 8d85f851..e7879fcb 100644 --- a/AIRA_MX_1/NotifyingSessionComponent.py +++ b/AIRA_MX_1/NotifyingSessionComponent.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AIRA_MX_1/NotifyingSessionComponent.py -from itertools import count +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AIRA_MX_1/NotifyingSessionComponent.py +from itertools import count, izip_longest from _Framework.SubjectSlot import subject_slot, subject_slot_group from _Framework.SessionComponent import SessionComponent, SceneComponent @@ -77,7 +77,7 @@ def __init__(self, *a, **k): def set_clip_launch_buttons(self, buttons): first_scene = self.scene(0) - for track_index, button in map(None, xrange(self._num_tracks), buttons or []): + for track_index, button in izip_longest(xrange(self._num_tracks), buttons or []): slot = first_scene.clip_slot(track_index) slot.set_launch_button(button) diff --git a/AIRA_MX_1/RolandMX1.py b/AIRA_MX_1/RolandMX1.py index 330b41a0..245f1320 100644 --- a/AIRA_MX_1/RolandMX1.py +++ b/AIRA_MX_1/RolandMX1.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AIRA_MX_1/RolandMX1.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AIRA_MX_1/RolandMX1.py from __future__ import with_statement from functools import partial from _Framework.Util import recursive_map diff --git a/AIRA_MX_1/SkinDefault.py b/AIRA_MX_1/SkinDefault.py index 638f430f..36cde98d 100644 --- a/AIRA_MX_1/SkinDefault.py +++ b/AIRA_MX_1/SkinDefault.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AIRA_MX_1/SkinDefault.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AIRA_MX_1/SkinDefault.py from _Framework.Skin import Skin from Colors import Rgb diff --git a/AIRA_MX_1/__init__.py b/AIRA_MX_1/__init__.py index ccba260d..f02ccee5 100644 --- a/AIRA_MX_1/__init__.py +++ b/AIRA_MX_1/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AIRA_MX_1/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AIRA_MX_1/__init__.py from _Framework.Capabilities import CONTROLLER_ID_KEY, PORTS_KEY, SCRIPT, controller_id, inport, outport from RolandMX1 import RolandMX1 diff --git a/APC20/APC20.py b/APC20/APC20.py index 388b4276..8854c7c3 100644 --- a/APC20/APC20.py +++ b/APC20/APC20.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC20/APC20.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC20/APC20.py from __future__ import with_statement from functools import partial from itertools import izip diff --git a/APC20/BackgroundComponent.py b/APC20/BackgroundComponent.py index 31baa669..7bdf4dce 100644 --- a/APC20/BackgroundComponent.py +++ b/APC20/BackgroundComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC20/BackgroundComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC20/BackgroundComponent.py from _Framework.BackgroundComponent import BackgroundComponent as BackgroundComponentBase from _Framework.Util import nop diff --git a/APC20/ShiftableSelectorComponent.py b/APC20/ShiftableSelectorComponent.py index 2a3ed9b6..8c13eb77 100644 --- a/APC20/ShiftableSelectorComponent.py +++ b/APC20/ShiftableSelectorComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC20/ShiftableSelectorComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC20/ShiftableSelectorComponent.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.Layer import Layer from consts import NOTE_MODE, ABLETON_MODE diff --git a/APC20/ShiftableZoomingComponent.py b/APC20/ShiftableZoomingComponent.py index 72208144..6ea4708c 100644 --- a/APC20/ShiftableZoomingComponent.py +++ b/APC20/ShiftableZoomingComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC20/ShiftableZoomingComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC20/ShiftableZoomingComponent.py from _Framework.ButtonElement import ButtonElement from _Framework.SessionZoomingComponent import DeprecatedSessionZoomingComponent diff --git a/APC20/SliderModesComponent.py b/APC20/SliderModesComponent.py index 3611a2ca..6ec033f0 100644 --- a/APC20/SliderModesComponent.py +++ b/APC20/SliderModesComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC20/SliderModesComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC20/SliderModesComponent.py from _Framework.ButtonElement import ButtonElement from _Framework.ModeSelectorComponent import ModeSelectorComponent diff --git a/APC20/__init__.py b/APC20/__init__.py index 6f499f92..b3bd5488 100644 --- a/APC20/__init__.py +++ b/APC20/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC20/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC20/__init__.py from _Framework.Capabilities import CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE, controller_id, inport, outport from APC20 import APC20 diff --git a/APC20/consts.py b/APC20/consts.py index f4cde002..a80a1506 100644 --- a/APC20/consts.py +++ b/APC20/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC20/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC20/consts.py MANUFACTURER_ID = 71 ABLETON_MODE = 65 NOTE_MODE = 67 \ No newline at end of file diff --git a/APC40/APC40.py b/APC40/APC40.py index 47748155..1f9d852c 100644 --- a/APC40/APC40.py +++ b/APC40/APC40.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40/APC40.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40/APC40.py from __future__ import with_statement from functools import partial from _Framework.ButtonMatrixElement import ButtonMatrixElement diff --git a/APC40/SessionComponent.py b/APC40/SessionComponent.py index f0ea68e5..de2288bd 100644 --- a/APC40/SessionComponent.py +++ b/APC40/SessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40/SessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40/SessionComponent.py from _Framework.Control import ButtonControl from _APC.SessionComponent import SessionComponent as SessionComponentBase diff --git a/APC40/TransportComponent.py b/APC40/TransportComponent.py index 3f2650b4..15836b57 100644 --- a/APC40/TransportComponent.py +++ b/APC40/TransportComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40/TransportComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40/TransportComponent.py import Live from _Framework.Control import ButtonControl from _Framework.TransportComponent import TransportComponent as TransportComponentBase diff --git a/APC40/__init__.py b/APC40/__init__.py index eb6197d0..bce82cf1 100644 --- a/APC40/__init__.py +++ b/APC40/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40/__init__.py from _Framework.Capabilities import CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE, controller_id, inport, outport from APC40 import APC40 diff --git a/APC40_MkII/APC40_MkII.py b/APC40_MkII/APC40_MkII.py index da507983..364b3987 100644 --- a/APC40_MkII/APC40_MkII.py +++ b/APC40_MkII/APC40_MkII.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40_MkII/APC40_MkII.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40_MkII/APC40_MkII.py from __future__ import with_statement from functools import partial from _Framework.ButtonMatrixElement import ButtonMatrixElement diff --git a/APC40_MkII/BankToggleComponent.py b/APC40_MkII/BankToggleComponent.py index 8e8315cc..ee0bf6fc 100644 --- a/APC40_MkII/BankToggleComponent.py +++ b/APC40_MkII/BankToggleComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40_MkII/BankToggleComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40_MkII/BankToggleComponent.py from _Framework.ComboElement import ToggleElement from _Framework.Control import ToggleButtonControl from _Framework.ControlSurfaceComponent import ControlSurfaceComponent diff --git a/APC40_MkII/MixerComponent.py b/APC40_MkII/MixerComponent.py index 61d55cf1..d47dd43e 100644 --- a/APC40_MkII/MixerComponent.py +++ b/APC40_MkII/MixerComponent.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40_MkII/MixerComponent.py -from itertools import ifilter +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40_MkII/MixerComponent.py +from itertools import ifilter, izip_longest from _Framework.Control import RadioButtonControl, control_list from _Framework.Dependency import depends from _Framework.Util import nop @@ -81,7 +81,7 @@ def set_user_controls(self, controls): self._show_message('Controlling User Mappings') def set_crossfade_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): strip.set_crossfade_toggle(button) def _update_pan_controls(self): diff --git a/APC40_MkII/QuantizationComponent.py b/APC40_MkII/QuantizationComponent.py index 161df59e..e5592e77 100644 --- a/APC40_MkII/QuantizationComponent.py +++ b/APC40_MkII/QuantizationComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40_MkII/QuantizationComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40_MkII/QuantizationComponent.py import Live from _Framework.Control import RadioButtonControl, control_list from _Framework.ControlSurfaceComponent import ControlSurfaceComponent diff --git a/APC40_MkII/TransportComponent.py b/APC40_MkII/TransportComponent.py index f9d84279..1221c393 100644 --- a/APC40_MkII/TransportComponent.py +++ b/APC40_MkII/TransportComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40_MkII/TransportComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40_MkII/TransportComponent.py import Live from _Framework.Control import ButtonControl from _Framework.SubjectSlot import subject_slot @@ -11,7 +11,9 @@ class TransportComponent(TransportComponentBase): def __init__(self, *a, **k): def play_toggle_model_transform(val): - return False if self.shift_button.is_pressed else val + if self.shift_button.is_pressed: + return False + return val k['play_toggle_model_transform'] = play_toggle_model_transform super(TransportComponent, self).__init__(*a, **k) diff --git a/APC40_MkII/__init__.py b/APC40_MkII/__init__.py index 3d5ea68e..3c2b01f9 100644 --- a/APC40_MkII/__init__.py +++ b/APC40_MkII/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC40_MkII/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC40_MkII/__init__.py from _Framework.Capabilities import CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, SYNC, REMOTE, controller_id, inport, outport from APC40_MkII import APC40_MkII diff --git a/APC_Key_25/APC_Key_25.py b/APC_Key_25/APC_Key_25.py index 577a06c4..3eb47f2c 100644 --- a/APC_Key_25/APC_Key_25.py +++ b/APC_Key_25/APC_Key_25.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC_Key_25/APC_Key_25.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC_Key_25/APC_Key_25.py from __future__ import with_statement from functools import partial from _Framework.ButtonMatrixElement import ButtonMatrixElement @@ -107,7 +107,9 @@ def _create_device_component(self): def _create_transport(self): def play_toggle_model_transform(value): - return False if self._shift_button.is_pressed() else value + if self._shift_button.is_pressed(): + return False + return value return TransportComponent(name='Transport', is_enabled=False, play_toggle_model_transform=play_toggle_model_transform, layer=Layer(play_button=self._play_button, record_button=self._record_button)) diff --git a/APC_Key_25/MixerComponent.py b/APC_Key_25/MixerComponent.py index 3d7738cb..9049f04d 100644 --- a/APC_Key_25/MixerComponent.py +++ b/APC_Key_25/MixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC_Key_25/MixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC_Key_25/MixerComponent.py from _APC.MixerComponent import MixerComponent as MixerComponentBase from _APC.MixerComponent import ChanStripComponent as ChanStripComponentBase from _Framework.Util import nop diff --git a/APC_Key_25/SendToggleComponent.py b/APC_Key_25/SendToggleComponent.py index 5b7cd0d7..7bda759a 100644 --- a/APC_Key_25/SendToggleComponent.py +++ b/APC_Key_25/SendToggleComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC_Key_25/SendToggleComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC_Key_25/SendToggleComponent.py from _Framework.Control import ButtonControl from _Framework.ControlSurfaceComponent import ControlSurfaceComponent diff --git a/APC_Key_25/__init__.py b/APC_Key_25/__init__.py index 602014ea..fc113440 100644 --- a/APC_Key_25/__init__.py +++ b/APC_Key_25/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC_Key_25/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC_Key_25/__init__.py from _Framework.Capabilities import CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE, controller_id, inport, outport from APC_Key_25 import APC_Key_25 diff --git a/APC_mini/APC_mini.py b/APC_mini/APC_mini.py index 62ed7ae3..2126db2d 100644 --- a/APC_mini/APC_mini.py +++ b/APC_mini/APC_mini.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC_mini/APC_mini.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC_mini/APC_mini.py from __future__ import with_statement from _Framework.Layer import Layer, SimpleLayerOwner from _APC.ControlElementUtils import make_slider diff --git a/APC_mini/__init__.py b/APC_mini/__init__.py index 4ae2a572..f8d910e8 100644 --- a/APC_mini/__init__.py +++ b/APC_mini/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/APC_mini/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/APC_mini/__init__.py from _Framework.Capabilities import CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE, controller_id, inport, outport from APC_mini import APC_mini diff --git a/Alesis_V/Alesis_V.py b/Alesis_V/Alesis_V.py index cac1e984..8bb776e8 100644 --- a/Alesis_V/Alesis_V.py +++ b/Alesis_V/Alesis_V.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Alesis_V/Alesis_V.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Alesis_V/Alesis_V.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/Alesis_V/__init__.py b/Alesis_V/__init__.py index 3c7df5c9..db7add0d 100644 --- a/Alesis_V/__init__.py +++ b/Alesis_V/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Alesis_V/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Alesis_V/__init__.py from .Alesis_V import Alesis_V from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE diff --git a/Alesis_VI/Alesis_VI.py b/Alesis_VI/Alesis_VI.py index d5972007..6cf2ab52 100644 --- a/Alesis_VI/Alesis_VI.py +++ b/Alesis_VI/Alesis_VI.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Alesis_VI/Alesis_VI.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Alesis_VI/Alesis_VI.py from __future__ import with_statement from _Framework.ControlSurface import ControlSurface from _Framework.MidiMap import make_encoder, MidiMap as MidiMapBase diff --git a/Alesis_VI/__init__.py b/Alesis_VI/__init__.py index 8ecf4832..01152633 100644 --- a/Alesis_VI/__init__.py +++ b/Alesis_VI/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Alesis_VI/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Alesis_VI/__init__.py from .Alesis_VI import Alesis_VI from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE diff --git a/Alesis_VX/Alesis_VX.py b/Alesis_VX/Alesis_VX.py new file mode 100644 index 00000000..ce395704 --- /dev/null +++ b/Alesis_VX/Alesis_VX.py @@ -0,0 +1,5 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Alesis_VX/Alesis_VX.py +from ADVANCE.Advance import Advance + +class Alesis_VX(Advance): + pass \ No newline at end of file diff --git a/Alesis_VX/__init__.py b/Alesis_VX/__init__.py new file mode 100644 index 00000000..f7bd2aba --- /dev/null +++ b/Alesis_VX/__init__.py @@ -0,0 +1,11 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Alesis_VX/__init__.py +from .Alesis_VX import Alesis_VX +from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE + +def get_capabilities(): + return {CONTROLLER_ID_KEY: controller_id(vendor_id=5042, product_ids=[4176], model_name='VX49'), + PORTS_KEY: [inport(props=[NOTES_CC, SCRIPT, REMOTE]), outport(props=[SCRIPT])]} + + +def create_instance(c_instance): + return Alesis_VX(c_instance) \ No newline at end of file diff --git a/Axiom/__init__.py b/Axiom/__init__.py index 5d8c9f46..ac02f6af 100644 --- a/Axiom/__init__.py +++ b/Axiom/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Axiom/config.py b/Axiom/config.py index 623e19ab..43d246f8 100644 --- a/Axiom/config.py +++ b/Axiom/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom/config.py from consts import * from _Axiom.consts import PAD_TRANSLATION TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, diff --git a/Axiom/consts.py b/Axiom/consts.py index 3f04e71e..116f9c0b 100644 --- a/Axiom/consts.py +++ b/Axiom/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/AxiomPro/AxiomPro.py b/AxiomPro/AxiomPro.py index 28c29c28..0fe99284 100644 --- a/AxiomPro/AxiomPro.py +++ b/AxiomPro/AxiomPro.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/AxiomPro.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/AxiomPro.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/AxiomPro/DisplayingMixerComponent.py b/AxiomPro/DisplayingMixerComponent.py index 9a3bb2b8..4e03d35c 100644 --- a/AxiomPro/DisplayingMixerComponent.py +++ b/AxiomPro/DisplayingMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/DisplayingMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/DisplayingMixerComponent.py from _Framework.ButtonElement import ButtonElement from _Framework.MixerComponent import MixerComponent from _Framework.PhysicalDisplayElement import PhysicalDisplayElement @@ -59,22 +59,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 + 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 found_recording_clip or song.exclusive_arm: + 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 diff --git a/AxiomPro/EncoderMixerModeSelector.py b/AxiomPro/EncoderMixerModeSelector.py index 96e72b4f..9b5c4413 100644 --- a/AxiomPro/EncoderMixerModeSelector.py +++ b/AxiomPro/EncoderMixerModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/EncoderMixerModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/EncoderMixerModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.ButtonElement import ButtonElement from _Framework.DisplayDataSource import DisplayDataSource diff --git a/AxiomPro/MixerOrDeviceModeSelector.py b/AxiomPro/MixerOrDeviceModeSelector.py index 8a28a380..a1d30c4f 100644 --- a/AxiomPro/MixerOrDeviceModeSelector.py +++ b/AxiomPro/MixerOrDeviceModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/MixerOrDeviceModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/MixerOrDeviceModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.ButtonElement import ButtonElement from _Framework.DisplayDataSource import DisplayDataSource diff --git a/AxiomPro/NotifyingMixerComponent.py b/AxiomPro/NotifyingMixerComponent.py index 78fa50c0..1299e602 100644 --- a/AxiomPro/NotifyingMixerComponent.py +++ b/AxiomPro/NotifyingMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/NotifyingMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/NotifyingMixerComponent.py from _Framework.MixerComponent import MixerComponent from _Framework.PhysicalDisplayElement import PhysicalDisplayElement diff --git a/AxiomPro/PageableDeviceComponent.py b/AxiomPro/PageableDeviceComponent.py index 85512d82..e3586751 100644 --- a/AxiomPro/PageableDeviceComponent.py +++ b/AxiomPro/PageableDeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/PageableDeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/PageableDeviceComponent.py import Live from _Generic.Devices import * from _Framework.DeviceComponent import DeviceComponent @@ -248,12 +248,12 @@ def __assign_parameters_plugin(self): display_string = ' - ' if index < num_banks: if index < num_double_pages: - if not (index == self._bank_index and self._page_index[index] == 0): - if index != self._bank_index: - add_offset_before = self._page_index[index] != 0 - add_offset_before and parameter_offset += num_controls - display_string = str(parameter_offset + 1).rjust(2) + '-' + str(parameter_offset + num_controls).rjust(2) - add_offset_before or parameter_offset += num_controls + add_offset_before = index == self._bank_index and self._page_index[index] == 0 or index != self._bank_index and self._page_index[index] != 0 + if add_offset_before: + parameter_offset += num_controls + display_string = str(parameter_offset + 1).rjust(2) + '-' + str(parameter_offset + num_controls).rjust(2) + if not add_offset_before: + parameter_offset += num_controls else: display_string = str(parameter_offset + 1).rjust(2) + '-' + str(parameter_offset + num_controls).rjust(2) self._page_name_data_sources[index].set_display_string(display_string) diff --git a/AxiomPro/PeekableEncoderElement.py b/AxiomPro/PeekableEncoderElement.py index 26099618..d39776c9 100644 --- a/AxiomPro/PeekableEncoderElement.py +++ b/AxiomPro/PeekableEncoderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/PeekableEncoderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/PeekableEncoderElement.py import Live from _Framework.EncoderElement import EncoderElement from _Framework.InputControlElement import * diff --git a/AxiomPro/SelectButtonModeSelector.py b/AxiomPro/SelectButtonModeSelector.py index 173b0914..d36593df 100644 --- a/AxiomPro/SelectButtonModeSelector.py +++ b/AxiomPro/SelectButtonModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/SelectButtonModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/SelectButtonModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.ButtonElement import ButtonElement from _Framework.PhysicalDisplayElement import PhysicalDisplayElement diff --git a/AxiomPro/TransportViewModeSelector.py b/AxiomPro/TransportViewModeSelector.py index 08bd2778..1567b6ba 100644 --- a/AxiomPro/TransportViewModeSelector.py +++ b/AxiomPro/TransportViewModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/TransportViewModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/TransportViewModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.ButtonElement import ButtonElement from _Framework.TransportComponent import TransportComponent diff --git a/AxiomPro/__init__.py b/AxiomPro/__init__.py index 9c81a99c..785545e9 100644 --- a/AxiomPro/__init__.py +++ b/AxiomPro/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/AxiomPro/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/AxiomPro/__init__.py from AxiomPro import AxiomPro def create_instance(c_instance): diff --git a/Axiom_25_Classic/Axiom.py b/Axiom_25_Classic/Axiom.py index e5323973..d8534e24 100644 --- a/Axiom_25_Classic/Axiom.py +++ b/Axiom_25_Classic/Axiom.py @@ -1,8 +1,9 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_25_Classic/Axiom.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_25_Classic/Axiom.py from _Axiom.consts import * from _Axiom.Transport import Transport from _Axiom.Pads import Pads from _Axiom.Encoders import Encoders +from _Generic.util import DeviceAppointer import Live import MidiRemoteScript @@ -17,6 +18,7 @@ def __init__(self, c_instance): self.__transport_unit = Transport(self) self.__encoder_unit = Encoders(self, False) self.__pad_unit = Pads(self) + self._device_appointer = DeviceAppointer(song=self.song(), appointed_device_setter=self._set_appointed_device) def application(self): """returns a reference to the application that we are running in @@ -33,6 +35,7 @@ def disconnect(self): Called right before we get disconnected from Live. """ self.song().remove_visible_tracks_listener(self.__tracks_changed) + self._device_appointer.disconnect() self.__encoder_unit.disconnect() def can_lock_to_devices(self): @@ -147,7 +150,7 @@ def lock_to_device(self, device): def unlock_from_device(self, device): self.__encoder_unit.unlock_from_device(device) - def set_appointed_device(self, device): + def _set_appointed_device(self, device): self.__encoder_unit.set_appointed_device(device) def __tracks_changed(self): diff --git a/Axiom_25_Classic/__init__.py b/Axiom_25_Classic/__init__.py index 4042f11f..5fb56343 100644 --- a/Axiom_25_Classic/__init__.py +++ b/Axiom_25_Classic/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_25_Classic/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_25_Classic/__init__.py from Axiom import Axiom def create_instance(c_instance): diff --git a/Axiom_49_61_Classic/Axiom.py b/Axiom_49_61_Classic/Axiom.py index ac55a378..6bbf8d73 100644 --- a/Axiom_49_61_Classic/Axiom.py +++ b/Axiom_49_61_Classic/Axiom.py @@ -1,9 +1,10 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_49_61_Classic/Axiom.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_49_61_Classic/Axiom.py from _Axiom.consts import * from _Axiom.Transport import Transport from _Axiom.Pads import Pads from _Axiom.Encoders import Encoders from SliderSection import SliderSection +from _Generic.util import DeviceAppointer import Live import MidiRemoteScript @@ -19,6 +20,7 @@ def __init__(self, c_instance): self.__encoder_unit = Encoders(self, True) self.__slider_unit = SliderSection(self) self.__pad_unit = Pads(self) + self._device_appointer = DeviceAppointer(song=self.song(), appointed_device_setter=self._set_appointed_device) def application(self): """returns a reference to the application that we are running in @@ -35,6 +37,7 @@ def disconnect(self): Called right before we get disconnected from Live. """ self.song().remove_visible_tracks_listener(self.__tracks_changed) + self._device_appointer.disconnect() self.__encoder_unit.disconnect() def can_lock_to_devices(self): @@ -146,7 +149,7 @@ def lock_to_device(self, device): def unlock_from_device(self, device): self.__encoder_unit.unlock_from_device(device) - def set_appointed_device(self, device): + def _set_appointed_device(self, device): self.__encoder_unit.set_appointed_device(device) def __tracks_changed(self): diff --git a/Axiom_49_61_Classic/SliderSection.py b/Axiom_49_61_Classic/SliderSection.py index b231b94c..4115e729 100644 --- a/Axiom_49_61_Classic/SliderSection.py +++ b/Axiom_49_61_Classic/SliderSection.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_49_61_Classic/SliderSection.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_49_61_Classic/SliderSection.py import Live from _Axiom.consts import * diff --git a/Axiom_49_61_Classic/__init__.py b/Axiom_49_61_Classic/__init__.py index a59383bc..4ffbf3a3 100644 --- a/Axiom_49_61_Classic/__init__.py +++ b/Axiom_49_61_Classic/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_49_61_Classic/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_49_61_Classic/__init__.py from Axiom import Axiom def create_instance(c_instance): diff --git a/Axiom_AIR_25_49_61/Axiom_AIR_25_49_61.py b/Axiom_AIR_25_49_61/Axiom_AIR_25_49_61.py index fccc5653..1dc3f3e5 100644 --- a/Axiom_AIR_25_49_61/Axiom_AIR_25_49_61.py +++ b/Axiom_AIR_25_49_61/Axiom_AIR_25_49_61.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/Axiom_AIR_25_49_61.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/Axiom_AIR_25_49_61.py from __future__ import with_statement import Live from Live import MidiMap diff --git a/Axiom_AIR_25_49_61/BestBankDeviceComponent.py b/Axiom_AIR_25_49_61/BestBankDeviceComponent.py index 7e610be6..20c52211 100644 --- a/Axiom_AIR_25_49_61/BestBankDeviceComponent.py +++ b/Axiom_AIR_25_49_61/BestBankDeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/BestBankDeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/BestBankDeviceComponent.py from _Framework.DeviceComponent import DeviceComponent from _Generic.Devices import parameter_bank_names, parameter_banks, DEVICE_DICT, BANK_NAME_DICT, DEVICE_BOB_DICT BOP_BANK_NAME = 'Best of Parameters' diff --git a/Axiom_AIR_25_49_61/ConfigurableButtonElement.py b/Axiom_AIR_25_49_61/ConfigurableButtonElement.py index 9761b33b..ec0848ab 100644 --- a/Axiom_AIR_25_49_61/ConfigurableButtonElement.py +++ b/Axiom_AIR_25_49_61/ConfigurableButtonElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/ConfigurableButtonElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/ConfigurableButtonElement.py from _Framework.ButtonElement import ButtonElement from _Framework.InputControlElement import MIDI_NOTE_TYPE, MIDI_CC_TYPE, MIDI_CC_STATUS from consts import * diff --git a/Axiom_AIR_25_49_61/DeviceNavComponent.py b/Axiom_AIR_25_49_61/DeviceNavComponent.py index c30c4b33..71350c8d 100644 --- a/Axiom_AIR_25_49_61/DeviceNavComponent.py +++ b/Axiom_AIR_25_49_61/DeviceNavComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/DeviceNavComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/DeviceNavComponent.py import Live from _Framework.ControlSurfaceComponent import ControlSurfaceComponent diff --git a/Axiom_AIR_25_49_61/DisplayingChanStripComponent.py b/Axiom_AIR_25_49_61/DisplayingChanStripComponent.py index d787af7b..9b04c31e 100644 --- a/Axiom_AIR_25_49_61/DisplayingChanStripComponent.py +++ b/Axiom_AIR_25_49_61/DisplayingChanStripComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/DisplayingChanStripComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/DisplayingChanStripComponent.py from _Framework.ButtonElement import ButtonElement from _Framework.ChannelStripComponent import ChannelStripComponent from consts import * @@ -60,21 +60,21 @@ def _on_arm_changed(self): def _mute_value(self, value): ChannelStripComponent._mute_value(self, value) - if self._track != None and self._track != self.song().master_track: - if self._name_display != None and self._value_display != None: - value != 0 and self._name_display.display_message('Mute :') + if self._track != None and self._track != self.song().master_track and self._name_display != None and self._value_display != None: + if value != 0: + self._name_display.display_message('Mute :') self._value_display.send_midi(DISPLAY_WORD_ON) if self._track.mute else self._value_display.send_midi(DISPLAY_WORD_OFF) def _solo_value(self, value): ChannelStripComponent._solo_value(self, value) - if self._track != None and self._track != self.song().master_track: - if self._name_display != None and self._value_display != None: - value != 0 and self._name_display.display_message('Solo :') + if self._track != None and self._track != self.song().master_track and self._name_display != None and self._value_display != None: + if value != 0: + self._name_display.display_message('Solo :') self._value_display.send_midi(DISPLAY_WORD_ON) if self._track.solo else self._value_display.send_midi(DISPLAY_WORD_OFF) def _arm_value(self, value): ChannelStripComponent._arm_value(self, value) - if self._track != None and self._track != self.song().master_track and self._name_display != None and self._value_display != None: - if self._track not in self.song().return_tracks: - value != 0 and self._name_display.display_message('Arm :') + if self._track != None and self._track != self.song().master_track and self._name_display != None and self._value_display != None and self._track not in self.song().return_tracks: + if value != 0: + self._name_display.display_message('Arm :') self._value_display.send_midi(DISPLAY_WORD_ON) if self._track.arm else self._value_display.send_midi(DISPLAY_WORD_OFF) \ No newline at end of file diff --git a/Axiom_AIR_25_49_61/EncoderModeSelector.py b/Axiom_AIR_25_49_61/EncoderModeSelector.py index acc9a05f..020b36ef 100644 --- a/Axiom_AIR_25_49_61/EncoderModeSelector.py +++ b/Axiom_AIR_25_49_61/EncoderModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/EncoderModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/EncoderModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from consts import * diff --git a/Axiom_AIR_25_49_61/FaderButtonModeSelector.py b/Axiom_AIR_25_49_61/FaderButtonModeSelector.py index 8471ffe5..9a702522 100644 --- a/Axiom_AIR_25_49_61/FaderButtonModeSelector.py +++ b/Axiom_AIR_25_49_61/FaderButtonModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/FaderButtonModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/FaderButtonModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from consts import * diff --git a/Axiom_AIR_25_49_61/FaderModeSelector.py b/Axiom_AIR_25_49_61/FaderModeSelector.py index 0593c895..ab33e923 100644 --- a/Axiom_AIR_25_49_61/FaderModeSelector.py +++ b/Axiom_AIR_25_49_61/FaderModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/FaderModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/FaderModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from consts import * diff --git a/Axiom_AIR_25_49_61/IdentifyingEncoderElement.py b/Axiom_AIR_25_49_61/IdentifyingEncoderElement.py index f26000f9..bf45dae6 100644 --- a/Axiom_AIR_25_49_61/IdentifyingEncoderElement.py +++ b/Axiom_AIR_25_49_61/IdentifyingEncoderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/IdentifyingEncoderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/IdentifyingEncoderElement.py from _Framework.EncoderElement import EncoderElement from _Framework.InputControlElement import * diff --git a/Axiom_AIR_25_49_61/MainModeSelector.py b/Axiom_AIR_25_49_61/MainModeSelector.py index 526b3cdb..830036c7 100644 --- a/Axiom_AIR_25_49_61/MainModeSelector.py +++ b/Axiom_AIR_25_49_61/MainModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/MainModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/MainModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from consts import * diff --git a/Axiom_AIR_25_49_61/NumericalDisplayElement.py b/Axiom_AIR_25_49_61/NumericalDisplayElement.py index d4e4c3e7..53a7a7a9 100644 --- a/Axiom_AIR_25_49_61/NumericalDisplayElement.py +++ b/Axiom_AIR_25_49_61/NumericalDisplayElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/NumericalDisplayElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/NumericalDisplayElement.py from _Framework.PhysicalDisplayElement import PhysicalDisplayElement from NumericalDisplaySegment import NumericalDisplaySegment diff --git a/Axiom_AIR_25_49_61/NumericalDisplaySegment.py b/Axiom_AIR_25_49_61/NumericalDisplaySegment.py index 34ead56c..e6ec4447 100644 --- a/Axiom_AIR_25_49_61/NumericalDisplaySegment.py +++ b/Axiom_AIR_25_49_61/NumericalDisplaySegment.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/NumericalDisplaySegment.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/NumericalDisplaySegment.py from _Framework.LogicalDisplaySegment import LogicalDisplaySegment class NumericalDisplaySegment(LogicalDisplaySegment): diff --git a/Axiom_AIR_25_49_61/SingleFaderButtonModeSelector.py b/Axiom_AIR_25_49_61/SingleFaderButtonModeSelector.py index e4127090..5d26ca57 100644 --- a/Axiom_AIR_25_49_61/SingleFaderButtonModeSelector.py +++ b/Axiom_AIR_25_49_61/SingleFaderButtonModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/SingleFaderButtonModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/SingleFaderButtonModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from consts import * diff --git a/Axiom_AIR_25_49_61/SpecialMixerComponent.py b/Axiom_AIR_25_49_61/SpecialMixerComponent.py index 8b080206..a3d3501e 100644 --- a/Axiom_AIR_25_49_61/SpecialMixerComponent.py +++ b/Axiom_AIR_25_49_61/SpecialMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/SpecialMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/SpecialMixerComponent.py from _Framework.MixerComponent import MixerComponent from DisplayingChanStripComponent import DisplayingChanStripComponent diff --git a/Axiom_AIR_25_49_61/SpecialSessionComponent.py b/Axiom_AIR_25_49_61/SpecialSessionComponent.py index 023cd80e..18ca67f6 100644 --- a/Axiom_AIR_25_49_61/SpecialSessionComponent.py +++ b/Axiom_AIR_25_49_61/SpecialSessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/SpecialSessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/SpecialSessionComponent.py from _Framework.SessionComponent import SessionComponent class SpecialSessionComponent(SessionComponent): @@ -56,20 +56,20 @@ def tracks_to_use(self): return list_of_tracks def _change_offsets(self, track_increment, scene_increment): - if not track_increment != 0: - offsets_changed = scene_increment != 0 - if offsets_changed: - self._track_offset += track_increment - self._scene_offset += scene_increment - if self._mixer != None: - self._mixer.set_track_offset(self.track_offset()) - if self._alt_mixer != None: - self._alt_mixer.set_track_offset(self.track_offset()) - self._reassign_tracks() - if offsets_changed: - self._reassign_scenes() - self.notify_offset() - self.width() > 0 and self.height() > 0 and self._do_show_highlight() + offsets_changed = track_increment != 0 or scene_increment != 0 + if offsets_changed: + self._track_offset += track_increment + self._scene_offset += scene_increment + if self._mixer != None: + self._mixer.set_track_offset(self.track_offset()) + if self._alt_mixer != None: + self._alt_mixer.set_track_offset(self.track_offset()) + self._reassign_tracks() + if offsets_changed: + self._reassign_scenes() + self.notify_offset() + if self.width() > 0 and self.height() > 0: + self._do_show_highlight() def _next_track_value(self, value): if self.is_enabled(): diff --git a/Axiom_AIR_25_49_61/TransportViewModeSelector.py b/Axiom_AIR_25_49_61/TransportViewModeSelector.py index fc82ac09..2ffcd14a 100644 --- a/Axiom_AIR_25_49_61/TransportViewModeSelector.py +++ b/Axiom_AIR_25_49_61/TransportViewModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/TransportViewModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/TransportViewModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent class TransportViewModeSelector(ModeSelectorComponent): diff --git a/Axiom_AIR_25_49_61/__init__.py b/Axiom_AIR_25_49_61/__init__.py index 5bc44d3a..70c13855 100644 --- a/Axiom_AIR_25_49_61/__init__.py +++ b/Axiom_AIR_25_49_61/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/__init__.py from Axiom_AIR_25_49_61 import Axiom_AIR_25_49_61 from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT diff --git a/Axiom_AIR_25_49_61/consts.py b/Axiom_AIR_25_49_61/consts.py index c585a69c..1e6e6016 100644 --- a/Axiom_AIR_25_49_61/consts.py +++ b/Axiom_AIR_25_49_61/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_25_49_61/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_25_49_61/consts.py SYSEX_START = (240, 0, 1, 5, 32, 127) IDENTITY_REQUEST = (240, 126, 127, 6, 1, 247) AXIOM_AIR_RESPONSE = (240, 126, 127, 6, 2, 0, 1, 5, 99, 14) diff --git a/Axiom_AIR_Mini32/AxiomAirMini32.py b/Axiom_AIR_Mini32/AxiomAirMini32.py index 7442b146..ef2e8f28 100644 --- a/Axiom_AIR_Mini32/AxiomAirMini32.py +++ b/Axiom_AIR_Mini32/AxiomAirMini32.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_Mini32/AxiomAirMini32.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_Mini32/AxiomAirMini32.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/Axiom_AIR_Mini32/DeviceNavComponent.py b/Axiom_AIR_Mini32/DeviceNavComponent.py index 23612cf6..12c344f7 100644 --- a/Axiom_AIR_Mini32/DeviceNavComponent.py +++ b/Axiom_AIR_Mini32/DeviceNavComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_Mini32/DeviceNavComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_Mini32/DeviceNavComponent.py import Live from _Framework.ControlSurfaceComponent import ControlSurfaceComponent diff --git a/Axiom_AIR_Mini32/EncoderMixerModeSelector.py b/Axiom_AIR_Mini32/EncoderMixerModeSelector.py index 08ba87b5..72233031 100644 --- a/Axiom_AIR_Mini32/EncoderMixerModeSelector.py +++ b/Axiom_AIR_Mini32/EncoderMixerModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_Mini32/EncoderMixerModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_Mini32/EncoderMixerModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent class EncoderMixerModeSelector(ModeSelectorComponent): diff --git a/Axiom_AIR_Mini32/MixerOrDeviceModeSelector.py b/Axiom_AIR_Mini32/MixerOrDeviceModeSelector.py index 019ff9e5..33d45bef 100644 --- a/Axiom_AIR_Mini32/MixerOrDeviceModeSelector.py +++ b/Axiom_AIR_Mini32/MixerOrDeviceModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_Mini32/MixerOrDeviceModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_Mini32/MixerOrDeviceModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent class MixerOrDeviceModeSelector(ModeSelectorComponent): diff --git a/Axiom_AIR_Mini32/__init__.py b/Axiom_AIR_Mini32/__init__.py index c94d0add..53f4028a 100644 --- a/Axiom_AIR_Mini32/__init__.py +++ b/Axiom_AIR_Mini32/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_AIR_Mini32/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_AIR_Mini32/__init__.py from AxiomAirMini32 import AxiomAirMini32 from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT diff --git a/Axiom_DirectLink/Axiom_DirectLink.py b/Axiom_DirectLink/Axiom_DirectLink.py index 3e44bf21..963a9f2f 100644 --- a/Axiom_DirectLink/Axiom_DirectLink.py +++ b/Axiom_DirectLink/Axiom_DirectLink.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_DirectLink/Axiom_DirectLink.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_DirectLink/Axiom_DirectLink.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/Axiom_DirectLink/BestBankDeviceComponent.py b/Axiom_DirectLink/BestBankDeviceComponent.py index 4cc5672d..ceffee78 100644 --- a/Axiom_DirectLink/BestBankDeviceComponent.py +++ b/Axiom_DirectLink/BestBankDeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_DirectLink/BestBankDeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_DirectLink/BestBankDeviceComponent.py import Live from _Framework.DeviceComponent import DeviceComponent from _Framework.DisplayDataSource import DisplayDataSource @@ -16,9 +16,9 @@ def __init__(self): self._device_bank_names = BANK_NAME_DICT self._device_best_banks = DEVICE_BOB_DICT for device_name, current_banks in self._device_banks.iteritems(): - raise len(current_banks) > 1 and (device_name in self._device_best_banks.keys() or AssertionError), "Could not find best-of-banks for '%s'" % device_name - if not device_name in self._device_bank_names.keys(): - raise AssertionError, "Could not find bank names for '%s'" % device_name + if len(current_banks) > 1: + raise device_name in self._device_best_banks.keys() or AssertionError("Could not find best-of-banks for '%s'" % device_name) + raise device_name in self._device_bank_names.keys() or AssertionError("Could not find bank names for '%s'" % device_name) current_banks = self._device_best_banks[device_name] + current_banks new_bank_names[device_name] = (BOP_BANK_NAME,) + self._device_bank_names[device_name] new_banks[device_name] = current_banks diff --git a/Axiom_DirectLink/DetailViewCntrlComponent.py b/Axiom_DirectLink/DetailViewCntrlComponent.py index b7e1ea08..7100a42d 100644 --- a/Axiom_DirectLink/DetailViewCntrlComponent.py +++ b/Axiom_DirectLink/DetailViewCntrlComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_DirectLink/DetailViewCntrlComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_DirectLink/DetailViewCntrlComponent.py import Live from _Framework.ControlSurfaceComponent import ControlSurfaceComponent from _Framework.ButtonElement import ButtonElement diff --git a/Axiom_DirectLink/PeekableEncoderElement.py b/Axiom_DirectLink/PeekableEncoderElement.py index 3c67a624..d342b103 100644 --- a/Axiom_DirectLink/PeekableEncoderElement.py +++ b/Axiom_DirectLink/PeekableEncoderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_DirectLink/PeekableEncoderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_DirectLink/PeekableEncoderElement.py import Live from _Framework.EncoderElement import EncoderElement from _Framework.InputControlElement import * diff --git a/Axiom_DirectLink/ShiftableMixerComponent.py b/Axiom_DirectLink/ShiftableMixerComponent.py index a3591a29..9f747505 100644 --- a/Axiom_DirectLink/ShiftableMixerComponent.py +++ b/Axiom_DirectLink/ShiftableMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_DirectLink/ShiftableMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_DirectLink/ShiftableMixerComponent.py from _Framework.MixerComponent import MixerComponent from _Framework.ButtonElement import ButtonElement @@ -97,22 +97,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 + 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 found_recording_clip or song.exclusive_arm: + 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 diff --git a/Axiom_DirectLink/ShiftableSessionComponent.py b/Axiom_DirectLink/ShiftableSessionComponent.py index b563404e..1152beba 100644 --- a/Axiom_DirectLink/ShiftableSessionComponent.py +++ b/Axiom_DirectLink/ShiftableSessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_DirectLink/ShiftableSessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_DirectLink/ShiftableSessionComponent.py from _Framework.SessionComponent import SessionComponent from _Framework.ButtonElement import ButtonElement diff --git a/Axiom_DirectLink/ShiftableTransportComponent.py b/Axiom_DirectLink/ShiftableTransportComponent.py index 830223d9..b82cfaf2 100644 --- a/Axiom_DirectLink/ShiftableTransportComponent.py +++ b/Axiom_DirectLink/ShiftableTransportComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_DirectLink/ShiftableTransportComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_DirectLink/ShiftableTransportComponent.py import Live from _Framework.ButtonElement import ButtonElement from _Framework.TransportComponent import TransportComponent diff --git a/Axiom_DirectLink/TransportViewModeSelector.py b/Axiom_DirectLink/TransportViewModeSelector.py index 0f0e9b49..1afccff0 100644 --- a/Axiom_DirectLink/TransportViewModeSelector.py +++ b/Axiom_DirectLink/TransportViewModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_DirectLink/TransportViewModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_DirectLink/TransportViewModeSelector.py import Live from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.ButtonElement import ButtonElement diff --git a/Axiom_DirectLink/__init__.py b/Axiom_DirectLink/__init__.py index 13a91f7f..e7079f8c 100644 --- a/Axiom_DirectLink/__init__.py +++ b/Axiom_DirectLink/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Axiom_DirectLink/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Axiom_DirectLink/__init__.py from Axiom_DirectLink import Axiom_DirectLink def create_instance(c_instance): diff --git a/BCF2000/__init__.py b/BCF2000/__init__.py index f7a43a55..2b29e06d 100644 --- a/BCF2000/__init__.py +++ b/BCF2000/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/BCF2000/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/BCF2000/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/BCF2000/config.py b/BCF2000/config.py index 25c1ac58..c3669ec2 100644 --- a/BCF2000/config.py +++ b/BCF2000/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/BCF2000/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/BCF2000/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/BCF2000/consts.py b/BCF2000/consts.py index 9735a5bc..d6f9ae30 100644 --- a/BCF2000/consts.py +++ b/BCF2000/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/BCF2000/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/BCF2000/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/BCR2000/__init__.py b/BCR2000/__init__.py index ec05bb64..5ba317ca 100644 --- a/BCR2000/__init__.py +++ b/BCR2000/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/BCR2000/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/BCR2000/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/BCR2000/config.py b/BCR2000/config.py index b489d2d8..9588e747 100644 --- a/BCR2000/config.py +++ b/BCR2000/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/BCR2000/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/BCR2000/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/BCR2000/consts.py b/BCR2000/consts.py index afbbdbb4..f1108def 100644 --- a/BCR2000/consts.py +++ b/BCR2000/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/BCR2000/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/BCR2000/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/BeatStep/BeatStep.py b/BeatStep/BeatStep.py new file mode 100644 index 00000000..82151be6 --- /dev/null +++ b/BeatStep/BeatStep.py @@ -0,0 +1,89 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/BeatStep/BeatStep.py +from __future__ import with_statement +from itertools import izip, chain +import Live +from _Arturia.ArturiaControlSurface import ArturiaControlSurface +from _Arturia.SessionComponent import SessionComponent +from _Arturia.MixerComponent import MixerComponent +from _Framework.Layer import Layer +from _Framework.Skin import Skin +from _Framework.DeviceComponent import DeviceComponent +from _Framework.TransportComponent import TransportComponent +from _Framework.InputControlElement import MIDI_CC_TYPE, MIDI_NOTE_TYPE +from _Framework.ButtonMatrixElement import ButtonMatrixElement +from _Framework.ButtonElement import ButtonElement, Color +from _Framework.EncoderElement import EncoderElement +HARDWARE_ENCODER_IDS = xrange(32, 48) +HARDWARE_STOP_BUTTON_ID = 89 +HARDWARE_PLAY_BUTTON_ID = 88 +HARDWARE_PAD_IDS = xrange(112, 128) +ENCODER_MSG_IDS = (10, 74, 71, 76, 77, 93, 73, 75, 114, 18, 19, 16, 17, 91, 79, 72) +PAD_MSG_IDS = (xrange(44, 52), xrange(36, 44)) +PAD_CHANNEL = 9 + +class Colors: + + class Session: + ClipStarted = Color(0) + ClipStopped = Color(0) + ClipRecording = Color(0) + ClipTriggeredPlay = Color(0) + ClipTriggeredRecord = Color(0) + RecordButton = Color(0) + ClipEmpty = Color(0) + + +class BeatStep(ArturiaControlSurface): + + def __init__(self, *a, **k): + super(BeatStep, self).__init__(*a, **k) + self._skin = Skin(Colors) + with self.component_guard(): + self._create_controls() + self._create_device() + self._create_session() + self._create_mixer() + self._create_transport() + + def _create_controls(self): + self._device_encoders = ButtonMatrixElement(rows=[ [ EncoderElement(MIDI_CC_TYPE, 0, identifier, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Encoder_%d_%d' % (column_index, row_index)) for column_index, identifier in enumerate(row) ] for row_index, row in enumerate((ENCODER_MSG_IDS[:4], ENCODER_MSG_IDS[8:12])) ]) + self._horizontal_scroll_encoder = EncoderElement(MIDI_CC_TYPE, 0, 75, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Horizontal_Scroll_Encoder') + self._vertical_scroll_encoder = EncoderElement(MIDI_CC_TYPE, 0, 72, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Vertical_Scroll_Encoder') + self._volume_encoder = EncoderElement(MIDI_CC_TYPE, 0, 91, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Volume_Encoder') + self._pan_encoder = EncoderElement(MIDI_CC_TYPE, 0, 17, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Pan_Encoder') + self._send_a_encoder = EncoderElement(MIDI_CC_TYPE, 0, 77, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Send_A_Encoder') + self._send_b_encoder = EncoderElement(MIDI_CC_TYPE, 0, 93, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Send_B_Encoder') + self._send_encoders = ButtonMatrixElement(rows=[[self._send_a_encoder, self._send_b_encoder]]) + self._return_a_encoder = EncoderElement(MIDI_CC_TYPE, 0, 73, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Return_A_Encoder') + self._return_b_encoder = EncoderElement(MIDI_CC_TYPE, 0, 79, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Return_B_Encoder') + self._return_encoders = ButtonMatrixElement(rows=[[self._return_a_encoder, self._return_b_encoder]]) + self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_NOTE_TYPE, PAD_CHANNEL, identifier, name='Pad_%d_%d' % (col_index, row_index), skin=self._skin) for col_index, identifier in enumerate(row) ] for row_index, row in enumerate(PAD_MSG_IDS) ]) + self._stop_button = ButtonElement(True, MIDI_CC_TYPE, 0, 1, name='Stop_Button') + self._play_button = ButtonElement(True, MIDI_CC_TYPE, 0, 2, name='Play_Button') + + def _create_device(self): + self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=self._device_encoders)) + self._device.set_enabled(True) + self.set_device_component(self._device) + self._device_selection_follows_track_selection = True + + def _create_session(self): + self._session = SessionComponent(name='Session', is_enabled=False, num_tracks=self._pads.width(), num_scenes=self._pads.height(), enable_skinning=True, layer=Layer(clip_launch_buttons=self._pads, scene_select_control=self._vertical_scroll_encoder)) + self._session.set_enabled(True) + + def _create_mixer(self): + self._mixer = MixerComponent(name='Mixer', is_enabled=False, num_returns=2, layer=Layer(track_select_encoder=self._horizontal_scroll_encoder, selected_track_volume_control=self._volume_encoder, selected_track_pan_control=self._pan_encoder, selected_track_send_controls=self._send_encoders, return_volume_controls=self._return_encoders)) + self._mixer.set_enabled(True) + + def _create_transport(self): + self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(stop_button=self._stop_button, play_button=self._play_button)) + self._transport.set_enabled(True) + + def _collect_setup_messages(self): + for identifier, hardware_id in izip(ENCODER_MSG_IDS, HARDWARE_ENCODER_IDS): + self._setup_hardware_encoder(hardware_id, identifier) + + self._setup_hardware_button(HARDWARE_STOP_BUTTON_ID, 1, msg_type='cc') + self._setup_hardware_button(HARDWARE_PLAY_BUTTON_ID, 2, msg_type='cc') + for hardware_id, identifier in izip(HARDWARE_PAD_IDS, chain(*PAD_MSG_IDS)): + self._setup_hardware_button(hardware_id, identifier, PAD_CHANNEL, msg_type='note') \ No newline at end of file diff --git a/BeatStep/__init__.py b/BeatStep/__init__.py new file mode 100644 index 00000000..02249600 --- /dev/null +++ b/BeatStep/__init__.py @@ -0,0 +1,11 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/BeatStep/__init__.py +import _Framework.Capabilities as caps +from .BeatStep import BeatStep + +def get_capabilities(): + return {caps.CONTROLLER_ID_KEY: caps.controller_id(vendor_id=7285, product_ids=[518], model_name=['Arturia BeatStep']), + caps.PORTS_KEY: [caps.inport(props=[caps.NOTES_CC, caps.SCRIPT, caps.REMOTE]), caps.outport(props=[caps.SCRIPT])]} + + +def create_instance(c_instance): + return BeatStep(c_instance) \ No newline at end of file diff --git a/FireOne/FireOne.py b/FireOne/FireOne.py index 747d04f0..e555e2d8 100644 --- a/FireOne/FireOne.py +++ b/FireOne/FireOne.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/FireOne/FireOne.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/FireOne/FireOne.py import Live import MidiRemoteScript NOTE_OFF_STATUS = 128 diff --git a/FireOne/__init__.py b/FireOne/__init__.py index ad430ae1..d2277fb3 100644 --- a/FireOne/__init__.py +++ b/FireOne/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/FireOne/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/FireOne/__init__.py from FireOne import FireOne def create_instance(c_instance): diff --git a/KONTROL49/__init__.py b/KONTROL49/__init__.py index cb80d258..1009f274 100644 --- a/KONTROL49/__init__.py +++ b/KONTROL49/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/KONTROL49/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KONTROL49/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/KONTROL49/config.py b/KONTROL49/config.py index 629fa5e3..ae5337c0 100644 --- a/KONTROL49/config.py +++ b/KONTROL49/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/KONTROL49/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KONTROL49/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/KONTROL49/consts.py b/KONTROL49/consts.py index d7551724..919c3b62 100644 --- a/KONTROL49/consts.py +++ b/KONTROL49/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/KONTROL49/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KONTROL49/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/KeyFadr/KeyFadr.py b/KeyFadr/KeyFadr.py index 011c41a0..ef62cc74 100644 --- a/KeyFadr/KeyFadr.py +++ b/KeyFadr/KeyFadr.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/KeyFadr/KeyFadr.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyFadr/KeyFadr.py from KeyPad import KeyPad class KeyFadr(KeyPad): diff --git a/KeyFadr/__init__.py b/KeyFadr/__init__.py index 3b65a242..0781d0ef 100644 --- a/KeyFadr/__init__.py +++ b/KeyFadr/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/KeyFadr/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyFadr/__init__.py from KeyFadr import KeyFadr from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT diff --git a/KeyLab/DeviceNavigationComponent.py b/KeyLab/DeviceNavigationComponent.py new file mode 100644 index 00000000..3d4f4513 --- /dev/null +++ b/KeyLab/DeviceNavigationComponent.py @@ -0,0 +1,25 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyLab/DeviceNavigationComponent.py +import Live +from _Framework.ControlSurfaceComponent import ControlSurfaceComponent +from _Framework.Control import ButtonControl +NavDirection = Live.Application.Application.View.NavDirection + +class DeviceNavigationComponent(ControlSurfaceComponent): + device_nav_left_button = ButtonControl() + device_nav_right_button = ButtonControl() + + @device_nav_left_button.pressed + def device_nav_left_button(self, value): + self._scroll_device_chain(NavDirection.left) + + @device_nav_right_button.pressed + def device_nav_right_button(self, value): + self._scroll_device_chain(NavDirection.right) + + def _scroll_device_chain(self, direction): + view = self.application().view + 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) \ No newline at end of file diff --git a/KeyLab/DisplayElement.py b/KeyLab/DisplayElement.py new file mode 100644 index 00000000..6bcf3c35 --- /dev/null +++ b/KeyLab/DisplayElement.py @@ -0,0 +1,76 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyLab/DisplayElement.py +from itertools import chain +from _Framework.PhysicalDisplayElement import PhysicalDisplayElement + +class DisplayElement(PhysicalDisplayElement): + _ascii_translations = {'\x00': 0, + ' ': 32, + '%': 37, + '1': 49, + '2': 50, + '3': 51, + '4': 52, + '5': 53, + '6': 54, + '7': 55, + '8': 56, + '9': 57, + ':': 58, + '?': 63, + 'A': 65, + 'B': 66, + 'C': 67, + 'D': 68, + 'E': 69, + 'F': 70, + 'G': 71, + 'H': 72, + 'I': 73, + 'J': 74, + 'K': 75, + 'L': 76, + 'M': 77, + 'N': 78, + 'O': 79, + 'P': 80, + 'Q': 81, + 'R': 82, + 'S': 83, + 'T': 84, + 'U': 85, + 'V': 86, + 'W': 87, + 'X': 88, + 'Y': 89, + 'Z': 90, + 'a': 97, + 'b': 98, + 'c': 99, + 'd': 100, + 'e': 101, + 'f': 102, + 'g': 103, + 'h': 104, + 'i': 105, + 'j': 106, + 'k': 107, + 'l': 108, + 'm': 109, + 'n': 110, + 'o': 111, + 'p': 112, + 'q': 113, + 'r': 114, + 's': 115, + 't': 116, + 'u': 117, + 'v': 118, + 'w': 119, + 'x': 120, + 'y': 121, + 'z': 122} + + def _build_display_message(self, display): + message_string = display.display_string + first_segment = display._logical_segments[0] + return chain(first_segment.position_identifier(), self._translate_string(message_string)) \ No newline at end of file diff --git a/KeyLab/KeyLab.py b/KeyLab/KeyLab.py new file mode 100644 index 00000000..27226f03 --- /dev/null +++ b/KeyLab/KeyLab.py @@ -0,0 +1,156 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyLab/KeyLab.py +from __future__ import with_statement +from itertools import izip +import Live +from _Arturia.ArturiaControlSurface import ArturiaControlSurface, MODE_PROPERTY, SETUP_MSG_PREFIX, SETUP_MSG_SUFFIX +from _Framework.Layer import Layer +from _Framework.DeviceComponent import DeviceComponent +from _Framework.DrumRackComponent import DrumRackComponent +from _Framework.TransportComponent import TransportComponent +from _Framework.SessionRecordingComponent import SessionRecordingComponent +from _Framework.ClipCreator import ClipCreator +from _Framework.ViewControlComponent import ViewControlComponent +from _Framework.InputControlElement import MIDI_CC_TYPE +from _Framework.ButtonMatrixElement import ButtonMatrixElement +from _Framework.ButtonElement import ButtonElement +from _Framework.EncoderElement import EncoderElement +from _Framework.SliderElement import SliderElement +from _Framework.DisplayDataSource import DisplayDataSource +from .DeviceNavigationComponent import DeviceNavigationComponent +from .MixerComponent import MixerComponent +from .SessionComponent import SessionComponent +from .DisplayElement import DisplayElement +PAD_NOTE_MODE = 10 +ENCODER_HARDWARE_IDS = xrange(33, 43) +SLIDER_HARDWARE_IDS = (43, 44, 45, 46, 107, 108, 109, 110, 111) +PAD_HARDWARE_IDS = xrange(112, 128) +ENCODER_MSG_IDS = (74, 71, 76, 77, 18, 19, 16, 17, 93, 91) +SLIDER_MSG_IDS = (73, 75, 79, 72, 80, 81, 82, 83, 85) +PAD_MSG_IDS = xrange(36, 52) +BUTTON_HARDWARE_AND_MESSAGE_IDS = {'session_record_button': (91, 5), + 'stop_all_clips_button': (92, 4), + 'stop_button': (89, 1), + 'play_button': (88, 2), + 'record_button': (90, 6), + 'loop_button': (93, 55), + 'device_left_button': (18, 22), + 'device_right_button': (19, 23), + 'scene_up_button': (25, 29), + 'scene_down_button': (26, 30), + 'scene_launch_button': (27, 31)} +ENCODER_CHANNEL = 1 +PAD_CHANNEL = 9 + +def get_button_identifier_by_name(identifier): + id_pair = BUTTON_HARDWARE_AND_MESSAGE_IDS.get(identifier, None) + if id_pair is not None: + return id_pair[1] + return id_pair + + +class KeyLab(ArturiaControlSurface): + + def __init__(self, *a, **k): + super(KeyLab, self).__init__(*a, **k) + with self.component_guard(): + self._create_controls() + self._create_display() + self._create_device() + self._create_drums() + self._create_transport() + self._create_session() + self._create_session_recording() + self._create_mixer() + + def _create_controls(self): + self._device_encoders = ButtonMatrixElement(rows=[ [ EncoderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, identifier, Live.MidiMap.MapMode.relative_smooth_binary_offset, name='Device_Encoder_%d_%d' % (col_index, row_index)) for col_index, identifier in enumerate(row) ] for row_index, row in enumerate((ENCODER_MSG_IDS[:4], ENCODER_MSG_IDS[4:8])) ]) + self._horizontal_scroll_encoder = EncoderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, ENCODER_MSG_IDS[-2], Live.MidiMap.MapMode.relative_smooth_binary_offset, name='Horizontal_Scroll_Encoder') + self._vertical_scroll_encoder = EncoderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, ENCODER_MSG_IDS[-1], Live.MidiMap.MapMode.relative_smooth_binary_offset, name='Vertical_Scroll_Encoder') + self._volume_sliders = ButtonMatrixElement(rows=[[ SliderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, identifier) for identifier in SLIDER_MSG_IDS[:-1] ]]) + self._master_slider = SliderElement(MIDI_CC_TYPE, ENCODER_CHANNEL, SLIDER_MSG_IDS[-1]) + + def make_keylab_button(name): + button = ButtonElement(True, MIDI_CC_TYPE, 0, get_button_identifier_by_name(name), name=name.title()) + return button + + for button_name in BUTTON_HARDWARE_AND_MESSAGE_IDS.keys(): + setattr(self, '_' + button_name, make_keylab_button(button_name)) + + self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_CC_TYPE, PAD_CHANNEL, col_index + row_offset, name='Pad_%d_%d' % (col_index, row_index)) for col_index in xrange(4) ] for row_index, row_offset in enumerate(xrange(48, 35, -4)) ]) + + def _create_display(self): + self._display_line1, self._display_line2 = DisplayElement(16, 1), DisplayElement(16, 1) + for index, display_line in enumerate((self._display_line1, self._display_line2)): + display_line.set_message_parts(SETUP_MSG_PREFIX + (4, 0, 96), SETUP_MSG_SUFFIX) + display_line.segment(0).set_position_identifier((index + 1,)) + + def adjust_null_terminated_string(string, width): + return string.ljust(width, ' ') + '\x00' + + self._display_line1_data_source, self._display_line2_data_source = DisplayDataSource(adjust_string_fn=adjust_null_terminated_string), DisplayDataSource(adjust_string_fn=adjust_null_terminated_string) + self._display_line1.segment(0).set_data_source(self._display_line1_data_source) + self._display_line2.segment(0).set_data_source(self._display_line2_data_source) + self._display_line1_data_source.set_display_string('KeyLab') + self._display_line2_data_source.set_display_string('Ableton Live') + + def _create_device(self): + self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=self._device_encoders)) + self._device.set_enabled(True) + self.set_device_component(self._device) + self._device_selection_follows_track_selection = True + self._device_navigation = DeviceNavigationComponent(name='Device_Navigation', is_enabled=False, layer=Layer(device_nav_left_button=self._device_left_button, device_nav_right_button=self._device_right_button)) + self._device_navigation.set_enabled(True) + + def _create_drums(self): + self._drums = DrumRackComponent(name='Drums', is_enabled=False, layer=Layer(pads=self._pads)) + self._drums.set_enabled(True) + + def _create_transport(self): + self._transport = TransportComponent(name='Transport', is_enabled=False, layer=Layer(play_button=self._play_button, stop_button=self._stop_button, record_button=self._record_button, loop_button=self._loop_button)) + self._transport.set_enabled(True) + + def _create_session(self): + self._session = SessionComponent(num_tracks=8, num_scenes=1, name='Session', is_enabled=False, layer=Layer(select_next_button=self._scene_down_button, select_prev_button=self._scene_up_button, selected_scene_launch_button=self._scene_launch_button, stop_all_clips_button=self._stop_all_clips_button, scene_select_encoder=self._vertical_scroll_encoder)) + self._session.set_enabled(True) + + def _create_session_recording(self): + self._session_recording = SessionRecordingComponent(ClipCreator(), ViewControlComponent(), name='Session_Recording', is_enabled=False, layer=Layer(record_button=self._session_record_button)) + self._session_recording.set_enabled(True) + + def _create_mixer(self): + self._mixer = MixerComponent(num_tracks=self._volume_sliders.width(), name='Mixer', is_enabled=False, layer=Layer(volume_controls=self._volume_sliders, track_select_encoder=self._horizontal_scroll_encoder)) + self._mixer.master_strip().layer = Layer(volume_control=self._master_slider) + self._mixer.set_enabled(True) + + def _collect_setup_messages(self): + for hardware_id, identifier in izip(ENCODER_HARDWARE_IDS, ENCODER_MSG_IDS): + self._setup_hardware_encoder(hardware_id, identifier, ENCODER_CHANNEL) + + for hardware_id, identifier in izip(SLIDER_HARDWARE_IDS, SLIDER_MSG_IDS): + self._setup_hardware_slider(hardware_id, identifier, ENCODER_CHANNEL) + + for hardware_id, identifier in BUTTON_HARDWARE_AND_MESSAGE_IDS.itervalues(): + self._setup_hardware_button(hardware_id, identifier) + + for hardware_id, identifier in izip(PAD_HARDWARE_IDS, PAD_MSG_IDS): + self._setup_hardware_pad(hardware_id, identifier) + + def _setup_hardware_encoder(self, hardware_id, identifier, channel = 0): + self._set_encoder_cc_msg_type(hardware_id, is_relative=True) + self._set_identifier(hardware_id, identifier) + self._set_channel(hardware_id, channel) + + def _setup_hardware_button(self, hardware_id, identifier, channel = 0, **k): + self._set_encoder_cc_msg_type(hardware_id) + self._set_identifier(hardware_id, identifier) + self._set_channel(hardware_id, channel) + self._set_value_minimum(hardware_id) + self._set_value_maximum(hardware_id) + + def _setup_hardware_pad(self, hardware_id, identifier, channel = PAD_CHANNEL): + self._set_pad_note_msg_type(hardware_id) + self._set_identifier(hardware_id, identifier) + self._set_channel(hardware_id, channel) + + def _set_pad_note_msg_type(self, hardware_id): + self._collect_setup_message(MODE_PROPERTY, hardware_id, PAD_NOTE_MODE) \ No newline at end of file diff --git a/KeyLab/MixerComponent.py b/KeyLab/MixerComponent.py new file mode 100644 index 00000000..36081bfc --- /dev/null +++ b/KeyLab/MixerComponent.py @@ -0,0 +1,42 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyLab/MixerComponent.py +from _Framework.MixerComponent import MixerComponent as MixerComponentBase +from _Arturia.ScrollComponent import ScrollComponent + +class MixerComponent(MixerComponentBase): + + def __init__(self, *a, **k): + super(MixerComponent, self).__init__(*a, **k) + self._track_selection = self.register_component(ScrollComponent()) + self._track_selection.can_scroll_up = self._can_select_prev_track + self._track_selection.can_scroll_down = self._can_select_next_track + self._track_selection.scroll_up = self._select_prev_track + self._track_selection.scroll_down = self._select_next_track + + def set_track_select_encoder(self, encoder): + self._track_selection.set_scroll_encoder(encoder) + + def all_tracks(self): + return self.tracks_to_use() + (self.song().master_track,) + + def tracks_to_use(self): + return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) + + def _can_select_prev_track(self): + return self.song().view.selected_track != self.song().tracks[0] + + def _can_select_next_track(self): + return self.song().view.selected_track != self.song().master_track + + def _select_prev_track(self): + selected_track = self.song().view.selected_track + all_tracks = self.all_tracks() + raise selected_track in all_tracks or AssertionError + index = list(all_tracks).index(selected_track) + self.song().view.selected_track = all_tracks[index - 1] + + def _select_next_track(self): + selected_track = self.song().view.selected_track + all_tracks = self.all_tracks() + raise selected_track in all_tracks or AssertionError + index = list(all_tracks).index(selected_track) + self.song().view.selected_track = all_tracks[index + 1] \ No newline at end of file diff --git a/KeyLab/SessionComponent.py b/KeyLab/SessionComponent.py new file mode 100644 index 00000000..c4d50cd3 --- /dev/null +++ b/KeyLab/SessionComponent.py @@ -0,0 +1,7 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyLab/SessionComponent.py +from _Arturia.SessionComponent import SessionComponent as SessionComponentBase + +class SessionComponent(SessionComponentBase): + + def set_selected_scene_launch_button(self, button): + self.selected_scene().set_launch_button(button) \ No newline at end of file diff --git a/KeyLab/__init__.py b/KeyLab/__init__.py new file mode 100644 index 00000000..89395116 --- /dev/null +++ b/KeyLab/__init__.py @@ -0,0 +1,11 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyLab/__init__.py +import _Framework.Capabilities as caps +from .KeyLab import KeyLab + +def get_capabilities(): + return {caps.CONTROLLER_ID_KEY: caps.controller_id(vendor_id=7285, product_ids=[517, 581, 645], model_name=['KeyLab 25', 'KeyLab 49', 'KeyLab 61']), + caps.PORTS_KEY: [caps.inport(props=[caps.NOTES_CC, caps.SCRIPT, caps.REMOTE]), caps.outport(props=[caps.SCRIPT])]} + + +def create_instance(c_instance): + return KeyLab(c_instance) \ No newline at end of file diff --git a/KeyLab_88/KeyLab88.py b/KeyLab_88/KeyLab88.py new file mode 100644 index 00000000..44a158e2 --- /dev/null +++ b/KeyLab_88/KeyLab88.py @@ -0,0 +1,18 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyLab_88/KeyLab88.py +from KeyLab.KeyLab import KeyLab + +class KeyLab88(KeyLab): + + def _setup_hardware_encoder(self, hardware_id, identifier, channel = 0): + self._set_encoder_cc_msg_type(hardware_id) + self._set_identifier(hardware_id, identifier) + self._set_channel(hardware_id, channel) + self._set_binary_offset_mode(hardware_id) + + def _setup_hardware_button(self, hardware_id, identifier, channel = 0, **k): + self._set_button_msg_type(hardware_id, 'cc') + self._set_channel(hardware_id, channel) + self._set_identifier(hardware_id, identifier) + self._set_value_minimum(hardware_id) + self._set_value_maximum(hardware_id) + self._set_momentary_mode(hardware_id, is_momentary=True) \ No newline at end of file diff --git a/KeyLab_88/__init__.py b/KeyLab_88/__init__.py new file mode 100644 index 00000000..fcfc7165 --- /dev/null +++ b/KeyLab_88/__init__.py @@ -0,0 +1,11 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyLab_88/__init__.py +import _Framework.Capabilities as caps +from .KeyLab88 import KeyLab88 + +def get_capabilities(): + return {caps.CONTROLLER_ID_KEY: caps.controller_id(vendor_id=7285, product_ids=[717], model_name=['KeyLab 88']), + caps.PORTS_KEY: [caps.inport(props=[caps.NOTES_CC, caps.SCRIPT, caps.REMOTE]), caps.outport(props=[caps.SCRIPT])]} + + +def create_instance(c_instance): + return KeyLab88(c_instance) \ No newline at end of file diff --git a/KeyPad/CombinedButtonsElement.py b/KeyPad/CombinedButtonsElement.py index a7e5fb54..c7306a5a 100644 --- a/KeyPad/CombinedButtonsElement.py +++ b/KeyPad/CombinedButtonsElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/KeyPad/CombinedButtonsElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyPad/CombinedButtonsElement.py from __future__ import with_statement from itertools import imap from _Framework.ButtonMatrixElement import ButtonMatrixElement @@ -15,7 +15,7 @@ def is_momentary(self): return True def is_pressed(self): - return any(imap(lambda (b, _): b.is_pressed() if b is not None else False, self.iterbuttons())) or bool(self._is_pressed) + return any(imap(lambda (b, _): (b.is_pressed() if b is not None else False), self.iterbuttons())) or bool(self._is_pressed) def on_nested_control_element_value(self, value, sender): with self._is_pressed(): diff --git a/KeyPad/CuePointControlComponent.py b/KeyPad/CuePointControlComponent.py index b84913a1..c2befbb7 100644 --- a/KeyPad/CuePointControlComponent.py +++ b/KeyPad/CuePointControlComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/KeyPad/CuePointControlComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyPad/CuePointControlComponent.py from _Framework.ControlSurfaceComponent import ControlSurfaceComponent from _Framework.SubjectSlot import subject_slot diff --git a/KeyPad/KeyPad.py b/KeyPad/KeyPad.py index 423dfc12..78a042ab 100644 --- a/KeyPad/KeyPad.py +++ b/KeyPad/KeyPad.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/KeyPad/KeyPad.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyPad/KeyPad.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/KeyPad/__init__.py b/KeyPad/__init__.py index 78a707bf..3e46545e 100644 --- a/KeyPad/__init__.py +++ b/KeyPad/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/KeyPad/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/KeyPad/__init__.py from KeyPad import KeyPad from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT diff --git a/Keystation_Pro_88/__init__.py b/Keystation_Pro_88/__init__.py index 989833a5..e1856cb8 100644 --- a/Keystation_Pro_88/__init__.py +++ b/Keystation_Pro_88/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Keystation_Pro_88/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Keystation_Pro_88/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Keystation_Pro_88/config.py b/Keystation_Pro_88/config.py index 7326d66a..8f785068 100644 --- a/Keystation_Pro_88/config.py +++ b/Keystation_Pro_88/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Keystation_Pro_88/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Keystation_Pro_88/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/Keystation_Pro_88/consts.py b/Keystation_Pro_88/consts.py index cb70a724..981e21f6 100644 --- a/Keystation_Pro_88/consts.py +++ b/Keystation_Pro_88/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Keystation_Pro_88/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Keystation_Pro_88/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/LPD8/__init__.py b/LPD8/__init__.py index 89813ce4..ad8b44ff 100644 --- a/LPD8/__init__.py +++ b/LPD8/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LPD8/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LPD8/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/LPD8/config.py b/LPD8/config.py index 1c24802b..446fb2ce 100644 --- a/LPD8/config.py +++ b/LPD8/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LPD8/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LPD8/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': -1, 'PLAY': -1, diff --git a/LPD8/consts.py b/LPD8/consts.py index a662fdf6..ed6a73dd 100644 --- a/LPD8/consts.py +++ b/LPD8/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LPD8/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LPD8/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/LV1_LX1/LV1_LX1.py b/LV1_LX1/LV1_LX1.py index 43180b6a..0eb8597a 100644 --- a/LV1_LX1/LV1_LX1.py +++ b/LV1_LX1/LV1_LX1.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV1_LX1/LV1_LX1.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV1_LX1/LV1_LX1.py from LV2_LX2_LC2_LD2.FaderfoxComponent import FaderfoxComponent from LV2_LX2_LC2_LD2.FaderfoxScript import FaderfoxScript from LV2_LX2_LC2_LD2.FaderfoxMixerController import FaderfoxMixerController diff --git a/LV1_LX1/__init__.py b/LV1_LX1/__init__.py index 0d67b73d..c0821058 100644 --- a/LV1_LX1/__init__.py +++ b/LV1_LX1/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV1_LX1/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV1_LX1/__init__.py from LV1_LX1 import LV1_LX1 def create_instance(c_instance): diff --git a/LV2_LX2_LC2_LD2/Devices.py b/LV2_LX2_LC2_LD2/Devices.py index b16ac939..47582c6f 100644 --- a/LV2_LX2_LC2_LD2/Devices.py +++ b/LV2_LX2_LC2_LD2/Devices.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/Devices.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/Devices.py import Live RCK_BANK1 = ('Macro 1', 'Macro 2', 'Macro 3', 'Macro 4', 'Macro 5', 'Macro 6', 'Macro 7', 'Macro 8') RCK_BANKS = RCK_BANK1 diff --git a/LV2_LX2_LC2_LD2/DevicesXY.py b/LV2_LX2_LC2_LD2/DevicesXY.py index ddbd98a2..f26c0bd5 100644 --- a/LV2_LX2_LC2_LD2/DevicesXY.py +++ b/LV2_LX2_LC2_LD2/DevicesXY.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/DevicesXY.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/DevicesXY.py import Live XY_DEVICE_DICT = {'AutoFilter': [['Frequency', 'Resonance']], 'BeatRepeat': [['Filter Freq', 'Filter Width']], diff --git a/LV2_LX2_LC2_LD2/FaderfoxComponent.py b/LV2_LX2_LC2_LD2/FaderfoxComponent.py index 80d6ca78..4810d85a 100644 --- a/LV2_LX2_LC2_LD2/FaderfoxComponent.py +++ b/LV2_LX2_LC2_LD2/FaderfoxComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/FaderfoxComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/FaderfoxComponent.py from consts import * class FaderfoxComponent: diff --git a/LV2_LX2_LC2_LD2/FaderfoxDeviceController.py b/LV2_LX2_LC2_LD2/FaderfoxDeviceController.py index 9092dd2a..06add085 100644 --- a/LV2_LX2_LC2_LD2/FaderfoxDeviceController.py +++ b/LV2_LX2_LC2_LD2/FaderfoxDeviceController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/FaderfoxDeviceController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/FaderfoxDeviceController.py import Live from FaderfoxComponent import FaderfoxComponent from consts import * diff --git a/LV2_LX2_LC2_LD2/FaderfoxHelper.py b/LV2_LX2_LC2_LD2/FaderfoxHelper.py index 6a01bb7e..b5b97347 100644 --- a/LV2_LX2_LC2_LD2/FaderfoxHelper.py +++ b/LV2_LX2_LC2_LD2/FaderfoxHelper.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/FaderfoxHelper.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/FaderfoxHelper.py import Live from ParamMap import Callable from Devices import * @@ -40,12 +40,11 @@ def trigger_track_clip(self, track_idx, clip_idx): slot = track.clip_slots[clip_idx] if slot.has_clip: clip = slot.clip - if not clip.is_playing: - clip.is_triggered or clip.fire() + if not (clip.is_playing or clip.is_triggered): + clip.fire() return 1 - else: - clip.stop() - return 0 + clip.stop() + return 0 self.song().view.selected_scene = self.song().scenes[clip_idx] else: self.stop_track(track_idx) diff --git a/LV2_LX2_LC2_LD2/FaderfoxMixerController.py b/LV2_LX2_LC2_LD2/FaderfoxMixerController.py index d056fb07..5e80c850 100644 --- a/LV2_LX2_LC2_LD2/FaderfoxMixerController.py +++ b/LV2_LX2_LC2_LD2/FaderfoxMixerController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/FaderfoxMixerController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/FaderfoxMixerController.py import Live from ParamMap import ParamMap from FaderfoxComponent import FaderfoxComponent diff --git a/LV2_LX2_LC2_LD2/FaderfoxScript.py b/LV2_LX2_LC2_LD2/FaderfoxScript.py index bfc84b5c..9d349484 100644 --- a/LV2_LX2_LC2_LD2/FaderfoxScript.py +++ b/LV2_LX2_LC2_LD2/FaderfoxScript.py @@ -1,10 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/FaderfoxScript.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/FaderfoxScript.py import Live from consts import * import sys from FaderfoxHelper import FaderfoxHelper from ParamMap import ParamMap from Devices import * +from _Generic.util import DeviceAppointer class FaderfoxScript: __filter_funcs__ = ['update_display', 'log', 'song'] @@ -31,6 +32,7 @@ def realinit(self, c_instance): live = 'Live 5' self.show_message(self.__name__ + ' ' + self.__version__ + ' for ' + live) self.is_lv1 = False + self._device_appointer = DeviceAppointer(song=self.song(), appointed_device_setter=self._set_appointed_device) def is_live_5(self): return hasattr(Live, 'is_live_5') @@ -45,6 +47,8 @@ def disconnect(self): for c in self.components: c.disconnect() + self._device_appointer.disconnect() + def application(self): return Live.Application.get_application() @@ -68,7 +72,7 @@ def unlock_to_device(self, device): if self.device_controller: self.device_controller.unlock_from_device(device) - def set_appointed_device(self, device): + def _set_appointed_device(self, device): if self.device_controller: self.device_controller.set_appointed_device(device) @@ -131,4 +135,4 @@ def receive_midi(self, midi_bytes): self.param_map.receive_midi_note(channel, status, note_no, note_vel) else: - raise False or AssertionError, 'Unknown MIDI message %s' % str(midi_bytes) \ No newline at end of file + raise False or AssertionError('Unknown MIDI message %s' % str(midi_bytes)) \ No newline at end of file diff --git a/LV2_LX2_LC2_LD2/FaderfoxTransportController.py b/LV2_LX2_LC2_LD2/FaderfoxTransportController.py index 4b6a9536..e6c6e778 100644 --- a/LV2_LX2_LC2_LD2/FaderfoxTransportController.py +++ b/LV2_LX2_LC2_LD2/FaderfoxTransportController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/FaderfoxTransportController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/FaderfoxTransportController.py import Live from FaderfoxComponent import FaderfoxComponent from FaderfoxHelper import FaderfoxHelper diff --git a/LV2_LX2_LC2_LD2/LV2DeviceController.py b/LV2_LX2_LC2_LD2/LV2DeviceController.py index 61dcaf06..b9a89635 100644 --- a/LV2_LX2_LC2_LD2/LV2DeviceController.py +++ b/LV2_LX2_LC2_LD2/LV2DeviceController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/LV2DeviceController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/LV2DeviceController.py import Live from FaderfoxDeviceController import FaderfoxDeviceController diff --git a/LV2_LX2_LC2_LD2/LV2MixerController.py b/LV2_LX2_LC2_LD2/LV2MixerController.py index 7979463a..4ce2a65a 100644 --- a/LV2_LX2_LC2_LD2/LV2MixerController.py +++ b/LV2_LX2_LC2_LD2/LV2MixerController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/LV2MixerController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/LV2MixerController.py import Live from ParamMap import ParamMap from FaderfoxMixerController import FaderfoxMixerController diff --git a/LV2_LX2_LC2_LD2/LV2TransportController.py b/LV2_LX2_LC2_LD2/LV2TransportController.py index 77b54436..65dedd7a 100644 --- a/LV2_LX2_LC2_LD2/LV2TransportController.py +++ b/LV2_LX2_LC2_LD2/LV2TransportController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/LV2TransportController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/LV2TransportController.py import Live from FaderfoxTransportController import FaderfoxTransportController from FaderfoxHelper import FaderfoxHelper diff --git a/LV2_LX2_LC2_LD2/LV2_LX2_LC2_LD2.py b/LV2_LX2_LC2_LD2/LV2_LX2_LC2_LD2.py index a1f20a3a..8f0c691b 100644 --- a/LV2_LX2_LC2_LD2/LV2_LX2_LC2_LD2.py +++ b/LV2_LX2_LC2_LD2/LV2_LX2_LC2_LD2.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/LV2_LX2_LC2_LD2.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/LV2_LX2_LC2_LD2.py import Live from FaderfoxScript import FaderfoxScript from LV2MixerController import LV2MixerController diff --git a/LV2_LX2_LC2_LD2/ParamMap.py b/LV2_LX2_LC2_LD2/ParamMap.py index 1130c1c0..3d64d165 100644 --- a/LV2_LX2_LC2_LD2/ParamMap.py +++ b/LV2_LX2_LC2_LD2/ParamMap.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/ParamMap.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/ParamMap.py import Live class Callable: diff --git a/LV2_LX2_LC2_LD2/Params.py b/LV2_LX2_LC2_LD2/Params.py index ac95d0b7..6f6eea21 100644 --- a/LV2_LX2_LC2_LD2/Params.py +++ b/LV2_LX2_LC2_LD2/Params.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/Params.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/Params.py AUTO_FILTER_PARAMS = {'LFO Sync Rate': 'LFO Synced Rate'} AUTO_PAN_PARAMS = {'Sync Rate': 'Synced Rate'} BEAT_REPEAT_PARAMS = {'Decay': 'Damp Volume', diff --git a/LV2_LX2_LC2_LD2/__init__.py b/LV2_LX2_LC2_LD2/__init__.py index f0c4c198..0376d98e 100644 --- a/LV2_LX2_LC2_LD2/__init__.py +++ b/LV2_LX2_LC2_LD2/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/__init__.py import Live from LV2_LX2_LC2_LD2 import LV2_LX2_LC2_LD2 from FaderfoxScript import FaderfoxScript diff --git a/LV2_LX2_LC2_LD2/consts.py b/LV2_LX2_LC2_LD2/consts.py index 42ff070e..8b5ddf3b 100644 --- a/LV2_LX2_LC2_LD2/consts.py +++ b/LV2_LX2_LC2_LD2/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/LV2_LX2_LC2_LD2/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/LV2_LX2_LC2_LD2/consts.py TRACK_CHANNEL_SETUP1 = 9 AUX_CHANNEL_SETUP1 = 10 CHANNEL_SETUP1 = 11 diff --git a/Launch_Control/ButtonSysexControl.py b/Launch_Control/ButtonSysexControl.py index 7eb8b7b3..d34cf17d 100644 --- a/Launch_Control/ButtonSysexControl.py +++ b/Launch_Control/ButtonSysexControl.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control/ButtonSysexControl.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control/ButtonSysexControl.py from _Framework.SysexValueControl import SysexValueControl class ButtonSysexControl(SysexValueControl): diff --git a/Launch_Control/Colors.py b/Launch_Control/Colors.py index 83c921a5..ddf088f5 100644 --- a/Launch_Control/Colors.py +++ b/Launch_Control/Colors.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control/Colors.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control/Colors.py LED_OFF = 4 LED_ON = 15 RED_FULL = 7 diff --git a/Launch_Control/ConfigurableButtonElement.py b/Launch_Control/ConfigurableButtonElement.py index 9006bdae..0125e1b8 100644 --- a/Launch_Control/ConfigurableButtonElement.py +++ b/Launch_Control/ConfigurableButtonElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control/ConfigurableButtonElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control/ConfigurableButtonElement.py from Launchpad.ConfigurableButtonElement import ConfigurableButtonElement as LaunchpadButtonElement import Colors diff --git a/Launch_Control/DeviceNavigationComponent.py b/Launch_Control/DeviceNavigationComponent.py index 9a85a532..131814d8 100644 --- a/Launch_Control/DeviceNavigationComponent.py +++ b/Launch_Control/DeviceNavigationComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control/DeviceNavigationComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control/DeviceNavigationComponent.py import Live from _Framework.ControlSurfaceComponent import ControlSurfaceComponent from _Framework.SubjectSlot import subject_slot diff --git a/Launch_Control/LaunchControl.py b/Launch_Control/LaunchControl.py index 11390331..e0819ccc 100644 --- a/Launch_Control/LaunchControl.py +++ b/Launch_Control/LaunchControl.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control/LaunchControl.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control/LaunchControl.py from __future__ import with_statement from functools import partial import Live diff --git a/Launch_Control/SpecialMixerComponent.py b/Launch_Control/SpecialMixerComponent.py index 36343199..af7dddb4 100644 --- a/Launch_Control/SpecialMixerComponent.py +++ b/Launch_Control/SpecialMixerComponent.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control/SpecialMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control/SpecialMixerComponent.py +from itertools import izip_longest from _Framework.MixerComponent import MixerComponent from _Framework.ModesComponent import ModesComponent, LayerMode, LatchingBehaviour from _Framework.SubjectSlot import subject_slot @@ -45,12 +46,12 @@ def _set_selected_send_index(self, value): selected_send_index = property(_get_selected_send_index, _set_selected_send_index) def set_pan_controls(self, controls): - for control, channel_strip in map(None, controls or [], self._channel_strips): + for control, channel_strip in izip_longest(controls or [], self._channel_strips): if channel_strip: channel_strip.set_pan_control(control) def set_volume_controls(self, controls): - for control, channel_strip in map(None, controls or [], self._channel_strips): + for control, channel_strip in izip_longest(controls or [], self._channel_strips): if channel_strip: channel_strip.set_volume_control(control) diff --git a/Launch_Control/SpecialSessionComponent.py b/Launch_Control/SpecialSessionComponent.py index fd81be5d..68c66c13 100644 --- a/Launch_Control/SpecialSessionComponent.py +++ b/Launch_Control/SpecialSessionComponent.py @@ -1,10 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control/SpecialSessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control/SpecialSessionComponent.py +from itertools import izip_longest from _Framework.SessionComponent import SessionComponent class SpecialSessionComponent(SessionComponent): def set_clip_launch_buttons(self, buttons): - for i, button in map(None, xrange(self._num_tracks), buttons or []): + for i, button in izip_longest(xrange(self._num_tracks), buttons or []): scene = self.selected_scene() slot = scene.clip_slot(i) slot.set_launch_button(button) \ No newline at end of file diff --git a/Launch_Control/Sysex.py b/Launch_Control/Sysex.py index b4bb783e..e1837e18 100644 --- a/Launch_Control/Sysex.py +++ b/Launch_Control/Sysex.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control/Sysex.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control/Sysex.py MODE_CHANGE_PREFIX = (240, 0, 32, 41, 2, 10, 119) MIXER_MODE = (240, 0, 32, 41, 2, 10, 119, 8, 247) SESSION_MODE = (240, 0, 32, 41, 2, 10, 119, 9, 247) diff --git a/Launch_Control/__init__.py b/Launch_Control/__init__.py index 0101a62d..76530c4c 100644 --- a/Launch_Control/__init__.py +++ b/Launch_Control/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control/__init__.py from LaunchControl import LaunchControl from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT diff --git a/Launch_Control_XL/ButtonElement.py b/Launch_Control_XL/ButtonElement.py index ff6f22e6..9aacc2a8 100644 --- a/Launch_Control_XL/ButtonElement.py +++ b/Launch_Control_XL/ButtonElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control_XL/ButtonElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control_XL/ButtonElement.py from _Framework.ButtonElement import ON_VALUE, OFF_VALUE, ButtonElement as ButtonElementBase class ButtonElement(ButtonElementBase): diff --git a/Launch_Control_XL/DeviceComponent.py b/Launch_Control_XL/DeviceComponent.py index b1addcca..0319216e 100644 --- a/Launch_Control_XL/DeviceComponent.py +++ b/Launch_Control_XL/DeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control_XL/DeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control_XL/DeviceComponent.py import Live from _Framework.Control import control_list, ButtonControl from _Framework.DeviceComponent import DeviceComponent as DeviceComponentBase diff --git a/Launch_Control_XL/LaunchControlXL.py b/Launch_Control_XL/LaunchControlXL.py index da9e4f91..e8f05d2e 100644 --- a/Launch_Control_XL/LaunchControlXL.py +++ b/Launch_Control_XL/LaunchControlXL.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control_XL/LaunchControlXL.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control_XL/LaunchControlXL.py from __future__ import with_statement from functools import partial from itertools import chain diff --git a/Launch_Control_XL/MixerComponent.py b/Launch_Control_XL/MixerComponent.py index 51bd40fa..83a5b935 100644 --- a/Launch_Control_XL/MixerComponent.py +++ b/Launch_Control_XL/MixerComponent.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control_XL/MixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control_XL/MixerComponent.py +from itertools import izip_longest from _Framework.Control import control_list, ButtonControl from _Framework.ChannelStripComponent import ChannelStripComponent as ChannelStripComponentBase from _Framework.MixerComponent import MixerComponent as MixerComponentBase @@ -44,7 +45,7 @@ def set_send_lights(self, lights): channel_strip.send_lights.set_control_element(elements) def set_pan_lights(self, lights): - for strip, light in map(None, self._channel_strips, lights or []): + for strip, light in izip_longest(self._channel_strips, lights or []): strip.pan_light.set_control_element(light) def _get_send_index(self): @@ -71,25 +72,25 @@ def prev_sends_button(self, button): self.send_index = max(self.send_index - 2, 0) def set_track_select_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.set_on_off_values('Mixer.TrackSelected', 'Mixer.TrackUnselected') strip.set_select_button(button) def set_solo_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.set_on_off_values('Mixer.SoloOn', 'Mixer.SoloOff') strip.set_solo_button(button) def set_mute_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.set_on_off_values('Mixer.MuteOn', 'Mixer.MuteOff') strip.set_mute_button(button) def set_arm_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.set_on_off_values('Mixer.ArmSelected', 'Mixer.ArmUnselected') strip.set_arm_button(button) \ No newline at end of file diff --git a/Launch_Control_XL/SkinDefault.py b/Launch_Control_XL/SkinDefault.py index d70e1b87..9dbadd2d 100644 --- a/Launch_Control_XL/SkinDefault.py +++ b/Launch_Control_XL/SkinDefault.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control_XL/SkinDefault.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control_XL/SkinDefault.py from _Framework.Skin import Skin from _Framework.ButtonElement import Color diff --git a/Launch_Control_XL/__init__.py b/Launch_Control_XL/__init__.py index 83afe763..1c4b8f88 100644 --- a/Launch_Control_XL/__init__.py +++ b/Launch_Control_XL/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launch_Control_XL/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launch_Control_XL/__init__.py from LaunchControlXL import LaunchControlXL from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, AUTO_LOAD_KEY diff --git a/Launchkey/Launchkey.py b/Launchkey/Launchkey.py index dfc20589..76a48dce 100644 --- a/Launchkey/Launchkey.py +++ b/Launchkey/Launchkey.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey/Launchkey.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey/Launchkey.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/Launchkey/SessionNavigationComponent.py b/Launchkey/SessionNavigationComponent.py index 9839baaf..754a030a 100644 --- a/Launchkey/SessionNavigationComponent.py +++ b/Launchkey/SessionNavigationComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey/SessionNavigationComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey/SessionNavigationComponent.py from _Framework.CompoundComponent import CompoundComponent from _Framework.ScrollComponent import ScrollComponent from _Framework import Task @@ -51,16 +51,17 @@ def is_scrolling(self): def _track_to_arm(self): track = self.song().view.selected_track can_arm_track = track != None and track.has_midi_input and track.can_be_armed and not track.arm - return track if can_arm_track else None + if can_arm_track: + return track def _try_arm(self): track_to_arm = self._track_to_arm() if track_to_arm != None: song = self.song() tracks = song.tracks - if song.is_playing: - check_arrangement = song.record_mode - if is_recording_clip(tracks, check_arrangement) or song.exclusive_arm: + check_arrangement = song.is_playing and song.record_mode + if not is_recording_clip(tracks, check_arrangement): + if song.exclusive_arm: for track in tracks: if track.can_be_armed and track != track_to_arm: track.arm = False diff --git a/Launchkey/SpecialMixerComponent.py b/Launchkey/SpecialMixerComponent.py index 70868606..272493f5 100644 --- a/Launchkey/SpecialMixerComponent.py +++ b/Launchkey/SpecialMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey/SpecialMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey/SpecialMixerComponent.py from _Framework.MixerComponent import MixerComponent class SpecialMixerComponent(MixerComponent): diff --git a/Launchkey/TransportViewModeSelector.py b/Launchkey/TransportViewModeSelector.py index c9d2a8dd..d1459a9a 100644 --- a/Launchkey/TransportViewModeSelector.py +++ b/Launchkey/TransportViewModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey/TransportViewModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey/TransportViewModeSelector.py from _Framework.ModeSelectorComponent import ModeSelectorComponent class TransportViewModeSelector(ModeSelectorComponent): diff --git a/Launchkey/__init__.py b/Launchkey/__init__.py index 60796c86..82e3cbe7 100644 --- a/Launchkey/__init__.py +++ b/Launchkey/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey/__init__.py from Launchkey import Launchkey from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT diff --git a/Launchkey/consts.py b/Launchkey/consts.py index 4d0983d5..32b0f565 100644 --- a/Launchkey/consts.py +++ b/Launchkey/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey/consts.py SIZE_QUERY = (240, 126, 127, 6, 1, 247) SIZE_RESPONSE = (240, 126, 127, 6, 2, 0, 32, 41, 0, 25, 0) LIVE_MODE_ON = (144, 12, 127) diff --git a/Launchkey_MK2/BackgroundComponent.py b/Launchkey_MK2/BackgroundComponent.py index 7c478a58..ea99a17e 100644 --- a/Launchkey_MK2/BackgroundComponent.py +++ b/Launchkey_MK2/BackgroundComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/BackgroundComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/BackgroundComponent.py from _Framework.BackgroundComponent import BackgroundComponent as BackgroundComponentBase class BackgroundComponent(BackgroundComponentBase): diff --git a/Launchkey_MK2/Colors.py b/Launchkey_MK2/Colors.py index e66429fe..6f5028d3 100644 --- a/Launchkey_MK2/Colors.py +++ b/Launchkey_MK2/Colors.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/Colors.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/Colors.py from _Framework.ButtonElement import Color from .consts import BLINK_LED_CHANNEL, PULSE_LED_CHANNEL diff --git a/Launchkey_MK2/ControlElementUtils.py b/Launchkey_MK2/ControlElementUtils.py index 1772a5d9..1655231a 100644 --- a/Launchkey_MK2/ControlElementUtils.py +++ b/Launchkey_MK2/ControlElementUtils.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/ControlElementUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/ControlElementUtils.py from functools import partial import Live from _Framework.Dependency import depends diff --git a/Launchkey_MK2/DeviceComponent.py b/Launchkey_MK2/DeviceComponent.py index dbd50465..ede18168 100644 --- a/Launchkey_MK2/DeviceComponent.py +++ b/Launchkey_MK2/DeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/DeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/DeviceComponent.py import Live from _Generic.Devices import DEVICE_DICT, BANK_NAME_DICT, DEVICE_BOB_DICT, parameter_banks, parameter_bank_names from _Framework.Control import ButtonControl @@ -18,9 +18,9 @@ def __init__(self, *a, **k): self._device_bank_names = BANK_NAME_DICT self._device_best_banks = DEVICE_BOB_DICT for device_name, current_banks in self._device_banks.iteritems(): - raise len(current_banks) > 1 and (device_name in self._device_best_banks.keys() or AssertionError), "Could not find best-of-banks for '%s'" % device_name - if not device_name in self._device_bank_names.keys(): - raise AssertionError, "Could not find bank names for '%s'" % device_name + if len(current_banks) > 1: + raise device_name in self._device_best_banks.keys() or AssertionError("Could not find best-of-banks for '%s'" % device_name) + raise device_name in self._device_bank_names.keys() or AssertionError("Could not find bank names for '%s'" % device_name) current_banks = self._device_best_banks[device_name] + current_banks new_bank_names[device_name] = (BOB_BANK_NAME,) + self._device_bank_names[device_name] new_banks[device_name] = current_banks diff --git a/Launchkey_MK2/InControlStatusComponent.py b/Launchkey_MK2/InControlStatusComponent.py index 036295fc..1b888d4b 100644 --- a/Launchkey_MK2/InControlStatusComponent.py +++ b/Launchkey_MK2/InControlStatusComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/InControlStatusComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/InControlStatusComponent.py from _Framework.SubjectSlot import subject_slot from _Framework.ControlSurfaceComponent import ControlSurfaceComponent diff --git a/Launchkey_MK2/Launchkey_MK2.py b/Launchkey_MK2/Launchkey_MK2.py index c5375b3e..0ee59a3e 100644 --- a/Launchkey_MK2/Launchkey_MK2.py +++ b/Launchkey_MK2/Launchkey_MK2.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/Launchkey_MK2.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/Launchkey_MK2.py from __future__ import with_statement from functools import partial from _Framework import Task diff --git a/Launchkey_MK2/MixerComponent.py b/Launchkey_MK2/MixerComponent.py index daef02e8..62583f38 100644 --- a/Launchkey_MK2/MixerComponent.py +++ b/Launchkey_MK2/MixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/MixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/MixerComponent.py from _Framework.MixerComponent import MixerComponent as MixerComponentBase class MixerComponent(MixerComponentBase): diff --git a/Launchkey_MK2/ModeUtils.py b/Launchkey_MK2/ModeUtils.py index 2507d090..fec94d82 100644 --- a/Launchkey_MK2/ModeUtils.py +++ b/Launchkey_MK2/ModeUtils.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/ModeUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/ModeUtils.py from _Framework.Dependency import depends from _Framework.ModesComponent import ModesComponent, ModeButtonBehaviour import consts diff --git a/Launchkey_MK2/SessionComponent.py b/Launchkey_MK2/SessionComponent.py index 8635fe50..7fc7aa75 100644 --- a/Launchkey_MK2/SessionComponent.py +++ b/Launchkey_MK2/SessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/SessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/SessionComponent.py from _Framework.Util import index_if from _Framework.SessionComponent import SessionComponent as SessionComponentBase diff --git a/Launchkey_MK2/Skin.py b/Launchkey_MK2/Skin.py index 4a3903f9..86446432 100644 --- a/Launchkey_MK2/Skin.py +++ b/Launchkey_MK2/Skin.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/Skin.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/Skin.py from _Framework.Skin import Skin from .Colors import Rgb diff --git a/Launchkey_MK2/__init__.py b/Launchkey_MK2/__init__.py index 6b462e01..37f9bf3c 100644 --- a/Launchkey_MK2/__init__.py +++ b/Launchkey_MK2/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/__init__.py import _Framework.Capabilities as caps from .Launchkey_MK2 import Launchkey_MK2 diff --git a/Launchkey_MK2/consts.py b/Launchkey_MK2/consts.py index b4b79552..62167057 100644 --- a/Launchkey_MK2/consts.py +++ b/Launchkey_MK2/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_MK2/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_MK2/consts.py PRODUCT_ID_BYTE_PREFIX = (0, 32, 41) LAUNCHKEY_25_ID_BYTE = 123 LAUNCHKEY_49_ID_BYTE = 124 diff --git a/Launchkey_Mini/LaunchkeyMini.py b/Launchkey_Mini/LaunchkeyMini.py index 55afcbf5..bfe4e918 100644 --- a/Launchkey_Mini/LaunchkeyMini.py +++ b/Launchkey_Mini/LaunchkeyMini.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_Mini/LaunchkeyMini.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_Mini/LaunchkeyMini.py from Launchkey.Launchkey import Launchkey, LaunchkeyControlFactory, make_button class LaunchkeyMiniControlFactory(LaunchkeyControlFactory): diff --git a/Launchkey_Mini/__init__.py b/Launchkey_Mini/__init__.py index a04e2953..b4b24fc5 100644 --- a/Launchkey_Mini/__init__.py +++ b/Launchkey_Mini/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchkey_Mini/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchkey_Mini/__init__.py from LaunchkeyMini import LaunchkeyMini from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT diff --git a/Launchpad/ConfigurableButtonElement.py b/Launchpad/ConfigurableButtonElement.py index df0d2af9..964e3ce5 100644 --- a/Launchpad/ConfigurableButtonElement.py +++ b/Launchpad/ConfigurableButtonElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad/ConfigurableButtonElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad/ConfigurableButtonElement.py import Live from _Framework.ButtonElement import * diff --git a/Launchpad/DefChannelStripComponent.py b/Launchpad/DefChannelStripComponent.py index befe97a2..c52ad291 100644 --- a/Launchpad/DefChannelStripComponent.py +++ b/Launchpad/DefChannelStripComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad/DefChannelStripComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad/DefChannelStripComponent.py import Live from _Framework.ChannelStripComponent import ChannelStripComponent from ConfigurableButtonElement import ConfigurableButtonElement @@ -177,8 +177,8 @@ def _default_send1_value(self, value): raise AssertionError if not value in range(128): raise AssertionError - if self.is_enabled() and self._track != None: - send1 = len(self._track.mixer_device.sends) > 0 and (value != 0 or not self._default_send1_button.is_momentary()) and self._track.mixer_device.sends[0] + if self.is_enabled() and self._track != None and len(self._track.mixer_device.sends) > 0: + send1 = (value != 0 or not self._default_send1_button.is_momentary()) and self._track.mixer_device.sends[0] send1.value = send1.is_enabled and send1.default_value def _default_send2_value(self, value): @@ -186,8 +186,8 @@ def _default_send2_value(self, value): raise AssertionError if not value in range(128): raise AssertionError - if self.is_enabled() and self._track != None: - send2 = len(self._track.mixer_device.sends) > 1 and (value != 0 or not self._default_send2_button.is_momentary()) and self._track.mixer_device.sends[1] + if self.is_enabled() and self._track != None and len(self._track.mixer_device.sends) > 1: + send2 = (value != 0 or not self._default_send2_button.is_momentary()) and self._track.mixer_device.sends[1] send2.value = send2.is_enabled and send2.default_value def _on_mute_changed(self): diff --git a/Launchpad/Launchpad.py b/Launchpad/Launchpad.py index 5d249fc6..5fe1124c 100644 --- a/Launchpad/Launchpad.py +++ b/Launchpad/Launchpad.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad/Launchpad.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad/Launchpad.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/Launchpad/MainSelectorComponent.py b/Launchpad/MainSelectorComponent.py index c4910b73..37a41bce 100644 --- a/Launchpad/MainSelectorComponent.py +++ b/Launchpad/MainSelectorComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad/MainSelectorComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad/MainSelectorComponent.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.ButtonElement import ButtonElement from _Framework.ButtonMatrixElement import ButtonMatrixElement diff --git a/Launchpad/PreciseButtonSliderElement.py b/Launchpad/PreciseButtonSliderElement.py index 85081564..2664c649 100644 --- a/Launchpad/PreciseButtonSliderElement.py +++ b/Launchpad/PreciseButtonSliderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad/PreciseButtonSliderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad/PreciseButtonSliderElement.py from _Framework.ButtonSliderElement import ButtonSliderElement from _Framework.InputControlElement import * SLIDER_MODE_SINGLE = 0 diff --git a/Launchpad/SpecialMixerComponent.py b/Launchpad/SpecialMixerComponent.py index 86bf309a..92ce5c4f 100644 --- a/Launchpad/SpecialMixerComponent.py +++ b/Launchpad/SpecialMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad/SpecialMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad/SpecialMixerComponent.py import Live from _Framework.MixerComponent import MixerComponent from DefChannelStripComponent import DefChannelStripComponent diff --git a/Launchpad/SpecialSessionComponent.py b/Launchpad/SpecialSessionComponent.py index 296e7266..c83a8297 100644 --- a/Launchpad/SpecialSessionComponent.py +++ b/Launchpad/SpecialSessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad/SpecialSessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad/SpecialSessionComponent.py from _Framework.SessionComponent import SessionComponent class SpecialSessionComponent(SessionComponent): diff --git a/Launchpad/SubSelectorComponent.py b/Launchpad/SubSelectorComponent.py index 0a7d423f..77dd600f 100644 --- a/Launchpad/SubSelectorComponent.py +++ b/Launchpad/SubSelectorComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad/SubSelectorComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad/SubSelectorComponent.py from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.ButtonElement import ButtonElement from _Framework.ButtonMatrixElement import ButtonMatrixElement diff --git a/Launchpad/__init__.py b/Launchpad/__init__.py index a95fe659..912a72e1 100644 --- a/Launchpad/__init__.py +++ b/Launchpad/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad/__init__.py from Launchpad import Launchpad def create_instance(c_instance): diff --git a/Launchpad_MK2/BackgroundComponent.py b/Launchpad_MK2/BackgroundComponent.py index 6d039af8..f268eb02 100644 --- a/Launchpad_MK2/BackgroundComponent.py +++ b/Launchpad_MK2/BackgroundComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/BackgroundComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/BackgroundComponent.py from _Framework.BackgroundComponent import BackgroundComponent as BackgroundComponentBase class BackgroundComponent(BackgroundComponentBase): diff --git a/Launchpad_MK2/ChannelStripComponent.py b/Launchpad_MK2/ChannelStripComponent.py index aa67f882..4765d897 100644 --- a/Launchpad_MK2/ChannelStripComponent.py +++ b/Launchpad_MK2/ChannelStripComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/ChannelStripComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/ChannelStripComponent.py from itertools import chain from _Framework.SubjectSlot import subject_slot from _Framework.Control import ButtonControl diff --git a/Launchpad_MK2/Colors.py b/Launchpad_MK2/Colors.py index f365e274..646f65e7 100644 --- a/Launchpad_MK2/Colors.py +++ b/Launchpad_MK2/Colors.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/Colors.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/Colors.py from _Framework.ButtonElement import Color from .consts import BLINK_LED_CHANNEL, PULSE_LED_CHANNEL diff --git a/Launchpad_MK2/ComponentUtils.py b/Launchpad_MK2/ComponentUtils.py index 9b6b23de..9d70e556 100644 --- a/Launchpad_MK2/ComponentUtils.py +++ b/Launchpad_MK2/ComponentUtils.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/ComponentUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/ComponentUtils.py def skin_scroll_component(component): diff --git a/Launchpad_MK2/ControlElementUtils.py b/Launchpad_MK2/ControlElementUtils.py index 5e0a3723..931a3978 100644 --- a/Launchpad_MK2/ControlElementUtils.py +++ b/Launchpad_MK2/ControlElementUtils.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/ControlElementUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/ControlElementUtils.py from _Framework.Dependency import depends from _Framework.Resource import PrioritizedResource from _Framework.InputControlElement import MIDI_NOTE_TYPE diff --git a/Launchpad_MK2/Launchpad_MK2.py b/Launchpad_MK2/Launchpad_MK2.py index 8bed5401..cb5ffa80 100644 --- a/Launchpad_MK2/Launchpad_MK2.py +++ b/Launchpad_MK2/Launchpad_MK2.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/Launchpad_MK2.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/Launchpad_MK2.py from __future__ import with_statement from functools import partial import Live diff --git a/Launchpad_MK2/MixerComponent.py b/Launchpad_MK2/MixerComponent.py index 3411b981..e4389001 100644 --- a/Launchpad_MK2/MixerComponent.py +++ b/Launchpad_MK2/MixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/MixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/MixerComponent.py from _Framework.Control import ButtonControl from _Framework.MixerComponent import MixerComponent as MixerComponentBase from .ChannelStripComponent import ChannelStripComponent diff --git a/Launchpad_MK2/ModeUtils.py b/Launchpad_MK2/ModeUtils.py index fb444bdd..23dc7d73 100644 --- a/Launchpad_MK2/ModeUtils.py +++ b/Launchpad_MK2/ModeUtils.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/ModeUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/ModeUtils.py from _Framework.Dependency import depends from _Framework.ModesComponent import ModesComponent, ModeButtonBehaviour, ImmediateBehaviour diff --git a/Launchpad_MK2/SessionComponent.py b/Launchpad_MK2/SessionComponent.py index 215a6090..a2a3375a 100644 --- a/Launchpad_MK2/SessionComponent.py +++ b/Launchpad_MK2/SessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/SessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/SessionComponent.py from _Framework.Util import in_range from _Framework.SubjectSlot import subject_slot_group from _Framework.SessionComponent import SessionComponent as SessionComponentBase diff --git a/Launchpad_MK2/SessionZoomingComponent.py b/Launchpad_MK2/SessionZoomingComponent.py index 92b3ba14..7225859d 100644 --- a/Launchpad_MK2/SessionZoomingComponent.py +++ b/Launchpad_MK2/SessionZoomingComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/SessionZoomingComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/SessionZoomingComponent.py from _Framework.SessionZoomingComponent import SessionZoomingComponent as SessionZoomingComponentBase from .ComponentUtils import skin_scroll_component from _Framework.SessionComponent import SessionComponent diff --git a/Launchpad_MK2/Skin.py b/Launchpad_MK2/Skin.py index 78a64e27..a68b6f30 100644 --- a/Launchpad_MK2/Skin.py +++ b/Launchpad_MK2/Skin.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/Skin.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/Skin.py from _Framework.Skin import Skin from .Colors import Rgb diff --git a/Launchpad_MK2/SliderElement.py b/Launchpad_MK2/SliderElement.py index f12108f7..d5e226c5 100644 --- a/Launchpad_MK2/SliderElement.py +++ b/Launchpad_MK2/SliderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/SliderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/SliderElement.py from _Framework.Dependency import depends from _Framework.Skin import SkinColorMissingError from _Framework.SliderElement import SliderElement as SliderElementBase diff --git a/Launchpad_MK2/__init__.py b/Launchpad_MK2/__init__.py index 301660a6..dfe32342 100644 --- a/Launchpad_MK2/__init__.py +++ b/Launchpad_MK2/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/__init__.py from .Launchpad_MK2 import Launchpad_MK2 from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, SYNC, REMOTE diff --git a/Launchpad_MK2/consts.py b/Launchpad_MK2/consts.py index fc547fec..a64fa096 100644 --- a/Launchpad_MK2/consts.py +++ b/Launchpad_MK2/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_MK2/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_MK2/consts.py PRODUCT_ID_BYTES = (0, 32, 41, 105, 0, 0, 0) IDENTITY_REQUEST = (240, 126, 127, 6, 1, 247) STANDARD_SYSEX_PREFIX = (240, 0, 32, 41, 2, 24) diff --git a/Launchpad_Pro/ActionsComponent.py b/Launchpad_Pro/ActionsComponent.py index 802d8eff..badad28d 100644 --- a/Launchpad_Pro/ActionsComponent.py +++ b/Launchpad_Pro/ActionsComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/ActionsComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/ActionsComponent.py from __future__ import with_statement import Live from _Framework.Util import BooleanContext diff --git a/Launchpad_Pro/BackgroundComponent.py b/Launchpad_Pro/BackgroundComponent.py index a3c9e95a..73c9e296 100644 --- a/Launchpad_Pro/BackgroundComponent.py +++ b/Launchpad_Pro/BackgroundComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/BackgroundComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/BackgroundComponent.py from _Framework.SubjectSlot import SubjectSlotError from _Framework.BackgroundComponent import BackgroundComponent as BackgroundComponentBase diff --git a/Launchpad_Pro/ClipActionsComponent.py b/Launchpad_Pro/ClipActionsComponent.py index 7e5926e5..c537ecbb 100644 --- a/Launchpad_Pro/ClipActionsComponent.py +++ b/Launchpad_Pro/ClipActionsComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/ClipActionsComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/ClipActionsComponent.py import Live from _Framework.SubjectSlot import Subject, subject_slot from _Framework.ControlSurfaceComponent import ControlSurfaceComponent @@ -13,13 +13,13 @@ def duplicate_clip(song, slot, should_launch = False): track = slot.canonical_parent view = song.view try: - if should_launch: - start_duplicate = clip.is_playing - target_index = list(track.clip_slots).index(slot) - destination_index = track.duplicate_clip_slot(target_index) - view.highlighted_clip_slot = track.clip_slots[destination_index] - view.detail_clip = view.highlighted_clip_slot.clip - start_duplicate and view.highlighted_clip_slot.fire(force_legato=True, launch_quantization=_Q.q_no_q) + start_duplicate = should_launch and clip.is_playing + target_index = list(track.clip_slots).index(slot) + destination_index = track.duplicate_clip_slot(target_index) + view.highlighted_clip_slot = track.clip_slots[destination_index] + view.detail_clip = view.highlighted_clip_slot.clip + if start_duplicate: + view.highlighted_clip_slot.fire(force_legato=True, launch_quantization=_Q.q_no_q) except Live.Base.LimitationError: pass except RuntimeError: diff --git a/Launchpad_Pro/Colors.py b/Launchpad_Pro/Colors.py index 55000bf8..04a32f83 100644 --- a/Launchpad_Pro/Colors.py +++ b/Launchpad_Pro/Colors.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/Colors.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/Colors.py from _Framework.ButtonElement import Color from .consts import BLINK_LED_CHANNEL, PULSE_LED_CHANNEL diff --git a/Launchpad_Pro/ConfigurableButtonElement.py b/Launchpad_Pro/ConfigurableButtonElement.py index 3d9e4205..078a8c47 100644 --- a/Launchpad_Pro/ConfigurableButtonElement.py +++ b/Launchpad_Pro/ConfigurableButtonElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/ConfigurableButtonElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/ConfigurableButtonElement.py from _Framework.Skin import SkinColorMissingError from _Framework.ButtonElement import ButtonElement, ON_VALUE, OFF_VALUE diff --git a/Launchpad_Pro/DeviceNavigationComponent.py b/Launchpad_Pro/DeviceNavigationComponent.py index 2ee7270a..200ca42b 100644 --- a/Launchpad_Pro/DeviceNavigationComponent.py +++ b/Launchpad_Pro/DeviceNavigationComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/DeviceNavigationComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/DeviceNavigationComponent.py import Live from _Framework.ControlSurfaceComponent import ControlSurfaceComponent from _Framework.Control import ButtonControl diff --git a/Launchpad_Pro/DrumGroupComponent.py b/Launchpad_Pro/DrumGroupComponent.py index d1fbeaa0..260d8bd2 100644 --- a/Launchpad_Pro/DrumGroupComponent.py +++ b/Launchpad_Pro/DrumGroupComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/DrumGroupComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/DrumGroupComponent.py from itertools import imap from _Framework.Util import find_if, first, clamp from _Framework.Dependency import depends @@ -121,11 +121,15 @@ def _set_position(self, index): @property def width(self): - return self.drum_matrix.width if self.drum_matrix.width else 4 + if self.drum_matrix.width: + return self.drum_matrix.width + return 4 @property def height(self): - return self.drum_matrix.height if self.drum_matrix.height else 4 + if self.drum_matrix.height: + return self.drum_matrix.height + return 4 @property def pressed_pads(self): diff --git a/Launchpad_Pro/DrumGroupFinderComponent.py b/Launchpad_Pro/DrumGroupFinderComponent.py index 1c52d7d5..55ec4016 100644 --- a/Launchpad_Pro/DrumGroupFinderComponent.py +++ b/Launchpad_Pro/DrumGroupFinderComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/DrumGroupFinderComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/DrumGroupFinderComponent.py from __future__ import with_statement from itertools import imap, chain import Live @@ -73,9 +73,8 @@ def find_instrument_devices(track_or_chain): or chain. """ instrument = find_if(lambda d: d.type == Live.Device.DeviceType.instrument, track_or_chain.devices) - if instrument and not instrument.can_have_drum_pads: - if instrument.can_have_chains: - return chain([instrument], *imap(find_instrument_devices, instrument.chains)) + if instrument and not instrument.can_have_drum_pads and instrument.can_have_chains: + return chain([instrument], *imap(find_instrument_devices, instrument.chains)) return [] @@ -87,5 +86,5 @@ def find_drum_group_device(track_or_chain): if instrument: if instrument.can_have_drum_pads: return instrument - elif instrument.can_have_chains: + if instrument.can_have_chains: return find_if(bool, imap(find_drum_group_device, instrument.chains)) \ No newline at end of file diff --git a/Launchpad_Pro/Launchpad_Pro.py b/Launchpad_Pro/Launchpad_Pro.py index 2d02d60e..33010b64 100644 --- a/Launchpad_Pro/Launchpad_Pro.py +++ b/Launchpad_Pro/Launchpad_Pro.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/Launchpad_Pro.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/Launchpad_Pro.py from __future__ import with_statement from functools import partial import Live diff --git a/Launchpad_Pro/MultiButtonElement.py b/Launchpad_Pro/MultiButtonElement.py index 943d7ed7..62f7d9d6 100644 --- a/Launchpad_Pro/MultiButtonElement.py +++ b/Launchpad_Pro/MultiButtonElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/MultiButtonElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/MultiButtonElement.py from .ConfigurableButtonElement import ConfigurableButtonElement class MultiButtonElement(ConfigurableButtonElement): diff --git a/Launchpad_Pro/SkinDefault.py b/Launchpad_Pro/SkinDefault.py index 9d8a3412..11e4d810 100644 --- a/Launchpad_Pro/SkinDefault.py +++ b/Launchpad_Pro/SkinDefault.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/SkinDefault.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/SkinDefault.py from _Framework.Skin import Skin from .Colors import Rgb diff --git a/Launchpad_Pro/SlideComponent.py b/Launchpad_Pro/SlideComponent.py index 70951e16..cdcac6c5 100644 --- a/Launchpad_Pro/SlideComponent.py +++ b/Launchpad_Pro/SlideComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/SlideComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/SlideComponent.py """ Component that navigates a series of pages. """ diff --git a/Launchpad_Pro/SliderElement.py b/Launchpad_Pro/SliderElement.py index a6e229f1..b2d8923e 100644 --- a/Launchpad_Pro/SliderElement.py +++ b/Launchpad_Pro/SliderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/SliderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/SliderElement.py from _Framework.SliderElement import SliderElement as SliderElementBase from _Framework.Skin import Skin, SkinColorMissingError import consts diff --git a/Launchpad_Pro/SpecialDeviceComponent.py b/Launchpad_Pro/SpecialDeviceComponent.py index 67df941c..e28fff52 100644 --- a/Launchpad_Pro/SpecialDeviceComponent.py +++ b/Launchpad_Pro/SpecialDeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/SpecialDeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/SpecialDeviceComponent.py from _Framework.DeviceComponent import DeviceComponent from .consts import FADER_TYPE_STANDARD, DEVICE_MAP_CHANNEL diff --git a/Launchpad_Pro/SpecialMidiMap.py b/Launchpad_Pro/SpecialMidiMap.py index e69ce5f5..2ad6ccbd 100644 --- a/Launchpad_Pro/SpecialMidiMap.py +++ b/Launchpad_Pro/SpecialMidiMap.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/SpecialMidiMap.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/SpecialMidiMap.py from __future__ import absolute_import from _Framework.MidiMap import MidiMap from _Framework.ButtonMatrixElement import ButtonMatrixElement diff --git a/Launchpad_Pro/SpecialMixerComponent.py b/Launchpad_Pro/SpecialMixerComponent.py index 3c6ec408..afe0e2ee 100644 --- a/Launchpad_Pro/SpecialMixerComponent.py +++ b/Launchpad_Pro/SpecialMixerComponent.py @@ -1,5 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/SpecialMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/SpecialMixerComponent.py from functools import partial +from itertools import izip_longest from _Framework.Util import clamp from _Framework.Dependency import depends from _Framework.MixerComponent import MixerComponent @@ -45,14 +46,14 @@ def _create_strip(self): return SpecialChanStripComponent() def set_volume_controls(self, controls): - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): if control: control.set_channel(VOLUME_MAP_CHANNEL) control.set_light_and_type('Mixer.Volume', FADER_TYPE_STANDARD) strip.set_volume_control(control) def set_pan_controls(self, controls): - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): if control: control.set_channel(PAN_MAP_CHANNEL) control.set_light_and_type('Mixer.Pan', FADER_TYPE_BIPOLAR) @@ -60,7 +61,7 @@ def set_pan_controls(self, controls): def set_send_controls(self, controls): self._send_controls = controls - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): if self.send_index is None or self.send_index not in xrange(8): strip.set_send_controls(None) else: @@ -70,28 +71,28 @@ def set_send_controls(self, controls): strip.set_send_controls((None,) * self._send_index + (control,)) def set_arm_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.reset_state() button.set_on_off_values('Mixer.ArmOn', 'Mixer.ArmOff') strip.set_arm_button(button) def set_solo_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.reset_state() button.set_on_off_values('Mixer.SoloOn', 'Mixer.SoloOff') strip.set_solo_button(button) def set_mute_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.reset_state() button.set_on_off_values('Mixer.MuteOff', 'Mixer.MuteOn') strip.set_mute_button(button) def set_track_select_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.reset_state() button.set_on_off_values('Mixer.Selected', 'Mixer.Unselected') diff --git a/Launchpad_Pro/SpecialModesComponent.py b/Launchpad_Pro/SpecialModesComponent.py index e305fe9c..4f815ded 100644 --- a/Launchpad_Pro/SpecialModesComponent.py +++ b/Launchpad_Pro/SpecialModesComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/SpecialModesComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/SpecialModesComponent.py from _Framework.ModesComponent import ReenterBehaviour, ModesComponent class SpecialModesComponent(ModesComponent): diff --git a/Launchpad_Pro/SpecialSessionComponent.py b/Launchpad_Pro/SpecialSessionComponent.py index 207b4306..51d8f3ee 100644 --- a/Launchpad_Pro/SpecialSessionComponent.py +++ b/Launchpad_Pro/SpecialSessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/SpecialSessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/SpecialSessionComponent.py import Live from _Framework.Util import find_if, in_range from _Framework.Dependency import depends diff --git a/Launchpad_Pro/SpecialSessionRecordingComponent.py b/Launchpad_Pro/SpecialSessionRecordingComponent.py index 18c3cd4f..1da57bf8 100644 --- a/Launchpad_Pro/SpecialSessionRecordingComponent.py +++ b/Launchpad_Pro/SpecialSessionRecordingComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/SpecialSessionRecordingComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/SpecialSessionRecordingComponent.py import Live from _Framework.ClipCreator import ClipCreator from _Framework.SessionRecordingComponent import SessionRecordingComponent, track_playing_slot, track_is_recording, subject_slot @@ -31,9 +31,9 @@ def _on_record_button_value(self, value): def _handle_note_mode_record_behavior(self): track = self._target_track_component.target_track - playing_slot = self._track_can_record(track) and track_playing_slot(track) - if not track_is_recording(track): - should_overdub = playing_slot != None + if self._track_can_record(track): + playing_slot = track_playing_slot(track) + should_overdub = not track_is_recording(track) and playing_slot != None if should_overdub: self.song().overdub = not self.song().overdub if not self.song().is_playing: diff --git a/Launchpad_Pro/TargetTrackComponent.py b/Launchpad_Pro/TargetTrackComponent.py index f203a674..b6d7d094 100644 --- a/Launchpad_Pro/TargetTrackComponent.py +++ b/Launchpad_Pro/TargetTrackComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/TargetTrackComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/TargetTrackComponent.py from _Framework.SubjectSlot import Subject, subject_slot, subject_slot_group from _Framework.ControlSurfaceComponent import ControlSurfaceComponent diff --git a/Launchpad_Pro/TranslationComponent.py b/Launchpad_Pro/TranslationComponent.py index 8a4e0d00..c42c3e30 100644 --- a/Launchpad_Pro/TranslationComponent.py +++ b/Launchpad_Pro/TranslationComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/TranslationComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/TranslationComponent.py from functools import partial from _Framework.ControlSurfaceComponent import ControlSurfaceComponent diff --git a/Launchpad_Pro/__init__.py b/Launchpad_Pro/__init__.py index 5167f687..c1bbab68 100644 --- a/Launchpad_Pro/__init__.py +++ b/Launchpad_Pro/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/__init__.py from _Framework.Capabilities import CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, SYNC, REMOTE, controller_id, inport, outport from Launchpad_Pro import Launchpad_Pro diff --git a/Launchpad_Pro/consts.py b/Launchpad_Pro/consts.py index b37e1fe8..6e98ec12 100644 --- a/Launchpad_Pro/consts.py +++ b/Launchpad_Pro/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Launchpad_Pro/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Launchpad_Pro/consts.py SYSEX_IDENTITY_REQUEST = (240, 126, 127, 6, 1, 247) DEVICE_CODE = (81, 0) MANUFACTURER_ID = (0, 32, 41) diff --git a/MIDI_Mix/ControlElementUtils.py b/MIDI_Mix/ControlElementUtils.py index ec0db735..fd9e5fcd 100644 --- a/MIDI_Mix/ControlElementUtils.py +++ b/MIDI_Mix/ControlElementUtils.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MIDI_Mix/ControlElementUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MIDI_Mix/ControlElementUtils.py import Live from _Framework.Dependency import depends from _Framework.InputControlElement import MIDI_CC_TYPE, MIDI_NOTE_TYPE diff --git a/MIDI_Mix/MIDI_Mix.py b/MIDI_Mix/MIDI_Mix.py index 2c4d774b..5e52c103 100644 --- a/MIDI_Mix/MIDI_Mix.py +++ b/MIDI_Mix/MIDI_Mix.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MIDI_Mix/MIDI_Mix.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MIDI_Mix/MIDI_Mix.py from __future__ import with_statement from itertools import chain from _Framework.Util import const diff --git a/MIDI_Mix/MixerComponent.py b/MIDI_Mix/MixerComponent.py index fb6eed0c..bcc2848f 100644 --- a/MIDI_Mix/MixerComponent.py +++ b/MIDI_Mix/MixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MIDI_Mix/MixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MIDI_Mix/MixerComponent.py from _Framework.Control import ButtonControl from _APC.MixerComponent import MixerComponent as MixerComponentBase diff --git a/MIDI_Mix/__init__.py b/MIDI_Mix/__init__.py index 853a4b55..4ccb31a0 100644 --- a/MIDI_Mix/__init__.py +++ b/MIDI_Mix/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MIDI_Mix/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MIDI_Mix/__init__.py import _Framework.Capabilities as caps from .MIDI_Mix import MIDI_Mix diff --git a/MPD18/__init__.py b/MPD18/__init__.py index 279e7f11..455c140b 100644 --- a/MPD18/__init__.py +++ b/MPD18/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD18/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD18/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/MPD18/config.py b/MPD18/config.py index f0da6323..36893305 100644 --- a/MPD18/config.py +++ b/MPD18/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD18/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD18/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/MPD18/consts.py b/MPD18/consts.py index 472c09a1..a470dd3d 100644 --- a/MPD18/consts.py +++ b/MPD18/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD18/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD18/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/MPD218/MPD218.py b/MPD218/MPD218.py index 44ff213e..d13f76ae 100644 --- a/MPD218/MPD218.py +++ b/MPD218/MPD218.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD218/MPD218.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD218/MPD218.py from _MPDMkIIBase.MPDMkIIBase import MPDMkIIBase PAD_CHANNEL = 9 PAD_IDS = [[48, diff --git a/MPD218/__init__.py b/MPD218/__init__.py index 76d34d46..89d7b557 100644 --- a/MPD218/__init__.py +++ b/MPD218/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD218/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD218/__init__.py import _Framework.Capabilities as caps from .MPD218 import MPD218 diff --git a/MPD226/MPD226.py b/MPD226/MPD226.py index 24ea87ea..58460337 100644 --- a/MPD226/MPD226.py +++ b/MPD226/MPD226.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD226/MPD226.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD226/MPD226.py from __future__ import with_statement from itertools import cycle, izip from _Framework.ButtonMatrixElement import ButtonMatrixElement diff --git a/MPD226/__init__.py b/MPD226/__init__.py index b46be8a0..9010193a 100644 --- a/MPD226/__init__.py +++ b/MPD226/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD226/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD226/__init__.py import _Framework.Capabilities as caps from .MPD226 import MPD226 diff --git a/MPD232/MPD232.py b/MPD232/MPD232.py index c310cbac..86e5cad6 100644 --- a/MPD232/MPD232.py +++ b/MPD232/MPD232.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD232/MPD232.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD232/MPD232.py from __future__ import with_statement from _Framework.ButtonMatrixElement import ButtonMatrixElement from _MPDMkIIBase.MPDMkIIBase import MPDMkIIBase diff --git a/MPD232/__init__.py b/MPD232/__init__.py index bcb49327..fb248508 100644 --- a/MPD232/__init__.py +++ b/MPD232/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD232/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD232/__init__.py import _Framework.Capabilities as caps from .MPD232 import MPD232 diff --git a/MPD24/__init__.py b/MPD24/__init__.py index a4449af7..b3662744 100644 --- a/MPD24/__init__.py +++ b/MPD24/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD24/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD24/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/MPD24/config.py b/MPD24/config.py index edb700ef..3043cb3c 100644 --- a/MPD24/config.py +++ b/MPD24/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD24/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD24/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/MPD24/consts.py b/MPD24/consts.py index 4c0ca18b..51ef2e1d 100644 --- a/MPD24/consts.py +++ b/MPD24/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD24/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD24/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/MPD32/__init__.py b/MPD32/__init__.py index 4d95a5c1..5927d474 100644 --- a/MPD32/__init__.py +++ b/MPD32/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD32/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD32/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/MPD32/config.py b/MPD32/config.py index 4c883e68..6b821773 100644 --- a/MPD32/config.py +++ b/MPD32/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD32/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD32/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/MPD32/consts.py b/MPD32/consts.py index 8cb59a93..5bbaa886 100644 --- a/MPD32/consts.py +++ b/MPD32/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPD32/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPD32/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/MPK225/MPK225.py b/MPK225/MPK225.py index 39842c33..efeea5d7 100644 --- a/MPK225/MPK225.py +++ b/MPK225/MPK225.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK225/MPK225.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK225/MPK225.py from __future__ import with_statement from _Framework.ControlSurface import ControlSurface from _Framework.Layer import Layer diff --git a/MPK225/__init__.py b/MPK225/__init__.py index a00fc36e..84b4e267 100644 --- a/MPK225/__init__.py +++ b/MPK225/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK225/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK225/__init__.py from .MPK225 import MPK225 from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE diff --git a/MPK249/MPK249.py b/MPK249/MPK249.py index 49a14345..ce586fe8 100644 --- a/MPK249/MPK249.py +++ b/MPK249/MPK249.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK249/MPK249.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK249/MPK249.py from __future__ import with_statement from _Framework.ControlSurface import ControlSurface from _Framework.Layer import Layer diff --git a/MPK249/__init__.py b/MPK249/__init__.py index 99e2d1b8..63b9fd05 100644 --- a/MPK249/__init__.py +++ b/MPK249/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK249/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK249/__init__.py from .MPK249 import MPK249 from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE diff --git a/MPK25/__init__.py b/MPK25/__init__.py index 9e5df1a4..7131b582 100644 --- a/MPK25/__init__.py +++ b/MPK25/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK25/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK25/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/MPK25/config.py b/MPK25/config.py index 761f3bc9..45d40913 100644 --- a/MPK25/config.py +++ b/MPK25/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK25/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK25/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/MPK25/consts.py b/MPK25/consts.py index 12f0590a..6f6b0777 100644 --- a/MPK25/consts.py +++ b/MPK25/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK25/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK25/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/MPK261/MPK261.py b/MPK261/MPK261.py index b4f86921..29805541 100644 --- a/MPK261/MPK261.py +++ b/MPK261/MPK261.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK261/MPK261.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK261/MPK261.py from __future__ import with_statement from _Framework.ControlSurface import ControlSurface from _Framework.Layer import Layer diff --git a/MPK261/__init__.py b/MPK261/__init__.py index 3e87206c..56052cd0 100644 --- a/MPK261/__init__.py +++ b/MPK261/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK261/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK261/__init__.py from .MPK261 import MPK261 from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE diff --git a/MPK49/__init__.py b/MPK49/__init__.py index 85008d39..68e15696 100644 --- a/MPK49/__init__.py +++ b/MPK49/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK49/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK49/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/MPK49/config.py b/MPK49/config.py index 7f859d05..5a4f1ac1 100644 --- a/MPK49/config.py +++ b/MPK49/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK49/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK49/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/MPK49/consts.py b/MPK49/consts.py index 58116527..734d634d 100644 --- a/MPK49/consts.py +++ b/MPK49/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK49/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK49/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/MPK61/__init__.py b/MPK61/__init__.py index 79fcedb8..69b8d6c3 100644 --- a/MPK61/__init__.py +++ b/MPK61/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK61/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK61/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/MPK61/config.py b/MPK61/config.py index d664af88..00a09dbf 100644 --- a/MPK61/config.py +++ b/MPK61/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK61/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK61/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/MPK61/consts.py b/MPK61/consts.py index 442d6702..c43a493e 100644 --- a/MPK61/consts.py +++ b/MPK61/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK61/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK61/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/MPK88/__init__.py b/MPK88/__init__.py index 93a350db..05d16bfd 100644 --- a/MPK88/__init__.py +++ b/MPK88/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK88/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK88/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/MPK88/config.py b/MPK88/config.py index ebc303d3..cbb0af8d 100644 --- a/MPK88/config.py +++ b/MPK88/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK88/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK88/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/MPK88/consts.py b/MPK88/consts.py index fd884e88..baff87bc 100644 --- a/MPK88/consts.py +++ b/MPK88/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK88/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK88/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/MPK_mini/__init__.py b/MPK_mini/__init__.py index 62dbe136..1a1791c1 100644 --- a/MPK_mini/__init__.py +++ b/MPK_mini/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK_mini/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK_mini/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/MPK_mini/config.py b/MPK_mini/config.py index bec0b010..e42f69ee 100644 --- a/MPK_mini/config.py +++ b/MPK_mini/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK_mini/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK_mini/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': -1, 'PLAY': -1, diff --git a/MPK_mini/consts.py b/MPK_mini/consts.py index b67c933e..54602d03 100644 --- a/MPK_mini/consts.py +++ b/MPK_mini/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MPK_mini/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MPK_mini/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/MackieControl/ChannelStrip.py b/MackieControl/ChannelStrip.py index 7502e455..9b3e8d8f 100644 --- a/MackieControl/ChannelStrip.py +++ b/MackieControl/ChannelStrip.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/ChannelStrip.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/ChannelStrip.py from MackieControlComponent import * from itertools import chain diff --git a/MackieControl/ChannelStripController.py b/MackieControl/ChannelStripController.py index 28e0e176..b0f42e1d 100644 --- a/MackieControl/ChannelStripController.py +++ b/MackieControl/ChannelStripController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/ChannelStripController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/ChannelStripController.py from MackieControlComponent import * from _Generic.Devices import * from itertools import chain @@ -236,7 +236,7 @@ def handle_vpot_rotation(self, strip_index, stack_offset, cc_value): pass else: channel_strip = self.__channel_strips[stack_offset + strip_index] - raise not channel_strip.assigned_track() or not channel_strip.assigned_track().has_audio_output or AssertionError, 'in every other mode, the midimap should handle the messages' + raise not channel_strip.assigned_track() or not channel_strip.assigned_track().has_audio_output or AssertionError('in every other mode, the midimap should handle the messages') def handle_fader_touch(self, strip_offset, stack_offset, touched): """ forwarded to us by the channel_strips """ @@ -255,14 +255,14 @@ def handle_pressed_v_pot(self, strip_index, stack_offset): param.value = param.value + 1 else: param.value = param.default_value - elif self.__assignment_mode == CSM_PLUGINS: - if self.__plugin_mode == PCM_DEVICES: - device_index = strip_index + stack_offset + self.__plugin_mode_offsets[PCM_DEVICES] - if device_index >= 0 and device_index < len(self.song().view.selected_track.devices): - if self.__chosen_plugin != None: - self.__chosen_plugin.remove_parameters_listener(self.__on_parameter_list_of_chosen_plugin_changed) - self.__chosen_plugin = self.song().view.selected_track.devices[device_index] - self.__chosen_plugin != None and self.__chosen_plugin.add_parameters_listener(self.__on_parameter_list_of_chosen_plugin_changed) + elif self.__assignment_mode == CSM_PLUGINS and self.__plugin_mode == PCM_DEVICES: + device_index = strip_index + stack_offset + self.__plugin_mode_offsets[PCM_DEVICES] + if device_index >= 0 and device_index < len(self.song().view.selected_track.devices): + if self.__chosen_plugin != None: + self.__chosen_plugin.remove_parameters_listener(self.__on_parameter_list_of_chosen_plugin_changed) + self.__chosen_plugin = self.song().view.selected_track.devices[device_index] + if self.__chosen_plugin != None: + self.__chosen_plugin.add_parameters_listener(self.__on_parameter_list_of_chosen_plugin_changed) self.__reorder_parameters() self.__plugin_mode_offsets[PCM_PARAMETERS] = 0 self.__set_plugin_mode(PCM_PARAMETERS) @@ -302,13 +302,13 @@ def __plugin_parameter(self, strip_index, stack_index): """ if not self.__assignment_mode == CSM_PLUGINS: raise AssertionError - return self.__plugin_mode == PCM_DEVICES and (None, None) - elif not (self.__plugin_mode == PCM_PARAMETERS and self.__chosen_plugin): - raise AssertionError - parameters = self.__ordered_plugin_parameters - parameter_index = strip_index + stack_index + self.__plugin_mode_offsets[PCM_PARAMETERS] - if parameter_index >= 0 and parameter_index < len(parameters): - return parameters[parameter_index] + if self.__plugin_mode == PCM_DEVICES: + return (None, None) + elif not (self.__plugin_mode == PCM_PARAMETERS and self.__chosen_plugin): + raise AssertionError + parameters = self.__ordered_plugin_parameters + parameter_index = strip_index + stack_index + self.__plugin_mode_offsets[PCM_PARAMETERS] + return parameter_index >= 0 and parameter_index < len(parameters) and parameters[parameter_index] else: return (None, None) else: @@ -324,7 +324,7 @@ def __any_slider_is_touched(self): def __can_flip(self): if self.__assignment_mode == CSM_PLUGINS and self.__plugin_mode == PCM_DEVICES: return False - elif self.__assignment_mode == CSM_IO: + if self.__assignment_mode == CSM_IO: return False return True @@ -343,48 +343,45 @@ def __can_switch_to_next_page(self): sel_track = self.song().view.selected_track if self.__plugin_mode == PCM_DEVICES: return self.__plugin_mode_offsets[PCM_DEVICES] + len(self.__channel_strips) < len(sel_track.devices) - elif not (self.__plugin_mode == PCM_PARAMETERS and self.__chosen_plugin): - raise AssertionError - parameters = self.__ordered_plugin_parameters - return self.__plugin_mode_offsets[PCM_PARAMETERS] + len(self.__channel_strips) < len(parameters) - else: - raise 0 or AssertionError - elif self.__assignment_mode == CSM_SENDS: - return self.__send_mode_offset + len(self.__channel_strips) < len(self.song().return_tracks) + raise self.__plugin_mode == PCM_PARAMETERS and (self.__chosen_plugin or AssertionError) + parameters = self.__ordered_plugin_parameters + return self.__plugin_mode_offsets[PCM_PARAMETERS] + len(self.__channel_strips) < len(parameters) + if not 0: + raise AssertionError else: + if self.__assignment_mode == CSM_SENDS: + return self.__send_mode_offset + len(self.__channel_strips) < len(self.song().return_tracks) return False def __available_routing_targets(self, channel_strip): - raise self.__assignment_mode == CSM_IO or AssertionError - t = channel_strip.assigned_track() - if t: - if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_MAIN: - return t.input_routings - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_SUB: - return t.input_sub_routings - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_MAIN: - return t.output_routings - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_SUB: - return t.output_sub_routings - else: - raise 0 or AssertionError + if not self.__assignment_mode == CSM_IO: + raise AssertionError + t = channel_strip.assigned_track() + if t: + if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_MAIN: + return t.input_routings + if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_SUB: + return t.input_sub_routings + if self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_MAIN: + return t.output_routings + return self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_SUB and t.output_sub_routings + raise 0 or AssertionError else: return None def __routing_target(self, channel_strip): - raise self.__assignment_mode == CSM_IO or AssertionError - t = channel_strip.assigned_track() - if t: - if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_MAIN: - return t.current_input_routing - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_SUB: - return t.current_input_sub_routing - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_MAIN: - return t.current_output_routing - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_SUB: - return t.current_output_sub_routing - else: - raise 0 or AssertionError + if not self.__assignment_mode == CSM_IO: + raise AssertionError + t = channel_strip.assigned_track() + if t: + if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_MAIN: + return t.current_input_routing + if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_SUB: + return t.current_input_sub_routing + if self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_MAIN: + return t.current_output_routing + return self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_SUB and t.current_output_sub_routing + raise 0 or AssertionError else: return None diff --git a/MackieControl/MackieControl.py b/MackieControl/MackieControl.py index 3e9f35bc..dda8431d 100644 --- a/MackieControl/MackieControl.py +++ b/MackieControl/MackieControl.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/MackieControl.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/MackieControl.py from consts import * from MainDisplay import MainDisplay from MainDisplayController import MainDisplayController diff --git a/MackieControl/MackieControlComponent.py b/MackieControl/MackieControlComponent.py index e778dd2f..6e89f1df 100644 --- a/MackieControl/MackieControlComponent.py +++ b/MackieControl/MackieControlComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/MackieControlComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/MackieControlComponent.py from consts import * import Live diff --git a/MackieControl/MainDisplay.py b/MackieControl/MainDisplay.py index 0b430d4b..c597a81f 100644 --- a/MackieControl/MainDisplay.py +++ b/MackieControl/MainDisplay.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/MainDisplay.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/MainDisplay.py from MackieControlComponent import * class MainDisplay(MackieControlComponent): diff --git a/MackieControl/MainDisplayController.py b/MackieControl/MainDisplayController.py index abe91a46..8c5b59a9 100644 --- a/MackieControl/MainDisplayController.py +++ b/MackieControl/MainDisplayController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/MainDisplayController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/MainDisplayController.py from MackieControlComponent import * class MainDisplayController(MackieControlComponent): diff --git a/MackieControl/SoftwareController.py b/MackieControl/SoftwareController.py index 149020e2..d7d358de 100644 --- a/MackieControl/SoftwareController.py +++ b/MackieControl/SoftwareController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/SoftwareController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/SoftwareController.py from MackieControlComponent import * class SoftwareController(MackieControlComponent): diff --git a/MackieControl/TimeDisplay.py b/MackieControl/TimeDisplay.py index dbeb3ca6..7f57e3a2 100644 --- a/MackieControl/TimeDisplay.py +++ b/MackieControl/TimeDisplay.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/TimeDisplay.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/TimeDisplay.py from MackieControlComponent import * class TimeDisplay(MackieControlComponent): diff --git a/MackieControl/Transport.py b/MackieControl/Transport.py index 8103b407..25ab5f87 100644 --- a/MackieControl/Transport.py +++ b/MackieControl/Transport.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/Transport.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/Transport.py from MackieControlComponent import * class Transport(MackieControlComponent): @@ -92,36 +92,36 @@ def on_update_display_timer(self): base_acceleration = self.song().signature_numerator if self.song().is_playing: base_acceleration *= 4 - if self.__forward_button_down: - if not self.____rewind_button_down: - if self.__forward_button_down: - self.____fast_forward_counter += 1 - self.__fast___rewind_counter -= 4 - if not self.alt_is_pressed(): - self.__fast_forward(base_acceleration + max(1, self.____fast_forward_counter / 4)) - else: - self.__fast_forward(base_acceleration) - if self.____rewind_button_down: - self.__fast___rewind_counter += 1 - self.____fast_forward_counter -= 4 - if not self.alt_is_pressed(): - self.__rewind(base_acceleration + max(1, self.__fast___rewind_counter / 4)) - else: - self.__rewind(base_acceleration) - else: - self.__transport_repeat_delay += 1 - if self.__cursor_repeat_delay > 2: - if self.__cursor_left_is_down: - self.__on_cursor_left_pressed() - if self.__cursor_right_is_down: - self.__on_cursor_right_pressed() - if self.__cursor_up_is_down: - self.__on_cursor_up_pressed() - if self.__cursor_down_is_down: - self.__on_cursor_down_pressed() - else: - self.__cursor_repeat_delay += 1 - self.session_is_visible() and self.__update_zoom_led_in_session() + if not (self.__forward_button_down and self.____rewind_button_down): + if self.__forward_button_down: + self.____fast_forward_counter += 1 + self.__fast___rewind_counter -= 4 + if not self.alt_is_pressed(): + self.__fast_forward(base_acceleration + max(1, self.____fast_forward_counter / 4)) + else: + self.__fast_forward(base_acceleration) + if self.____rewind_button_down: + self.__fast___rewind_counter += 1 + self.____fast_forward_counter -= 4 + if not self.alt_is_pressed(): + self.__rewind(base_acceleration + max(1, self.__fast___rewind_counter / 4)) + else: + self.__rewind(base_acceleration) + else: + self.__transport_repeat_delay += 1 + if self.__cursor_repeat_delay > 2: + if self.__cursor_left_is_down: + self.__on_cursor_left_pressed() + if self.__cursor_right_is_down: + self.__on_cursor_right_pressed() + if self.__cursor_up_is_down: + self.__on_cursor_up_pressed() + if self.__cursor_down_is_down: + self.__on_cursor_down_pressed() + else: + self.__cursor_repeat_delay += 1 + if self.session_is_visible(): + self.__update_zoom_led_in_session() def handle_marker_switch_ids(self, switch_id, value): if switch_id == SID_MARKER_FROM_PREV: diff --git a/MackieControl/__init__.py b/MackieControl/__init__.py index ad13be55..1032bcc6 100644 --- a/MackieControl/__init__.py +++ b/MackieControl/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/__init__.py from MackieControl import MackieControl def create_instance(c_instance): diff --git a/MackieControl/consts.py b/MackieControl/consts.py index 6aec0253..dbf0988f 100644 --- a/MackieControl/consts.py +++ b/MackieControl/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl/consts.py NOTE_OFF_STATUS = 128 NOTE_ON_STATUS = 144 CC_STATUS = 176 diff --git a/MackieControlXT/MackieControlXT.py b/MackieControlXT/MackieControlXT.py index 4a99f21d..b8c2968e 100644 --- a/MackieControlXT/MackieControlXT.py +++ b/MackieControlXT/MackieControlXT.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControlXT/MackieControlXT.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControlXT/MackieControlXT.py from MackieControl.consts import * from MackieControl.MainDisplay import MainDisplay from MackieControl.ChannelStrip import ChannelStrip diff --git a/MackieControlXT/__init__.py b/MackieControlXT/__init__.py index 70cdbee8..95b20b69 100644 --- a/MackieControlXT/__init__.py +++ b/MackieControlXT/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControlXT/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControlXT/__init__.py from MackieControlXT import MackieControlXT def create_instance(c_instance): diff --git a/MackieControl_Classic/ChannelStrip.py b/MackieControl_Classic/ChannelStrip.py index 05f411d6..059abc8e 100644 --- a/MackieControl_Classic/ChannelStrip.py +++ b/MackieControl_Classic/ChannelStrip.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/ChannelStrip.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/ChannelStrip.py from MackieControlComponent import * from itertools import chain diff --git a/MackieControl_Classic/ChannelStripController.py b/MackieControl_Classic/ChannelStripController.py index 61e1c962..832a04eb 100644 --- a/MackieControl_Classic/ChannelStripController.py +++ b/MackieControl_Classic/ChannelStripController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/ChannelStripController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/ChannelStripController.py from MackieControlComponent import * from _Generic.Devices import * from itertools import chain @@ -236,7 +236,7 @@ def handle_vpot_rotation(self, strip_index, stack_offset, cc_value): pass else: channel_strip = self.__channel_strips[stack_offset + strip_index] - raise not channel_strip.assigned_track() or not channel_strip.assigned_track().has_audio_output or AssertionError, 'in every other mode, the midimap should handle the messages' + raise not channel_strip.assigned_track() or not channel_strip.assigned_track().has_audio_output or AssertionError('in every other mode, the midimap should handle the messages') def handle_fader_touch(self, strip_offset, stack_offset, touched): """ forwarded to us by the channel_strips """ @@ -255,14 +255,14 @@ def handle_pressed_v_pot(self, strip_index, stack_offset): param.value = param.value + 1 else: param.value = param.default_value - elif self.__assignment_mode == CSM_PLUGINS: - if self.__plugin_mode == PCM_DEVICES: - device_index = strip_index + stack_offset + self.__plugin_mode_offsets[PCM_DEVICES] - if device_index >= 0 and device_index < len(self.song().view.selected_track.devices): - if self.__chosen_plugin != None: - self.__chosen_plugin.remove_parameters_listener(self.__on_parameter_list_of_chosen_plugin_changed) - self.__chosen_plugin = self.song().view.selected_track.devices[device_index] - self.__chosen_plugin != None and self.__chosen_plugin.add_parameters_listener(self.__on_parameter_list_of_chosen_plugin_changed) + elif self.__assignment_mode == CSM_PLUGINS and self.__plugin_mode == PCM_DEVICES: + device_index = strip_index + stack_offset + self.__plugin_mode_offsets[PCM_DEVICES] + if device_index >= 0 and device_index < len(self.song().view.selected_track.devices): + if self.__chosen_plugin != None: + self.__chosen_plugin.remove_parameters_listener(self.__on_parameter_list_of_chosen_plugin_changed) + self.__chosen_plugin = self.song().view.selected_track.devices[device_index] + if self.__chosen_plugin != None: + self.__chosen_plugin.add_parameters_listener(self.__on_parameter_list_of_chosen_plugin_changed) self.__reorder_parameters() self.__plugin_mode_offsets[PCM_PARAMETERS] = 0 self.__set_plugin_mode(PCM_PARAMETERS) @@ -302,13 +302,13 @@ def __plugin_parameter(self, strip_index, stack_index): """ if not self.__assignment_mode == CSM_PLUGINS: raise AssertionError - return self.__plugin_mode == PCM_DEVICES and (None, None) - elif not (self.__plugin_mode == PCM_PARAMETERS and self.__chosen_plugin): - raise AssertionError - parameters = self.__ordered_plugin_parameters - parameter_index = strip_index + stack_index + self.__plugin_mode_offsets[PCM_PARAMETERS] - if parameter_index >= 0 and parameter_index < len(parameters): - return parameters[parameter_index] + if self.__plugin_mode == PCM_DEVICES: + return (None, None) + elif not (self.__plugin_mode == PCM_PARAMETERS and self.__chosen_plugin): + raise AssertionError + parameters = self.__ordered_plugin_parameters + parameter_index = strip_index + stack_index + self.__plugin_mode_offsets[PCM_PARAMETERS] + return parameter_index >= 0 and parameter_index < len(parameters) and parameters[parameter_index] else: return (None, None) else: @@ -324,7 +324,7 @@ def __any_slider_is_touched(self): def __can_flip(self): if self.__assignment_mode == CSM_PLUGINS and self.__plugin_mode == PCM_DEVICES: return False - elif self.__assignment_mode == CSM_IO: + if self.__assignment_mode == CSM_IO: return False return True @@ -343,48 +343,45 @@ def __can_switch_to_next_page(self): sel_track = self.song().view.selected_track if self.__plugin_mode == PCM_DEVICES: return self.__plugin_mode_offsets[PCM_DEVICES] + len(self.__channel_strips) < len(sel_track.devices) - elif not (self.__plugin_mode == PCM_PARAMETERS and self.__chosen_plugin): - raise AssertionError - parameters = self.__ordered_plugin_parameters - return self.__plugin_mode_offsets[PCM_PARAMETERS] + len(self.__channel_strips) < len(parameters) - else: - raise 0 or AssertionError - elif self.__assignment_mode == CSM_SENDS: - return self.__send_mode_offset + len(self.__channel_strips) < len(self.song().return_tracks) + raise self.__plugin_mode == PCM_PARAMETERS and (self.__chosen_plugin or AssertionError) + parameters = self.__ordered_plugin_parameters + return self.__plugin_mode_offsets[PCM_PARAMETERS] + len(self.__channel_strips) < len(parameters) + if not 0: + raise AssertionError else: + if self.__assignment_mode == CSM_SENDS: + return self.__send_mode_offset + len(self.__channel_strips) < len(self.song().return_tracks) return False def __available_routing_targets(self, channel_strip): - raise self.__assignment_mode == CSM_IO or AssertionError - t = channel_strip.assigned_track() - if t: - if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_MAIN: - return t.input_routings - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_SUB: - return t.input_sub_routings - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_MAIN: - return t.output_routings - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_SUB: - return t.output_sub_routings - else: - raise 0 or AssertionError + if not self.__assignment_mode == CSM_IO: + raise AssertionError + t = channel_strip.assigned_track() + if t: + if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_MAIN: + return t.input_routings + if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_SUB: + return t.input_sub_routings + if self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_MAIN: + return t.output_routings + return self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_SUB and t.output_sub_routings + raise 0 or AssertionError else: return None def __routing_target(self, channel_strip): - raise self.__assignment_mode == CSM_IO or AssertionError - t = channel_strip.assigned_track() - if t: - if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_MAIN: - return t.current_input_routing - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_SUB: - return t.current_input_sub_routing - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_MAIN: - return t.current_output_routing - elif self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_SUB: - return t.current_output_sub_routing - else: - raise 0 or AssertionError + if not self.__assignment_mode == CSM_IO: + raise AssertionError + t = channel_strip.assigned_track() + if t: + if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_MAIN: + return t.current_input_routing + if self.__sub_mode_in_io_mode == CSM_IO_MODE_INPUT_SUB: + return t.current_input_sub_routing + if self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_MAIN: + return t.current_output_routing + return self.__sub_mode_in_io_mode == CSM_IO_MODE_OUTPUT_SUB and t.current_output_sub_routing + raise 0 or AssertionError else: return None diff --git a/MackieControl_Classic/MackieControl.py b/MackieControl_Classic/MackieControl.py index b200f7f1..8e25f65a 100644 --- a/MackieControl_Classic/MackieControl.py +++ b/MackieControl_Classic/MackieControl.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/MackieControl.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/MackieControl.py from consts import * from MainDisplay import MainDisplay from MainDisplayController import MainDisplayController diff --git a/MackieControl_Classic/MackieControlComponent.py b/MackieControl_Classic/MackieControlComponent.py index 71403987..a2154d70 100644 --- a/MackieControl_Classic/MackieControlComponent.py +++ b/MackieControl_Classic/MackieControlComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/MackieControlComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/MackieControlComponent.py from consts import * import Live diff --git a/MackieControl_Classic/MainDisplay.py b/MackieControl_Classic/MainDisplay.py index 9c098cf2..fdd5663b 100644 --- a/MackieControl_Classic/MainDisplay.py +++ b/MackieControl_Classic/MainDisplay.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/MainDisplay.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/MainDisplay.py from MackieControlComponent import * class MainDisplay(MackieControlComponent): diff --git a/MackieControl_Classic/MainDisplayController.py b/MackieControl_Classic/MainDisplayController.py index 29649528..6dc5ba70 100644 --- a/MackieControl_Classic/MainDisplayController.py +++ b/MackieControl_Classic/MainDisplayController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/MainDisplayController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/MainDisplayController.py from MackieControlComponent import * class MainDisplayController(MackieControlComponent): diff --git a/MackieControl_Classic/SoftwareController.py b/MackieControl_Classic/SoftwareController.py index 52b3d7d7..f0e57ec6 100644 --- a/MackieControl_Classic/SoftwareController.py +++ b/MackieControl_Classic/SoftwareController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/SoftwareController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/SoftwareController.py from MackieControlComponent import * class SoftwareController(MackieControlComponent): diff --git a/MackieControl_Classic/TimeDisplay.py b/MackieControl_Classic/TimeDisplay.py index c7360811..abad43c3 100644 --- a/MackieControl_Classic/TimeDisplay.py +++ b/MackieControl_Classic/TimeDisplay.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/TimeDisplay.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/TimeDisplay.py from MackieControlComponent import * class TimeDisplay(MackieControlComponent): diff --git a/MackieControl_Classic/Transport.py b/MackieControl_Classic/Transport.py index 3f0c7c2d..7dd5a859 100644 --- a/MackieControl_Classic/Transport.py +++ b/MackieControl_Classic/Transport.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/Transport.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/Transport.py from MackieControlComponent import * class Transport(MackieControlComponent): @@ -92,36 +92,36 @@ def on_update_display_timer(self): base_acceleration = self.song().signature_numerator if self.song().is_playing: base_acceleration *= 4 - if self.__forward_button_down: - if not self.____rewind_button_down: - if self.__forward_button_down: - self.____fast_forward_counter += 1 - self.__fast___rewind_counter -= 4 - if not self.alt_is_pressed(): - self.__fast_forward(base_acceleration + max(1, self.____fast_forward_counter / 4)) - else: - self.__fast_forward(base_acceleration) - if self.____rewind_button_down: - self.__fast___rewind_counter += 1 - self.____fast_forward_counter -= 4 - if not self.alt_is_pressed(): - self.__rewind(base_acceleration + max(1, self.__fast___rewind_counter / 4)) - else: - self.__rewind(base_acceleration) - else: - self.__transport_repeat_delay += 1 - if self.__cursor_repeat_delay > 2: - if self.__cursor_left_is_down: - self.__on_cursor_left_pressed() - if self.__cursor_right_is_down: - self.__on_cursor_right_pressed() - if self.__cursor_up_is_down: - self.__on_cursor_up_pressed() - if self.__cursor_down_is_down: - self.__on_cursor_down_pressed() - else: - self.__cursor_repeat_delay += 1 - self.session_is_visible() and self.__update_zoom_led_in_session() + if not (self.__forward_button_down and self.____rewind_button_down): + if self.__forward_button_down: + self.____fast_forward_counter += 1 + self.__fast___rewind_counter -= 4 + if not self.alt_is_pressed(): + self.__fast_forward(base_acceleration + max(1, self.____fast_forward_counter / 4)) + else: + self.__fast_forward(base_acceleration) + if self.____rewind_button_down: + self.__fast___rewind_counter += 1 + self.____fast_forward_counter -= 4 + if not self.alt_is_pressed(): + self.__rewind(base_acceleration + max(1, self.__fast___rewind_counter / 4)) + else: + self.__rewind(base_acceleration) + else: + self.__transport_repeat_delay += 1 + if self.__cursor_repeat_delay > 2: + if self.__cursor_left_is_down: + self.__on_cursor_left_pressed() + if self.__cursor_right_is_down: + self.__on_cursor_right_pressed() + if self.__cursor_up_is_down: + self.__on_cursor_up_pressed() + if self.__cursor_down_is_down: + self.__on_cursor_down_pressed() + else: + self.__cursor_repeat_delay += 1 + if self.session_is_visible(): + self.__update_zoom_led_in_session() def handle_marker_switch_ids(self, switch_id, value): if switch_id == SID_MARKER_FROM_PREV: diff --git a/MackieControl_Classic/__init__.py b/MackieControl_Classic/__init__.py index aee1440d..f219fd14 100644 --- a/MackieControl_Classic/__init__.py +++ b/MackieControl_Classic/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/__init__.py from MackieControl import MackieControl def create_instance(c_instance): diff --git a/MackieControl_Classic/consts.py b/MackieControl_Classic/consts.py index ca17e9f8..ff1c053f 100644 --- a/MackieControl_Classic/consts.py +++ b/MackieControl_Classic/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MackieControl_Classic/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MackieControl_Classic/consts.py NOTE_OFF_STATUS = 128 NOTE_ON_STATUS = 144 CC_STATUS = 176 diff --git a/MasterControl/MasterControl.py b/MasterControl/MasterControl.py index f1c9568c..82b192e8 100644 --- a/MasterControl/MasterControl.py +++ b/MasterControl/MasterControl.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MasterControl/MasterControl.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MasterControl/MasterControl.py from MackieControl.MackieControl import MackieControl class MasterControl(MackieControl): diff --git a/MasterControl/__init__.py b/MasterControl/__init__.py index e7e9a05e..f45f54be 100644 --- a/MasterControl/__init__.py +++ b/MasterControl/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MasterControl/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MasterControl/__init__.py from MasterControl import MasterControl def create_instance(c_instance): diff --git a/MidAir25/__init__.py b/MidAir25/__init__.py index ceb8eb8a..a2e5eb83 100644 --- a/MidAir25/__init__.py +++ b/MidAir25/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MidAir25/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MidAir25/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/MidAir25/config.py b/MidAir25/config.py index 2c7414f9..a1270e38 100644 --- a/MidAir25/config.py +++ b/MidAir25/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MidAir25/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MidAir25/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/MidAir25/consts.py b/MidAir25/consts.py index ad3199ca..370885cb 100644 --- a/MidAir25/consts.py +++ b/MidAir25/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/MidAir25/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MidAir25/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/MiniLab/MiniLab.py b/MiniLab/MiniLab.py new file mode 100644 index 00000000..974649a5 --- /dev/null +++ b/MiniLab/MiniLab.py @@ -0,0 +1,65 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MiniLab/MiniLab.py +from __future__ import with_statement +from itertools import izip +import Live +from _Arturia.ArturiaControlSurface import ArturiaControlSurface +from _Arturia.SessionComponent import SessionComponent +from _Arturia.MixerComponent import MixerComponent +from _Framework.Layer import Layer +from _Framework.DeviceComponent import DeviceComponent +from _Framework.InputControlElement import MIDI_CC_TYPE, MIDI_NOTE_TYPE +from _Framework.ButtonMatrixElement import ButtonMatrixElement +from _Framework.ButtonElement import ButtonElement +from _Framework.EncoderElement import EncoderElement +HARDWARE_ENCODER_IDS = (48, 1, 2, 9, 11, 12, 13, 14, 51, 3, 4, 10, 5, 6, 7, 8) +HARDWARE_BUTTON_IDS = xrange(112, 128) +ENCODER_MSG_IDS = (7, 74, 71, 76, 77, 93, 73, 75, 114, 18, 19, 16, 17, 91, 79, 72) +PAD_IDENTIFIER_OFFSET = 36 +PAD_CHANNEL = 9 + +class MiniLab(ArturiaControlSurface): + + def __init__(self, *a, **k): + super(MiniLab, self).__init__(*a, **k) + with self.component_guard(): + self._create_controls() + self._create_device() + self._create_session() + self._create_mixer() + + def _create_controls(self): + self._device_controls = ButtonMatrixElement(rows=[ [ EncoderElement(MIDI_CC_TYPE, 0, identifier, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Encoder_%d_%d' % (column_index, row_index)) for column_index, identifier in enumerate(row) ] for row_index, row in enumerate((ENCODER_MSG_IDS[:4], ENCODER_MSG_IDS[8:12])) ]) + self._horizontal_scroll_encoder = EncoderElement(MIDI_CC_TYPE, 0, 75, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Horizontal_Scroll_Encoder') + self._vertical_scroll_encoder = EncoderElement(MIDI_CC_TYPE, 0, 72, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Vertical_Scroll_Encoder') + self._volume_encoder = EncoderElement(MIDI_CC_TYPE, 0, 91, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Volume_Encoder') + self._pan_encoder = EncoderElement(MIDI_CC_TYPE, 0, 17, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Pan_Encoder') + self._send_a_encoder = EncoderElement(MIDI_CC_TYPE, 0, 77, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Send_A_Encoder') + self._send_b_encoder = EncoderElement(MIDI_CC_TYPE, 0, 93, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Send_B_Encoder') + self._send_encoders = ButtonMatrixElement(rows=[[self._send_a_encoder, self._send_b_encoder]]) + self._return_a_encoder = EncoderElement(MIDI_CC_TYPE, 0, 73, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Return_A_Encoder') + self._return_b_encoder = EncoderElement(MIDI_CC_TYPE, 0, 79, Live.MidiMap.MapMode.relative_smooth_two_compliment, name='Return_B_Encoder') + self._return_encoders = ButtonMatrixElement(rows=[[self._return_a_encoder, self._return_b_encoder]]) + self._pads = ButtonMatrixElement(rows=[ [ ButtonElement(True, MIDI_NOTE_TYPE, PAD_CHANNEL, col + 36 + 8 * row, name='Pad_%d_%d' % (col, row)) for col in xrange(8) ] for row in xrange(2) ]) + + def _create_device(self): + self._device = DeviceComponent(name='Device', is_enabled=False, layer=Layer(parameter_controls=self._device_controls)) + self._device.set_enabled(True) + self.set_device_component(self._device) + self._device_selection_follows_track_selection = True + + def _create_session(self): + self._session = SessionComponent(num_tracks=self._pads.width(), num_scenes=self._pads.height(), name='Session', is_enabled=False, layer=Layer(clip_launch_buttons=self._pads, scene_select_control=self._vertical_scroll_encoder)) + self._session.set_enabled(True) + + def _create_mixer(self): + self._mixer = MixerComponent(name='Mixer', is_enabled=False, num_returns=2, layer=Layer(track_select_encoder=self._horizontal_scroll_encoder, selected_track_volume_control=self._volume_encoder, selected_track_pan_control=self._pan_encoder, selected_track_send_controls=self._send_encoders, return_volume_controls=self._return_encoders)) + self._mixer.set_enabled(True) + + def _collect_setup_messages(self): + for cc_id, encoder_id in izip(ENCODER_MSG_IDS, HARDWARE_ENCODER_IDS): + self._setup_hardware_encoder(encoder_id, cc_id) + + for index, pad_id in enumerate(HARDWARE_BUTTON_IDS): + identifier = index + PAD_IDENTIFIER_OFFSET + channel = PAD_CHANNEL + self._setup_hardware_button(pad_id, identifier, channel) \ No newline at end of file diff --git a/MiniLab/__init__.py b/MiniLab/__init__.py new file mode 100644 index 00000000..524753de --- /dev/null +++ b/MiniLab/__init__.py @@ -0,0 +1,11 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/MiniLab/__init__.py +from .MiniLab import MiniLab +import _Framework.Capabilities as caps + +def get_capabilities(): + return {caps.CONTROLLER_ID_KEY: caps.controller_id(vendor_id=7285, product_ids=[516], model_name=['Arturia MINILAB']), + caps.PORTS_KEY: [caps.inport(props=[caps.NOTES_CC, caps.SCRIPT, caps.REMOTE]), caps.outport(props=[caps.SCRIPT])]} + + +def create_instance(c_instance): + return MiniLab(c_instance) \ No newline at end of file diff --git a/Novation_Impulse/EncoderModeSelector.py b/Novation_Impulse/EncoderModeSelector.py index dcf1256d..113ab40c 100644 --- a/Novation_Impulse/EncoderModeSelector.py +++ b/Novation_Impulse/EncoderModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Novation_Impulse/EncoderModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Novation_Impulse/EncoderModeSelector.py import Live from _Framework.ModeSelectorComponent import ModeSelectorComponent diff --git a/Novation_Impulse/Novation_Impulse.py b/Novation_Impulse/Novation_Impulse.py index c4a91c05..1db34328 100644 --- a/Novation_Impulse/Novation_Impulse.py +++ b/Novation_Impulse/Novation_Impulse.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Novation_Impulse/Novation_Impulse.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Novation_Impulse/Novation_Impulse.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/Novation_Impulse/PeekableEncoderElement.py b/Novation_Impulse/PeekableEncoderElement.py index 8d6f8fff..f50add57 100644 --- a/Novation_Impulse/PeekableEncoderElement.py +++ b/Novation_Impulse/PeekableEncoderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Novation_Impulse/PeekableEncoderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Novation_Impulse/PeekableEncoderElement.py import Live from _Framework.EncoderElement import EncoderElement from _Framework.InputControlElement import * diff --git a/Novation_Impulse/ShiftableTransportComponent.py b/Novation_Impulse/ShiftableTransportComponent.py index 262b06a2..d372e5dd 100644 --- a/Novation_Impulse/ShiftableTransportComponent.py +++ b/Novation_Impulse/ShiftableTransportComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Novation_Impulse/ShiftableTransportComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Novation_Impulse/ShiftableTransportComponent.py import Live from _Framework.ButtonElement import ButtonElement from _Framework.TransportComponent import TransportComponent diff --git a/Novation_Impulse/SpecialMixerComponent.py b/Novation_Impulse/SpecialMixerComponent.py index 18ef8470..a97c2c56 100644 --- a/Novation_Impulse/SpecialMixerComponent.py +++ b/Novation_Impulse/SpecialMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Novation_Impulse/SpecialMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Novation_Impulse/SpecialMixerComponent.py from _Framework.MixerComponent import MixerComponent from _Framework.ButtonElement import ButtonElement @@ -97,22 +97,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 + 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 found_recording_clip or song.exclusive_arm: + 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 diff --git a/Novation_Impulse/TransportViewModeSelector.py b/Novation_Impulse/TransportViewModeSelector.py index 4686c3dd..323af71f 100644 --- a/Novation_Impulse/TransportViewModeSelector.py +++ b/Novation_Impulse/TransportViewModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Novation_Impulse/TransportViewModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Novation_Impulse/TransportViewModeSelector.py import Live from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.ButtonElement import ButtonElement diff --git a/Novation_Impulse/__init__.py b/Novation_Impulse/__init__.py index 7ead6cb0..14d9b54e 100644 --- a/Novation_Impulse/__init__.py +++ b/Novation_Impulse/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Novation_Impulse/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Novation_Impulse/__init__.py from Novation_Impulse import Novation_Impulse def create_instance(c_instance): diff --git a/O2/__init__.py b/O2/__init__.py index a3f77b03..4a2419d3 100644 --- a/O2/__init__.py +++ b/O2/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/O2/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/O2/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/O2/config.py b/O2/config.py index 0cf9c801..67ddbff1 100644 --- a/O2/config.py +++ b/O2/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/O2/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/O2/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/O2/consts.py b/O2/consts.py index 522358f5..84f657d0 100644 --- a/O2/consts.py +++ b/O2/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/O2/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/O2/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/OpenLabs/OpenLabs.py b/OpenLabs/OpenLabs.py index 6d5cc658..3874183c 100644 --- a/OpenLabs/OpenLabs.py +++ b/OpenLabs/OpenLabs.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/OpenLabs/OpenLabs.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/OpenLabs/OpenLabs.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/OpenLabs/SpecialDeviceComponent.py b/OpenLabs/SpecialDeviceComponent.py index 3b22222d..cd53d5ad 100644 --- a/OpenLabs/SpecialDeviceComponent.py +++ b/OpenLabs/SpecialDeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/OpenLabs/SpecialDeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/OpenLabs/SpecialDeviceComponent.py import Live from _Framework.DeviceComponent import DeviceComponent diff --git a/OpenLabs/SpecialTransportComponent.py b/OpenLabs/SpecialTransportComponent.py index f597101c..0eebbea8 100644 --- a/OpenLabs/SpecialTransportComponent.py +++ b/OpenLabs/SpecialTransportComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/OpenLabs/SpecialTransportComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/OpenLabs/SpecialTransportComponent.py import Live from _Framework.TransportComponent import TransportComponent from _Framework.InputControlElement import * diff --git a/OpenLabs/__init__.py b/OpenLabs/__init__.py index 7d01c3da..191164a7 100644 --- a/OpenLabs/__init__.py +++ b/OpenLabs/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/OpenLabs/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/OpenLabs/__init__.py import Live from OpenLabs import OpenLabs diff --git a/Oxygen49_61/__init__.py b/Oxygen49_61/__init__.py index 175e2dec..c1ea67f7 100644 --- a/Oxygen49_61/__init__.py +++ b/Oxygen49_61/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen49_61/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen49_61/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Oxygen49_61/config.py b/Oxygen49_61/config.py index ac70ba2a..7bb0069f 100644 --- a/Oxygen49_61/config.py +++ b/Oxygen49_61/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen49_61/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen49_61/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/Oxygen49_61/consts.py b/Oxygen49_61/consts.py index 4a3910e0..50112c2b 100644 --- a/Oxygen49_61/consts.py +++ b/Oxygen49_61/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen49_61/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen49_61/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/Oxygen8/__init__.py b/Oxygen8/__init__.py index a3f3ba45..b4b7e691 100644 --- a/Oxygen8/__init__.py +++ b/Oxygen8/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen8/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen8/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Oxygen8/config.py b/Oxygen8/config.py index 28b8ed42..3b4d8726 100644 --- a/Oxygen8/config.py +++ b/Oxygen8/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen8/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen8/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/Oxygen8/consts.py b/Oxygen8/consts.py index cf1cc2b5..3d9ab72a 100644 --- a/Oxygen8/consts.py +++ b/Oxygen8/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen8/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen8/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/Oxygen8v2/__init__.py b/Oxygen8v2/__init__.py index 7e13c136..bba8a2c6 100644 --- a/Oxygen8v2/__init__.py +++ b/Oxygen8v2/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen8v2/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen8v2/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Oxygen8v2/config.py b/Oxygen8v2/config.py index 4cb7439a..a4eebc14 100644 --- a/Oxygen8v2/config.py +++ b/Oxygen8v2/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen8v2/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen8v2/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/Oxygen8v2/consts.py b/Oxygen8v2/consts.py index 09efe4de..5393f591 100644 --- a/Oxygen8v2/consts.py +++ b/Oxygen8v2/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen8v2/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen8v2/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/Oxygen_3rd_Gen/Oxygen_3rd_Gen.py b/Oxygen_3rd_Gen/Oxygen_3rd_Gen.py index b4254827..b9245623 100644 --- a/Oxygen_3rd_Gen/Oxygen_3rd_Gen.py +++ b/Oxygen_3rd_Gen/Oxygen_3rd_Gen.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen_3rd_Gen/Oxygen_3rd_Gen.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen_3rd_Gen/Oxygen_3rd_Gen.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/Oxygen_3rd_Gen/SpecialMixerComponent.py b/Oxygen_3rd_Gen/SpecialMixerComponent.py index 75ed90c1..f7bf08dc 100644 --- a/Oxygen_3rd_Gen/SpecialMixerComponent.py +++ b/Oxygen_3rd_Gen/SpecialMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen_3rd_Gen/SpecialMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen_3rd_Gen/SpecialMixerComponent.py from _Framework.MixerComponent import MixerComponent class SpecialMixerComponent(MixerComponent): @@ -30,22 +30,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 diff --git a/Oxygen_3rd_Gen/TransportViewModeSelector.py b/Oxygen_3rd_Gen/TransportViewModeSelector.py index 5371458a..e78b5660 100644 --- a/Oxygen_3rd_Gen/TransportViewModeSelector.py +++ b/Oxygen_3rd_Gen/TransportViewModeSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen_3rd_Gen/TransportViewModeSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen_3rd_Gen/TransportViewModeSelector.py import Live from _Framework.ModeSelectorComponent import ModeSelectorComponent from _Framework.ButtonElement import ButtonElement diff --git a/Oxygen_3rd_Gen/__init__.py b/Oxygen_3rd_Gen/__init__.py index b2abd543..52892eb7 100644 --- a/Oxygen_3rd_Gen/__init__.py +++ b/Oxygen_3rd_Gen/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen_3rd_Gen/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen_3rd_Gen/__init__.py from Oxygen_3rd_Gen import Oxygen_3rd_Gen def create_instance(c_instance): diff --git a/Oxygen_4th_Gen/__init__.py b/Oxygen_4th_Gen/__init__.py index 81b36b2a..2a8a90f4 100644 --- a/Oxygen_4th_Gen/__init__.py +++ b/Oxygen_4th_Gen/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Oxygen_4th_Gen/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Oxygen_4th_Gen/__init__.py from Oxygen_3rd_Gen import Oxygen_3rd_Gen def create_instance(c_instance): diff --git a/Ozone/__init__.py b/Ozone/__init__.py index 9d403b11..43fe116e 100644 --- a/Ozone/__init__.py +++ b/Ozone/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Ozone/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Ozone/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Ozone/config.py b/Ozone/config.py index 46ef1e12..c4276d06 100644 --- a/Ozone/config.py +++ b/Ozone/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Ozone/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Ozone/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/Ozone/consts.py b/Ozone/consts.py index 53d1a959..4fd7bff0 100644 --- a/Ozone/consts.py +++ b/Ozone/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Ozone/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Ozone/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/Ozonic/__init__.py b/Ozonic/__init__.py index 3bd5f78a..31085295 100644 --- a/Ozonic/__init__.py +++ b/Ozonic/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Ozonic/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Ozonic/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Ozonic/config.py b/Ozonic/config.py index 3e1a2448..7c3bd806 100644 --- a/Ozonic/config.py +++ b/Ozonic/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Ozonic/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Ozonic/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/Ozonic/consts.py b/Ozonic/consts.py index f04317bb..cb054306 100644 --- a/Ozonic/consts.py +++ b/Ozonic/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Ozonic/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Ozonic/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/Photon_25/__init__.py b/Photon_25/__init__.py index 12fe22f0..cc95d56d 100644 --- a/Photon_25/__init__.py +++ b/Photon_25/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Photon_25/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Photon_25/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Photon_25/config.py b/Photon_25/config.py index e895ee89..5aaf09f7 100644 --- a/Photon_25/config.py +++ b/Photon_25/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Photon_25/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Photon_25/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/Photon_25/consts.py b/Photon_25/consts.py index aaa437e5..5bb6e18f 100644 --- a/Photon_25/consts.py +++ b/Photon_25/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Photon_25/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Photon_25/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/Photon_X25/__init__.py b/Photon_X25/__init__.py index bb747a65..eb38db17 100644 --- a/Photon_X25/__init__.py +++ b/Photon_X25/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Photon_X25/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Photon_X25/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Photon_X25/config.py b/Photon_X25/config.py index 48a98cb4..ca6ac650 100644 --- a/Photon_X25/config.py +++ b/Photon_X25/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Photon_X25/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Photon_X25/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/Photon_X25/consts.py b/Photon_X25/consts.py index d28a983b..653a1863 100644 --- a/Photon_X25/consts.py +++ b/Photon_X25/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Photon_X25/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Photon_X25/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/ProjectMixIO/ProjectMixIO.py b/ProjectMixIO/ProjectMixIO.py index dca8cb3e..0db17ba0 100644 --- a/ProjectMixIO/ProjectMixIO.py +++ b/ProjectMixIO/ProjectMixIO.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ProjectMixIO/ProjectMixIO.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ProjectMixIO/ProjectMixIO.py from MackieControl.consts import * from MackieControl.MainDisplay import MainDisplay from MackieControl.MainDisplayController import MainDisplayController @@ -74,6 +74,9 @@ def is_extension(self): def request_rebuild_midi_map(self): self.__c_instance.request_rebuild_midi_map() + def can_lock_to_devices(self): + return False + def build_midi_map(self, midi_map_handle): for s in self.__channel_strips: s.build_midi_map(midi_map_handle) diff --git a/ProjectMixIO/__init__.py b/ProjectMixIO/__init__.py index 13b2916a..aea076cb 100644 --- a/ProjectMixIO/__init__.py +++ b/ProjectMixIO/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ProjectMixIO/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ProjectMixIO/__init__.py from ProjectMixIO import ProjectMixIO def create_instance(c_instance): diff --git a/Push/Actions.py b/Push/Actions.py index 671e8490..527fa91b 100644 --- a/Push/Actions.py +++ b/Push/Actions.py @@ -1,9 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/actions.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/actions.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import depends, listens, task from ableton.v2.control_surface import CompoundComponent from ableton.v2.control_surface.mode import SetAttributeMode, ModesComponent from pushbase.consts import MessageBoxText +from pushbase.device_chain_utils import is_empty_drum_pad from pushbase.browser_modes import BrowserAddEffectMode from pushbase.action_with_options_component import OptionsComponent from pushbase.message_box_component import Messenger @@ -107,8 +109,7 @@ def __init__(self, selection = None, browser_component = None, browser_mode = No def on_enabled_changed(self): self._go_to_hotswap_task.kill() if self.is_enabled(): - selected = self._selection.selected_object - if isinstance(selected, Live.DrumPad.DrumPad) and (not selected.chains or not selected.chains[0].devices): + if is_empty_drum_pad(self._selection.selected_object): self._create_device_modes.selected_mode = 'hotswap' else: self._create_device_modes.selected_mode = 'create' diff --git a/Push/Push.py b/Push/Push.py index bc78c37b..6084fea5 100644 --- a/Push/Push.py +++ b/Push/Push.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/push.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/push.py +from __future__ import absolute_import, print_function from functools import partial import logging from copy import copy @@ -13,15 +13,20 @@ from pushbase.colors import CLIP_COLOR_TABLE, RGB_COLOR_TABLE from pushbase.browser_modes import BrowserHotswapMode from pushbase.control_element_factory import create_sysex_element +from pushbase.device_component import DeviceComponent +from pushbase.note_editor_component import NoteEditorComponent from pushbase.note_settings_component import NoteSettingsComponent from pushbase.playhead_element import NullPlayhead from pushbase.push_base import PushBase from pushbase.quantization_component import QuantizationComponent from pushbase.sysex import LIVE_MODE from pushbase.session_recording_component import FixedLengthSessionRecordingComponent +from pushbase.special_mixer_component import SpecialMixerComponent +from pushbase.simpler_decoration import SimplerDecoratorFactory from .actions import CreateDeviceComponent, CreateDefaultTrackComponent, CreateInstrumentTrackComponent from .browser_component import BrowserComponent from .browser_model_factory import make_browser_model +from .custom_bank_definitions import BANK_DEFINITIONS from .device_navigation_component import DeviceNavigationComponent from .drum_group_component import DrumGroupComponent from .elements import Elements @@ -53,6 +58,9 @@ class Push(PushBase): applicable to your use. """ input_target_name_for_auto_arm = 'Push Input' + device_component_class = DeviceComponent + bank_definitions = BANK_DEFINITIONS + note_editor_class = NoteEditorComponent def __init__(self, *a, **k): super(Push, self).__init__(*a, **k) @@ -93,6 +101,9 @@ def _create_settings(self): self.__on_aftertouch_threshold.subject = settings['aftertouch_threshold'] return settings + def _create_device_decorator_factory(self): + return SimplerDecoratorFactory() + def _init_settings(self): super(Push, self)._init_settings() self._init_global_pad_parameters() @@ -363,16 +374,46 @@ def _init_main_modes(self): self.elements.browse_mode_button]) def _create_mixer_layer(self): - return super(Push, self)._create_mixer_layer() + Layer(track_names_display='display_line4') + return Layer(track_select_buttons='select_buttons', track_names_display='display_line4') + + def _create_mixer_solo_layer(self): + return Layer(solo_buttons='track_state_buttons') + + def _create_mixer_mute_layer(self): + return Layer(mute_buttons='track_state_buttons') def _create_mixer_pan_send_layer(self): - return super(Push, self)._create_mixer_pan_send_layer() + Layer(track_names_display='display_line4', pan_send_names_display='display_line1', pan_send_graphics_display='display_line2', selected_track_name_display='display_line3', pan_send_values_display=ComboElement('display_line3', 'any_touch_button')) + return Layer(track_select_buttons='select_buttons', pan_send_toggle='pan_send_mix_mode_button', pan_send_controls='fine_grain_param_controls', track_names_display='display_line4', pan_send_names_display='display_line1', pan_send_graphics_display='display_line2', selected_track_name_display='display_line3', pan_send_values_display=ComboElement('display_line3', 'any_touch_button')) def _create_mixer_volume_layer(self): - return super(Push, self)._create_mixer_volume_layer() + Layer(track_names_display='display_line4', volume_names_display='display_line1', volume_graphics_display='display_line2', selected_track_name_display='display_line3', volume_values_display=ComboElement('display_line3', 'any_touch_button')) + return Layer(track_select_buttons='select_buttons', volume_controls='fine_grain_param_controls', track_names_display='display_line4', volume_names_display='display_line1', volume_graphics_display='display_line2', selected_track_name_display='display_line3', volume_values_display=ComboElement('display_line3', 'any_touch_button')) def _create_mixer_track_layer(self): - return super(Push, self)._create_mixer_track_layer() + Layer(selected_track_name_display='display_line3', track_names_display='display_line4') + return Layer(track_select_buttons='select_buttons', selected_track_name_display='display_line3', track_names_display='display_line4') + + def _init_mixer(self): + self._mixer = SpecialMixerComponent(tracks_provider=self._session_ring, is_root=True) + self._mixer.set_enabled(False) + self._mixer.name = 'Mixer' + self._mixer_layer = self._create_mixer_layer() + self._mixer_pan_send_layer = self._create_mixer_pan_send_layer() + self._mixer_volume_layer = self._create_mixer_volume_layer() + self._mixer_track_layer = self._create_mixer_track_layer() + self._mixer_solo_layer = self._create_mixer_solo_layer() + self._mixer_mute_layer = self._create_mixer_mute_layer() + for track in xrange(self.elements.matrix.width()): + strip = self._mixer.channel_strip(track) + strip.name = 'Channel_Strip_' + str(track) + strip.set_invert_mute_feedback(True) + strip.set_delete_handler(self._delete_component) + strip._do_select_track = self.on_select_track + strip.layer = Layer(shift_button='shift_button', duplicate_button='duplicate_button', selector_button='select_button') + + self._mixer.selected_strip().name = 'Selected_Channel_strip' + self._mixer.master_strip().name = 'Master_Channel_strip' + self._mixer.master_strip()._do_select_track = self.on_select_track + self._mixer.master_strip().layer = Layer(select_button='master_select_button', selector_button='select_button') + self._mixer.set_enabled(True) def _create_track_mixer_layer(self): return super(Push, self)._create_track_mixer_layer() + Layer(name_display_line='display_line1', graphic_display_line='display_line2', value_display_line=ComboElement('display_line3', 'any_touch_button')) @@ -381,7 +422,7 @@ def _create_device_parameter_layer(self): return super(Push, self)._create_device_parameter_layer() + Layer(name_display_line='display_line1', value_display_line='display_line2', graphic_display_line=ComboElement('display_line3', 'any_touch_button')) def _create_device_navigation(self): - return DeviceNavigationComponent(device_bank_registry=self._device_bank_registry, is_enabled=False, session_ring=self._session_ring, layer=Layer(enter_button='in_button', exit_button='out_button', select_buttons='select_buttons', state_buttons='track_state_buttons', display_line='display_line4', _notification=self._notification.use_single_line(2)), info_layer=Layer(display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', _notification=self._notification.use_full_display(2)), delete_handler=self._delete_component) + return DeviceNavigationComponent(device_bank_registry=self._device_bank_registry, banking_info=self._banking_info, is_enabled=False, session_ring=self._session_ring, layer=Layer(enter_button='in_button', exit_button='out_button', select_buttons='select_buttons', state_buttons='track_state_buttons', display_line='display_line4', _notification=self._notification.use_single_line(2)), info_layer=Layer(display_line1='display_line1', display_line2='display_line2', display_line3='display_line3', display_line4='display_line4', _notification=self._notification.use_full_display(2)), delete_handler=self._delete_component) @listens_group('value') def __on_main_mode_button_value(self, value, sender): diff --git a/Push/Settings.py b/Push/Settings.py index cccefb1f..cdb1d5e1 100644 --- a/Push/Settings.py +++ b/Push/Settings.py @@ -1,5 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/settings.py -from ableton.v2.base.collection import OrderedDict +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/settings.py +from __future__ import absolute_import, print_function +from collections import OrderedDict from pushbase.setting import OnOffSetting, EnumerableSetting from .pad_sensitivity import PadParameters MIN_OFF_THRESHOLD = 10 @@ -33,7 +34,9 @@ def _create_pad_settings(): def _threshold_formatter(value): - return str(value) if value != 0 else '0 (Default)' + if value != 0: + return str(value) + return '0 (Default)' def create_settings(preferences = None): diff --git a/Push/Sysex.py b/Push/Sysex.py index d186b105..af49d41d 100644 --- a/Push/Sysex.py +++ b/Push/Sysex.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/sysex.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/sysex.py +from __future__ import absolute_import, print_function from ableton.v2.base import group, in_range from pushbase.touch_strip_element import TouchStripModes, TouchStripStates START = (240, 71, 127, 21) diff --git a/Push/__init__.py b/Push/__init__.py index 33350a5b..9835fe30 100644 --- a/Push/__init__.py +++ b/Push/__init__.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/__init__.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface.capabilities import controller_id, inport, outport, AUTO_LOAD_KEY, CONTROLLER_ID_KEY, FIRMWARE_KEY, HIDDEN, NOTES_CC, PORTS_KEY, SCRIPT, SYNC, TYPE_KEY from .firmware_handling import get_provided_firmware_version from .push import Push diff --git a/Push/browser_component.py b/Push/browser_component.py index d440b424..ab1da979 100644 --- a/Push/browser_component.py +++ b/Push/browser_component.py @@ -1,7 +1,7 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/browser_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/browser_component.py +from __future__ import absolute_import, print_function from functools import partial -from itertools import izip +from itertools import izip, izip_longest import string import re import Live @@ -267,7 +267,9 @@ def is_short_enough(item_name): if is_short_enough(item_name): break - return item_name[:-1] if len(item_name) >= shortening_limit and item_name[-1] == consts.CHAR_ELLIPSIS else item_name + if len(item_name) >= shortening_limit and item_name[-1] == consts.CHAR_ELLIPSIS: + return item_name[:-1] + return item_name def _item_formatter(self, depth, index, item, action_in_progress): display_string = '' @@ -371,7 +373,7 @@ def _on_content_lists_changed(self): scroll_depth = len(self._browser_model.content_lists) - len(self._list_components) self._max_scroll_offset = max(0, scroll_depth + 2) self._max_hierarchy = max(0, scroll_depth) - for component, content, message in map(None, components, contents, messages): + for component, content, message in izip_longest(components, contents, messages): if component != None: component.scrollable_list = content component.empty_list_message = message diff --git a/Push/browser_model.py b/Push/browser_model.py index 649e143a..3b078daa 100644 --- a/Push/browser_model.py +++ b/Push/browser_model.py @@ -1,10 +1,10 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/browser_model.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/browser_model.py +from __future__ import absolute_import, print_function import os from functools import partial -from itertools import imap +from itertools import imap, chain import Live -from ableton.v2.base import chain_from_iterable, first, nop, find_if, index_if, in_range, lazy_attribute, BooleanContext, SlotManager, Subject +from ableton.v2.base import first, nop, find_if, index_if, in_range, lazy_attribute, BooleanContext, SlotManager, Subject from pushbase.scrollable_list import ActionList, ActionListItem from pushbase.browser_util import filter_type_for_hotswap_target @@ -46,7 +46,9 @@ class BrowserListItem(ActionListItem): """ def __str__(self): - return os.path.splitext(self.content.name)[0] if self.content else '' + if self.content: + return os.path.splitext(self.content.name)[0] + return '' def action(self): if self.container and self.container.browser: @@ -266,10 +268,10 @@ def _on_item_activated(self, level): with self._inside_item_activated_notification(): contents, _ = self._contents[level] selected = contents.selected_item - if selected != None: - is_folder = selected.content.is_folder - children = self.get_children(selected.content, level) if selected != None else [] - (children or is_folder or level < 1) and self._fit_content_lists(level + 2) + is_folder = selected != None and selected.content.is_folder + children = self.get_children(selected.content, level) if selected != None else [] + if children or is_folder or level < 1: + self._fit_content_lists(level + 2) child_contents, _ = self._contents[level + 1] child_contents.assign_items(children) else: @@ -295,7 +297,7 @@ def __init__(self, queries = [], *a, **k): def get_root_children(self): browser = self.browser - return chain_from_iterable(imap(lambda q: q(browser), self.queries)) + return chain.from_iterable(imap(lambda q: q(browser), self.queries)) def can_be_exchanged(self, model): return isinstance(model, QueryingBrowserModel) and super(QueryingBrowserModel, self).can_be_exchanged(model) diff --git a/Push/browser_model_factory.py b/Push/browser_model_factory.py index f8041885..7eaa82bb 100644 --- a/Push/browser_model_factory.py +++ b/Push/browser_model_factory.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/browser_model_factory.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/browser_model_factory.py +from __future__ import absolute_import, print_function import Live from .browser_model import filter_type_for_browser, EmptyBrowserModel, QueryingBrowserModel from .browser_query import TagBrowserQuery, PathBrowserQuery, PlacesBrowserQuery, SourceBrowserQuery diff --git a/Push/browser_query.py b/Push/browser_query.py index bb51c026..b9bc72cb 100644 --- a/Push/browser_query.py +++ b/Push/browser_query.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/browser_query.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/browser_query.py +from __future__ import absolute_import, print_function from functools import partial from ableton.v2.base import first, find_if, const from .browser_model import VirtualBrowserItem @@ -41,7 +42,9 @@ def _find_item(self, path, items = None, browser = None): name = path[0] elem = find_if(lambda x: x.name == name, items) if elem: - return [elem] if len(path) == 1 else self._find_item(path[1:], elem.children) + if len(path) == 1: + return [elem] + return self._find_item(path[1:], elem.children) class TagBrowserQuery(BrowserQuery): diff --git a/Push/custom_bank_definitions.py b/Push/custom_bank_definitions.py new file mode 100644 index 00000000..98125cf0 --- /dev/null +++ b/Push/custom_bank_definitions.py @@ -0,0 +1,1733 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/custom_bank_definitions.py +from __future__ import absolute_import, print_function +from ableton.v2.base.collection import IndexedDict +from pushbase.parameter_slot_description import use +from pushbase.banking_util import PARAMETERS_KEY, MAIN_KEY +RACK_BANKS = IndexedDict((('Macros', {PARAMETERS_KEY: ('Macro 1', + 'Macro 2', + 'Macro 3', + 'Macro 4', + 'Macro 5', + 'Macro 6', + 'Macro 7', + 'Macro 8')}),)) +BANK_DEFINITIONS = {'AudioEffectGroupDevice': RACK_BANKS, + 'MidiEffectGroupDevice': RACK_BANKS, + 'InstrumentGroupDevice': RACK_BANKS, + 'DrumGroupDevice': RACK_BANKS, + 'UltraAnalog': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('OSC1 Shape').if_parameter('OSC1 On/Off').has_value('1').else_use('OSC2 Shape').if_parameter('OSC2 On/Off').has_value('1'), + use('OSC1 Octave').if_parameter('OSC1 On/Off').has_value('1').else_use('OSC2 Octave').if_parameter('OSC2 On/Off').has_value('1'), + use('OSC2 Shape').if_parameter('OSC1 On/Off').has_value('1').and_parameter('OSC2 On/Off').has_value('1').else_use('OSC1 Semi').if_parameter('OSC1 On/Off').has_value('1').else_use('OSC2 Semi').if_parameter('OSC2 On/Off').has_value('1'), + use('OSC2 Octave').if_parameter('OSC1 On/Off').has_value('1').and_parameter('OSC2 On/Off').has_value('1').else_use('OSC1 Detune').if_parameter('OSC1 On/Off').has_value('1').else_use('OSC2 Detune').if_parameter('OSC2 On/Off').has_value('1'), + use('F1 Type').if_parameter('F1 On/Off').has_value('1').else_use('F2 Type').if_parameter('F2 On/Off').has_value('1'), + use('F1 Freq').if_parameter('F1 On/Off').has_value('1').else_use('F2 Freq').if_parameter('F2 On/Off').has_value('1'), + use('F1 Resonance').if_parameter('F1 On/Off').has_value('1').else_use('F2 Resonance').if_parameter('F2 On/Off').has_value('1'), + 'Volume')}), + ('Osc. 1 Shape', {PARAMETERS_KEY: ('OSC1 On/Off', + use('OSC1 Shape').if_parameter('OSC1 On/Off').has_value('1'), + use('').if_parameter('OSC1 On/Off').has_value('0').else_use('OSC1 PW').if_parameter('OSC1 Shape').has_value('Rect'), + use('').if_parameter('OSC1 On/Off').has_value('0').else_use('O1 PW < LFO').if_parameter('OSC1 Shape').has_value('Rect').else_use('').if_parameter('LFO1 On/Off').has_value('0'), + use('').if_parameter('OSC1 On/Off').has_value('0').else_use('').if_parameter('OSC1 Shape').has_value('Noise').else_use('').if_parameter('OSC1 Shape').has_value('Sine').else_use('OSC1 Mode'), + use('').if_parameter('OSC1 On/Off').has_value('0').else_use('').if_parameter('OSC1 Shape').has_value('Noise').else_use('O1 Sub/Sync'), + use('OSC1 Balance').if_parameter('OSC1 On/Off').has_value('1'), + use('OSC1 Level').if_parameter('OSC1 On/Off').has_value('1'))}), + ('Osc. 1 Pitch', {PARAMETERS_KEY: ('OSC1 On/Off', + use('OSC1 Octave').if_parameter('OSC1 On/Off').has_value('1'), + use('OSC1 Semi').if_parameter('OSC1 On/Off').has_value('1'), + use('OSC1 Detune').if_parameter('OSC1 On/Off').has_value('1'), + use('PEG1 Amount').if_parameter('OSC1 On/Off').has_value('1'), + use('PEG1 Time').if_parameter('OSC1 On/Off').has_value('1'), + use('O1 Keytrack').if_parameter('OSC1 On/Off').has_value('1'), + use('').if_parameter('OSC1 On/Off').has_value('0').else_use('').if_parameter('LFO1 On/Off').has_value('0').else_use('OSC1 < LFO'))}), + ('Osc. 2 Shape', {PARAMETERS_KEY: ('OSC2 On/Off', + use('OSC2 Shape').if_parameter('OSC2 On/Off').has_value('1'), + use('').if_parameter('OSC2 On/Off').has_value('0').else_use('OSC2 PW').if_parameter('OSC2 Shape').has_value('Rect'), + use('').if_parameter('OSC2 On/Off').has_value('0').else_use('O2 PW < LFO').if_parameter('OSC2 Shape').has_value('Rect').else_use('').if_parameter('LFO2 On/Off').has_value('0'), + use('').if_parameter('OSC2 On/Off').has_value('0').else_use('').if_parameter('OSC2 Shape').has_value('Noise').else_use('').if_parameter('OSC2 Shape').has_value('Sine').else_use('OSC2 Mode'), + use('').if_parameter('OSC2 On/Off').has_value('0').else_use('').if_parameter('OSC2 Shape').has_value('Noise').else_use('O2 Sub/Sync'), + use('OSC2 Balance').if_parameter('OSC2 On/Off').has_value('1'), + use('OSC2 Level').if_parameter('OSC2 On/Off').has_value('1'))}), + ('Osc. 2 Pitch', {PARAMETERS_KEY: ('OSC2 On/Off', + use('OSC2 Octave').if_parameter('OSC2 On/Off').has_value('1'), + use('OSC2 Semi').if_parameter('OSC2 On/Off').has_value('1'), + use('OSC2 Detune').if_parameter('OSC2 On/Off').has_value('1'), + use('PEG2 Amount').if_parameter('OSC2 On/Off').has_value('1'), + use('PEG2 Time').if_parameter('OSC2 On/Off').has_value('1'), + use('O2 Keytrack').if_parameter('OSC2 On/Off').has_value('1'), + use('').if_parameter('OSC2 On/Off').has_value('0').else_use('').if_parameter('LFO2 On/Off').has_value('0').else_use('OSC2 < LFO'))}), + ('Filters', {PARAMETERS_KEY: ('F1 On/Off', + use('F1 Type').if_parameter('F1 On/Off').has_value('1'), + use('F1 Freq').if_parameter('F1 On/Off').has_value('1'), + use('F1 Resonance').if_parameter('F1 On/Off').has_value('1'), + 'F2 On/Off', + use('F2 Type').if_parameter('F2 On/Off').has_value('1'), + use('F2 Freq').if_parameter('F2 On/Off').has_value('1'), + use('F2 Resonance').if_parameter('F2 On/Off').has_value('1'))}), + ('Filt. 1 Env.', {PARAMETERS_KEY: ('F1 On/Off', + use('FEG1 < Vel').if_parameter('F1 On/Off').has_value('1'), + use('FEG1 A < Vel').if_parameter('F1 On/Off').has_value('1'), + use('FEG1 Attack').if_parameter('F1 On/Off').has_value('1'), + use('FEG1 Decay').if_parameter('F1 On/Off').has_value('1'), + use('FEG1 Sustain').if_parameter('F1 On/Off').has_value('1'), + use('FEG1 S Time').if_parameter('F1 On/Off').has_value('1'), + use('FEG1 Rel').if_parameter('F1 On/Off').has_value('1'))}), + ('Filt. 2 Env.', {PARAMETERS_KEY: ('F2 On/Off', + use('FEG2 < Vel').if_parameter('F1 On/Off').has_value('1'), + use('FEG2 A < Vel').if_parameter('F1 On/Off').has_value('1'), + use('FEG2 Attack').if_parameter('F1 On/Off').has_value('1'), + use('FEG2 Decay').if_parameter('F1 On/Off').has_value('1'), + use('FEG2 Sustain').if_parameter('F1 On/Off').has_value('1'), + use('FEG2 S Time').if_parameter('F1 On/Off').has_value('1'), + use('FEG2 Rel').if_parameter('F1 On/Off').has_value('1'))}), + ('Filt. Modulation', {PARAMETERS_KEY: ('F1 On/Off', + use('F1 Freq < LFO').if_parameter('F1 On/Off').has_value('1'), + use('F1 Freq < Env').if_parameter('F1 On/Off').has_value('1'), + use('F1 Res < LFO').if_parameter('F1 On/Off').has_value('1'), + 'F2 On/Off', + use('F2 Freq < LFO').if_parameter('F2 On/Off').has_value('1'), + use('F2 Freq < Env').if_parameter('F2 On/Off').has_value('1'), + use('F2 Res < LFO').if_parameter('F2 On/Off').has_value('1'))}), + ('Amp', {PARAMETERS_KEY: (use('AMP1 Level').if_parameter('AMP1 On/Off').has_value('1'), + use('AMP1 Pan').if_parameter('AMP1 On/Off').has_value('1'), + use('AMP1 < LFO').if_parameter('AMP1 On/Off').has_value('1'), + use('').if_parameter('LFO1 On/Off').has_value('0').else_use('LFO1 Speed').if_parameter('LFO1 Sync').has_value('Hertz').else_use('LFO1 SncRate'), + use('AMP2 Level').if_parameter('AMP2 On/Off').has_value('1'), + use('AMP2 Pan').if_parameter('AMP2 On/Off').has_value('1'), + use('AMP2 < LFO').if_parameter('AMP2 On/Off').has_value('1'), + use('').if_parameter('LFO2 On/Off').has_value('0').else_use('LFO2 Speed').if_parameter('LFO2 Sync').has_value('Hertz').else_use('LFO2 SncRate'))}), + ('Amp 1 Envelope', {PARAMETERS_KEY: ('AMP1 On/Off', + use('AEG1 < Vel').if_parameter('AMP1 On/Off').has_value('1'), + use('AEG1 A < Vel').if_parameter('AMP1 On/Off').has_value('1'), + use('AEG1 Attack').if_parameter('AMP1 On/Off').has_value('1'), + use('AEG1 Decay').if_parameter('AMP1 On/Off').has_value('1'), + use('AEG1 Sustain').if_parameter('AMP1 On/Off').has_value('1'), + use('AEG1 S Time').if_parameter('AMP1 On/Off').has_value('1'), + use('AEG1 Rel').if_parameter('AMP1 On/Off').has_value('1'))}), + ('Amp 2 Envelope', {PARAMETERS_KEY: ('AMP2 On/Off', + use('AEG2 < Vel').if_parameter('AMP2 On/Off').has_value('1'), + use('AEG2 A < Vel').if_parameter('AMP2 On/Off').has_value('1'), + use('AEG2 Attack').if_parameter('AMP2 On/Off').has_value('1'), + use('AEG2 Decay').if_parameter('AMP2 On/Off').has_value('1'), + use('AEG2 Sustain').if_parameter('AMP2 On/Off').has_value('1'), + use('AEG2 S Time').if_parameter('AMP2 On/Off').has_value('1'), + use('AEG2 Rel').if_parameter('AMP2 On/Off').has_value('1'))}), + ('Noise & Unison', {PARAMETERS_KEY: ('Noise On/Off', + use('Noise Level').if_parameter('Noise On/Off').has_value('1'), + use('Noise Color').if_parameter('Noise On/Off').has_value('1'), + use('Noise Balance').if_parameter('Noise On/Off').has_value('1'), + 'Unison On/Off', + use('Unison Detune').if_parameter('Unison On/Off').has_value('1'), + use('Unison Delay').if_parameter('Unison On/Off').has_value('1'), + '')}), + ('Performance', {PARAMETERS_KEY: ('Glide On/Off', + use('Glide Time').if_parameter('Glide On/Off').has_value('1'), + use('Glide Mode').if_parameter('Glide On/Off').has_value('1'), + use('Glide Legato').if_parameter('Glide On/Off').has_value('1'), + 'PB Range', + 'Key Stretch', + 'Key Error', + 'Voices')}), + ('LFO 1', {PARAMETERS_KEY: ('LFO1 On/Off', + use('LFO1 Sync').if_parameter('LFO1 On/Off').has_value('1'), + use('').if_parameter('LFO1 On/Off').has_value('0').else_use('LFO1 Speed').if_parameter('LFO1 Sync').has_value('Hertz').else_use('LFO1 SncRate'), + use('LFO1 Shape').if_parameter('LFO1 On/Off').has_value('1'), + use('').if_parameter('LFO1 On/Off').has_value('0').else_use('LFO1 PW').if_parameter('LFO1 Shape').has_value('Rect').else_use('LFO1 PW').if_parameter('LFO1 Shape').has_value('Tri'), + use('LFO1 Phase').if_parameter('LFO1 On/Off').has_value('1'), + use('LFO1 Delay').if_parameter('LFO1 On/Off').has_value('1'), + use('LFO1 Fade In').if_parameter('LFO1 On/Off').has_value('1'))}), + ('LFO 2', {PARAMETERS_KEY: ('LFO2 On/Off', + use('LFO2 Sync').if_parameter('LFO2 On/Off').has_value('1'), + use('').if_parameter('LFO2 On/Off').has_value('0').else_use('LFO2 Speed').if_parameter('LFO2 Sync').has_value('Hertz').else_use('LFO2 SncRate'), + use('LFO2 Shape').if_parameter('LFO2 On/Off').has_value('1'), + use('').if_parameter('LFO2 On/Off').has_value('0').else_use('LFO2 PW').if_parameter('LFO2 Shape').has_value('Rect').else_use('LFO2 PW').if_parameter('LFO2 Shape').has_value('Tri'), + use('LFO2 Phase').if_parameter('LFO2 On/Off').has_value('1'), + use('LFO2 Delay').if_parameter('LFO2 On/Off').has_value('1'), + use('LFO2 Fade In').if_parameter('LFO2 On/Off').has_value('1'))}), + ('Vibrato', {PARAMETERS_KEY: ('Vib On/Off', + use('Vib Amount').if_parameter('Vib On/Off').has_value('1'), + use('Vib Speed').if_parameter('Vib On/Off').has_value('1'), + use('Vib Delay').if_parameter('Vib On/Off').has_value('1'), + use('Vib Fade-In').if_parameter('Vib On/Off').has_value('1'), + use('Vib Error').if_parameter('Vib On/Off').has_value('1'), + use('Vib < ModWh').if_parameter('Vib On/Off').has_value('1'), + '')}))), + 'Collision': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('Res 1 Type').if_parameter('Res 1 On/Off').has_value('on'), + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('').if_parameter('Res 1 Type').has_value('Tube').else_use('').if_parameter('Res 1 Type').has_value('Pipe').else_use('Res 1 Brightness'), + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('').if_parameter('Res 1 Type').has_value('Tube').else_use('Res 1 Opening').if_parameter('Res 1 Type').has_value('Pipe').else_use('Res 1 Inharmonics'), + use('Res 1 Decay').if_parameter('Res 1 On/Off').has_value('on'), + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('Res 1 Radius').if_parameter('Res 1 Type').has_value('Tube').else_use('Res 1 Radius').if_parameter('Res 1 Type').has_value('Pipe').else_use('Res 1 Material'), + use('Mallet Stiffness').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Noise Amount').if_parameter('Mallet On/Off').has_value('on'), + 'Volume')}), + ('Mix', {PARAMETERS_KEY: (use('Res 1 Volume').if_parameter('Res 1 On/Off').has_value('on'), + use('Panorama').if_parameter('Res 1 On/Off').has_value('on'), + use('Res 1 Bleed').if_parameter('Res 1 On/Off').has_value('on'), + use('Res 2 Volume').if_parameter('Res 2 On/Off').has_value('on'), + use('Res 2 Panorama').if_parameter('Res 2 On/Off').has_value('on'), + use('Res 2 Bleed').if_parameter('Res 2 On/Off').has_value('on'), + 'Structure', + 'Volume')}), + ('Mallet', {PARAMETERS_KEY: ('Mallet On/Off', + use('Mallet Volume').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Noise Amount').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Stiffness').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Noise Color').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Modulation').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Volume < Vel').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Noise Amount < Vel').if_parameter('Mallet On/Off').has_value('on'))}), + ('Noise Envelope', {PARAMETERS_KEY: ('Noise On/Off', + use('Noise Volume').if_parameter('Noise On/Off').has_value('on'), + use('Noise Volume < Key').if_parameter('Noise On/Off').has_value('on'), + use('Noise Volume < Vel').if_parameter('Noise On/Off').has_value('on'), + use('Noise Attack').if_parameter('Noise On/Off').has_value('on'), + use('Noise Sustain').if_parameter('Noise On/Off').has_value('on'), + use('Noise Decay').if_parameter('Noise On/Off').has_value('on'), + use('Noise Release').if_parameter('Noise On/Off').has_value('on'))}), + ('Noise Filter', {PARAMETERS_KEY: ('Noise On/Off', + use('Noise Volume').if_parameter('Noise On/Off').has_value('on'), + use('Noise Filter Type').if_parameter('Noise On/Off').has_value('on'), + use('Noise Filter Freq').if_parameter('Noise On/Off').has_value('on'), + use('Noise Filter Q').if_parameter('Noise On/Off').has_value('on'), + use('Noise Freq < Key').if_parameter('Noise On/Off').has_value('on'), + use('Noise Freq < Vel').if_parameter('Noise On/Off').has_value('on'), + use('Noise Freq < Env').if_parameter('Noise On/Off').has_value('on'))}), + ('Res. 1 Body', {PARAMETERS_KEY: ('Res 1 On/Off', + use('Res 1 Type').if_parameter('Res 1 On/Off').has_value('on'), + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('Res 1 Ratio').if_parameter('Res 1 Type').has_value('Plate').else_use('Res 1 Ratio').if_parameter('Res 1 Type').has_value('Membrane'), + use('Res 1 Decay').if_parameter('Res 1 On/Off').has_value('on'), + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('Res 1 Radius').if_parameter('Res 1 Type').has_value('Tube').else_use('Res 1 Radius').if_parameter('Res 1 Type').has_value('Pipe').else_use('Res 1 Material'), + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('').if_parameter('Res 1 Type').has_value('Tube').else_use('').if_parameter('Res 1 Type').has_value('Pipe').else_use('Res 1 Listening L'), + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('').if_parameter('Res 1 Type').has_value('Tube').else_use('').if_parameter('Res 1 Type').has_value('Pipe').else_use('Res 1 Listening R'), + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('').if_parameter('Res 1 Type').has_value('Tube').else_use('').if_parameter('Res 1 Type').has_value('Pipe').else_use('Res 1 Hit'))}), + ('Res. 1 Tune', {PARAMETERS_KEY: ('Res 1 On/Off', + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('').if_parameter('Res 1 Type').has_value('Tube').else_use('').if_parameter('Res 1 Type').has_value('Pipe').else_use('Res 1 Brightness'), + use('Res 1 Quality').if_parameter('Res 1 On/Off').has_value('on'), + use('').if_parameter('Res 1 On/Off').has_value('off').else_use('').if_parameter('Res 1 Type').has_value('Tube').else_use('Res 1 Opening').if_parameter('Res 1 Type').has_value('Pipe').else_use('Res 1 Inharmonics'), + use('Res 1 Tune').if_parameter('Res 1 On/Off').has_value('on'), + use('Res 1 Fine Tune').if_parameter('Res 1 On/Off').has_value('on'), + use('Res 1 Pitch Env.').if_parameter('Res 1 On/Off').has_value('on'), + use('Res 1 Pitch Env. Time').if_parameter('Res 1 On/Off').has_value('on'))}), + ('Res. 2 Body', {PARAMETERS_KEY: ('Res 2 On/Off', + use('Res 2 Type').if_parameter('Res 2 On/Off').has_value('on'), + use('').if_parameter('Res 2 On/Off').has_value('off').else_use('Res 2 Ratio').if_parameter('Res 2 Type').has_value('Plate').else_use('Res 2 Ratio').if_parameter('Res 2 Type').has_value('Membrane'), + use('Res 2 Decay').if_parameter('Res 2 On/Off').has_value('on'), + use('').if_parameter('Res 2 On/Off').has_value('off').else_use('Res 2 Radius').if_parameter('Res 2 Type').has_value('Tube').else_use('Res 2 Radius').if_parameter('Res 2 Type').has_value('Pipe').else_use('Res 2 Material'), + use('').if_parameter('Res 2 On/Off').has_value('off').else_use('').if_parameter('Res 2 Type').has_value('Tube').else_use('').if_parameter('Res 2 Type').has_value('Pipe').else_use('Res 2 Listening L'), + use('').if_parameter('Res 2 On/Off').has_value('off').else_use('').if_parameter('Res 2 Type').has_value('Tube').else_use('').if_parameter('Res 2 Type').has_value('Pipe').else_use('Res 2 Listening R'), + use('').if_parameter('Res 2 On/Off').has_value('off').else_use('').if_parameter('Res 2 Type').has_value('Tube').else_use('').if_parameter('Res 2 Type').has_value('Pipe').else_use('Res 2 Hit'))}), + ('Res. 2 Tune', {PARAMETERS_KEY: ('Res 2 On/Off', + use('').if_parameter('Res 2 On/Off').has_value('off').else_use('').if_parameter('Res 2 Type').has_value('Tube').else_use('').if_parameter('Res 2 Type').has_value('Pipe').else_use('Res 2 Brightness'), + use('Res 2 Quality').if_parameter('Res 2 On/Off').has_value('on'), + use('').if_parameter('Res 2 On/Off').has_value('off').else_use('').if_parameter('Res 2 Type').has_value('Tube').else_use('Res 2 Opening').if_parameter('Res 2 Type').has_value('Pipe').else_use('Res 2 Inharmonics'), + use('Res 2 Tune').if_parameter('Res 2 On/Off').has_value('on'), + use('Res 2 Fine Tune').if_parameter('Res 2 On/Off').has_value('on'), + use('Res 2 Pitch Env.').if_parameter('Res 2 On/Off').has_value('on'), + use('Res 2 Pitch Env. Time').if_parameter('Res 2 On/Off').has_value('on'))}), + ('LFO 1', {PARAMETERS_KEY: ('LFO 1 On/Off', + use('LFO 1 Depth').if_parameter('LFO 1 On/Off').has_value('on'), + use('LFO 1 Shape').if_parameter('LFO 1 On/Off').has_value('on'), + use('LFO 1 Sync').if_parameter('LFO 1 On/Off').has_value('on'), + use('').if_parameter('LFO 1 On/Off').has_value('off').else_use('LFO 1 Sync Rate').if_parameter('LFO 1 Sync').has_value('Sync').else_use('LFO 1 Rate'), + use('LFO 1 Offset').if_parameter('LFO 1 On/Off').has_value('on'), + use('LFO 1 Destination A').if_parameter('LFO 1 On/Off').has_value('on'), + use('LFO 1 Destination A Amount').if_parameter('LFO 1 On/Off').has_value('on'))}), + ('LFO 2', {PARAMETERS_KEY: ('LFO 2 On/Off', + use('LFO 2 Depth').if_parameter('LFO 2 On/Off').has_value('on'), + use('LFO 2 Shape').if_parameter('LFO 2 On/Off').has_value('on'), + use('LFO 2 Sync').if_parameter('LFO 2 On/Off').has_value('on'), + use('').if_parameter('LFO 2 On/Off').has_value('off').else_use('LFO 2 Sync Rate').if_parameter('LFO 2 Sync').has_value('Sync').else_use('LFO 2 Rate'), + use('LFO 2 Offset').if_parameter('LFO 2 On/Off').has_value('on'), + use('LFO 2 Destination A').if_parameter('LFO 2 On/Off').has_value('on'), + use('LFO 2 Destination A Amount').if_parameter('LFO 2 On/Off').has_value('on'))}), + ('Mallet Mod.', {PARAMETERS_KEY: ('Mallet On/Off', + use('Mallet Volume < Key').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Volume < Vel').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Noise Amount < Key').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Noise Amount < Vel').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Stiffness < Key').if_parameter('Mallet On/Off').has_value('on'), + use('Mallet Stiffness < Vel').if_parameter('Mallet On/Off').has_value('on'), + '')}))), + 'LoungeLizard': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('M Stiffness', + 'M Force', + 'Noise Amount', + 'F Tine Vol', + 'F Tone Vol', + 'F Release', + 'P Symmetry', + 'Volume')}), + ('Mallet', {PARAMETERS_KEY: ('M Stiffness', + 'M Force', + 'Noise Pitch', + 'Noise Decay', + 'Noise Amount', + 'M Stiff < Vel', + 'M Force < Vel', + 'Volume')}), + ('Fork', {PARAMETERS_KEY: ('F Tine Color', + 'F Tine Decay', + 'F Tine Vol', + 'F Tone Vol', + 'F Tone Decay', + 'F Release', + 'F Tine < Key', + 'Volume')}), + ('Damper', {PARAMETERS_KEY: ('Damp Tone', + 'Damp Balance', + 'Damp Amount', + '', + '', + '', + '', + 'Volume')}), + ('Pickup', {PARAMETERS_KEY: ('P Symmetry', + 'P Distance', + 'P Amp In', + 'P Amp Out', + 'Pickup Model', + 'P Amp < Key', + '', + 'Volume')}), + ('Modulation', {PARAMETERS_KEY: ('M Stiff < Vel', + 'M Stiff < Key', + 'M Force < Vel', + 'M Force < Key', + 'Noise < Key', + 'F Tine < Key', + 'P Amp < Key', + 'Volume')}), + ('Global', {PARAMETERS_KEY: ('KB Stretch', + 'PB Range', + '', + '', + 'Voices', + 'Semitone', + 'Detune', + 'Volume')}))), + 'InstrumentImpulse': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('1 Transpose', + '1 Volume', + '3 Transpose', + '3 Volume', + '7 Transpose', + '7 Volume', + '8 Transpose', + '8 Volume')}), + ('Pad 1', {PARAMETERS_KEY: ('1 Start', + '1 Envelope Decay', + '1 Stretch Factor', + '1 Saturator Drive', + '1 Envelope Type', + '1 Transpose', + '1 Volume <- Vel', + '1 Volume')}), + ('1 Filt/Mod/Pan', {PARAMETERS_KEY: ('1 Filter Freq', + '1 Filter Res', + '1 Filter Type', + '1 Filter <- Vel', + '1 Filter <- Random', + '1 Pan', + '1 Pan <- Vel', + '1 Pan <- Random')}), + ('Pad 2', {PARAMETERS_KEY: ('2 Start', + '2 Envelope Decay', + '2 Stretch Factor', + '2 Saturator Drive', + '2 Envelope Type', + '2 Transpose', + '2 Volume <- Vel', + '2 Volume')}), + ('2 Filt/Mod/Pan', {PARAMETERS_KEY: ('2 Filter Freq', + '2 Filter Res', + '2 Filter Type', + '2 Filter <- Vel', + '2 Filter <- Random', + '2 Pan', + '2 Pan <- Vel', + '2 Pan <- Random')}), + ('Pad 3', {PARAMETERS_KEY: ('3 Start', + '3 Envelope Decay', + '3 Stretch Factor', + '3 Saturator Drive', + '3 Envelope Type', + '3 Transpose', + '3 Volume <- Vel', + '3 Volume')}), + ('3 Filt/Mod/Pan', {PARAMETERS_KEY: ('3 Filter Freq', + '3 Filter Res', + '3 Filter Type', + '3 Filter <- Vel', + '3 Filter <- Random', + '3 Pan', + '3 Pan <- Vel', + '3 Pan <- Random')}), + ('Pad 4', {PARAMETERS_KEY: ('4 Start', + '4 Envelope Decay', + '4 Stretch Factor', + '4 Saturator Drive', + '4 Envelope Type', + '4 Transpose', + '4 Volume <- Vel', + '4 Volume')}), + ('4 Filt/Mod/Pan', {PARAMETERS_KEY: ('4 Filter Freq', + '4 Filter Res', + '4 Filter Type', + '4 Filter <- Vel', + '4 Filter <- Random', + '4 Pan', + '4 Pan <- Vel', + '4 Pan <- Random')}), + ('Pad 5', {PARAMETERS_KEY: ('5 Start', + '5 Envelope Decay', + '5 Stretch Factor', + '5 Saturator Drive', + '5 Envelope Type', + '5 Transpose', + '5 Volume <- Vel', + '5 Volume')}), + ('5 Filt/Mod/Pan', {PARAMETERS_KEY: ('5 Filter Freq', + '5 Filter Res', + '5 Filter Type', + '5 Filter <- Vel', + '5 Filter <- Random', + '5 Pan', + '5 Pan <- Vel', + '5 Pan <- Random')}), + ('Pad 6', {PARAMETERS_KEY: ('6 Start', + '6 Envelope Decay', + '6 Stretch Factor', + '6 Saturator Drive', + '6 Envelope Type', + '6 Transpose', + '6 Volume <- Vel', + '6 Volume')}), + ('6 Filt/Mod/Pan', {PARAMETERS_KEY: ('6 Filter Freq', + '6 Filter Res', + '6 Filter Type', + '6 Filter <- Vel', + '6 Filter <- Random', + '6 Pan', + '6 Pan <- Vel', + '6 Pan <- Random')}), + ('Pad 7', {PARAMETERS_KEY: ('7 Start', + '7 Envelope Decay', + '7 Stretch Factor', + '7 Saturator Drive', + '7 Envelope Type', + '7 Transpose', + '7 Volume <- Vel', + '7 Volume')}), + ('7 Filt/Mod/Pan', {PARAMETERS_KEY: ('7 Filter Freq', + '7 Filter Res', + '7 Filter Type', + '7 Filter <- Vel', + '7 Filter <- Random', + '7 Pan', + '7 Pan <- Vel', + '7 Pan <- Random')}), + ('Pad 8', {PARAMETERS_KEY: ('8 Start', + '8 Envelope Decay', + '8 Stretch Factor', + '8 Saturator Drive', + '8 Envelope Type', + '8 Transpose', + '8 Volume <- Vel', + '8 Volume')}), + ('8 Filt/Mod/Pan', {PARAMETERS_KEY: ('8 Filter Freq', + '8 Filter Res', + '8 Filter Type', + '8 Filter <- Vel', + '8 Filter <- Random', + '8 Pan', + '8 Pan <- Vel', + '8 Pan <- Random')}), + ('Global', {PARAMETERS_KEY: ('Global Time', + 'Global Transpose', + 'Global Volume', + '', + '', + '', + '', + '')}))), + 'Operator': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('Algorithm').if_parameter('Filter On').has_value('off').else_use('Filter Freq'), + use('Filter Res (Legacy)').if_parameter('Filter Res').is_available(False).and_parameter('Filter On').has_value('on').else_use('Filter Res').if_parameter('Filter On').has_value('on').else_use('Tone'), + use('').if_parameter('Osc-A On').has_value('off').else_use('A Coarse').if_parameter('A Fix On ').has_value('off').else_use('A Fix Freq'), + use('').if_parameter('Osc-A On').has_value('off').else_use('A Fine').if_parameter('A Fix On ').has_value('off').else_use('A Fix Freq Mul'), + use('').if_parameter('Osc-B On').has_value('off').else_use('B Coarse').if_parameter('B Fix On ').has_value('off').else_use('B Fix Freq'), + use('').if_parameter('Osc-B On').has_value('off').else_use('B Fine').if_parameter('B Fix On ').has_value('off').else_use('B Fix Freq Mul'), + use('Osc-B Level').if_parameter('Osc-B On').has_value('on'), + 'Volume')}), + ('Global', {PARAMETERS_KEY: ('Time', + 'Time < Key', + 'Tone', + 'Algorithm', + 'Panorama', + 'Pan < Key', + 'Pan < Rnd', + 'Volume')}), + ('Osc. A', {PARAMETERS_KEY: ('Osc-A On', + use('Osc-A Level').if_parameter('Osc-A On').has_value('on'), + use('A Fix On ').if_parameter('Osc-A On').has_value('on'), + use('').if_parameter('Osc-A On').has_value('off').else_use('A Coarse').if_parameter('A Fix On ').has_value('off').else_use('A Fix Freq'), + use('').if_parameter('Osc-A On').has_value('off').else_use('A Fine').if_parameter('A Fix On ').has_value('off').else_use('A Fix Freq Mul'), + use('Osc-A Wave').if_parameter('Osc-A On').has_value('on'), + use('Osc-A Retrig').if_parameter('Osc-A On').has_value('on'), + use('').if_parameter('Osc-A On').has_value('off').else_use('Osc-A Phase').if_parameter('Osc-A Retrig').has_value('on'))}), + ('Osc. A Env.', {PARAMETERS_KEY: ('Osc-A On', + use('Ae Init').if_parameter('Osc-A On').has_value('on'), + use('Ae Attack').if_parameter('Osc-A On').has_value('on'), + use('Ae Peak').if_parameter('Osc-A On').has_value('on'), + use('Ae Decay').if_parameter('Osc-A On').has_value('on'), + use('Ae Sustain').if_parameter('Osc-A On').has_value('on'), + use('Ae Release').if_parameter('Osc-A On').has_value('on'), + use('Osc-A Lev < Vel').if_parameter('Osc-A On').has_value('on'))}), + ('Osc. B', {PARAMETERS_KEY: ('Osc-B On', + use('Osc-B Level').if_parameter('Osc-B On').has_value('on'), + use('B Fix On ').if_parameter('Osc-B On').has_value('on'), + use('').if_parameter('Osc-B On').has_value('off').else_use('B Coarse').if_parameter('B Fix On ').has_value('off').else_use('B Fix Freq'), + use('').if_parameter('Osc-B On').has_value('off').else_use('B Fine').if_parameter('B Fix On ').has_value('off').else_use('B Fix Freq Mul'), + use('Osc-B Wave').if_parameter('Osc-B On').has_value('on'), + use('Osc-B Retrig').if_parameter('Osc-B On').has_value('on'), + use('').if_parameter('Osc-B On').has_value('off').else_use('Osc-B Phase').if_parameter('Osc-B Retrig').has_value('on'))}), + ('Osc. B Env.', {PARAMETERS_KEY: ('Osc-B On', + use('Be Init').if_parameter('Osc-B On').has_value('on'), + use('Be Attack').if_parameter('Osc-B On').has_value('on'), + use('Be Peak').if_parameter('Osc-B On').has_value('on'), + use('Be Decay').if_parameter('Osc-B On').has_value('on'), + use('Be Sustain').if_parameter('Osc-B On').has_value('on'), + use('Be Release').if_parameter('Osc-B On').has_value('on'), + use('Osc-B Lev < Vel').if_parameter('Osc-B On').has_value('on'))}), + ('Osc. C', {PARAMETERS_KEY: ('Osc-C On', + use('Osc-C Level').if_parameter('Osc-C On').has_value('on'), + use('C Fix On ').if_parameter('Osc-C On').has_value('on'), + use('').if_parameter('Osc-C On').has_value('off').else_use('C Coarse').if_parameter('C Fix On ').has_value('off').else_use('C Fix Freq'), + use('').if_parameter('Osc-C On').has_value('off').else_use('C Fine').if_parameter('C Fix On ').has_value('off').else_use('C Fix Freq Mul'), + use('Osc-C Wave').if_parameter('Osc-C On').has_value('on'), + use('Osc-C Retrig').if_parameter('Osc-C On').has_value('on'), + use('').if_parameter('Osc-C On').has_value('off').else_use('Osc-C Phase').if_parameter('Osc-C Retrig').has_value('on'))}), + ('Osc. C Env.', {PARAMETERS_KEY: ('Osc-C On', + use('Ce Init').if_parameter('Osc-C On').has_value('on'), + use('Ce Attack').if_parameter('Osc-C On').has_value('on'), + use('Ce Peak').if_parameter('Osc-C On').has_value('on'), + use('Ce Decay').if_parameter('Osc-C On').has_value('on'), + use('Ce Sustain').if_parameter('Osc-C On').has_value('on'), + use('Ce Release').if_parameter('Osc-C On').has_value('on'), + use('Osc-C Lev < Vel').if_parameter('Osc-C On').has_value('on'))}), + ('Osc. D', {PARAMETERS_KEY: ('Osc-D On', + use('Osc-D Level').if_parameter('Osc-D On').has_value('on'), + use('D Fix On ').if_parameter('Osc-D On').has_value('on'), + use('').if_parameter('Osc-D On').has_value('off').else_use('D Coarse').if_parameter('D Fix On ').has_value('off').else_use('D Fix Freq'), + use('').if_parameter('Osc-D On').has_value('off').else_use('D Fine').if_parameter('D Fix On ').has_value('off').else_use('D Fix Freq Mul'), + use('Osc-D Wave').if_parameter('Osc-D On').has_value('on'), + use('Osc-D Retrig').if_parameter('Osc-D On').has_value('on'), + use('').if_parameter('Osc-D On').has_value('off').else_use('Osc-D Phase').if_parameter('Osc-D Retrig').has_value('on'))}), + ('Osc. D Env.', {PARAMETERS_KEY: ('Osc-D On', + use('De Init').if_parameter('Osc-D On').has_value('on'), + use('De Attack').if_parameter('Osc-D On').has_value('on'), + use('De Peak').if_parameter('Osc-D On').has_value('on'), + use('De Decay').if_parameter('Osc-D On').has_value('on'), + use('De Sustain').if_parameter('Osc-D On').has_value('on'), + use('De Release').if_parameter('Osc-D On').has_value('on'), + use('Osc-D Lev < Vel').if_parameter('Osc-D On').has_value('on'))}), + ('Filter', {PARAMETERS_KEY: ('Filter On', + use('').if_parameter('Filter On').has_value('off').else_use('Filter Type').if_parameter('Filter Type').is_available(True).else_use('Filter Type (Legacy)'), + use('Filter Freq').if_parameter('Filter On').has_value('on'), + use('').if_parameter('Filter On').has_value('off').else_use('Filter Res').if_parameter('Filter Res').is_available(True).else_use('Filter Res (Legacy)'), + use('').if_parameter('Filter On').has_value('off').else_use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Lowpass').else_use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Highpass').else_use('Filter Circuit - BP/NO/Morph'), + use('').if_parameter('Filter On').has_value('off').else_use('Filter Morph').if_parameter('Filter Type').has_value('Morph').else_use('').if_parameter('Filter Type').has_value('Lowpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Highpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Bandpass').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Notch').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('Filter Drive'), + use('Filter Slope').if_parameter('Filter On').has_value('on').and_parameter('Filter Slope').is_available(True), + use('Filt < Vel').if_parameter('Filter On').has_value('on'))}), + ('Filt. Env.', {PARAMETERS_KEY: (use('Fe Amount').if_parameter('Filter On').has_value('on'), + use('Fe Init').if_parameter('Filter On').has_value('on'), + use('Fe Attack').if_parameter('Filter On').has_value('on'), + use('Fe Peak').if_parameter('Filter On').has_value('on'), + use('Fe Decay').if_parameter('Filter On').has_value('on'), + use('Fe Sustain').if_parameter('Filter On').has_value('on'), + use('Fe Release').if_parameter('Filter On').has_value('on'), + use('Fe End').if_parameter('Filter On').has_value('on'))}), + ('LFO', {PARAMETERS_KEY: ('LFO On', + use('LFO Type').if_parameter('LFO On').has_value('on'), + use('LFO Range').if_parameter('LFO On').has_value('on'), + use('').if_parameter('LFO On').has_value('off').else_use('LFO Sync').if_parameter('LFO Range').has_value('Sync').else_use('LFO Rate'), + use('LFO Retrigger').if_parameter('LFO On').has_value('on'), + use('LFO Amt').if_parameter('LFO On').has_value('on'), + '', + '')}), + ('LFO Env.', {PARAMETERS_KEY: ('LFO On', + use('Le Init').if_parameter('LFO On').has_value('on'), + use('Le Attack').if_parameter('LFO On').has_value('on'), + use('Le Peak').if_parameter('LFO On').has_value('on'), + use('Le Decay').if_parameter('LFO On').has_value('on'), + use('Le Sustain').if_parameter('LFO On').has_value('on'), + use('Le Release').if_parameter('LFO On').has_value('on'), + use('Le End').if_parameter('LFO On').has_value('on'))}), + ('Pitch', {PARAMETERS_KEY: ('Transpose', + 'Spread', + 'Glide On', + use('Glide Time').if_parameter('Glide On').has_value('on'), + 'Pe On', + use('Pe Amount').if_parameter('Pe On').has_value('on'), + use('LFO < Pe').if_parameter('Pe On').has_value('on'), + use('Pe Dst B').if_parameter('Pe On').has_value('on'))}), + ('Pitch Env.', {PARAMETERS_KEY: ('Pe On', + use('Pe Attack').if_parameter('Pe On').has_value('on'), + use('Pe Peak').if_parameter('Pe On').has_value('on'), + use('Pe Decay').if_parameter('Pe On').has_value('on'), + use('Pe Sustain').if_parameter('Pe On').has_value('on'), + use('Pe Release').if_parameter('Pe On').has_value('on'), + use('Pe End').if_parameter('Pe On').has_value('on'), + use('Pe R < Vel').if_parameter('Pe On').has_value('on'))}))), + 'MultiSampler': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Ve Attack', + 'Ve Decay', + 'Ve Sustain', + 'Ve Release', + use('Pan').if_parameter('F On').has_value('off').else_use('Filter Type').if_parameter('Filter Type').is_available(True).else_use('Filter Type (Legacy)'), + use('Transpose').if_parameter('F On').has_value('off').else_use('Filter Freq'), + use('Detune').if_parameter('F On').has_value('off').else_use('Filter Res').if_parameter('Filter Res').is_available(True).else_use('Filter Res (Legacy)'), + 'Volume')}), + ('Volume Env.', {PARAMETERS_KEY: ('Ve Init', + 'Ve Attack', + 'Ve Peak', + 'Ve Decay', + 'Ve Sustain', + 'Ve Release', + 'Vol < Vel', + 'Volume')}), + ('Env. Loop & Pan', {PARAMETERS_KEY: ('Ve Mode', + use('Ve Loop').if_parameter('Ve Mode').has_value('Loop').else_use('Ve Retrig').if_parameter('Ve Mode').has_value('Beat').else_use('Ve Retrig').if_parameter('Ve Mode').has_value('Sync').else_use(''), + 'Ve R < Vel', + '', + 'Pan', + 'Pan < Rnd', + 'Time', + 'Time < Key')}), + ('Filter', {PARAMETERS_KEY: ('F On', + use('').if_parameter('F On').has_value('off').else_use('Filter Type').if_parameter('Filter Type').is_available(True).else_use('Filter Type (Legacy)'), + use('').if_parameter('F On').has_value('off').else_use('Filter Freq'), + use('').if_parameter('F On').has_value('off').else_use('Filter Res').if_parameter('Filter Res').is_available(True).else_use('Filter Res (Legacy)'), + use('').if_parameter('F On').has_value('off').else_use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Lowpass').else_use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Highpass').else_use('Filter Circuit - BP/NO/Morph'), + use('').if_parameter('F On').has_value('off').else_use('Filter Morph').if_parameter('Filter Type').has_value('Morph').else_use('').if_parameter('Filter Type').has_value('Lowpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Highpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Bandpass').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Notch').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('Filter Drive'), + use('Filter Slope').if_parameter('F On').has_value('on').and_parameter('Filter Slope').is_available(True), + use('Filt < Vel').if_parameter('F On').has_value('on'))}), + ('Filt. Env', {PARAMETERS_KEY: ('Fe On', + use('Fe < Env').if_parameter('Fe On').has_value('on'), + use('Fe Init').if_parameter('Fe On').has_value('on'), + use('Fe Attack').if_parameter('Fe On').has_value('on'), + use('Fe Decay').if_parameter('Fe On').has_value('on'), + use('Fe Peak').if_parameter('Fe On').has_value('on'), + use('Fe Sustain').if_parameter('Fe On').has_value('on'), + use('Fe Release').if_parameter('Fe On').has_value('on'))}), + ('Shaper', {PARAMETERS_KEY: ('Fe On', + use('Fe End').if_parameter('Fe On').has_value('on'), + use('Fe Mode').if_parameter('Fe On').has_value('on'), + use('').if_parameter('Fe On').has_value('off').else_use('Fe Loop').if_parameter('Fe Mode').has_value('Loop').else_use('Fe Retrig').if_parameter('Fe Mode').has_value('Beat').else_use('Fe Retrig').if_parameter('Fe Mode').has_value('Sync').else_use(''), + use('Fe R < Vel').if_parameter('Fe On').has_value('on'), + 'Shaper On', + use('Shaper Type').if_parameter('Shaper On').has_value('on'), + use('Shaper Amt').if_parameter('Shaper On').has_value('on'))}), + ('Osc. pg. 1', {PARAMETERS_KEY: ('Osc On', + use('O Mode').if_parameter('Osc On').has_value('on'), + use('Oe Init').if_parameter('Osc On').has_value('on'), + use('Oe Attack').if_parameter('Osc On').has_value('on'), + use('Oe Peak').if_parameter('Osc On').has_value('on'), + use('Oe Decay').if_parameter('Osc On').has_value('on'), + use('Oe Sustain').if_parameter('Osc On').has_value('on'), + use('Oe Release').if_parameter('Osc On').has_value('on'))}), + ('Osc. pg. 2', {PARAMETERS_KEY: (use('Oe End').if_parameter('Osc On').has_value('on'), + use('Oe Mode').if_parameter('Osc On').has_value('on'), + use('').if_parameter('Osc On').has_value('off').else_use('Oe Loop').if_parameter('Oe Mode').has_value('Loop').else_use('Oe Retrig').if_parameter('Oe Mode').has_value('Beat').else_use('Oe Retrig').if_parameter('Oe Mode').has_value('Sync').else_use(''), + use('O Type').if_parameter('Osc On').has_value('on'), + use('O Volume').if_parameter('Osc On').has_value('on'), + use('O Fix On').if_parameter('Osc On').has_value('on'), + use('').if_parameter('Osc On').has_value('off').else_use('O Coarse').if_parameter('O Fix On').has_value('off').else_use('O Fix Freq'), + use('').if_parameter('Osc On').has_value('off').else_use('O Fine').if_parameter('O Fix On').has_value('off').else_use('O Fix Freq Mul'))}), + ('Pitch Env.', {PARAMETERS_KEY: ('Pe On', + use('Pe < Env').if_parameter('Pe On').has_value('on'), + use('Pe Init').if_parameter('Pe On').has_value('on'), + use('Pe Attack').if_parameter('Pe On').has_value('on'), + use('Pe Peak').if_parameter('Pe On').has_value('on'), + use('Pe Decay').if_parameter('Pe On').has_value('on'), + use('Pe Sustain').if_parameter('Pe On').has_value('on'), + use('Pe Release').if_parameter('Pe On').has_value('on'))}), + ('Pitch Env. 2', {PARAMETERS_KEY: ('Pe On', + use('Pe End').if_parameter('Pe On').has_value('on'), + use('Pe R < Vel').if_parameter('Pe On').has_value('on'), + use('Pe Mode').if_parameter('Pe On').has_value('on'), + use('').if_parameter('Pe On').has_value('off').else_use('Pe Loop').if_parameter('Pe Mode').has_value('Loop').else_use('Pe Retrig').if_parameter('Pe Mode').has_value('Beat').else_use('Pe Retrig').if_parameter('Pe Mode').has_value('Sync').else_use(''), + '', + '', + '')}), + ('Pitch/Glide', {PARAMETERS_KEY: ('Pe On', + 'Spread', + 'Transpose', + 'Detune', + 'Key Zone Shift', + 'Glide Mode', + use('Glide Time').if_parameter('Glide Mode').has_value('On'), + '')}), + ('LFO1 pg. 1', {PARAMETERS_KEY: ('L 1 On', + use('L 1 Wave').if_parameter('L 1 On').has_value('on'), + use('L 1 Sync').if_parameter('L 1 On').has_value('on'), + use('').if_parameter('L 1 On').has_value('off').else_use('L 1 Sync Rate').if_parameter('L 1 Sync').has_value('Sync').else_use('L 1 Rate'), + use('Vol < LFO').if_parameter('L 1 On').has_value('on'), + use('Filt < LFO').if_parameter('L 1 On').has_value('on'), + use('Pan < LFO').if_parameter('L 1 On').has_value('on'), + use('Pitch < LFO').if_parameter('L 1 On').has_value('on'))}), + ('LFO1 pg. 2', {PARAMETERS_KEY: ('L 1 On', + use('L 1 Retrig').if_parameter('L 1 On').has_value('on'), + use('').if_parameter('L 1 On').has_value('off').else_use('L 1 Offset').if_parameter('L 1 Retrig').has_value('on').else_use(''), + use('L 1 Attack').if_parameter('L 1 On').has_value('on'), + '', + '', + '', + '')}), + ('LFO2 pg. 1', {PARAMETERS_KEY: ('L 2 On', + use('L 2 Wave').if_parameter('L 2 On').has_value('on'), + use('L 2 Sync').if_parameter('L 2 On').has_value('on'), + use('').if_parameter('L 2 On').has_value('off').else_use('L 2 Sync Rate').if_parameter('L 2 Sync').has_value('Sync').else_use('L 2 Rate'), + use('L 2 Retrig').if_parameter('L 2 On').has_value('on'), + use('').if_parameter('L 2 On').has_value('off').else_use('L 2 Offset').if_parameter('L 2 Retrig').has_value('on').else_use(''), + use('L 2 Attack').if_parameter('L 2 On').has_value('on'), + '')}), + ('LFO2 pg. 2', {PARAMETERS_KEY: ('L 2 On', + use('L 2 St Mode').if_parameter('L 2 On').has_value('on'), + use('').if_parameter('L 2 On').has_value('off').else_use('L 2 Spin').if_parameter('L 2 St Mode').has_value('Spin').else_use('L 2 Phase'), + '', + '', + '', + '', + '')}), + ('LFO3 pg. 1', {PARAMETERS_KEY: ('L 3 On', + use('L 3 Wave').if_parameter('L 3 On').has_value('on'), + use('L 3 Sync').if_parameter('L 3 On').has_value('on'), + use('').if_parameter('L 3 On').has_value('off').else_use('L 3 Sync Rate').if_parameter('L 3 Sync').has_value('Sync').else_use('L 3 Rate'), + use('L 3 Retrig').if_parameter('L 3 On').has_value('on'), + use('').if_parameter('L 3 On').has_value('off').else_use('L 3 Offset').if_parameter('L 3 Retrig').has_value('on').else_use(''), + use('L 3 Attack').if_parameter('L 3 On').has_value('on'), + '')}), + ('LFO3 pg. 2', {PARAMETERS_KEY: ('L 3 On', + use('L 3 St Mode').if_parameter('L 3 On').has_value('on'), + use('').if_parameter('L 3 On').has_value('off').else_use('L 3 Spin').if_parameter('L 3 St Mode').has_value('Spin').else_use('L 3 Phase'), + '', + '', + '', + '', + '')}), + ('Aux Env.', {PARAMETERS_KEY: ('Ae On', + use('Ae < Env').if_parameter('Ae On').has_value('on'), + use('Ae Init').if_parameter('Ae On').has_value('on'), + use('Ae Attack').if_parameter('Ae On').has_value('on'), + use('Ae Peak').if_parameter('Ae On').has_value('on'), + use('Ae Decay').if_parameter('Ae On').has_value('on'), + use('Ae Sustain').if_parameter('Ae On').has_value('on'), + use('Ae Release').if_parameter('Ae On').has_value('on'))}), + ('Aux Env. 2', {PARAMETERS_KEY: ('Ae On', + use('Ae End').if_parameter('Ae On').has_value('off'), + use('Ae R < Vel').if_parameter('Ae On').has_value('off'), + use('Ae Mode').if_parameter('Ae On').has_value('off'), + use('').if_parameter('Ae On').has_value('off').else_use('Ae Loop').if_parameter('Ae Mode').has_value('Loop').else_use('Ae Retrig').if_parameter('Ae Mode').has_value('Beat').else_use('Ae Retrig').if_parameter('Ae Mode').has_value('Sync').else_use(''), + '', + '', + '')}))), + 'OriginalSimpler': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('Ve Attack').if_parameter('Multi Sample').has_value('on').else_use('Start'), + use('Ve Decay').if_parameter('Multi Sample').has_value('on').else_use('End'), + use('Ve Sustain').if_parameter('Multi Sample').has_value('on').else_use('Fade In').if_parameter('Mode').has_value('One-Shot').else_use('Nudge').if_parameter('Mode').has_value('Slicing').else_use('S Start').if_parameter('Mode').has_value('Classic'), + use('Ve Release').if_parameter('Multi Sample').has_value('on').else_use('Fade Out').if_parameter('Mode').has_value('One-Shot').else_use('Playback').if_parameter('Mode').has_value('Slicing').else_use('S Length').if_parameter('Mode').has_value('Classic'), + use('Pan').if_parameter('Multi Sample').has_value('on').and_parameter('F On').has_value('off').else_use('Filter Type').if_parameter('Filter Type').is_available(True).and_parameter('Multi Sample').has_value('on').else_use('Filter Type (Legacy)').if_parameter('Multi Sample').has_value('on').else_use('Transpose').if_parameter('Mode').has_value('One-Shot').else_use('Pad Slicing').if_parameter('Mode').has_value('Slicing').else_use('S Loop On').if_parameter('Mode').has_value('Classic'), + use('Filter Freq').if_parameter('Multi Sample').has_value('on').and_parameter('F On').has_value('on').else_use('Transpose').if_parameter('Multi Sample').has_value('on').else_use('Volume').if_parameter('Mode').has_value('One-Shot').else_use('Sensitivity').if_parameter('Mode').has_value('Slicing').else_use('S Loop Length').if_parameter('Mode').has_value('Classic').and_parameter('S Loop On').has_value('on').else_use('Transpose'), + use('Detune').if_parameter('Multi Sample').has_value('on').and_parameter('F On').has_value('off').else_use('Filter Res').if_parameter('Filter Res').is_available(True).and_parameter('Multi Sample').has_value('on').else_use('Filter Res (Legacy)').if_parameter('Multi Sample').has_value('on').else_use('Trigger Mode').if_parameter('Mode').has_value('One-Shot').else_use('Trigger Mode').if_parameter('Mode').has_value('Slicing').else_use('S Loop Fade').if_parameter('Mode').has_value('Classic').and_parameter('Warp').has_value('Off').else_use('Detune'), + use('Volume').if_parameter('Multi Sample').has_value('on').else_use('Mode'))}), + ('Global', {PARAMETERS_KEY: ('Glide Mode', + use('').if_parameter('Glide Mode').has_value('Off').else_use('Glide Time'), + 'Voices', + 'Transpose', + 'Detune', + 'Vol < Vel', + 'Gain', + 'Volume')}), + ('Volume Envelope', {PARAMETERS_KEY: (use('Ve Attack').if_parameter('Mode').has_value('Classic').else_use('Fade In'), + use('Ve Decay').if_parameter('Mode').has_value('Classic').else_use('Fade Out'), + use('Ve Sustain').if_parameter('Mode').has_value('Classic'), + use('Ve Release').if_parameter('Mode').has_value('Classic'), + 'Filt < Vel', + 'Vol < Vel', + 'Vol < LFO', + 'Volume')}), + ('Warp', {PARAMETERS_KEY: (use('').if_parameter('Multi Sample').has_value('on').else_use('Warp'), + use('').if_parameter('Multi Sample').has_value('on').else_use('').if_parameter('Warp').has_value('off').else_use('Warp Mode'), + use('').if_parameter('Multi Sample').has_value('on').else_use('').if_parameter('Warp').has_value('off').else_use('Preserve').if_parameter('Warp Mode').has_value('Beats').else_use('Grain Size Tones').if_parameter('Warp Mode').has_value('Tones').else_use('Grain Size Texture').if_parameter('Warp Mode').has_value('Texture').else_use('Formants').if_parameter('Warp Mode').has_value('Pro'), + use('').if_parameter('Multi Sample').has_value('on').else_use('').if_parameter('Warp').has_value('off').else_use('Loop Mode').if_parameter('Warp Mode').has_value('Beats').else_use('Flux').if_parameter('Warp Mode').has_value('Texture').else_use('Envelope Complex Pro').if_parameter('Warp Mode').has_value('Pro'), + use('').if_parameter('Multi Sample').has_value('on').else_use('').if_parameter('Warp').has_value('off').else_use('Envelope').if_parameter('Warp Mode').has_value('Beats'), + '', + '', + '')}), + ('Filter', {PARAMETERS_KEY: ('F On', + use('').if_parameter('F On').has_value('off').else_use('Filter Type').if_parameter('Filter Type').is_available(True).else_use('Filter Type (Legacy)'), + use('Filter Freq').if_parameter('F On').has_value('on'), + use('').if_parameter('F On').has_value('off').else_use('Filter Res').if_parameter('Filter Res').is_available(True).else_use('Filter Res (Legacy)'), + use('').if_parameter('F On').has_value('off').else_use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Lowpass').else_use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Highpass').else_use('Filter Circuit - BP/NO/Morph'), + use('').if_parameter('F On').has_value('off').else_use('Filter Morph').if_parameter('Filter Type').has_value('Morph').else_use('').if_parameter('Filter Type').has_value('Lowpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Highpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Bandpass').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Notch').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('Filter Drive'), + use('Filter Slope').if_parameter('F On').has_value('on').and_parameter('Filter Slope').is_available(True), + use('Filt < LFO').if_parameter('F On').has_value('on'))}), + ('Filter Envelope', {PARAMETERS_KEY: ('Fe On', + use('Fe Attack').if_parameter('Fe On').has_value('on'), + use('Fe Decay').if_parameter('Fe On').has_value('on'), + use('Fe Sustain').if_parameter('Fe On').has_value('on'), + use('Fe Release').if_parameter('Fe On').has_value('on'), + use('Filter Freq').if_parameter('Fe On').has_value('on').and_parameter('F On').has_value('on'), + use('Filter Res').if_parameter('Fe On').has_value('on').and_parameter('F On').has_value('on'), + use('Fe < Env').if_parameter('Fe On').has_value('on'))}), + ('Pitch Envelope', {PARAMETERS_KEY: ('Pe On', + use('Pe Attack').if_parameter('Pe On').has_value('on'), + use('Pe Decay').if_parameter('Pe On').has_value('on'), + use('Pe Sustain').if_parameter('Pe On').has_value('on'), + use('Pe Release').if_parameter('Pe On').has_value('on'), + use('Pe < Env').if_parameter('Pe On').has_value('on'), + '', + '')}), + ('LFO', {PARAMETERS_KEY: ('L On', + use('L Wave').if_parameter('L On').has_value('on'), + use('L Sync').if_parameter('L On').has_value('on'), + use('').if_parameter('L On').has_value('off').else_use('L Rate').if_parameter('L Sync').has_value('Free').else_use('L Sync Rate'), + use('L Attack').if_parameter('L On').has_value('on'), + use('L R < Key').if_parameter('L On').has_value('on'), + use('L Retrig').if_parameter('L On').has_value('on'), + use('L Offset').if_parameter('L On').has_value('on'))}), + ('Pan', {PARAMETERS_KEY: ('Pan', + 'Spread', + 'Pan < Rnd', + 'Pan < LFO', + '', + '', + '', + '')}))), + 'StringStudio': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('Excitator Type').if_parameter('Exc On/Off').has_value('1'), + use('Exc ForceMassProt').if_parameter('Exc On/Off').has_value('1'), + use('Exc FricStiff').if_parameter('Exc On/Off').has_value('1'), + use('Exc Velocity').if_parameter('Exc On/Off').has_value('1'), + use('E Pos').if_parameter('Exc On/Off').has_value('1'), + 'String Decay', + 'Str Damping', + 'Volume')}), + ('Excitator', {PARAMETERS_KEY: ('Exc On/Off', + use('Excitator Type').if_parameter('Exc On/Off').has_value('1'), + use('Exc ForceMassProt').if_parameter('Exc On/Off').has_value('1'), + use('Exc FricStiff').if_parameter('Exc On/Off').has_value('1'), + use('Exc Velocity').if_parameter('Exc On/Off').has_value('1'), + use('E Pos').if_parameter('Exc On/Off').has_value('1'), + use('E Pos Abs').if_parameter('Exc On/Off').has_value('1'), + 'Volume')}), + ('String & Pickup', {PARAMETERS_KEY: ('String Decay', + 'S Decay < Key', + 'S Decay Ratio', + 'Str Inharmon', + 'Str Damping', + 'S Damp < Key', + 'Pickup On/Off', + use('Pickup Pos').if_parameter('Pickup On/Off').has_value('1'))}), + ('Damper', {PARAMETERS_KEY: ('Damper On', + use('Damper Mass').if_parameter('Damper On').has_value('1'), + use('D Stiffness').if_parameter('Damper On').has_value('1'), + use('Damp Pos').if_parameter('Damper On').has_value('1'), + use('D Damping').if_parameter('Damper On').has_value('1'), + use('Damper Gated').if_parameter('Damper On').has_value('1'), + use('').if_parameter('Damper On').has_value('0').else_use('D Velocity').if_parameter('Damper Gated').has_value('1').else_use(''), + use('D Pos Abs').if_parameter('Damper On').has_value('1'))}), + ('Termination', {PARAMETERS_KEY: ('Term On/Off', + use('Term Mass').if_parameter('Term On/Off').has_value('1'), + use('Term Fng Stiff').if_parameter('Term On/Off').has_value('1'), + use('Term Fret Stiff').if_parameter('Term On/Off').has_value('1'), + use('T Mass < Vel').if_parameter('Term On/Off').has_value('1'), + use('T Mass < Key').if_parameter('Term On/Off').has_value('1'), + '', + 'Volume')}), + ('Body', {PARAMETERS_KEY: ('Body On/Off', + use('Body Type').if_parameter('Body On/Off').has_value('1'), + use('Body Size').if_parameter('Body On/Off').has_value('1'), + use('Body Decay').if_parameter('Body On/Off').has_value('1'), + use('Body Low-Cut').if_parameter('Body On/Off').has_value('1'), + use('Body High-Cut').if_parameter('Body On/Off').has_value('1'), + use('Body Mix').if_parameter('Body On/Off').has_value('1'), + 'Volume')}), + ('Filter', {PARAMETERS_KEY: ('Filter On/Off', + use('Filter Freq').if_parameter('Filter On/Off').has_value('1'), + use('Filter Reso').if_parameter('Filter On/Off').has_value('1'), + use('Filter Type').if_parameter('Filter On/Off').has_value('1'), + use('Freq < Env').if_parameter('Filter On/Off').has_value('1'), + use('Freq < LFO').if_parameter('Filter On/Off').has_value('1'), + use('Reso < Env').if_parameter('Filter On/Off').has_value('1'), + use('Reso < LFO').if_parameter('Filter On/Off').has_value('1'))}), + ('LFO', {PARAMETERS_KEY: ('LFO On/Off', + use('LFO Shape').if_parameter('LFO On/Off').has_value('1'), + use('LFO Sync On').if_parameter('LFO On/Off').has_value('1'), + use('').if_parameter('LFO On/Off').has_value('0').else_use('LFO SyncRate').if_parameter('LFO Sync On').has_value('Beat').else_use('LFO Speed'), + use('LFO Delay').if_parameter('LFO On/Off').has_value('1'), + use('LFO Fade In').if_parameter('LFO On/Off').has_value('1'), + '', + '')}), + ('Vibrato', {PARAMETERS_KEY: ('Vibrato On/Off', + use('Vib Delay').if_parameter('Vibrato On/Off').has_value('1'), + use('Vib Fade-In').if_parameter('Vibrato On/Off').has_value('1'), + use('Vib Speed').if_parameter('Vibrato On/Off').has_value('1'), + use('Vib Amount').if_parameter('Vibrato On/Off').has_value('1'), + use('Vib < ModWh').if_parameter('Vibrato On/Off').has_value('1'), + use('Vib Error').if_parameter('Vibrato On/Off').has_value('1'), + use('Vib Delay').if_parameter('Vibrato On/Off').has_value('1'))}), + ('Unison & Portamento', {PARAMETERS_KEY: ('Unison On/Off', + use('Unison Voices').if_parameter('Unison On/Off').has_value('1'), + use('Uni Delay').if_parameter('Unison On/Off').has_value('1'), + use('Uni Detune').if_parameter('Unison On/Off').has_value('1'), + 'Porta On/Off', + use('Porta Time').if_parameter('Porta On/Off').has_value('1'), + use('Porta Legato').if_parameter('Porta On/Off').has_value('1'), + use('Porta Prop').if_parameter('Porta On/Off').has_value('1'))}), + ('Global', {PARAMETERS_KEY: ('Octave', + 'Semitone', + 'Fine Tune', + 'Voices', + 'PB Depth', + 'Stretch', + 'Error', + 'Key Priority')}), + ('Filt. Env.', {PARAMETERS_KEY: ('FEG On/Off', + use('FEG Attack').if_parameter('FEG On/Off').has_value('1'), + use('FEG Decay').if_parameter('FEG On/Off').has_value('1'), + use('FEG Sustain').if_parameter('FEG On/Off').has_value('1'), + use('FEG Release').if_parameter('FEG On/Off').has_value('1'), + use('FEG Att < Vel').if_parameter('FEG On/Off').has_value('1'), + use('FEG < Vel').if_parameter('FEG On/Off').has_value('1'), + '')}), + ('Excitator Mod.', {PARAMETERS_KEY: (use('Exc Prot < Vel').if_parameter('Exc On/Off').has_value('1'), + use('Exc Prot < Key').if_parameter('Exc On/Off').has_value('1'), + use('Exc Stiff < Vel').if_parameter('Exc On/Off').has_value('1'), + use('Exc Stiff < Key').if_parameter('Exc On/Off').has_value('1'), + use('Exc Vel < Vel').if_parameter('Exc On/Off').has_value('1'), + use('Exc Vel < Key').if_parameter('Exc On/Off').has_value('1'), + use('E Pos < Vel').if_parameter('Exc On/Off').has_value('1'), + use('E Pos < Key').if_parameter('Exc On/Off').has_value('1'))}), + ('Mass Mod.', {PARAMETERS_KEY: (use('D Mass < Key').if_parameter('Damper On').has_value('1'), + use('D Stiff < Key').if_parameter('Damper On').has_value('1'), + use('D Pos < Key').if_parameter('Damper On').has_value('1'), + use('D Pos < Vel').if_parameter('Damper On').has_value('1'), + use('Damper Gated').if_parameter('Damper On').has_value('1'), + use('').if_parameter('Damper On').has_value('0').else_use('D Velo < Key').if_parameter('Damper Gated').has_value('1').else_use(''), + '', + '')}))), + 'MidiArpeggiator': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Style', + use('Synced Rate').if_parameter('Sync On').has_value('on').else_use('Free Rate'), + 'Gate', + 'Offset', + 'Hold On', + 'Tranpose Key', + 'Transp. Steps', + 'Transp. Dist.')}), ('Rhythm', {PARAMETERS_KEY: ('Sync On', + use('Synced Rate').if_parameter('Sync On').has_value('on').else_use('Free Rate'), + use('Groove').if_parameter('Sync On').has_value('on'), + 'Offset', + 'Repeats', + 'Gate', + 'Retrigger Mode', + use('Ret. Interval').if_parameter('Retrigger Mode').has_value('Beat'))}), ('Pitch/Vel.', {PARAMETERS_KEY: ('Tranpose Mode', + use('').if_parameter('Tranpose Mode').has_value('Shift').else_use('Tranpose Key'), + use('').if_parameter('Tranpose Mode').has_value('Shift').else_use('Transp. Steps'), + use('').if_parameter('Tranpose Mode').has_value('Shift').else_use('Transp. Dist.'), + 'Velocity On', + use('Vel. Retrigger').if_parameter('Velocity On').has_value('on'), + use('Velocity Decay').if_parameter('Velocity On').has_value('on'), + use('Velocity Target').if_parameter('Velocity On').has_value('on'))}))), + 'MidiChord': IndexedDict((('Shift', {PARAMETERS_KEY: ('Shift1', + 'Shift2', + 'Shift3', + 'Shift4', + 'Shift5', + 'Shift6', + '', + '')}), ('Velocity', {PARAMETERS_KEY: ('Velocity1', + 'Velocity2', + 'Velocity3', + 'Velocity4', + 'Velocity5', + 'Velocity6', + '', + '')}))), + 'MidiNoteLength': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Trigger Mode', + 'Sync On', + use('Synced Length').if_parameter('Sync On').has_value('on').else_use('Time Length'), + 'Gate', + use('On/Off-Balance').if_parameter('Trigger Mode').has_value('on'), + use('Decay Time').if_parameter('Trigger Mode').has_value('on'), + use('Decay Key Scale').if_parameter('Trigger Mode').has_value('on'), + '')}),)), + 'MidiPitcher': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Pitch', + 'Range', + 'Lowest', + '', + '', + '', + '', + '')}),)), + 'MidiRandom': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Chance', + 'Choices', + 'Mode', + 'Scale', + 'Sign', + '', + '', + '')}),)), + 'MidiScale': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Base', + 'Transpose', + 'Range', + 'Lowest', + 'Fold', + '', + '', + '')}),)), + 'MidiVelocity': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Mode', + use('').if_parameter('Mode').has_value('Fixed').else_use('Drive'), + use('').if_parameter('Mode').has_value('Fixed').else_use('Compand'), + 'Out Hi', + use('').if_parameter('Mode').has_value('Fixed').else_use('Out Low'), + use('').if_parameter('Mode').has_value('Fixed').else_use('Range'), + use('').if_parameter('Mode').has_value('Fixed').else_use('Lowest'), + 'Random')}),)), + 'Amp': IndexedDict((('Global', {PARAMETERS_KEY: ('Amp Type', + 'Bass', + 'Middle', + 'Treble', + 'Presence', + 'Gain', + 'Volume', + 'Dry/Wet')}), ('Dual/Mono', {PARAMETERS_KEY: ('Dual Mono', + '', + '', + '', + '', + '', + '', + '')}))), + 'AutoFilter': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('Filter Type').if_parameter('Filter Type').is_available(True).else_use('Filter Type (Legacy)'), + use('Frequency'), + use('Resonance').if_parameter('Resonance').is_available(True).else_use('Resonance (Legacy)'), + use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Lowpass').else_use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Highpass').else_use('Filter Circuit - BP/NO/Morph'), + use('Morph').if_parameter('Filter Type').has_value('Morph').else_use('').if_parameter('Filter Type').has_value('Lowpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Highpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Bandpass').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Notch').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('Drive').if_parameter('Drive').is_available(True), + 'LFO Amount', + 'LFO Sync', + use('LFO Frequency').if_parameter('LFO Sync').has_value('Free').else_use('LFO Sync Rate'))}), + ('Envelope', {PARAMETERS_KEY: (use('Filter Type').if_parameter('Filter Type').is_available(True).else_use('Filter Type (Legacy)'), + use('Frequency'), + use('Resonance').if_parameter('Resonance').is_available(True).else_use('Resonance (Legacy)'), + use('Slope').if_parameter('Slope').is_available(True), + use('Morph').if_parameter('Filter Type').has_value('Morph').else_use('').if_parameter('Filter Type').has_value('Lowpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Highpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Bandpass').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Notch').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('Drive').if_parameter('Drive').is_available(True), + 'Env. Attack', + 'Env. Release', + 'Env. Modulation')}), + ('LFO', {PARAMETERS_KEY: ('LFO Amount', + 'LFO Waveform', + 'LFO Sync', + use('LFO Frequency').if_parameter('LFO Sync').has_value('Free').else_use('LFO Sync Rate'), + use('').if_parameter('LFO Waveform').has_value('S&H Mono').else_use('LFO Offset').if_parameter('LFO Sync').has_value('Sync').else_use('LFO Stereo Mode'), + use('').if_parameter('LFO Waveform').has_value('S&H Mono').else_use('LFO Phase').if_parameter('LFO Sync').has_value('Sync').else_use('LFO Phase').if_parameter('LFO Stereo Mode').has_value('Phase').else_use('LFO Spin'), + 'LFO Quantize On', + use('LFO Quantize Rate').if_parameter('LFO Quantize On').has_value('on'))}), + ('Sidechain', {PARAMETERS_KEY: ('Ext. In On', + use('Ext. In Mix').if_parameter('Ext. In On').has_value('on'), + use('Ext. In Gain').if_parameter('Ext. In On').has_value('on'), + '', + '', + '', + '', + '')}))), + 'AutoPan': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Amount', + 'Shape', + 'Invert', + 'Waveform', + 'LFO Type', + use('Sync Rate').if_parameter('LFO Type').has_value('Beats').else_use('Frequency'), + use('').if_parameter('Waveform').has_value('S&H Width').else_use('Stereo Mode').if_parameter('LFO Type').has_value('Frequency').else_use('Offset'), + use('Width (Random)').if_parameter('Waveform').has_value('S&H Width').else_use('Phase').if_parameter('LFO Type').has_value('Beats').else_use('Spin').if_parameter('Stereo Mode').has_value('Spin').else_use('Phase'))}),)), + 'BeatRepeat': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Grid', + 'Interval', + 'Offset', + 'Gate', + 'Pitch', + 'Pitch Decay', + 'Variation', + 'Chance')}), ('Filt/Mix', {PARAMETERS_KEY: ('Filter On', + use('Filter Freq').if_parameter('Filter On').has_value('on'), + use('Filter Width').if_parameter('Filter On').has_value('on'), + '', + 'Mix Type', + 'Volume', + 'Decay', + 'Chance')}), ('Repeat Rate', {PARAMETERS_KEY: ('Repeat', + 'Interval', + 'Offset', + 'Gate', + 'Grid', + 'Block Triplets', + 'Variation', + 'Variation Type')}))), + 'Cabinet': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Cabinet Type', + 'Microphone Type', + 'Microphone Position', + 'Dual Mono', + '', + '', + '', + 'Dry/Wet')}),)), + 'Chorus': IndexedDict((('Chorus', {PARAMETERS_KEY: ('LFO Amount', + 'LFO Rate', + 'Delay 1 Time', + 'Delay 1 HiPass', + 'Delay 2 Mode', + use('').if_parameter('Delay 2 Mode').has_value('off').else_use('Delay 2 Time'), + 'Feedback', + 'Dry/Wet')}), ('Other', {PARAMETERS_KEY: ('LFO Extend On', + 'Polarity', + 'Link On', + '', + '', + '', + '', + '')}))), + 'Compressor2': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Threshold', + use('Expansion Ratio').if_parameter('Model').has_value('Expand').else_use('Ratio'), + 'Model', + 'Knee', + 'Attack', + use('Release').if_parameter('Auto Release On/Off').has_value('off').else_use('Makeup').if_parameter('Ext. In On').has_value('off'), + 'Dry/Wet', + 'Output Gain')}), ('Sidechain', {PARAMETERS_KEY: ('Ext. In On', + use('Ext. In Gain').if_parameter('Ext. In On').has_value('on'), + use('Ext. In Mix').if_parameter('Ext. In On').has_value('on'), + 'Side Listen', + 'EQ On', + use('EQ Mode').if_parameter('EQ On').has_value('on'), + use('EQ Freq').if_parameter('EQ On').has_value('on'), + use('').if_parameter('EQ On').has_value('off').else_use('EQ Gain').if_parameter('EQ Mode').has_value('Low Shelf').else_use('EQ Gain').if_parameter('EQ Mode').has_value('High Shelf').else_use('EQ Gain').if_parameter('EQ Mode').has_value('Bell').else_use('EQ Q'))}), ('Global', {PARAMETERS_KEY: ('Auto Release On/Off', + 'Env Mode', + use('Makeup').if_parameter('Ext. In On').has_value('off'), + 'LookAhead', + '', + '', + 'Dry/Wet', + 'Output Gain')}))), + 'Corpus': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Resonance Type', + use('').if_parameter('Resonance Type').has_value('Tube').else_use('').if_parameter('Resonance Type').has_value('Pipe').else_use('Brightness'), + 'Decay', + use('Radius').if_parameter('Resonance Type').has_value('Tube').else_use('Radius').if_parameter('Resonance Type').has_value('Pipe').else_use('Material'), + use('').if_parameter('Resonance Type').has_value('Tube').else_use('Opening').if_parameter('Resonance Type').has_value('Pipe').else_use('Inharmonics'), + use('Ratio').if_parameter('Resonance Type').has_value('Plate').else_use('Ratio').if_parameter('Resonance Type').has_value('Membrane').else_use(''), + use('Transpose').if_parameter('MIDI Frequency').has_value('1').else_use('Tune'), + 'Dry Wet')}), + ('Body', {PARAMETERS_KEY: ('Resonance Type', + use('Ratio').if_parameter('Resonance Type').has_value('Plate').else_use('Ratio').if_parameter('Resonance Type').has_value('Membrane'), + 'Decay', + use('Radius').if_parameter('Resonance Type').has_value('Tube').else_use('Radius').if_parameter('Resonance Type').has_value('Pipe').else_use('Material'), + use('').if_parameter('Resonance Type').has_value('Tube').else_use('Opening').if_parameter('Resonance Type').has_value('Pipe').else_use('Inharmonics'), + use('').if_parameter('Resonance Type').has_value('Tube').else_use('').if_parameter('Resonance Type').has_value('Pipe').else_use('Listening L'), + use('').if_parameter('Resonance Type').has_value('Tube').else_use('').if_parameter('Resonance Type').has_value('Pipe').else_use('Listening R'), + use('').if_parameter('Resonance Type').has_value('Tube').else_use('').if_parameter('Resonance Type').has_value('Pipe').else_use('Hit'))}), + ('LFO', {PARAMETERS_KEY: ('LFO On/Off', + use('LFO Shape').if_parameter('LFO On/Off').has_value('1'), + use('LFO Amount').if_parameter('LFO On/Off').has_value('1'), + use('LFO Sync').if_parameter('LFO On/Off').has_value('1'), + use('').if_parameter('LFO On/Off').has_value('0').else_use('LFO Rate').if_parameter('LFO Sync').has_value('Free').else_use('LFO Sync Rate'), + use('').if_parameter('LFO On/Off').has_value('0').else_use('LFO Stereo Mode').if_parameter('LFO Sync').has_value('Free').else_use('Offset'), + use('').if_parameter('LFO On/Off').has_value('0').else_use('Phase').if_parameter('LFO Sync').has_value('Sync').else_use('Spin').if_parameter('LFO Stereo Mode').has_value('Spin'), + '')}), + ('Tune & Sidechain', {PARAMETERS_KEY: ('MIDI Frequency', + 'MIDI Mode', + use('Transpose').if_parameter('MIDI Frequency').has_value('1').else_use('Tune'), + use('Fine').if_parameter('MIDI Frequency').has_value('1'), + 'Spread', + use('').if_parameter('Resonance Type').has_value('Tube').else_use('').if_parameter('Resonance Type').has_value('Pipe').else_use('Brightness'), + 'Note Off', + use('Off Decay').if_parameter('Note Off').has_value('1'))}), + ('Filter & Mix', {PARAMETERS_KEY: ('Filter On/Off', + use('Mid Freq').if_parameter('Filter On/Off').has_value('1'), + use('Width').if_parameter('Filter On/Off').has_value('1'), + use('').if_parameter('Resonance Type').has_value('Tube').else_use('').if_parameter('Resonance Type').has_value('Pipe').else_use('Resonator Quality'), + 'Bleed', + 'Gain', + 'Dry Wet', + '')}))), + 'Tube': IndexedDict((('Character', {PARAMETERS_KEY: ('Drive', + 'Tube Type', + 'Bias', + 'Tone', + 'Attack', + 'Release', + 'Envelope', + 'Dry/Wet')}), ('Output', {PARAMETERS_KEY: ('', + '', + '', + '', + '', + '', + 'Output', + 'Dry/Wet')}))), + 'Eq8': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('1 Frequency A').if_parameter('1 Filter On A').has_value('on'), + use('').if_parameter('1 Filter On A').has_value('off').else_use('1 Gain A').if_parameter('1 Filter Type A').has_value('Low Shelf').else_use('1 Gain A').if_parameter('1 Filter Type A').has_value('Bell').else_use('1 Gain A').if_parameter('1 Filter Type A').has_value('High Shelf').else_use('1 Resonance A'), + use('2 Frequency A').if_parameter('2 Filter On A').has_value('on'), + use('').if_parameter('2 Filter On A').has_value('off').else_use('2 Gain A').if_parameter('2 Filter Type A').has_value('Low Shelf').else_use('2 Gain A').if_parameter('2 Filter Type A').has_value('Bell').else_use('2 Gain A').if_parameter('2 Filter Type A').has_value('High Shelf').else_use('2 Resonance A'), + use('3 Frequency A').if_parameter('3 Filter On A').has_value('on'), + use('').if_parameter('3 Filter On A').has_value('off').else_use('3 Gain A').if_parameter('3 Filter Type A').has_value('Low Shelf').else_use('3 Gain A').if_parameter('3 Filter Type A').has_value('Bell').else_use('3 Gain A').if_parameter('3 Filter Type A').has_value('High Shelf').else_use('3 Resonance A'), + use('4 Frequency A').if_parameter('4 Filter On A').has_value('on'), + use('').if_parameter('4 Filter On A').has_value('off').else_use('4 Gain A').if_parameter('4 Filter Type A').has_value('Low Shelf').else_use('4 Gain A').if_parameter('4 Filter Type A').has_value('Bell').else_use('4 Gain A').if_parameter('4 Filter Type A').has_value('High Shelf').else_use('4 Resonance A'))}), + ('EQ Band 1', {PARAMETERS_KEY: ('1 Filter On A', + use('1 Filter Type A').if_parameter('1 Filter On A').has_value('on'), + use('1 Frequency A').if_parameter('1 Filter On A').has_value('on'), + use('1 Gain A').if_parameter('1 Filter On A').has_value('on'), + use('1 Resonance A').if_parameter('1 Filter On A').has_value('on'), + 'Adaptive Q', + 'Scale', + 'Output Gain')}), + ('EQ Band 2', {PARAMETERS_KEY: ('2 Filter On A', + use('2 Filter Type A').if_parameter('2 Filter On A').has_value('on'), + use('2 Frequency A').if_parameter('2 Filter On A').has_value('on'), + use('2 Gain A').if_parameter('2 Filter On A').has_value('on'), + use('2 Resonance A').if_parameter('2 Filter On A').has_value('on'), + 'Adaptive Q', + 'Scale', + 'Output Gain')}), + ('EQ Band 3', {PARAMETERS_KEY: ('3 Filter On A', + use('3 Filter Type A').if_parameter('3 Filter On A').has_value('on'), + use('3 Frequency A').if_parameter('3 Filter On A').has_value('on'), + use('3 Gain A').if_parameter('3 Filter On A').has_value('on'), + use('3 Resonance A').if_parameter('3 Filter On A').has_value('on'), + 'Adaptive Q', + 'Scale', + 'Output Gain')}), + ('EQ Band 4', {PARAMETERS_KEY: ('4 Filter On A', + use('4 Filter Type A').if_parameter('4 Filter On A').has_value('on'), + use('4 Frequency A').if_parameter('4 Filter On A').has_value('on'), + use('4 Gain A').if_parameter('4 Filter On A').has_value('on'), + use('4 Resonance A').if_parameter('4 Filter On A').has_value('on'), + 'Adaptive Q', + 'Scale', + 'Output Gain')}), + ('EQ Band 5', {PARAMETERS_KEY: ('5 Filter On A', + use('5 Filter Type A').if_parameter('5 Filter On A').has_value('on'), + use('5 Frequency A').if_parameter('5 Filter On A').has_value('on'), + use('5 Gain A').if_parameter('5 Filter On A').has_value('on'), + use('5 Resonance A').if_parameter('5 Filter On A').has_value('on'), + 'Adaptive Q', + 'Scale', + 'Output Gain')}), + ('EQ Band 6', {PARAMETERS_KEY: ('6 Filter On A', + use('6 Filter Type A').if_parameter('6 Filter On A').has_value('on'), + use('6 Frequency A').if_parameter('6 Filter On A').has_value('on'), + use('6 Gain A').if_parameter('6 Filter On A').has_value('on'), + use('6 Resonance A').if_parameter('6 Filter On A').has_value('on'), + 'Adaptive Q', + 'Scale', + 'Output Gain')}), + ('EQ Band 7', {PARAMETERS_KEY: ('7 Filter On A', + use('7 Filter Type A').if_parameter('7 Filter On A').has_value('on'), + use('7 Frequency A').if_parameter('7 Filter On A').has_value('on'), + use('7 Gain A').if_parameter('7 Filter On A').has_value('on'), + use('7 Resonance A').if_parameter('7 Filter On A').has_value('on'), + 'Adaptive Q', + 'Scale', + 'Output Gain')}), + ('EQ Band 8', {PARAMETERS_KEY: ('8 Filter On A', + use('8 Filter Type A').if_parameter('8 Filter On A').has_value('on'), + use('8 Frequency A').if_parameter('8 Filter On A').has_value('on'), + use('8 Gain A').if_parameter('8 Filter On A').has_value('on'), + use('8 Resonance A').if_parameter('8 Filter On A').has_value('on'), + 'Adaptive Q', + 'Scale', + 'Output Gain')}), + ('8 x Frequency', {PARAMETERS_KEY: (use('1 Frequency A').if_parameter('1 Filter On A').has_value('on'), + use('2 Frequency A').if_parameter('2 Filter On A').has_value('on'), + use('3 Frequency A').if_parameter('3 Filter On A').has_value('on'), + use('4 Frequency A').if_parameter('4 Filter On A').has_value('on'), + use('5 Frequency A').if_parameter('5 Filter On A').has_value('on'), + use('6 Frequency A').if_parameter('6 Filter On A').has_value('on'), + use('7 Frequency A').if_parameter('7 Filter On A').has_value('on'), + use('8 Frequency A').if_parameter('8 Filter On A').has_value('on'))}), + ('8 x Gain', {PARAMETERS_KEY: (use('').if_parameter('1 Filter On A').has_value('off').else_use('1 Gain A').if_parameter('1 Filter Type A').has_value('Low Shelf').else_use('1 Gain A').if_parameter('1 Filter Type A').has_value('Bell').else_use('1 Gain A').if_parameter('1 Filter Type A').has_value('High Shelf').else_use(''), + use('').if_parameter('2 Filter On A').has_value('off').else_use('2 Gain A').if_parameter('2 Filter Type A').has_value('Low Shelf').else_use('2 Gain A').if_parameter('2 Filter Type A').has_value('Bell').else_use('2 Gain A').if_parameter('2 Filter Type A').has_value('High Shelf').else_use(''), + use('').if_parameter('3 Filter On A').has_value('off').else_use('3 Gain A').if_parameter('3 Filter Type A').has_value('Low Shelf').else_use('3 Gain A').if_parameter('3 Filter Type A').has_value('Bell').else_use('3 Gain A').if_parameter('3 Filter Type A').has_value('High Shelf').else_use(''), + use('').if_parameter('4 Filter On A').has_value('off').else_use('4 Gain A').if_parameter('4 Filter Type A').has_value('Low Shelf').else_use('4 Gain A').if_parameter('4 Filter Type A').has_value('Bell').else_use('4 Gain A').if_parameter('4 Filter Type A').has_value('High Shelf').else_use(''), + use('').if_parameter('5 Filter On A').has_value('off').else_use('5 Gain A').if_parameter('5 Filter Type A').has_value('Low Shelf').else_use('5 Gain A').if_parameter('5 Filter Type A').has_value('Bell').else_use('5 Gain A').if_parameter('5 Filter Type A').has_value('High Shelf').else_use(''), + use('').if_parameter('6 Filter On A').has_value('off').else_use('6 Gain A').if_parameter('6 Filter Type A').has_value('Low Shelf').else_use('6 Gain A').if_parameter('6 Filter Type A').has_value('Bell').else_use('6 Gain A').if_parameter('6 Filter Type A').has_value('High Shelf').else_use(''), + use('').if_parameter('7 Filter On A').has_value('off').else_use('7 Gain A').if_parameter('7 Filter Type A').has_value('Low Shelf').else_use('7 Gain A').if_parameter('7 Filter Type A').has_value('Bell').else_use('7 Gain A').if_parameter('7 Filter Type A').has_value('High Shelf').else_use(''), + use('').if_parameter('8 Filter On A').has_value('off').else_use('8 Gain A').if_parameter('8 Filter Type A').has_value('Low Shelf').else_use('8 Gain A').if_parameter('8 Filter Type A').has_value('Bell').else_use('8 Gain A').if_parameter('8 Filter Type A').has_value('High Shelf').else_use(''))}), + ('8 x Resonance', {PARAMETERS_KEY: ('1 Resonance A', + '2 Resonance A', + '3 Resonance A', + '4 Resonance A', + '5 Resonance A', + '6 Resonance A', + '7 Resonance A', + '8 Resonance A')}))), + 'FilterEQ3': IndexedDict((('EQ', {PARAMETERS_KEY: ('LowOn', + 'MidOn', + 'HighOn', + use('GainLo').if_parameter('LowOn').has_value('on'), + use('GainMid').if_parameter('MidOn').has_value('on'), + use('GainHi').if_parameter('HighOn').has_value('on'), + 'FreqLo', + 'FreqHi')}), ('Slope', {PARAMETERS_KEY: ('Slope', + '', + '', + '', + '', + '', + '', + '')}))), + 'Erosion': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Mode', + 'Frequency', + use('').if_parameter('Mode').has_value('Sine').else_use('Width'), + 'Amount', + '', + '', + '', + '')}),)), + 'ProxyAudioEffectDevice': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Input Gain', + 'Output Gain', + 'Dry/Wet', + '', + '', + '', + '', + '')}),)), + 'FilterDelay': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('2 Filter Freq').if_parameter('2 Input On').has_value('on'), + use('2 Filter Width').if_parameter('2 Input On').has_value('on'), + use('2 Delay Mode').if_parameter('2 Input On').has_value('on'), + use('').if_parameter('2 Input On').has_value('off').else_use('2 Time Delay').if_parameter('2 Delay Mode').has_value('off').else_use('2 Beat Delay'), + use('2 Feedback').if_parameter('2 Input On').has_value('on'), + use('1 Volume').if_parameter('1 Input On').has_value('on').else_use('2 Pan'), + use('2 Volume').if_parameter('2 Input On').has_value('on'), + use('3 Volume').if_parameter('3 Input On').has_value('on').else_use('Dry'))}), + ('L Filter', {PARAMETERS_KEY: ('1 Input On', + use('1 Filter Freq').if_parameter('1 Input On').has_value('on'), + use('1 Filter Width').if_parameter('1 Input On').has_value('on'), + use('1 Feedback').if_parameter('1 Input On').has_value('on'), + use('1 Delay Mode').if_parameter('1 Input On').has_value('on'), + use('').if_parameter('1 Input On').has_value('off').else_use('1 Time Delay').if_parameter('1 Delay Mode').has_value('off').else_use('1 Beat Delay'), + use('').if_parameter('1 Input On').has_value('off').else_use('1 Beat Swing').if_parameter('1 Delay Mode').has_value('on').else_use(''), + use('1 Volume').if_parameter('1 Input On').has_value('off'))}), + ('L+R Filter', {PARAMETERS_KEY: ('2 Input On', + use('2 Filter Freq').if_parameter('2 Input On').has_value('on'), + use('2 Filter Width').if_parameter('2 Input On').has_value('on'), + use('2 Feedback').if_parameter('2 Input On').has_value('on'), + use('2 Delay Mode').if_parameter('2 Input On').has_value('on'), + use('').if_parameter('2 Input On').has_value('off').else_use('2 Time Delay').if_parameter('2 Delay Mode').has_value('off').else_use('2 Beat Delay'), + use('').if_parameter('2 Input On').has_value('off').else_use('2 Beat Swing').if_parameter('2 Delay Mode').has_value('on').else_use(''), + use('2 Volume').if_parameter('2 Input On').has_value('on'))}), + ('R Filter', {PARAMETERS_KEY: ('3 Input On', + use('3 Filter Freq').if_parameter('3 Input On').has_value('on'), + use('3 Filter Width').if_parameter('3 Input On').has_value('on'), + use('3 Feedback').if_parameter('3 Input On').has_value('on'), + use('3 Delay Mode').if_parameter('3 Input On').has_value('on'), + use('').if_parameter('3 Input On').has_value('off').else_use('3 Time Delay').if_parameter('3 Delay Mode').has_value('off').else_use('3 Beat Delay'), + use('').if_parameter('3 Input On').has_value('off').else_use('3 Beat Swing').if_parameter('3 Delay Mode').has_value('on').else_use(''), + use('3 Volume').if_parameter('3 Input On').has_value('on'))}), + ('Mix', {PARAMETERS_KEY: (use('1 Pan').if_parameter('1 Input On').has_value('on'), + use('2 Pan').if_parameter('2 Input On').has_value('on'), + use('3 Pan').if_parameter('3 Input On').has_value('on'), + '', + use('1 Volume').if_parameter('1 Input On').has_value('on'), + use('2 Volume').if_parameter('2 Input On').has_value('on'), + use('3 Volume').if_parameter('3 Input On').has_value('on'), + 'Dry')}))), + 'Flanger': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('LFO Amount', + 'Sync', + use('Frequency').if_parameter('Sync').has_value('Free').else_use('Sync Rate'), + 'Delay Time', + 'Hi Pass', + 'Env. Modulation', + 'Feedback', + 'Dry/Wet')}), ('Envelope', {PARAMETERS_KEY: ('Env. Attack', + 'Env. Release', + 'Env. Modulation', + 'Hi Pass', + 'Delay Time', + 'Feedback', + 'Polarity', + 'Dry/Wet')}), ('LFO / S&H', {PARAMETERS_KEY: ('LFO Amount', + 'LFO Waveform', + 'Sync', + use('Frequency').if_parameter('Sync').has_value('Free').else_use('Sync Rate'), + use('').if_parameter('LFO Waveform').has_value('S&H Width').else_use('LFO Stereo Mode').if_parameter('Sync').has_value('Free').else_use('LFO Offset'), + use('LFO Width (Random)').if_parameter('LFO Waveform').has_value('S&H Width').else_use('LFO Phase').if_parameter('Sync').has_value('Sync').else_use('LFO Phase').if_parameter('LFO Stereo Mode').has_value('Phase').else_use('LFO Spin'), + '', + '')}))), + 'FrequencyShifter': IndexedDict((('FreqDrive', {PARAMETERS_KEY: ('Mode', + use('Ring Mod Frequency').if_parameter('Mode').has_value('Ring Modulation').else_use('Coarse'), + 'Wide', + use('Fine').if_parameter('Wide').has_value('0').else_use('Spread'), + 'Drive On/Off', + use('Drive').if_parameter('Drive On/Off').has_value('1'), + 'LFO Amount', + 'Dry/Wet')}), ('LFO / S&H', {PARAMETERS_KEY: ('LFO Amount', + 'LFO Waveform', + 'Sync', + use('LFO Frequency').if_parameter('Sync').has_value('Free').else_use('Sync Rate'), + use('').if_parameter('LFO Waveform').has_value('S&H Width').else_use('LFO Stereo Mode').if_parameter('Sync').has_value('Free').else_use('LFO Offset'), + use('LFO Width (Random)').if_parameter('LFO Waveform').has_value('S&H Width').else_use('LFO Phase').if_parameter('Sync').has_value('Sync').else_use('LFO Phase').if_parameter('LFO Stereo Mode').has_value('Phase').else_use('LFO Spin'), + '', + '')}))), + 'Gate': IndexedDict((('Gate', {PARAMETERS_KEY: ('Threshold', + 'Return', + 'FlipMode', + 'LookAhead', + 'Attack', + 'Hold', + 'Release', + 'Floor')}), ('Sidechain', {PARAMETERS_KEY: ('Ext. In On', + use('Ext. In Gain').if_parameter('Ext. In On').has_value('on'), + use('Ext. In Mix').if_parameter('Ext. In On').has_value('on'), + 'Side Listen', + 'EQ On', + use('EQ Mode').if_parameter('EQ On').has_value('on'), + use('EQ Freq').if_parameter('EQ On').has_value('on'), + use('').if_parameter('EQ On').has_value('off').else_use('EQ Gain').if_parameter('EQ Mode').has_value('Low Shelf').else_use('EQ Gain').if_parameter('EQ Mode').has_value('High Shelf').else_use('EQ Gain').if_parameter('EQ Mode').has_value('Bell').else_use('EQ Q'))}))), + 'GlueCompressor': IndexedDict((('Compression', {PARAMETERS_KEY: ('Threshold', + 'Ratio', + 'Attack', + 'Release', + 'Peak Clip In', + 'Range', + 'Makeup', + 'Dry/Wet')}), ('Sidechain', {PARAMETERS_KEY: ('Ext. In On', + use('Ext. In Gain').if_parameter('Ext. In On').has_value('on'), + use('Ext. In Mix').if_parameter('Ext. In On').has_value('on'), + '', + 'EQ On', + use('EQ Mode').if_parameter('EQ On').has_value('on'), + use('EQ Freq').if_parameter('EQ On').has_value('on'), + use('').if_parameter('EQ On').has_value('off').else_use('EQ Gain').if_parameter('EQ Mode').has_value('Low Shelf').else_use('EQ Gain').if_parameter('EQ Mode').has_value('High Shelf').else_use('EQ Gain').if_parameter('EQ Mode').has_value('Bell').else_use('EQ Q'))}))), + 'GrainDelay': IndexedDict((('Pitch', {PARAMETERS_KEY: ('Frequency', + 'Pitch', + 'Delay Mode', + use('Time Delay').if_parameter('Delay Mode').has_value('off').else_use('Beat Delay'), + 'Random', + 'Spray', + 'Feedback', + 'DryWet')}), ('Time', {PARAMETERS_KEY: ('Delay Mode', + use('Time Delay').if_parameter('Delay Mode').has_value('off').else_use('Beat Delay'), + 'Beat Swing', + 'Feedback', + '', + '', + '', + 'DryWet')}))), + 'Limiter': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Gain', + 'Ceiling', + 'Link Channels', + 'Lookahead', + 'Auto', + use('Release time').if_parameter('Auto').has_value('off'), + '', + '')}),)), + 'Looper': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('State', + 'Speed', + 'Reverse', + 'Quantization', + 'Monitor', + 'Song Control', + 'Tempo Control', + 'Feedback')}),)), + 'MultibandDynamics': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('Above Threshold (Low)').if_parameter('Band Activator (Low)').has_value('on'), + use('Above Ratio (Low)').if_parameter('Band Activator (Low)').has_value('on'), + use('Above Threshold (Mid)').if_parameter('Band Activator (Mid)').has_value('on'), + use('Above Ratio (Mid)').if_parameter('Band Activator (Mid)').has_value('on'), + use('Above Threshold (High)').if_parameter('Band Activator (High)').has_value('on'), + use('Above Ratio (High)').if_parameter('Band Activator (High)').has_value('on'), + 'Master Output', + 'Amount')}), + ('Low Band', {PARAMETERS_KEY: ('Band Activator (Low)', + use('Input Gain (Low)').if_parameter('Band Activator (Low)').has_value('on'), + use('Below Threshold (Low)').if_parameter('Band Activator (Low)').has_value('on'), + use('Below Ratio (Low)').if_parameter('Band Activator (Low)').has_value('on'), + use('Above Threshold (Low)').if_parameter('Band Activator (Low)').has_value('on'), + use('Above Ratio (Low)').if_parameter('Band Activator (Low)').has_value('on'), + use('Attack Time (Low)').if_parameter('Band Activator (Low)').has_value('on'), + use('Release Time (Low)').if_parameter('Band Activator (Low)').has_value('on'))}), + ('Mid Band', {PARAMETERS_KEY: ('Band Activator (Mid)', + use('Input Gain (Mid)').if_parameter('Band Activator (Mid)').has_value('on'), + use('Below Threshold (Mid)').if_parameter('Band Activator (Mid)').has_value('on'), + use('Below Ratio (Mid)').if_parameter('Band Activator (Mid)').has_value('off'), + use('Above Threshold (Mid)').if_parameter('Band Activator (Mid)').has_value('on'), + use('Above Ratio (Mid)').if_parameter('Band Activator (Mid)').has_value('on'), + use('Attack Time (Mid)').if_parameter('Band Activator (Mid)').has_value('on'), + use('Release Time (Mid)').if_parameter('Band Activator (Mid)').has_value('on'))}), + ('High Band', {PARAMETERS_KEY: ('Band Activator (High)', + use('Input Gain (High)').if_parameter('Band Activator (High)').has_value('on'), + use('Below Threshold (High)').if_parameter('Band Activator (High)').has_value('on'), + use('Below Ratio (High)').if_parameter('Band Activator (High)').has_value('on'), + use('Above Threshold (High)').if_parameter('Band Activator (High)').has_value('on'), + use('Above Ratio (High)').if_parameter('Band Activator (High)').has_value('on'), + use('Attack Time (High)').if_parameter('Band Activator (High)').has_value('on'), + use('Release Time (High)').if_parameter('Band Activator (High)').has_value('on'))}), + ('Mix & Split', {PARAMETERS_KEY: (use('Output Gain (Low)').if_parameter('Band Activator (Low)').has_value('on'), + 'Low-Mid Crossover', + use('Output Gain (Mid)').if_parameter('Band Activator (Mid)').has_value('on'), + 'Mid-High Crossover', + use('Output Gain (High)').if_parameter('Band Activator (High)').has_value('on'), + 'Peak/RMS Mode', + 'Amount', + 'Master Output')}), + ('Sidechain', {PARAMETERS_KEY: ('Ext. In On', + use('Ext. In Mix').if_parameter('Ext. In On').has_value('on'), + use('Ext. In Gain').if_parameter('Ext. In On').has_value('on'), + '', + 'Time Scaling', + 'Soft Knee On/Off', + '', + '')}))), + 'Overdrive': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Filter Freq', + 'Filter Width', + 'Drive', + 'Tone', + 'Preserve Dynamics', + '', + '', + 'Dry/Wet')}),)), + 'Phaser': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Poles', + 'Frequency', + 'Feedback', + 'Env. Modulation', + 'LFO Amount', + 'LFO Sync', + use('LFO Frequency').if_parameter('LFO Sync').has_value('Free').else_use('LFO Sync Rate'), + 'Dry/Wet')}), ('Envelope', {PARAMETERS_KEY: ('Poles', + 'Type', + use('').if_parameter('Type').has_value('Space').else_use('Color'), + 'Frequency', + 'Feedback', + 'Env. Modulation', + 'Env. Attack', + 'Env. Release')}), ('LFO', {PARAMETERS_KEY: ('LFO Amount', + 'LFO Waveform', + 'LFO Sync', + use('LFO Frequency').if_parameter('LFO Sync').has_value('Free').else_use('LFO Sync Rate'), + use('').if_parameter('LFO Waveform').has_value('S&H Width').else_use('LFO Stereo Mode').if_parameter('LFO Sync').has_value('Free').else_use('LFO Offset'), + use('LFO Width (Random)').if_parameter('LFO Waveform').has_value('S&H Width').else_use('LFO Phase').if_parameter('LFO Sync').has_value('Sync').else_use('LFO Phase').if_parameter('LFO Stereo Mode').has_value('Phase').else_use('LFO Spin'), + '', + '')}))), + 'PingPongDelay': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Delay Mode', + use('Beat Delay').if_parameter('Delay Mode').has_value('Sync').else_use('Time Delay'), + use('Beat Swing').if_parameter('Delay Mode').has_value('Sync').else_use(''), + 'Freeze', + 'Filter Freq', + 'Filter Width', + 'Feedback', + 'Dry/Wet')}),)), + 'Redux': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Bit On', + use('Bit Depth').if_parameter('Bit On').has_value('on'), + 'Sample Mode', + use('Sample Hard').if_parameter('Sample Mode').has_value('Hard').else_use('Sample Soft'), + '', + '', + '', + '')}),)), + 'Resonator': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: (use('Frequency').if_parameter('Filter On').has_value('on'), + 'Decay', + 'Color', + use('I Gain').if_parameter('I On').has_value('on'), + use('II Gain').if_parameter('II On').has_value('on'), + use('III Gain').if_parameter('III On').has_value('on'), + 'Width', + 'Dry/Wet')}), + ('Global', {PARAMETERS_KEY: ('Mode', + 'Decay', + 'Const', + 'Color', + '', + 'Width', + 'Global Gain', + 'Dry/Wet')}), + ('Filter', {PARAMETERS_KEY: ('Filter On', + use('Frequency').if_parameter('Filter On').has_value('on'), + use('Filter Type').if_parameter('Filter On').has_value('on'), + '', + '', + '', + '', + '')}), + ('Mode I & II', {PARAMETERS_KEY: ('I On', + use('I Note').if_parameter('I On').has_value('on'), + use('I Tune').if_parameter('I On').has_value('on'), + use('I Gain').if_parameter('I On').has_value('on'), + 'II On', + use('II Pitch').if_parameter('II On').has_value('on'), + use('II Tune').if_parameter('II On').has_value('on'), + use('II Gain').if_parameter('II On').has_value('on'))}), + ('Mode III & IV', {PARAMETERS_KEY: ('III On', + use('III Pitch').if_parameter('III On').has_value('on'), + use('III Tune').if_parameter('III On').has_value('on'), + use('III Gain').if_parameter('III On').has_value('on'), + 'IV On', + use('IV Pitch').if_parameter('IV On').has_value('on'), + use('IV Tune').if_parameter('IV On').has_value('on'), + use('IV Gain').if_parameter('IV On').has_value('on'))}), + ('Mode V', {PARAMETERS_KEY: ('V On', + use('V Pitch').if_parameter('V On').has_value('on'), + use('V Tune').if_parameter('V On').has_value('on'), + use('V Gain').if_parameter('V On').has_value('on'), + '', + '', + '', + '')}), + ('Mix', {PARAMETERS_KEY: (use('I Gain').if_parameter('I On').has_value('on'), + use('II Gain').if_parameter('II On').has_value('on'), + use('III Gain').if_parameter('III On').has_value('on'), + use('IV Gain').if_parameter('IV On').has_value('on'), + use('V Gain').if_parameter('V On').has_value('on'), + '', + '', + '')}), + ('Pitch', {PARAMETERS_KEY: (use('I Note').if_parameter('I On').has_value('on'), + use('II Pitch').if_parameter('II On').has_value('on'), + use('III Pitch').if_parameter('III On').has_value('on'), + use('IV Pitch').if_parameter('IV On').has_value('on'), + use('V Pitch').if_parameter('V On').has_value('on'), + '', + '', + '')}))), + 'Reverb': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('PreDelay', + use('In Filter Freq').if_parameter('In LowCut On').has_value('on').else_use('ER Shape').if_parameter('In HighCut On').has_value('off').else_use('In Filter Freq'), + use('Chorus Amount').if_parameter('Chorus On').has_value('on').else_use('ER Level'), + 'Stereo Image', + 'Room Size', + 'DecayTime', + use('HiShelf Gain').if_parameter('HiShelf On').has_value('on').else_use('Diffuse Level'), + 'Dry/Wet')}), + ('Global', {PARAMETERS_KEY: ('Chorus On', + use('Chorus Rate').if_parameter('Chorus On').has_value('on'), + use('Chorus Amount').if_parameter('Chorus On').has_value('on'), + 'Quality', + 'Freeze On', + 'Flat On', + 'ER Level', + 'Diffuse Level')}), + ('Diffusion Network', {PARAMETERS_KEY: ('HiShelf On', + use('HiShelf Freq').if_parameter('HiShelf On').has_value('on'), + use('HiShelf Gain').if_parameter('HiShelf On').has_value('on'), + 'LowShelf On', + use('LowShelf Freq').if_parameter('LowShelf On').has_value('on'), + use('LowShelf Gain').if_parameter('LowShelf On').has_value('on'), + 'Density', + 'Scale')}), + ('Input/Reflections', {PARAMETERS_KEY: ('In LowCut On', + 'In HighCut On', + use('In Filter Freq').if_parameter('In LowCut On').has_value('on').else_use('').if_parameter('In HighCut On').has_value('off').else_use('In Filter Freq'), + use('In Filter Width').if_parameter('In LowCut On').has_value('on').else_use('').if_parameter('In HighCut On').has_value('off').else_use('In Filter Width'), + 'ER Spin On', + use('ER Spin Rate').if_parameter('ER Spin On').has_value('on'), + use('ER Spin Amount').if_parameter('ER Spin On').has_value('on'), + 'ER Shape')}))), + 'Saturator': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Drive', + 'Type', + 'Color', + use('Base').if_parameter('Color').has_value('on'), + use('Frequency').if_parameter('Color').has_value('on'), + use('Width').if_parameter('Color').has_value('on'), + use('Depth').if_parameter('Color').has_value('on'), + 'Output')}), ('Waveshaper', {PARAMETERS_KEY: ('Type', + use('WS Drive').if_parameter('Type').has_value('Waveshaper'), + use('WS Curve').if_parameter('Type').has_value('Waveshaper'), + use('WS Depth').if_parameter('Type').has_value('Waveshaper'), + use('WS Lin').if_parameter('Type').has_value('Waveshaper'), + use('WS Damp').if_parameter('Type').has_value('Waveshaper'), + use('WS Period').if_parameter('Type').has_value('Waveshaper'), + 'Dry/Wet')}), ('Output', {PARAMETERS_KEY: ('', + '', + '', + '', + '', + 'Soft Clip', + 'Output', + 'Dry/Wet')}))), + 'CrossDelay': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('L Delay Mode', + use('L Beat Delay').if_parameter('L Delay Mode').has_value('on').else_use('L Time Delay'), + use('L Beat Swing').if_parameter('L Delay Mode').has_value('on'), + use('R Delay Mode').if_parameter('Link On').has_value('off'), + use('').if_parameter('Link On').has_value('on').else_use('R Beat Delay').if_parameter('R Delay Mode').has_value('on').else_use('R Time Delay'), + use('').if_parameter('Link On').has_value('on').else_use('R Beat Swing').if_parameter('R Delay Mode').has_value('on').else_use(''), + 'Feedback', + 'Dry/Wet')}), ('Global', {PARAMETERS_KEY: ('', + '', + '', + '', + '', + 'Link On', + 'Feedback', + 'Dry/Wet')}))), + 'StereoGain': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Mute', + use('BlockDc').if_parameter('Mute').has_value('off'), + use('PhaseInvertL').if_parameter('Mute').has_value('off'), + use('PhaseInvertR').if_parameter('Mute').has_value('off'), + use('Signal Source').if_parameter('Mute').has_value('off'), + use('Panorama').if_parameter('Mute').has_value('off'), + use('').if_parameter('Mute').has_value('on').else_use('').if_parameter('Signal Source').has_value('Left').else_use('').if_parameter('Signal Source').has_value('Right').else_use('StereoSeparation'), + use('Gain').if_parameter('Mute').has_value('off'))}),)), + 'Vinyl': IndexedDict((('Global', {PARAMETERS_KEY: ('Tracing On', + use('Tracing Drive').if_parameter('Tracing On').has_value('on'), + use('Tracing Freq.').if_parameter('Tracing On').has_value('on'), + use('Tracing Width').if_parameter('Tracing On').has_value('on'), + 'Pinch On', + 'Global Drive', + 'Crackle Density', + 'Crackle Volume')}), ('Pinch', {PARAMETERS_KEY: ('Pinch On', + use('Pinch Soft On').if_parameter('Pinch On').has_value('on'), + use('Pinch Mono On').if_parameter('Pinch On').has_value('on'), + use('Pinch Width').if_parameter('Pinch On').has_value('on'), + use('Pinch Drive').if_parameter('Pinch On').has_value('on'), + use('Pinch Freq.').if_parameter('Pinch On').has_value('on'), + 'Crackle Density', + 'Crackle Volume')}))), + 'Vocoder': IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Formant Shift', + 'Attack Time', + 'Release Time', + 'Unvoiced Level', + 'Gate Threshold', + 'Filter Bandwidth', + 'Envelope Depth', + 'Dry/Wet')}), + ('Carrier', {PARAMETERS_KEY: ('Noise Rate', + 'Noise Crackle', + 'Upper Pitch Detection', + 'Lower Pitch Detection', + 'Oscillator Pitch', + 'Oscillator Waveform', + '', + '')}), + ('Global', {PARAMETERS_KEY: ('Formant Shift', + 'Attack Time', + 'Release Time', + 'Mono/Stereo', + 'Output Level', + 'Gate Threshold', + 'Envelope Depth', + 'Dry/Wet')}), + ('Filters/Voicing', {PARAMETERS_KEY: ('Filter Bandwidth', + 'Upper Filter Band', + 'Lower Filter Band', + 'Precise/Retro', + 'Unvoiced Level', + 'Unvoiced Sensitivity', + 'Unvoiced Speed', + 'Enhance')})))} +PARAMETERS_BLACKLIST_FOR_CPP_SANITY_CHECK = {'OriginalSimpler': ('Start', + 'End', + 'Sensitivity', + 'Mode', + 'Playback', + 'Pad Slicing', + 'Multi Sample', + 'Warp', + 'Warp Mode', + 'Voices', + 'Preserve', + 'Loop Mode', + 'Envelope', + 'Grain Size Tones', + 'Grain Size Texture', + 'Flux', + 'Formants', + 'Envelope Complex Pro', + 'Gain')} \ No newline at end of file diff --git a/Push/device_navigation_component.py b/Push/device_navigation_component.py index d13ec847..071506ed 100644 --- a/Push/device_navigation_component.py +++ b/Push/device_navigation_component.py @@ -1,9 +1,9 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/device_navigation_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/device_navigation_component.py +from __future__ import absolute_import, print_function from functools import partial from contextlib import contextmanager import Live.DrumPad -from ableton.v2.base import const, depends, disconnectable, find_if, inject, in_range, listens, liveobj_valid, NamedTuple +from ableton.v2.base import const, depends, disconnectable, inject, in_range, listens, liveobj_valid, NamedTuple from ableton.v2.control_surface import CompoundComponent from pushbase import consts from pushbase.device_chain_utils import is_first_device_on_pad @@ -17,9 +17,9 @@ class DeviceNavigationComponent(CompoundComponent): track and navigates in its hierarchy. """ - def __init__(self, device_bank_registry = None, info_layer = None, delete_handler = None, session_ring = None, *a, **k): + def __init__(self, device_bank_registry = None, banking_info = None, info_layer = None, delete_handler = None, session_ring = None, *a, **k): super(DeviceNavigationComponent, self).__init__(*a, **k) - self._make_navigation_node = partial(make_navigation_node, session_ring=session_ring, device_bank_registry=device_bank_registry) + self._make_navigation_node = partial(make_navigation_node, session_ring=session_ring, device_bank_registry=device_bank_registry, banking_info=banking_info) self._delete_handler = delete_handler self._device_list = self.register_component(ScrollableListWithTogglesComponent()) self._on_selection_clicked_in_controller.subject = self._device_list @@ -96,9 +96,9 @@ def _on_selected_device_changed(self): if isinstance(selected, Live.Chain.Chain) and selected_device and selected_device.canonical_parent == selected and selected.devices[0] == selected_device: is_just_default_child_selection = True if not is_just_default_child_selection: - if selected_device: - target = selected_device.canonical_parent - node = (not self._current_node or self._current_node.object != target) and self._make_navigation_node(target, is_entering=False) + target = selected_device and selected_device.canonical_parent + if not self._current_node or self._current_node.object != target: + node = self._make_navigation_node(target, is_entering=False) self._set_current_node(node) def _set_current_node(self, node): @@ -187,11 +187,11 @@ def _on_selection_clicked_in_controller(self, index): if self._current_node: self._current_node.delete_child(index) return True - elif consts.PROTO_FAST_DEVICE_NAVIGATION: + if consts.PROTO_FAST_DEVICE_NAVIGATION: if self._device_list.selected_option == index: self._set_current_node(self._make_enter_node()) return True - elif not in_range(index, 0, len(self._device_list.option_names)): + if not in_range(index, 0, len(self._device_list.option_names)): self._set_current_node(self._make_exit_node()) return True return index == None @@ -221,10 +221,9 @@ def _update_hotswap_target(self): pass def _make_enter_node(self): - if self._device_list.selected_option >= 0: - if self._device_list.selected_option < len(self._current_node.children): - child = self._current_node.children[self._device_list.selected_option][1] - return self._make_navigation_node(child, is_entering=True) + if self._device_list.selected_option >= 0 and self._device_list.selected_option < len(self._current_node.children): + child = self._current_node.children[self._device_list.selected_option][1] + return self._make_navigation_node(child, is_entering=True) def _make_exit_node(self): return self._make_navigation_node(self._current_node and self._current_node.parent, is_entering=False) diff --git a/Push/drum_group_component.py b/Push/drum_group_component.py index f4ca4a3c..8d9d3248 100644 --- a/Push/drum_group_component.py +++ b/Push/drum_group_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/drum_group_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/drum_group_component.py +from __future__ import absolute_import, print_function from pushbase.drum_group_component import DrumGroupComponent as DrumGroupComponentBase class DrumGroupComponent(DrumGroupComponentBase): diff --git a/Push/elements.py b/Push/elements.py index 53ff1f20..8c14c418 100644 --- a/Push/elements.py +++ b/Push/elements.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/elements.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/elements.py +from __future__ import absolute_import, print_function from functools import partial from ableton.v2.base import recursive_map from ableton.v2.control_surface.elements import ButtonMatrixElement, ComboElement, SysexElement diff --git a/Push/firmware_handling.py b/Push/firmware_handling.py index 3c2f255d..b4852b9e 100644 --- a/Push/firmware_handling.py +++ b/Push/firmware_handling.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/firmware_handling.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/firmware_handling.py +from __future__ import absolute_import, print_function from os import path VERSION_PREFIX = '10F4000041444139204E69636F6C6C73' NUM_VERSION_BYTES = 8 diff --git a/Push/global_pad_parameters.py b/Push/global_pad_parameters.py index f49e0e5b..2ed23ead 100644 --- a/Push/global_pad_parameters.py +++ b/Push/global_pad_parameters.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/global_pad_parameters.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/global_pad_parameters.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface import Component from . import sysex diff --git a/Push/handshake_component.py b/Push/handshake_component.py index 6313158e..4821adc6 100644 --- a/Push/handshake_component.py +++ b/Push/handshake_component.py @@ -1,7 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/handshake_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/handshake_component.py """ Component for handling the initialization process of Push. """ +from __future__ import absolute_import, print_function from functools import partial import Live from ableton.v2.base import NamedTuple, listens, task diff --git a/Push/mode_behaviours.py b/Push/mode_behaviours.py index e3fb6dc9..58ae5062 100644 --- a/Push/mode_behaviours.py +++ b/Push/mode_behaviours.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/mode_behaviours.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/mode_behaviours.py +from __future__ import absolute_import, print_function from itertools import imap from ableton.v2.control_surface.mode import ModeButtonBehaviour @@ -13,10 +14,10 @@ class CancellableBehaviour(ModeButtonBehaviour): def press_immediate(self, component, mode): active_modes = component.active_modes groups = component.get_mode_groups(mode) - if not mode in active_modes: - can_cancel_mode = any(imap(lambda other: groups & component.get_mode_groups(other), active_modes)) - if can_cancel_mode: - groups and component.pop_groups(groups) + can_cancel_mode = mode in active_modes or any(imap(lambda other: groups & component.get_mode_groups(other), active_modes)) + if can_cancel_mode: + if groups: + component.pop_groups(groups) else: component.pop_mode(mode) self.restore_previous_mode(component) diff --git a/Push/multi_entry_mode.py b/Push/multi_entry_mode.py index e8379521..a12bb1d2 100644 --- a/Push/multi_entry_mode.py +++ b/Push/multi_entry_mode.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/multi_entry_mode.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/multi_entry_mode.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface.mode import tomode, Mode class MultiEntryMode(Mode): diff --git a/Push/navigation_node.py b/Push/navigation_node.py index b4e6bde4..3634cacf 100644 --- a/Push/navigation_node.py +++ b/Push/navigation_node.py @@ -1,15 +1,16 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/navigation_node.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/navigation_node.py +from __future__ import absolute_import, print_function from itertools import imap from functools import partial import Live.DrumPad import Live.Song import Live.Track -from _Generic.Devices import parameter_bank_names from ableton.v2.base import compose, find_if, flatten, index_if, in_range, listens, liveobj_valid, second, SlotManager, Subject +from ableton.v2.control_surface.components import select_and_appoint_device from pushbase import consts DeviceType = Live.Device.DeviceType -def make_navigation_node(model_object, is_entering = True, session_ring = None, device_bank_registry = None): +def make_navigation_node(model_object, is_entering = True, session_ring = None, device_bank_registry = None, banking_info = None): """ Returns a proper navigation node wrapper for the model_object """ @@ -30,19 +31,19 @@ def make_navigation_node(model_object, is_entering = True, session_ring = None, if is_entering: node = None else: - node = make_navigation_node(model_object.canonical_parent, is_entering=is_entering, device_bank_registry=device_bank_registry) + node = make_navigation_node(model_object.canonical_parent, is_entering=is_entering, device_bank_registry=device_bank_registry, banking_info=banking_info) else: node = RackNode(model_object) else: - raise device_bank_registry or AssertionError, 'Navigating a device needs a bank registry' - node = SimpleDeviceNode(device_bank_registry, model_object) + raise device_bank_registry or AssertionError('Navigating a device needs a bank registry') + node = SimpleDeviceNode(device_bank_registry, banking_info, model_object) if node and node.parent and not node.children: node.disconnect() node = None if isinstance(node, RackNode) and len(node.children) == 1: actual_model_object = node.children[0][1] if is_entering else node.parent node.disconnect() - node = make_navigation_node(actual_model_object, is_entering=is_entering, device_bank_registry=device_bank_registry) + node = make_navigation_node(actual_model_object, is_entering=is_entering, device_bank_registry=device_bank_registry, banking_info=banking_info) return node @@ -159,7 +160,8 @@ def get_object(self): return self._object def get_parent(self): - return self._object.canonical_parent if liveobj_valid(self._object) else None + if liveobj_valid(self._object): + return self._object.canonical_parent def _get_song(self): return self._get_parent_with_class(Live.Song.Song) @@ -226,18 +228,18 @@ def preselect(self): super(ChainNode, self).preselect() new_selected_child_index = self.selected_child track = self._get_track() - if new_selected_child_index == old_selected_child_index: - if new_selected_child_index != None: - _, selected_object = self.children[new_selected_child_index] - isinstance(selected_object, Live.Device.Device) and track and track.view.selected_device != selected_object and self._get_song().view.select_device(selected_object) - self._device_bank_registry.set_device_bank(track.view.selected_device, None) + if new_selected_child_index == old_selected_child_index and new_selected_child_index != None: + _, selected_object = self.children[new_selected_child_index] + if isinstance(selected_object, Live.Device.Device) and track and track.view.selected_device != selected_object: + select_and_appoint_device(self._get_song(), selected_object) + self._device_bank_registry.set_device_bank(track.view.selected_device, 0) def delete_child(self, index): - if index >= 0 and index < len(self._children): - if not isinstance(self._children[index][1], Live.DrumPad.DrumPad): - drumpads_before = len(filter(lambda (_, x): isinstance(x, Live.DrumPad.DrumPad), self._children[:index])) - delete_index = index - drumpads_before - len(self.object.devices) > delete_index and self.object.delete_device(delete_index) + if index >= 0 and index < len(self._children) and not isinstance(self._children[index][1], Live.DrumPad.DrumPad): + drumpads_before = len(filter(lambda (_, x): isinstance(x, Live.DrumPad.DrumPad), self._children[:index])) + delete_index = index - drumpads_before + if len(self.object.devices) > delete_index: + self.object.delete_device(delete_index) def _get_children_from_model(self): @@ -255,11 +257,11 @@ def _set_selected_child_in_model(self, selected): song = self._get_song() if selected and isinstance(selected, Live.DrumPad.DrumPad): if selected.chains and selected.chains[0].devices: - song.view.select_device(selected.chains[0].devices[0]) + select_and_appoint_device(song, selected.chains[0].devices[0]) selected.canonical_parent.view.selected_drum_pad = selected elif selected and isinstance(selected, Live.Device.Device): - song.view.select_device(selected) - self._device_bank_registry.set_device_bank(selected, None) + select_and_appoint_device(song, selected) + self._device_bank_registry.set_device_bank(selected, 0) def _get_selected_child_from_model(self): devices = map(second, self.children) @@ -291,12 +293,12 @@ def _get_state_from_model(self, child): def _set_state_in_model(self, child, value): if child == None: return False - elif isinstance(child, Live.DrumPad.DrumPad): + if isinstance(child, Live.DrumPad.DrumPad): if child.mute == value: child.mute = not value return value return not child.mute - elif child.parameters: + if child.parameters: on_off = child.parameters[0] if value != on_off.value and on_off.is_enabled: child.parameters[0].value = int(value) @@ -368,11 +370,12 @@ def _get_children_from_model(self): class SimpleDeviceNode(ModelNode): - def __init__(self, device_bank_registry = None, *a, **k): + def __init__(self, device_bank_registry = None, banking_info = None, *a, **k): super(SimpleDeviceNode, self).__init__(*a, **k) - raise device_bank_registry or AssertionError, 'Need a device bank registry.' + raise device_bank_registry or AssertionError('Need a device bank registry.') self._mute_next_update = False self._device_bank_registry = device_bank_registry + self._banking_info = banking_info self._on_device_bank_changed.subject = self._device_bank_registry self._update_children() self._update_selected_child() @@ -382,15 +385,20 @@ def _on_device_bank_changed(self, device, bank): self._update_selected_child() def _get_selected_child_from_model(self): - return self._device_bank_registry.get_device_bank(self.object) if self.children else None + if self.children: + return self._device_bank_registry.get_device_bank(self.object) def _set_selected_child_in_model(self, value): if value != None: self._device_bank_registry.set_device_bank(self.object, value) def _get_children_from_model(self): - names = parameter_bank_names(self.object) - return zip(names, range(len(names))) + names = self._banking_info.device_bank_names(device=self.object) + offset = 0 + if names and len(names) > 1 and self._banking_info.has_main_bank(self.object): + names = names[1:] + offset = 1 + return zip(names, range(offset, len(names) + offset)) class RackNode(ModelNode): diff --git a/Push/notification_component.py b/Push/notification_component.py index 480b03f4..46c97d06 100644 --- a/Push/notification_component.py +++ b/Push/notification_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/notification_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/notification_component.py +from __future__ import absolute_import, print_function from functools import partial from weakref import ref from ableton.v2.base import forward_property, maybe, task diff --git a/Push/pad_sensitivity.py b/Push/pad_sensitivity.py index ff805e19..a228fb33 100644 --- a/Push/pad_sensitivity.py +++ b/Push/pad_sensitivity.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/pad_sensitivity.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/pad_sensitivity.py +from __future__ import absolute_import, print_function from itertools import repeat from ableton.v2.base import find_if, second, lazy_attribute, nop, NamedTuple, task from ableton.v2.control_surface import Component diff --git a/Push/quantization_settings.py b/Push/quantization_settings.py index 85a07ef4..49d27d69 100644 --- a/Push/quantization_settings.py +++ b/Push/quantization_settings.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/quantization_settings.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/quantization_settings.py +from __future__ import absolute_import, print_function from ableton.v2.base import listens from ableton.v2.control_surface.control import TextDisplayControl from pushbase.quantization_component import QuantizationSettingsComponent as QuantizationSettingsComponentBase, QUANTIZATION_NAMES, quantize_amount_to_string diff --git a/Push/scales_component.py b/Push/scales_component.py index 72f37486..a5b49a62 100644 --- a/Push/scales_component.py +++ b/Push/scales_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/scales_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/scales_component.py +from __future__ import absolute_import, print_function from functools import partial from ableton.v2.base import forward_property, listens, listens_group, recursive_map from ableton.v2.control_surface import CompoundComponent diff --git a/Push/special_physical_display.py b/Push/special_physical_display.py index 86d3da0c..0a5646e9 100644 --- a/Push/special_physical_display.py +++ b/Push/special_physical_display.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/special_physical_display.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/special_physical_display.py +from __future__ import absolute_import, print_function from ableton.v2.base import group, flatten from ableton.v2.control_surface.elements import PhysicalDisplayElement DISPLAY_BLOCK_LENGTH = 18 diff --git a/Push/user_settings_component.py b/Push/user_settings_component.py index 77afa5f8..69d2e366 100644 --- a/Push/user_settings_component.py +++ b/Push/user_settings_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/user_settings_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/user_settings_component.py +from __future__ import absolute_import, print_function from itertools import count from ableton.v2.base import forward_property, listens_group from ableton.v2.control_surface import Component, CompoundComponent diff --git a/Push/with_priority.py b/Push/with_priority.py index 57c80f11..a140b8fb 100644 --- a/Push/with_priority.py +++ b/Push/with_priority.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push/with_priority.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push/with_priority.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface import DEFAULT_PRIORITY from ableton.v2.control_surface.elements import WrapperElement diff --git a/Push2/.DS_Store_failed b/Push2/.DS_Store_failed new file mode 100644 index 00000000..e69de29b diff --git a/Push2/__init__.py b/Push2/__init__.py index 8f5934cc..e444948e 100644 --- a/Push2/__init__.py +++ b/Push2/__init__.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/__init__.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/__init__.py +from __future__ import absolute_import, print_function def get_capabilities(): from ableton.v2.control_surface import capabilities as caps @@ -18,5 +18,5 @@ def get_capabilities(): def create_instance(c_instance): from .push2 import Push2 from .push2_model import Root, Sender - root = Root(sender=Sender(logger=c_instance, message_sink=c_instance.send_model_update, process_connected=c_instance.process_connected)) + root = Root(sender=Sender(message_sink=c_instance.send_model_update, process_connected=c_instance.process_connected)) return Push2(c_instance=c_instance, model=root) \ No newline at end of file diff --git a/Push2/actions.py b/Push2/actions.py index 5a309f9b..63a2d5c6 100644 --- a/Push2/actions.py +++ b/Push2/actions.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/actions.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/actions.py +from __future__ import absolute_import, print_function from pushbase.actions import CaptureAndInsertSceneComponent as CaptureAndInsertSceneComponentBase from .clip_decoration import ClipDecoratedPropertiesCopier @@ -12,7 +13,8 @@ def post_trigger_action(self): def get_playing_clip(track): slot_ix = track.playing_slot_index - return track.clip_slots[slot_ix].clip if slot_ix > -1 else None + if slot_ix > -1: + return track.clip_slots[slot_ix].clip played_clips = [ get_playing_clip(track) for track in self.song.tracks ] super(CaptureAndInsertSceneComponent, self).post_trigger_action() diff --git a/Push2/automation.py b/Push2/automation.py index 7949167b..8588dbae 100644 --- a/Push2/automation.py +++ b/Push2/automation.py @@ -1,10 +1,10 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/automation.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/automation.py +from __future__ import absolute_import, print_function from itertools import ifilter from ableton.v2.base import liveobj_valid, listenable_property from pushbase.automation_component import AutomationComponent as AutomationComponentBase +from pushbase.internal_parameter import InternalParameterBase from pushbase.parameter_provider import ParameterInfo -from .internal_parameter import InternalParameterBase class StepAutomationParameter(InternalParameterBase): @@ -82,7 +82,7 @@ def deviceType(self): @property def parameters(self): - return map(lambda info: info.parameter if info else None, self._parameter_infos) + return map(lambda info: (info.parameter if info else None), self._parameter_infos) @property def parameter_infos(self): @@ -122,4 +122,5 @@ def _update_parameter_values(self): self.notify_parameters() def _parameter_for_index(self, parameters, index): - return parameters[index].original_parameter if parameters[index] else None \ No newline at end of file + if parameters[index]: + return parameters[index].original_parameter \ No newline at end of file diff --git a/Push2/bank_selection_component.py b/Push2/bank_selection_component.py index e3ba7941..fcad4d42 100644 --- a/Push2/bank_selection_component.py +++ b/Push2/bank_selection_component.py @@ -1,10 +1,10 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/bank_selection_component.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/bank_selection_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import NamedTuple, listenable_property, listens, listens_group, liveobj_valid, SlotManager, nop from ableton.v2.control_surface import Component -from ableton.v2.control_surface.control import control_list, forward_control, ButtonControl +from ableton.v2.control_surface.control import control_list, ButtonControl +from pushbase.banking_util import MAIN_KEY from .item_lister_component import ItemListerComponent, ItemProvider -from .bank_definitions import MAIN_KEY class BankProvider(ItemProvider, SlotManager): @@ -53,7 +53,9 @@ def _on_device_bank_changed(self, device, _): def internal_bank_names(self, original_bank_names): num_banks = len(original_bank_names) - return original_bank_names if num_banks > 0 else [MAIN_KEY] + if num_banks > 0: + return original_bank_names + return [MAIN_KEY] class EditModeOptionsComponent(Component): @@ -70,7 +72,8 @@ def __init__(self, back_callback = nop, device_options_provider = None, *a, **k) def _option_for_button(self, button): options = self.options - return options[button.index - 1] if len(options) > button.index - 1 else None + if len(options) > button.index - 1: + return options[button.index - 1] @option_buttons.pressed def option_buttons(self, button): @@ -91,11 +94,15 @@ def _set_device(self, device): @listenable_property def device(self): - return self._device.name if liveobj_valid(self._device) else '' + if liveobj_valid(self._device): + return self._device.name + return '' @listenable_property def options(self): - return self._device_options_provider.options if self._device_options_provider else [] + if self._device_options_provider: + return self._device_options_provider.options + return [] @listens('device') def __on_device_changed(self): @@ -133,7 +140,6 @@ def update(self): class BankSelectionComponent(ItemListerComponent): __events__ = ('back',) - select_buttons = forward_control(ItemListerComponent.select_buttons) def __init__(self, bank_registry = None, banking_info = None, device_options_provider = None, *a, **k): self._bank_provider = BankProvider(bank_registry=bank_registry, banking_info=banking_info) @@ -141,8 +147,7 @@ def __init__(self, bank_registry = None, banking_info = None, device_options_pro self._options = self.register_component(EditModeOptionsComponent(back_callback=self.notify_back, device_options_provider=device_options_provider)) self.register_disconnectable(self._bank_provider) - @select_buttons.checked - def select_buttons(self, button): + def _on_select_button_pressed(self, button): self._bank_provider.select_item(self.items[button.index].item) def set_option_buttons(self, buttons): diff --git a/Push2/browser_component.py b/Push2/browser_component.py index 34a13b77..d4548b29 100644 --- a/Push2/browser_component.py +++ b/Push2/browser_component.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/browser_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/browser_component.py +from __future__ import absolute_import, print_function from contextlib import contextmanager from itertools import imap from math import ceil @@ -37,7 +37,9 @@ def __init__(self, wrapped_loadable = None, *a, **k): @property def is_selected(self): - return self._is_selected if self._contained_item is None else self._contained_item.is_selected + if self._contained_item is None: + return self._is_selected + return self._contained_item.is_selected @lazy_attribute def children(self): @@ -108,7 +110,7 @@ class BrowserComponent(Component, Messenger): load_text = listenable_property.managed('') @depends(commit_model_changes=None, selection=None) - def __init__(self, preferences = dict(), commit_model_changes = None, selection = None, *a, **k): + def __init__(self, preferences = dict(), commit_model_changes = None, selection = None, main_modes_ref = None, *a, **k): raise commit_model_changes is not None or AssertionError super(BrowserComponent, self).__init__(*a, **k) self._lists = [] @@ -123,6 +125,7 @@ def __init__(self, preferences = dict(), commit_model_changes = None, selection self._delay_preview_list = BooleanContext() self._selection = selection self._load_next = False + self._main_modes_ref = main_modes_ref if main_modes_ref is not None else nop self._content_filter_type = None self._content_hotswap_target = None self._preview_list_task = self._tasks.add(task.sequence(task.wait(self.REVEAL_PREVIEW_LIST_TIME), task.run(self._replace_preview_list_by_task))).kill() @@ -133,6 +136,7 @@ def __init__(self, preferences = dict(), commit_model_changes = None, selection self.prehear_button.is_toggled = preferences.setdefault('browser_prehear', True) self._on_selected_track_color_index_changed.subject = self.song.view self._on_selected_track_name_changed.subject = self.song.view + self._on_detail_clip_name_changed.subject = self.song.view self._on_hotswap_target_changed.subject = self._browser self.register_slot(self, self.notify_focused_item, 'focused_list_index') @@ -209,6 +213,7 @@ def scroll_encoders(self, encoder): try: if self._focus_list_with_index(list_index, crop=False): self._unexpand_with_scroll_encoder = True + self._prehear_selected_item() if self.focused_list.selected_item.is_loadable and encoder.index == self.scroll_encoders.control_count - 1: self._update_list_offset() self._on_encoder_touched() @@ -261,19 +266,23 @@ def _on_encoder_touched(self): self._update_horizontal_navigation() def _on_encoder_released(self): - if not any(imap(lambda e: e.is_touched, self.scroll_encoders)): - any_encoder_touched = self.scroll_focused_encoder.is_touched - not any_encoder_touched and self._unexpand_with_scroll_encoder and self._unexpand_task.restart() + any_encoder_touched = any(imap(lambda e: e.is_touched, self.scroll_encoders)) or self.scroll_focused_encoder.is_touched + if not any_encoder_touched and self._unexpand_with_scroll_encoder: + self._unexpand_task.restart() self._update_scrolling() def _get_list_index_for_encoder(self, encoder): if self.expanded: - return self.list_offset if encoder.index == 0 else self.list_offset + 1 + if encoder.index == 0: + return self.list_offset + return self.list_offset + 1 + index = self.list_offset + encoder.index + if self.focused_list_index + 1 == index and self.focused_list.selected_item.is_loadable: + index = self.focused_list_index + if 0 <= index < len(self._lists): + return index else: - index = self.list_offset + encoder.index - if self.focused_list_index + 1 == index and self.focused_list.selected_item.is_loadable: - index = self.focused_list_index - return index if 0 <= index < len(self._lists) else None + return None @load_button.pressed def load_button(self, button): @@ -342,6 +351,11 @@ def _on_selected_track_name_changed(self): if self.is_enabled(): self._update_context() + @listens('detail_clip.name') + def _on_detail_clip_name_changed(self): + if self.is_enabled(): + self._update_context() + @listens('hotswap_target') def _on_hotswap_target_changed(self): if self.is_enabled(): @@ -351,6 +365,14 @@ def _on_hotswap_target_changed(self): self._update_list_offset() self._current_hotswap_target = self._browser.hotswap_target + @property + def browse_for_audio_clip(self): + main_modes = self._main_modes_ref() + if main_modes is None: + return False + has_midi_support = self.song.view.selected_track.has_midi_input + return not has_midi_support and 'clip' in main_modes.active_modes + def _switched_to_empty_pad(self): hotswap_target = self._browser.hotswap_target is_browsing_drumpad = isinstance(hotswap_target, Live.DrumPad.DrumPad) @@ -401,22 +423,24 @@ def _on_focused_selection_changed(self): def _get_actual_item(self, item): contained_item = getattr(item, 'contained_item', None) - return contained_item if contained_item is not None else item + if contained_item is not None: + return contained_item + return item def _load_selected_item(self): focused_list = self.focused_list if self._load_next: focused_list.selected_index += 1 - if focused_list.selected_index < len(focused_list.items) - 1: - self._load_next = liveobj_valid(self._browser.hotswap_target) - self._update_load_text() - item = self._get_actual_item(focused_list.selected_item) - notification_ref = self.show_notification(self._make_notification_text(item)) - self._commit_model_changes() - self._load_item(item) - self.notify_loaded() - notification = notification_ref() - notification is not None and notification.reschedule_after_slow_operation() + self._load_next = focused_list.selected_index < len(focused_list.items) - 1 and liveobj_valid(self._browser.hotswap_target) + self._update_load_text() + item = self._get_actual_item(focused_list.selected_item) + notification_ref = self.show_notification(self._make_notification_text(item)) + self._commit_model_changes() + self._load_item(item) + self.notify_loaded() + notification = notification_ref() + if notification is not None: + notification.reschedule_after_slow_operation() def _make_notification_text(self, browser_item): return 'Loading %s' % browser_item.name @@ -466,17 +490,17 @@ def _update_navigation_buttons(self): self.up_button.enabled = focused_list.selected_index > 0 self.down_button.enabled = focused_list.selected_index < len(focused_list.items) - 1 selected_item_loadable = self.focused_list.selected_item.is_loadable - if self._preview_list_task.is_running: - assume_can_enter = not selected_item_loadable - can_exit = self._focused_list_index > 0 - can_enter = self._focused_list_index < len(self._lists) - 1 or assume_can_enter - self.back_button.enabled = can_exit - self.open_button.enabled = can_enter - self.load_button.enabled = selected_item_loadable - context_button_color = translate_color_index(self.context_color_index) if self.context_color_index > -1 else 'Browser.Navigation' - self.load_button.color = context_button_color - self.close_button.color = context_button_color - self.left_button.enabled = self._expanded or self.back_button.enabled + assume_can_enter = self._preview_list_task.is_running and not selected_item_loadable + can_exit = self._focused_list_index > 0 + can_enter = self._focused_list_index < len(self._lists) - 1 or assume_can_enter + self.back_button.enabled = can_exit + self.open_button.enabled = can_enter + self.load_button.enabled = selected_item_loadable + context_button_color = translate_color_index(self.context_color_index) if self.context_color_index > -1 else 'Browser.Navigation' + self.load_button.color = context_button_color + self.close_button.color = context_button_color + if not self._expanded: + self.left_button.enabled = self.back_button.enabled self.right_button.enabled = can_enter or self._can_auto_expand() else: num_columns = int(ceil(float(len(self.focused_list.items)) / self.NUM_ITEMS_PER_COLUMN)) @@ -494,7 +518,10 @@ def _update_horizontal_navigation(self): def _update_context(self): selected_track = self.song.view.selected_track - if liveobj_valid(self._browser.hotswap_target): + clip = self.song.view.detail_clip + if self.browse_for_audio_clip and clip: + self.context_text = clip.name + elif liveobj_valid(self._browser.hotswap_target): self.context_text = self._browser.hotswap_target.name else: self.context_text = selected_track.name @@ -623,7 +650,9 @@ def _select_hotswap_target(self, list_index = 0): @property def num_preview_items(self): - return self.NUM_ITEMS_PER_COLUMN * self.NUM_COLUMNS_IN_EXPANDED_LIST if self._expanded else 6 + if self._expanded: + return self.NUM_ITEMS_PER_COLUMN * self.NUM_COLUMNS_IN_EXPANDED_LIST + return 6 def update(self): super(BrowserComponent, self).update() @@ -642,7 +671,7 @@ def update(self): def _wrap_item(self, item): if item.is_device: return self._wrap_device_item(item) - elif self._is_hotswap_target_plugin(item): + if self._is_hotswap_target_plugin(item): return self._wrap_hotswapped_plugin_item(item) return item @@ -725,6 +754,10 @@ def disconnect(self): super(NewTrackBrowserComponent, self).disconnect() self._content = [] + @property + def browse_for_audio_clip(self): + return False + def _update_root_content(self): real_root_items = super(NewTrackBrowserComponent, self)._make_root_browser_items() self._content[:] = [DefaultTrackBrowserItem()] + real_root_items @@ -756,7 +789,9 @@ def _make_notification_text(self, browser_item): def _selected_track_index(self): song = self.song selected_track = self._selection.selected_track - return list(song.tracks).index(selected_track) + 1 if selected_track in song.tracks else -1 + if selected_track in song.tracks: + return list(song.tracks).index(selected_track) + 1 + return -1 def _selected_track_item(self): return self._lists[0].selected_item @@ -801,18 +836,24 @@ def make_root_browser_items(browser, filter_type): instruments = wrap_item(browser.instruments, 'browser_instruments.svg') audio_effects = wrap_item(browser.audio_effects, 'browser_audioeffect.svg') midi_effects = wrap_item(browser.midi_effects, 'browser_midieffect.svg') - common_items = [wrap_item(browser.max_for_live, 'browser_max.svg'), wrap_item(browser.plugins, 'browser_plugins.svg'), wrap_item(browser.packs, 'browser_packs.svg')] + wrap_items(list(browser.legacy_libraries), 'browser_8folder.svg') + [wrap_item(browser.current_project, 'browser_currentproject.svg')] - if filter_type == Live.Browser.FilterType.audio_effect_hotswap: - categories = [audio_effects] + common_items - elif filter_type == Live.Browser.FilterType.midi_effect_hotswap: - categories = [midi_effects] + common_items - elif filter_type == Live.Browser.FilterType.instrument_hotswap: - categories = [sounds, drums, instruments] + common_items + packs = wrap_item(browser.packs, 'browser_packs.svg') + legacy_libraries = wrap_items(list(browser.legacy_libraries), 'browser_8folder.svg') + current_project = wrap_item(browser.current_project, 'browser_currentproject.svg') + if filter_type == Live.Browser.FilterType.samples: + categories = [packs] + legacy_libraries + [current_project] else: - categories = [sounds, - drums, - instruments, - audio_effects, - midi_effects] + common_items + common_items = [wrap_item(browser.max_for_live, 'browser_max.svg'), wrap_item(browser.plugins, 'browser_plugins.svg'), packs] + legacy_libraries + [current_project] + if filter_type == Live.Browser.FilterType.audio_effect_hotswap: + categories = [audio_effects] + common_items + elif filter_type == Live.Browser.FilterType.midi_effect_hotswap: + categories = [midi_effects] + common_items + elif filter_type == Live.Browser.FilterType.instrument_hotswap: + categories = [sounds, drums, instruments] + common_items + else: + categories = [sounds, + drums, + instruments, + audio_effects, + midi_effects] + common_items user_files = UserFilesBrowserItem(browser, name='User Files', icon='browser_userfiles.svg') return [user_files] + categories \ No newline at end of file diff --git a/Push2/browser_item.py b/Push2/browser_item.py index fa286a2e..f9ec5278 100644 --- a/Push2/browser_item.py +++ b/Push2/browser_item.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/browser_item.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/browser_item.py +from __future__ import absolute_import, print_function from ableton.v2.base import Proxy class BrowserItem(object): @@ -51,7 +52,9 @@ def enable_wrapping(self): @property def uri(self): - return self._contained_item.uri if self._contained_item is not None else self._name + if self._contained_item is not None: + return self._contained_item.uri + return self._name class ProxyBrowserItem(Proxy): diff --git a/Push2/browser_list.py b/Push2/browser_list.py index 923fe1e1..b55da452 100644 --- a/Push2/browser_list.py +++ b/Push2/browser_list.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/browser_list.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/browser_list.py +from __future__ import absolute_import, print_function import Live from itertools import islice from ableton.v2.base import Subject, listenable_property, clamp, nop @@ -49,7 +50,7 @@ def _set_access_all(self, access_all): def items(self): if self.limit > 0: return self._items[:self.limit] - elif not self._access_all: + if not self._access_all: return self._items[:self.LAZY_ACCESS_COUNT] return self._items @@ -67,7 +68,9 @@ def _update_items(self): @property def selected_item(self): - return None if self.selected_index == -1 else self.items[self.selected_index] + if self.selected_index == -1: + return None + return self.items[self.selected_index] @listenable_property def selected_index(self): diff --git a/Push2/browser_modes.py b/Push2/browser_modes.py new file mode 100644 index 00000000..79403e66 --- /dev/null +++ b/Push2/browser_modes.py @@ -0,0 +1,115 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/browser_modes.py +from __future__ import absolute_import, print_function +import Live +from ableton.v2.base import depends, liveobj_valid +from ableton.v2.control_surface.mode import LazyComponentMode, Mode, ModeButtonBehaviour +from pushbase.browser_modes import BrowserHotswapMode +from pushbase.device_chain_utils import is_empty_drum_pad + +def get_filter_type_for_track(song): + has_midi_support = song.view.selected_track.has_midi_input + if has_midi_support: + return Live.Browser.FilterType.midi_track_devices + return Live.Browser.FilterType.audio_effect_hotswap + + +class BrowserModeBehaviour(ModeButtonBehaviour): + + def press_immediate(self, component, mode): + if mode == component.selected_mode: + component.selected_mode = component.active_modes[0] + else: + component.push_mode(mode) + + +class BrowserComponentMode(LazyComponentMode): + + def __init__(self, model_ref, *a, **k): + super(BrowserComponentMode, self).__init__(*a, **k) + self._model_ref = model_ref + + def enter_mode(self): + model = self._model_ref() + model.browserView = self.component + model.browserData = self.component + super(BrowserComponentMode, self).enter_mode() + + +class BrowseModeBase(Mode): + + def __init__(self, component_mode = None, *a, **k): + raise component_mode is not None or AssertionError + super(BrowseModeBase, self).__init__() + self._component_mode = component_mode + + def enter_mode(self): + self._component_mode.enter_mode() + + def leave_mode(self): + self._component_mode.leave_mode() + + +class HotswapBrowseMode(BrowseModeBase): + + def __init__(self, application, *a, **k): + super(HotswapBrowseMode, self).__init__(*a, **k) + self._hotswap_mode = BrowserHotswapMode(application=application) + self._in_hotswap_mode = False + + def leave_mode(self): + super(HotswapBrowseMode, self).leave_mode() + if self._in_hotswap_mode: + self._hotswap_mode.leave_mode() + + def _enter_hotswap_mode(self): + self._hotswap_mode.enter_mode() + self._in_hotswap_mode = True + + +class AddDeviceMode(HotswapBrowseMode): + + @depends(selection=None) + def __init__(self, song, browser, selection = None, *a, **k): + super(AddDeviceMode, self).__init__(*a, **k) + self._song = song + self._browser = browser + self._selection = selection + + def enter_mode(self): + if is_empty_drum_pad(self._selection.selected_object): + self._enter_hotswap_mode() + self._browser.filter_type = Live.Browser.FilterType.disabled + else: + self._browser.hotswap_target = None + self._browser.filter_type = get_filter_type_for_track(self._song) + super(AddDeviceMode, self).enter_mode() + + +class AddTrackMode(BrowseModeBase): + + def __init__(self, browser, *a, **k): + super(AddTrackMode, self).__init__(*a, **k) + self._browser = browser + + def enter_mode(self): + self._browser.hotswap_target = None + super(AddTrackMode, self).enter_mode() + + +class BrowseMode(HotswapBrowseMode): + + def __init__(self, song, browser, *a, **k): + super(BrowseMode, self).__init__(*a, **k) + self._song = song + self._browser = browser + + def enter_mode(self): + if self._component_mode.component.browse_for_audio_clip: + self._browser.filter_type = Live.Browser.FilterType.samples + else: + self._enter_hotswap_mode() + if liveobj_valid(self._browser.hotswap_target): + self._browser.filter_type = Live.Browser.FilterType.disabled + else: + self._browser.filter_type = get_filter_type_for_track(self._song) + super(BrowseMode, self).enter_mode() \ No newline at end of file diff --git a/Push2/chain_selection_component.py b/Push2/chain_selection_component.py index 883ddc77..ddf77344 100644 --- a/Push2/chain_selection_component.py +++ b/Push2/chain_selection_component.py @@ -1,7 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/chain_selection_component.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/chain_selection_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import SlotManager, listens, liveobj_valid -from ableton.v2.control_surface.control import forward_control from .item_lister_component import ItemListerComponent, ItemProvider class ChainProvider(SlotManager, ItemProvider): @@ -26,7 +25,8 @@ def items(self): @property def selected_item(self): - return self._rack.view.selected_chain if liveobj_valid(self._rack) else None + if liveobj_valid(self._rack): + return self._rack.view.selected_chain def select_chain(self, chain): self._rack.view.selected_chain = chain @@ -41,15 +41,13 @@ def __on_selected_chain_changed(self): class ChainSelectionComponent(ItemListerComponent): - select_buttons = forward_control(ItemListerComponent.select_buttons) def __init__(self, *a, **k): self._chain_parent = ChainProvider() super(ChainSelectionComponent, self).__init__(item_provider=self._chain_parent, *a, **k) self.register_disconnectable(self._chain_parent) - @select_buttons.checked - def select_buttons(self, button): + def _on_select_button_pressed(self, button): self._chain_parent.select_chain(self.items[button.index].item) def set_parent(self, parent): diff --git a/Push2/clip_control.py b/Push2/clip_control.py index c9e88c1b..d95cb99d 100644 --- a/Push2/clip_control.py +++ b/Push2/clip_control.py @@ -1,12 +1,13 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/clip_control.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/clip_control.py +from __future__ import absolute_import, print_function from ableton.v2.base import listens, liveobj_valid, listenable_property from ableton.v2.control_surface import CompoundComponent -from ableton.v2.control_surface.control import ToggleButtonControl +from ableton.v2.control_surface.control import EncoderControl, ToggleButtonControl from pushbase.clip_control_component import convert_length_to_bars_beats_sixteenths, convert_time_to_bars_beats_sixteenths, LoopSettingsControllerComponent as LoopSettingsControllerComponentBase, AudioClipSettingsControllerComponent as AudioClipSettingsControllerComponentBase, ONE_YEAR_AT_120BPM_IN_BEATS, WARP_MODE_NAMES +from pushbase.internal_parameter import WrappingParameter +from pushbase.mapped_control import MappedControl from .clip_decoration import ClipDecoratorFactory from .decoration import find_decorated_object -from .internal_parameter import WrappingParameter -from .mapped_control import MappedControl from .real_time_channel import RealTimeDataComponent from .simpler_zoom import ZoomHandling PARAMETERS_LOOPED = ('Loop position', 'Loop length', 'Start offset') @@ -21,10 +22,13 @@ def __init__(self, use_length_conversion = False, *a, **k): super(LoopSetting, self).__init__(*a, **k) self._conversion = convert_length_to_bars_beats_sixteenths if use_length_conversion else convert_time_to_bars_beats_sixteenths self.recording = False + self.set_property_host(self._parent) @property def display_value(self): - return unicode(self._conversion(self._get_property_value())) if not self.recording else unicode('...') + if not self.recording: + return unicode(self._conversion(self._get_property_value())) + return unicode('...') class ClipZoomHandling(ZoomHandling): @@ -49,6 +53,7 @@ def max_zoom(self): class LoopSettingsControllerComponent(LoopSettingsControllerComponentBase): __events__ = ('looping', 'loop_parameters', 'zoom') zoom_encoder = MappedControl() + zoom_touch_encoder = EncoderControl() loop_button = ToggleButtonControl(toggled_color='Clip.Option', untoggled_color='Clip.OptionDisabled') def __init__(self, zoom_handler = None, *a, **k): @@ -62,6 +67,11 @@ def __init__(self, zoom_handler = None, *a, **k): self._processed_zoom_requests = 0 self.__on_looping_changed.subject = self._loop_model self.__on_looping_changed() + self.__on_loop_position_value_changed.subject = self._looping_settings[0] + self.__on_loop_length_value_changed.subject = self._looping_settings[1] + self.__on_start_offset_value_changed.subject = self._looping_settings[2] + self.__on_start_value_changed.subject = self._non_looping_settings[0] + self.__on_end_value_changed.subject = self._non_looping_settings[1] @loop_button.toggled def loop_button(self, toggled, button): @@ -69,23 +79,33 @@ def loop_button(self, toggled, button): @property def looping(self): - return self._loop_model.looping if self.clip else False + if self.clip: + return self._loop_model.looping + return False @property def loop_parameters(self): if not liveobj_valid(self.clip): return [] parameters = self._looping_settings if self.looping else self._non_looping_settings - return [self.zoom] + parameters if self.zoom else parameters + if self.zoom: + return [self.zoom] + parameters + return parameters @property def zoom(self): - return getattr(self.clip, 'zoom', None) if liveobj_valid(self.clip) else None + if liveobj_valid(self.clip): + return getattr(self.clip, 'zoom', None) @listenable_property def processed_zoom_requests(self): return self._processed_zoom_requests + @listenable_property + def waveform_navigation(self): + if liveobj_valid(self.clip): + return getattr(self.clip, 'waveform_navigation', None) + @listens('is_recording') def __on_is_recording_changed(self): recording = False @@ -104,11 +124,73 @@ def _update_loop_button(self): self.loop_button.is_toggled = self._loop_model.looping def _on_clip_changed(self): + if self.waveform_navigation is not None: + self.waveform_navigation.reset_focus_and_animation() self._update_and_notify() self.__on_is_recording_changed.subject = self._loop_model.clip self.__on_is_recording_changed() self._zoom_handler.set_parameter_host(self._loop_model.clip) self._connect_encoder() + self.notify_waveform_navigation() + + @listens('value') + def __on_loop_position_value_changed(self): + if self.waveform_navigation is not None and self._loop_model.looping: + self.waveform_navigation.change_object(self.waveform_navigation.loop_start_focus) + + @listens('value') + def __on_loop_length_value_changed(self): + if self.waveform_navigation is not None and self._loop_model.looping: + self.waveform_navigation.change_object(self.waveform_navigation.loop_end_focus) + + @listens('value') + def __on_start_offset_value_changed(self): + if self.waveform_navigation is not None and self._loop_model.looping: + self.waveform_navigation.change_object(self.waveform_navigation.start_marker_focus) + + @listens('value') + def __on_start_value_changed(self): + if self.waveform_navigation is not None and not self._loop_model.looping: + self.waveform_navigation.change_object(self.waveform_navigation.start_marker_focus) + + @listens('value') + def __on_end_value_changed(self): + if self.waveform_navigation is not None and not self._loop_model.looping: + self.waveform_navigation.change_object(self.waveform_navigation.loop_end_focus) + + def _on_clip_start_marker_touched(self): + if self.waveform_navigation is not None: + self.waveform_navigation.touch_object(self.waveform_navigation.start_marker_focus) + + def _on_clip_position_touched(self): + if self.waveform_navigation is not None: + self.waveform_navigation.touch_object(self.waveform_navigation.loop_start_focus) + + def _on_clip_end_touched(self): + if self.waveform_navigation is not None: + self.waveform_navigation.touch_object(self.waveform_navigation.loop_end_focus) + + def _on_clip_start_marker_released(self): + if self.waveform_navigation is not None: + self.waveform_navigation.release_object(self.waveform_navigation.start_marker_focus) + + def _on_clip_position_released(self): + if self.waveform_navigation is not None: + self.waveform_navigation.release_object(self.waveform_navigation.loop_start_focus) + + def _on_clip_end_released(self): + if self.waveform_navigation is not None: + self.waveform_navigation.release_object(self.waveform_navigation.loop_end_focus) + + @zoom_touch_encoder.touched + def zoom_touch_encoder(self, encoder): + if self.waveform_navigation is not None: + self.waveform_navigation.touch_object(self.waveform_navigation.zoom_focus) + + @zoom_touch_encoder.released + def zoom_touch_encoder(self, encoder): + if self.waveform_navigation is not None: + self.waveform_navigation.release_object(self.waveform_navigation.zoom_focus) def _update_and_notify(self): self._update_loop_button() @@ -121,6 +203,7 @@ def _connect_encoder(self): def set_zoom_encoder(self, encoder): self.zoom_encoder.set_control_element(encoder) + self.zoom_touch_encoder.set_control_element(encoder) self._connect_encoder() def request_zoom(self, zoom_factor): @@ -131,9 +214,13 @@ def request_zoom(self, zoom_factor): class GainSetting(WrappingParameter): + def __init__(self, *a, **k): + super(GainSetting, self).__init__(*a, **k) + self.set_property_host(self._parent) + @property def display_value(self): - return unicode(self._parent.clip.gain_display_string if self._parent.clip else '') + return unicode(self._property_host.clip.gain_display_string if self._property_host.clip else '') class PitchSetting(WrappingParameter): @@ -143,6 +230,7 @@ def __init__(self, min_value, max_value, unit, *a, **k): self._min = min_value self._max = max_value self._unit = unit + self.set_property_host(self._parent) @property def min(self): @@ -161,9 +249,13 @@ def display_value(self): class WarpSetting(WrappingParameter): + def __init__(self, *a, **k): + super(WarpSetting, self).__init__(*a, **k) + self.set_property_host(self._parent) + @property def max(self): - return len(self._parent.available_warp_modes) - 1 + return len(self._property_host.available_warp_modes) - 1 @property def is_quantized(self): @@ -171,10 +263,10 @@ def is_quantized(self): @property def value_items(self): - return map(lambda x: unicode(WARP_MODE_NAMES[x]), self._parent.available_warp_modes) + return map(lambda x: unicode(WARP_MODE_NAMES[x]), self._property_host.available_warp_modes) def _get_property_value(self): - return self._parent.available_warp_modes.index(getattr(self._parent, self._source_property)) + return self._property_host.available_warp_modes.index(getattr(self._property_host, self._source_property)) class AudioClipSettingsControllerComponent(AudioClipSettingsControllerComponentBase, CompoundComponent): @@ -203,15 +295,21 @@ def disconnect(self): @property def audio_parameters(self): - return self._audio_clip_parameters if liveobj_valid(self.clip) else [] + if liveobj_valid(self.clip): + return self._audio_clip_parameters + return [] @property def warping(self): - return self._audio_clip_model.warping if liveobj_valid(self.clip) else False + if liveobj_valid(self.clip): + return self._audio_clip_model.warping + return False @property def gain(self): - return self._audio_clip_model.gain if liveobj_valid(self.clip) else 0.0 + if liveobj_valid(self.clip): + return self._audio_clip_model.gain + return 0.0 @property def waveform_real_time_channel_id(self): @@ -224,6 +322,7 @@ def playhead_real_time_channel_id(self): def _on_clip_changed(self): self._playhead_real_time_data.set_data(self.clip) self._waveform_real_time_data.set_data(self.clip) + self.__on_file_path_changed.subject = self.clip self.notify_audio_parameters() self.notify_warping() self.notify_gain() @@ -242,6 +341,10 @@ def __on_warping_changed(self): def __on_gain_changed(self): self.notify_gain() + @listens('file_path') + def __on_file_path_changed(self): + self._waveform_real_time_data.invalidate() + class ClipControlComponent(CompoundComponent): __events__ = ('clip',) diff --git a/Push2/clip_decoration.py b/Push2/clip_decoration.py index 6aa9a8c0..fe48b863 100644 --- a/Push2/clip_decoration.py +++ b/Push2/clip_decoration.py @@ -1,19 +1,33 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/clip_decoration.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/clip_decoration.py +from __future__ import absolute_import, print_function from ableton.v2.base import liveobj_valid, SlotManager, Subject -from .decoration import DecoratorFactory, find_decorated_object, LiveObjectDecorator -from .internal_parameter import InternalParameter +from pushbase.decoration import DecoratorFactory, LiveObjectDecorator +from pushbase.internal_parameter import InternalParameter +from .decoration import find_decorated_object +from .waveform_navigation import AudioClipWaveformNavigation + +class ZoomParameter(AudioClipWaveformNavigation, InternalParameter): + pass + class ClipDecoration(Subject, SlotManager, LiveObjectDecorator): __events__ = ('zoom',) def __init__(self, *a, **k): super(ClipDecoration, self).__init__(*a, **k) - self._zoom_parameter = InternalParameter(name='Zoom', parent=self._live_object) + waveform_length = max(self._live_object.view.sample_length, 1) + self._zoom_parameter = ZoomParameter(name='Zoom', parent=self._live_object, waveform_length=waveform_length, clip=self) + self._zoom_parameter.focus_object(self._zoom_parameter.start_marker_focus) + self.register_disconnectable(self._zoom_parameter) @property def zoom(self): return self._zoom_parameter + @property + def waveform_navigation(self): + return self._zoom_parameter + class ClipDecoratorFactory(DecoratorFactory): _decorator = ClipDecoration diff --git a/Push2/colors.py b/Push2/colors.py index a0b4b6e7..38615389 100644 --- a/Push2/colors.py +++ b/Push2/colors.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/colors.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/colors.py +from __future__ import absolute_import, print_function from ableton.v2.base.util import in_range from pushbase.colors import Blink, FallbackColor, Pulse, PushColor WHITE_MIDI_VALUE = 122 @@ -40,7 +41,9 @@ def __init__(self, index = None, *a, **k): def translate_color_index(index): try: - return COLOR_INDEX_TO_PUSH_INDEX[index] if index > -1 else TRANSLATED_WHITE_INDEX + if index > -1: + return COLOR_INDEX_TO_PUSH_INDEX[index] + return TRANSLATED_WHITE_INDEX except: return TRANSLATED_WHITE_INDEX diff --git a/Push2/convert.py b/Push2/convert.py index ff0cebc7..481c0143 100644 --- a/Push2/convert.py +++ b/Push2/convert.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/convert.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/convert.py +from __future__ import absolute_import, print_function from functools import partial from itertools import izip import Live @@ -60,7 +61,8 @@ def __init__(self, track = None, *a, **k): class MoveDeviceChain(TrackBasedConvertAction): - name = 'Drum Pad' + label = 'Drum Pad' + internal_name = 'midi_track_to_drum_pad' def __init__(self, device = None, decorator_factory = None, *a, **k): super(MoveDeviceChain, self).__init__(*a, **k) @@ -90,13 +92,15 @@ def _create_copiers(self): def create_copier_if_decorated(simpler): decorated = find_decorated_object(simpler, self._decorator_factory) - return SimplerDecoratedPropertiesCopier(decorated, self._decorator_factory) if decorated else None + if decorated: + return SimplerDecoratedPropertiesCopier(decorated, self._decorator_factory) return map(create_copier_if_decorated, find_simplers(self._track)) class CreateTrackWithSimpler(ConvertAction): - name = 'Simpler' + label = 'Simpler' + internal_name = 'audio_clip_to_simpler' def __init__(self, clip_slot = None, track = None, *a, **k): raise liveobj_valid(clip_slot) or AssertionError @@ -117,14 +121,15 @@ def __on_has_clip_changed(self): class SlicesToDrumRack(TrackBasedConvertAction): needs_deferred_invocation = True - name = 'Drum Rack' + label = 'Drum Rack' + internal_name = 'sliced_simpler_to_drum_rack' def __init__(self, device = None, *a, **k): raise isinstance(device, Live.SimplerDevice.SimplerDevice) or AssertionError super(SlicesToDrumRack, self).__init__(*a, **k) self._device = device self.__on_playback_mode_changed.subject = self._device - self.__on_sample_file_path_changed.subject = self._device + self.__on_sample_changed.subject = self._device def convert(self, song): Live.Conversions.sliced_simpler_to_drum_rack(song, self._device) @@ -133,13 +138,14 @@ def convert(self, song): def __on_playback_mode_changed(self): self.notify_action_invalidated() - @listens('sample_file_path') - def __on_sample_file_path_changed(self): + @listens('sample') + def __on_sample_changed(self): self.notify_action_invalidated() class DrumPadToMidiTrack(ConvertAction): - name = 'MIDI track' + label = 'MIDI track' + internal_name = 'drum_pad_to_midi_track' def __init__(self, drum_pad = None, track = None, *a, **k): raise liveobj_valid(drum_pad) or AssertionError @@ -161,7 +167,7 @@ def convert(self, song): class ConvertComponent(Component): - __events__ = ('cancel',) + __events__ = ('cancel', 'success') action_buttons = control_list(ButtonControl, color='Option.Unselected', pressed_color='Option.Selected') cancel_button = ButtonControl(color='Option.Unselected', pressed_color='Option.Selected') source_color_index = listenable_property.managed(UNCOLORED_INDEX) @@ -179,7 +185,7 @@ def __init__(self, tracks_provider = None, conversions_provider = possible_conve @listenable_property def available_conversions(self): - return map(lambda x: x.name, self._available_conversions) + return map(lambda x: x.label, self._available_conversions) def on_enabled_changed(self): super(ConvertComponent, self).on_enabled_changed() @@ -223,8 +229,7 @@ def _do_conversion(self, action_index): if action.needs_deferred_invocation: self._tasks.add(task.sequence(task.delay(1), task.run(lambda : self._do_conversion_deferred(action)))) return False - else: - self._invoke_conversion(action) + self._invoke_conversion(action) return True def _do_conversion_deferred(self, action): @@ -233,6 +238,7 @@ def _do_conversion_deferred(self, action): def _invoke_conversion(self, action): action.convert(self.song) + self.notify_success(action.internal_name) @cancel_button.released def cancel_button(self, button): diff --git a/Push2/custom_bank_definitions.py b/Push2/custom_bank_definitions.py index 942bb774..f9175a56 100644 --- a/Push2/custom_bank_definitions.py +++ b/Push2/custom_bank_definitions.py @@ -1,166 +1,987 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/custom_bank_definitions.py -from __future__ import absolute_import -from copy import deepcopy +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/custom_bank_definitions.py +from __future__ import absolute_import, print_function from ableton.v2.base.collection import IndexedDict -from .bank_definitions import BANK_DEFINITIONS as ORIGINAL_DEFINITIONS -from .bank_definitions import PARAMETERS_KEY, MAIN_KEY -from .parameter_slot_description import use +from pushbase.parameter_slot_description import use +from pushbase.banking_util import PARAMETERS_KEY, MAIN_KEY OPTIONS_KEY = 'Options' SHOW_WAVEFORM_KEY = 'show_waveform' -BANK_DEFINITIONS = deepcopy(ORIGINAL_DEFINITIONS) -BANK_DEFINITIONS['OriginalSimpler'] = IndexedDict(((MAIN_KEY, {PARAMETERS_KEY: ('Zoom', - use('Start').if_parameter('Mode').has_value('One-Shot').else_use('Start').if_parameter('Mode').has_value('Slicing').else_use('Start').if_parameter('Mode').has_value('Classic'), - use('End').if_parameter('Mode').has_value('One-Shot').else_use('End').if_parameter('Mode').has_value('Slicing').else_use('End').if_parameter('Mode').has_value('Classic'), - use('Fade In').if_parameter('Mode').has_value('One-Shot').else_use('Nudge').if_parameter('Mode').has_value('Slicing').else_use('S Start').if_parameter('Mode').has_value('Classic'), - use('Fade Out').if_parameter('Mode').has_value('One-Shot').else_use('Playback').if_parameter('Mode').has_value('Slicing').else_use('S Length').if_parameter('Mode').has_value('Classic'), - use('Transpose').if_parameter('Mode').has_value('One-Shot').else_use('Pad Slicing').if_parameter('Mode').has_value('Slicing').else_use('S Loop Length').if_parameter('Mode').has_value('Classic'), - use('Volume').if_parameter('Mode').has_value('One-Shot').else_use('Sensitivity').if_parameter('Mode').has_value('Slicing').else_use('S Loop Fade').if_parameter('Mode').has_value('Classic').and_parameter('Warp').has_value('off').else_use(''), - 'Mode'), - OPTIONS_KEY: (use('Loop').if_parameter('Mode').has_value('Classic').else_use('Trigger Mode'), - 'Warp as X Bars', - ':2', - 'x2', - 'Normalize', - 'Crop', - 'Reverse'), - SHOW_WAVEFORM_KEY: True}), - ('Global', {PARAMETERS_KEY: ('Glide Mode', - 'Glide Time', - use('').if_parameter('Mode').has_value('One-Shot').else_use('Voices').if_parameter('Mode').has_value('Classic').else_use('Voices').if_parameter('Mode').has_value('Slicing').and_parameter('Playback').has_value('Poly'), - 'Transpose', - 'Detune', - 'Vol < Vel', - 'Gain', - 'Volume'), - OPTIONS_KEY: ('', - use('').if_parameter('Mode').has_value('One-Shot').else_use('Retrigger').if_parameter('Mode').has_value('Classic').else_use('Retrigger').if_parameter('Mode').has_value('Slicing').and_parameter('Playback').has_value('Poly'), - '', - '', - '', - '', - ''), - SHOW_WAVEFORM_KEY: True}), - ('Envelopes', {PARAMETERS_KEY: ('Env. Type', - use('Fe On').if_parameter('Env. Type').has_value('Filter').else_use('Pe On').if_parameter('Env. Type').has_value('Pitch').else_use('Ve Attack').if_parameter('Mode').has_value('Classic').else_use('Fade In'), - use('Fe Attack').if_parameter('Env. Type').has_value('Filter').else_use('Pe Attack').if_parameter('Env. Type').has_value('Pitch').else_use('Ve Decay').if_parameter('Mode').has_value('Classic').else_use('Fade Out'), - use('Fe Decay').if_parameter('Env. Type').has_value('Filter').else_use('Pe Decay').if_parameter('Env. Type').has_value('Pitch').else_use('Ve Sustain').if_parameter('Mode').has_value('Classic').else_use('Volume'), - use('Fe Sustain').if_parameter('Env. Type').has_value('Filter').else_use('Pe Sustain').if_parameter('Env. Type').has_value('Pitch').else_use('Ve Release').if_parameter('Mode').has_value('Classic'), - use('Fe Release').if_parameter('Env. Type').has_value('Filter').else_use('Pe Release').if_parameter('Env. Type').has_value('Pitch'), - use('Fe < Env').if_parameter('Env. Type').has_value('Filter').else_use('Pe < Env').if_parameter('Env. Type').has_value('Pitch'), - use('Filter Freq').if_parameter('Env. Type').has_value('Filter').else_use('Transpose').if_parameter('Env. Type').has_value('Pitch')), - OPTIONS_KEY: ('', '', '', '', '', '', ''), - SHOW_WAVEFORM_KEY: False}), - ('Warp', {PARAMETERS_KEY: ('Zoom', - 'Start', - 'End', - 'Warp', - use('').if_parameter('Warp').has_value('off').else_use('Warp Mode'), - use('').if_parameter('Warp').has_value('off').else_use('Preserve').if_parameter('Warp Mode').has_value('Beats').else_use('Grain Size Tones').if_parameter('Warp Mode').has_value('Tones').else_use('Grain Size Texture').if_parameter('Warp Mode').has_value('Texture').else_use('Formants').if_parameter('Warp Mode').has_value('Pro'), - use('').if_parameter('Warp').has_value('off').else_use('Loop Mode').if_parameter('Warp Mode').has_value('Beats').else_use('Flux').if_parameter('Warp Mode').has_value('Texture').else_use('Envelope Complex Pro').if_parameter('Warp Mode').has_value('Pro'), - use('').if_parameter('Warp').has_value('off').else_use('Envelope').if_parameter('Warp Mode').has_value('Beats')), - OPTIONS_KEY: ('Warp as X Bars', ':2', 'x2', '', '', '', ''), - SHOW_WAVEFORM_KEY: True}), - ('Filter', {PARAMETERS_KEY: ('F On', - use('Filter Type').if_parameter('Filter Type').is_available(True).else_use('Filter Type (Legacy)'), - use('Filter Freq'), - use('Filter Res').if_parameter('Filter Res').is_available(True).else_use('Filter Res (Legacy)'), - use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Lowpass').else_use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Highpass').else_use('Filter Circuit - BP/NO/Morph'), - use('Filter Morph').if_parameter('Filter Type').has_value('Morph').else_use('').if_parameter('Filter Type').has_value('Lowpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Highpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Bandpass').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Notch').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('Filter Drive'), - 'Filt < Vel', - 'Filt < LFO'), - OPTIONS_KEY: (use('Filter Slope').if_parameter('F On').has_value('on'), - '', - '', - '', - '', - '', - '')}), - ('LFO', {PARAMETERS_KEY: ('L On', - 'L Wave', - use('L Rate').if_parameter('L Sync').has_value('Free').else_use('L Sync Rate'), - 'L Attack', - 'L R < Key', - 'Vol < LFO', - 'L Retrig', - 'L Offset'), - OPTIONS_KEY: ('', - use('LFO Sync Type').if_parameter('L On').has_value('on'), - '', - '', - '', - '', - '')}), - ('Pan', {PARAMETERS_KEY: ('Pan', 'Spread', 'Pan < Rnd', 'Pan < LFO', '', '', '', ''), - OPTIONS_KEY: ('', '', '', '', '', '', '')}))) -BANK_DEFINITIONS['Operator'] = IndexedDict((('Oscillators', {PARAMETERS_KEY: ('Oscillator', - use('Osc-A On').if_parameter('Oscillator').has_value('A').else_use('Osc-B On').if_parameter('Oscillator').has_value('B').else_use('Osc-C On').if_parameter('Oscillator').has_value('C').else_use('Osc-D On').if_parameter('Oscillator').has_value('D'), - use('Osc-A Wave').if_parameter('Oscillator').has_value('A').else_use('Osc-B Wave').if_parameter('Oscillator').has_value('B').else_use('Osc-C Wave').if_parameter('Oscillator').has_value('C').else_use('Osc-D Wave').if_parameter('Oscillator').has_value('D'), - use('A Fix On ').if_parameter('Oscillator').has_value('A').else_use('B Fix On ').if_parameter('Oscillator').has_value('B').else_use('C Fix On ').if_parameter('Oscillator').has_value('C').else_use('D Fix On ').if_parameter('Oscillator').has_value('D'), - use('A Fix Freq').if_parameter('Oscillator').has_value('A').and_parameter('A Fix On ').has_value('on').else_use('A Coarse').if_parameter('Oscillator').has_value('A').else_use('B Fix Freq').if_parameter('Oscillator').has_value('B').and_parameter('B Fix On ').has_value('on').else_use('B Coarse').if_parameter('Oscillator').has_value('B').else_use('C Fix Freq').if_parameter('Oscillator').has_value('C').and_parameter('C Fix On ').has_value('on').else_use('C Coarse').if_parameter('Oscillator').has_value('C').else_use('D Fix Freq').if_parameter('Oscillator').has_value('D').and_parameter('D Fix On ').has_value('on').else_use('D Coarse').if_parameter('Oscillator').has_value('D'), - use('A Fix Freq Mul').if_parameter('Oscillator').has_value('A').and_parameter('A Fix On ').has_value('on').else_use('A Fine').if_parameter('Oscillator').has_value('A').else_use('B Fix Freq Mul').if_parameter('Oscillator').has_value('B').and_parameter('B Fix On ').has_value('on').else_use('B Fine').if_parameter('Oscillator').has_value('B').else_use('C Fix Freq Mul').if_parameter('Oscillator').has_value('C').and_parameter('C Fix On ').has_value('on').else_use('C Fine').if_parameter('Oscillator').has_value('C').else_use('D Fix Freq Mul').if_parameter('Oscillator').has_value('D').and_parameter('D Fix On ').has_value('on').else_use('D Fine').if_parameter('Oscillator').has_value('D'), - use('Osc-A Level').if_parameter('Oscillator').has_value('A').else_use('Osc-B Level').if_parameter('Oscillator').has_value('B').else_use('Osc-C Level').if_parameter('Oscillator').has_value('C').else_use('Osc-D Level').if_parameter('Oscillator').has_value('D'), - 'Algorithm')}), - ('Osc. Envelopes', {PARAMETERS_KEY: ('Oscillator', - use('Osc-A On').if_parameter('Oscillator').has_value('A').else_use('Osc-B On').if_parameter('Oscillator').has_value('B').else_use('Osc-C On').if_parameter('Oscillator').has_value('C').else_use('Osc-D On').if_parameter('Oscillator').has_value('D'), - use('Ae Init').if_parameter('Oscillator').has_value('A').else_use('Be Init').if_parameter('Oscillator').has_value('B').else_use('Ce Init').if_parameter('Oscillator').has_value('C').else_use('De Init').if_parameter('Oscillator').has_value('D'), - use('Ae Attack').if_parameter('Oscillator').has_value('A').else_use('Be Attack').if_parameter('Oscillator').has_value('B').else_use('Ce Attack').if_parameter('Oscillator').has_value('C').else_use('De Attack').if_parameter('Oscillator').has_value('D'), - use('Ae Peak').if_parameter('Oscillator').has_value('A').else_use('Be Peak').if_parameter('Oscillator').has_value('B').else_use('Ce Peak').if_parameter('Oscillator').has_value('C').else_use('De Peak').if_parameter('Oscillator').has_value('D'), - use('Ae Decay').if_parameter('Oscillator').has_value('A').else_use('Be Decay').if_parameter('Oscillator').has_value('B').else_use('Ce Decay').if_parameter('Oscillator').has_value('C').else_use('De Decay').if_parameter('Oscillator').has_value('D'), - use('Ae Sustain').if_parameter('Oscillator').has_value('A').else_use('Be Sustain').if_parameter('Oscillator').has_value('B').else_use('Ce Sustain').if_parameter('Oscillator').has_value('C').else_use('De Sustain').if_parameter('Oscillator').has_value('D'), - use('Ae Release').if_parameter('Oscillator').has_value('A').else_use('Be Release').if_parameter('Oscillator').has_value('B').else_use('Ce Release').if_parameter('Oscillator').has_value('C').else_use('De Release').if_parameter('Oscillator').has_value('D'))}), - ('Filter', {PARAMETERS_KEY: ('Filter On', - use('Filter Type').if_parameter('Filter Type').is_available(True).else_use('Filter Type (Legacy)'), - use('Filter Freq'), - use('Filter Res').if_parameter('Filter Res').is_available(True).else_use('Filter Res (Legacy)'), - use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Lowpass').else_use('Filter Circuit - LP/HP').if_parameter('Filter Type').has_value('Highpass').else_use('Filter Circuit - BP/NO/Morph'), - use('Filter Morph').if_parameter('Filter Type').has_value('Morph').else_use('').if_parameter('Filter Type').has_value('Lowpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Highpass').and_parameter('Filter Circuit - LP/HP').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Bandpass').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('').if_parameter('Filter Type').has_value('Notch').and_parameter('Filter Circuit - BP/NO/Morph').has_value('Clean').else_use('Filter Drive'), - 'Shaper Type', - 'Shaper Amt')}), - ('Filt. Env.', {PARAMETERS_KEY: ('Filter On', 'Fe Init', 'Fe Attack', 'Fe Decay', 'Fe Sustain', 'Fe Release', 'Fe End', 'Fe Amount')}), - ('Filt. Mod.', {PARAMETERS_KEY: ('Filter On', 'Filt < Vel', 'Filt < LFO', 'Filt < Key', '', '', '', '')}), - ('LFO', {PARAMETERS_KEY: ('LFO On', - 'LFO Type', - 'LFO Range', - use('LFO Sync').if_parameter('LFO Range').has_value('Sync').else_use('LFO Rate'), - 'LFO Amt', - 'Filt < LFO', - use('Oscillator').if_parameter('LFO On').has_value('on'), - use('Osc-A < LFO').if_parameter('Oscillator').has_value('A').else_use('Osc-B < LFO').if_parameter('Oscillator').has_value('B').else_use('Osc-C < LFO').if_parameter('Oscillator').has_value('C').else_use('Osc-D < LFO').if_parameter('Oscillator').has_value('D'))}), - ('LFO Env.', {PARAMETERS_KEY: ('LFO On', 'Le Init', 'Le Attack', 'Le Decay', 'Le Sustain', 'Le Release', 'Le End', 'LFO Amt')}), - ('Pitch', {PARAMETERS_KEY: ('Transpose', - 'Spread', - 'Glide On', - 'Glide Time', - 'Pe R < Vel', - 'LFO < Pe', - use('Oscillator').if_parameter('Pe On').has_value('on'), - use('Osc-A < Pe').if_parameter('Oscillator').has_value('A').else_use('Osc-B < Pe').if_parameter('Oscillator').has_value('B').else_use('Osc-C < Pe').if_parameter('Oscillator').has_value('C').else_use('Osc-D < Pe').if_parameter('Oscillator').has_value('D'))}), - ('Pitch Env.', {PARAMETERS_KEY: ('Pe On', 'Pe Init', 'Pe Attack', 'Pe DecayPe Sustain', 'Pe Release', 'Pe End', 'Pe Amount')}), - ('Global', {PARAMETERS_KEY: ('Panorama', 'Pan < Rnd', 'Pan < Key', 'Filt < Key', 'Time', 'Time < Key', 'Tone', 'Volume')}), - ('Modulation', {PARAMETERS_KEY: ('Oscillator', - use('Osc-A Lev < Vel').if_parameter('Oscillator').has_value('A').else_use('Osc-B Lev < Vel').if_parameter('Oscillator').has_value('B').else_use('Osc-C Lev < Vel').if_parameter('Oscillator').has_value('C').else_use('Osc-D Lev < Vel').if_parameter('Oscillator').has_value('D'), - use('A Freq 0: - if parameter.name in self.ZOOMABLE_PARAMETERS: - sensitivity *= self._zoom_handling.zoom_factor + if liveobj_valid(parameter) and is_simpler(device) and liveobj_valid(device.sample): + if parameter.name in self.ZOOM_SENSITIVE_PARAMETERS: + if self.use_waveform_navigation: + sensitivity *= device.waveform_navigation.visible_proportion + else: + sensitivity *= self._zoom_handling.zoom_factor if parameter.name in self.PARAMETERS_RELATIVE_TO_ACTIVE_AREA: - active_area_quotient = device.sample_length / float(device.end_marker - device.start_marker + 1) + active_area_quotient = device.sample.length / float(device.sample.end_marker - device.sample.start_marker + 1) sensitivity *= active_area_quotient return sensitivity - def update_device_selection(self): - if self.allow_update_callback(): - super(DeviceComponent, self).update_device_selection() - @listenable_property def options(self): return getattr(self._bank, 'options', [None] * OPTIONS_PER_BANK) diff --git a/Push2/device_decoration.py b/Push2/device_decoration.py index ab33b13a..60cca0ed 100644 --- a/Push2/device_decoration.py +++ b/Push2/device_decoration.py @@ -1,31 +1,17 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/device_decoration.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/device_decoration.py +from __future__ import absolute_import, print_function from functools import partial -import Live -from ableton.v2.base import clamp, find_if, listens, liveobj_valid, SlotManager, Subject, listenable_property -from ableton.v2.base.collection import IndexedDict -from .decoration import LiveObjectDecorator, DecoratorFactory -from .internal_parameter import EnumWrappingParameter, InternalParameter, RelativeInternalParameter, WrappingParameter, to_percentage_display +from ableton.v2.base import depends, find_if, listenable_property, listens, liveobj_valid, SlotManager, Subject +from pushbase.decoration import LiveObjectDecorator, DecoratorFactory +from pushbase.internal_parameter import EnumWrappingParameter, InternalParameter +from pushbase.simpler_decoration import SimplerDeviceDecorator as SimplerDeviceDecoratorBase from .device_options import DeviceTriggerOption, DeviceSwitchOption, DeviceOnOffOption +from .waveform_navigation import SimplerWaveformNavigation -def from_sample_count(value, simpler): - return float(value) / simpler.sample_length +def get_parameter_by_name(decorator, name): + return find_if(lambda p: p.name == name, decorator._live_object.parameters) -def to_sample_count(value, simpler): - return clamp(int(value * simpler.sample_length), 0, simpler.sample_length - 1) - - -def from_user_range(minv, maxv): - return lambda v, s: (v - minv) / float(maxv - minv) - - -def to_user_range(minv, maxv): - return lambda v, s: clamp(v * (maxv - minv) + minv, minv, maxv) - - -BoolWrappingParameter = partial(WrappingParameter, to_property_value=lambda integer, _simpler: bool(integer), from_property_value=lambda boolean, _simpler: int(boolean), value_items=['off', 'on'], display_value_conversion=lambda val: 'on' if val else 'off') - class EnvelopeType(int): pass @@ -42,12 +28,6 @@ class OscillatorType(int): OscillatorType.b = OscillatorType(1) OscillatorType.c = OscillatorType(2) OscillatorType.d = OscillatorType(3) -SimplerWarpModes = IndexedDict(((Live.Clip.WarpMode.beats, 'Beats'), - (Live.Clip.WarpMode.tones, 'Tones'), - (Live.Clip.WarpMode.texture, 'Texture'), - (Live.Clip.WarpMode.repitch, 'Re-Pitch'), - (Live.Clip.WarpMode.complex, 'Complex'), - (Live.Clip.WarpMode.complex_pro, 'Pro'))) class NotifyingList(Subject): __events__ = ('index',) @@ -94,74 +74,88 @@ def __init__(self): super(BandTypesList, self).__init__(available_values=range(1, 9)) -class _SimplerDeviceDecorator(Subject, SlotManager, LiveObjectDecorator): - __events__ = ('slices',) +class WaveformNavigationParameter(SlotManager, InternalParameter): + """ Class for connecting a Simpler with a WaveformNavigation. It will create a new + instance of WaveformNavigation for every sample. It also still acts as a + parameter, for the current zooming implemenation. + + It also provides the "zoom" method interface, so it works with the + pushbase.mapped_control.MappedControl class. + """ + + def __init__(self, simpler = None, *a, **k): + super(WaveformNavigationParameter, self).__init__(*a, **k) + self._simpler = simpler + self._waveform_navigation = None + self.__on_sample_changed.subject = simpler + self.__on_sample_changed() + + @listenable_property + def waveform_navigation(self): + return self._waveform_navigation + + def zoom(self, value): + if self._waveform_navigation: + self._waveform_navigation.zoom(value) + + def touch_object(self, parameter): + if self._waveform_navigation: + self._waveform_navigation.touch_object(parameter) + + def release_object(self, parameter): + if self._waveform_navigation: + self._waveform_navigation.release_object(parameter) + + def change_object(self, parameter): + if self._waveform_navigation: + self._waveform_navigation.change_object(parameter) + + def focus_object(self, parameter): + if self._waveform_navigation: + self._waveform_navigation.focus_object(parameter) + + def reset_focus_and_animation(self): + if self._waveform_navigation: + self._waveform_navigation.reset_focus_and_animation() + + @listens('sample') + def __on_sample_changed(self): + sample = self._simpler.sample + if self._waveform_navigation is not None: + self.unregister_disconnectable(self._waveform_navigation) + self._waveform_navigation.disconnect() + if liveobj_valid(sample): + self._waveform_navigation = self.register_disconnectable(SimplerWaveformNavigation(simpler=self._simpler, waveform_length=sample.length)) + else: + self._waveform_navigation = None + self.notify_waveform_navigation() + + +class _SimplerDeviceDecorator(SimplerDeviceDecoratorBase): waveform_real_time_channel_id = '' playhead_real_time_channel_id = '' def __init__(self, song = None, envelope_types_provider = None, *a, **k): - super(_SimplerDeviceDecorator, self).__init__(*a, **k) self._song = song self._envelope_types_provider = envelope_types_provider if envelope_types_provider is not None else EnvelopeTypesList() - self.setup_parameters() + super(_SimplerDeviceDecorator, self).__init__(*a, **k) self.setup_options() - for disconnectable in self.options + self._additional_parameters: - self.register_disconnectable(disconnectable) - + self.register_disconnectables(self.options) self.__on_parameters_changed.subject = self._live_object - self.__on_sample_changed.subject = self._live_object - self.__on_playback_mode_changed.subject = self._live_object - self.__on_slices_changed.subject = self._live_object - self.__on_start_marker_changed.subject = self._live_object - self.__on_end_marker_changed.subject = self._live_object self.__on_signature_numerator_changed.subject = song self.__on_can_warp_as_changed.subject = self._live_object self.__on_can_warp_half_changed.subject = self._live_object self.__on_can_warp_double_changed.subject = self._live_object + self.__on_start_marker_changed.subject = self._live_object.sample + self.__on_end_marker_changed.subject = self._live_object.sample def setup_parameters(self): - self.zoom = InternalParameter(name='Zoom', parent=self._live_object) - self.start = WrappingParameter(name='Start', parent=self._live_object, source_property='start_marker', from_property_value=from_sample_count, to_property_value=to_sample_count) - self.end = WrappingParameter(name='End', parent=self._live_object, source_property='end_marker', from_property_value=from_sample_count, to_property_value=to_sample_count) - self.sensitivity = WrappingParameter(name='Sensitivity', parent=self._live_object, source_property='slicing_sensitivity', display_value_conversion=to_percentage_display) - self.mode = EnumWrappingParameter(name='Mode', parent=self, values_property='available_playback_modes', index_property='playback_mode', value_type=Live.SimplerDevice.PlaybackMode) - self.envelope = EnumWrappingParameter(name='Env. Type', parent=self._envelope_types_provider, values_property='available_values', index_property='index', value_type=EnvelopeType) - self.warp = BoolWrappingParameter(name='Warp', parent=self._live_object, source_property='warping') - self.warp_mode_param = EnumWrappingParameter(name='Warp Mode', parent=self, values_property='available_warp_modes', index_property='warp_mode', value_type=Live.Clip.WarpMode, to_index_conversion=lambda i: Live.Clip.WarpMode(SimplerWarpModes.key_by_index(i)), from_index_conversion=lambda i: SimplerWarpModes.index_by_key(i)) - self.nudge = RelativeInternalParameter(name='Nudge', parent=self._live_object) - self.slicing_playback_mode_param = EnumWrappingParameter(name='Playback', parent=self, values_property='available_slicing_playback_modes', index_property='slicing_playback_mode', value_type=Live.SimplerDevice.SlicingPlaybackMode) - self.voices_param = EnumWrappingParameter(name='Voices', parent=self, values_property='available_voice_numbers', index_property='voices', to_index_conversion=lambda i: self.available_voice_numbers[i], from_index_conversion=lambda i: self.available_voice_numbers.index(i), value_type=int) - self.granulation_resolution = EnumWrappingParameter(name='Preserve', parent=self, values_property='available_resolutions', index_property='beats_granulation_resolution', value_type=int) - self.transient_loop_mode = EnumWrappingParameter(name='Loop Mode', parent=self, values_property='available_transient_loop_modes', index_property='beats_transient_loop_mode', value_type=Live.SimplerDevice.TransientLoopMode) - self.transient_envelope = WrappingParameter(name='Envelope', parent=self._live_object, source_property='beats_transient_envelope', from_property_value=from_user_range(0.0, 100.0), to_property_value=to_user_range(0.0, 100.0)) - self.tones_grain_size_param = WrappingParameter(name='Grain Size Tones', parent=self._live_object, source_property='tones_grain_size', from_property_value=from_user_range(12.0, 100.0), to_property_value=to_user_range(12.0, 100.0)) - self.texture_grain_size_param = WrappingParameter(name='Grain Size Texture', parent=self._live_object, source_property='texture_grain_size', from_property_value=from_user_range(2.0, 263.0), to_property_value=to_user_range(2.0, 263.0)) - self.flux = WrappingParameter(name='Flux', parent=self._live_object, source_property='texture_flux', from_property_value=from_user_range(0.0, 100.0), to_property_value=to_user_range(0.0, 100.0)) - self.formants = WrappingParameter(name='Formants', parent=self._live_object, source_property='complex_pro_formants', from_property_value=from_user_range(0.0, 100.0), to_property_value=to_user_range(0.0, 100.0)) - self.complex_pro_envelope_param = WrappingParameter(name='Envelope Complex Pro', parent=self._live_object, source_property='complex_pro_envelope', from_property_value=from_user_range(8.0, 256.0), to_property_value=to_user_range(8.0, 256.0)) - self.pad_slicing_param = BoolWrappingParameter(name='Pad Slicing', parent=self._live_object, source_property='pad_slicing') - self.gain_param = WrappingParameter(name='Gain', parent=self._live_object, source_property='gain', display_value_conversion=lambda _: self._live_object.gain_display_string() if liveobj_valid(self._live_object) else '') - self._additional_parameters = (self.zoom, - self.end, - self.start, - self.sensitivity, - self.mode, - self.envelope, - self.warp, - self.warp_mode_param, - self.nudge, - self.slicing_playback_mode_param, - self.voices_param, - self.granulation_resolution, - self.transient_loop_mode, - self.transient_envelope, - self.tones_grain_size_param, - self.texture_grain_size_param, - self.flux, - self.formants, - self.complex_pro_envelope_param, - self.pad_slicing_param, - self.gain_param) + super(_SimplerDeviceDecorator, self).setup_parameters() + self.zoom = WaveformNavigationParameter(name='Zoom', parent=self, simpler=self) + self.zoom.focus_object(self.start) + self.zoom.add_waveform_navigation_listener(self.notify_waveform_navigation) + self.envelope = EnumWrappingParameter(name='Env. Type', parent=self, values_property_host=self._envelope_types_provider, index_property_host=self._envelope_types_provider, values_property='available_values', index_property='index', value_type=EnvelopeType) + self._additional_parameters.extend([self.zoom, self.envelope]) def setup_options(self): @@ -174,29 +168,17 @@ def call_simpler_function(name, *a): self.crop_option = DeviceTriggerOption(name='Crop', callback=partial(call_simpler_function, 'crop')) self.reverse_option = DeviceTriggerOption(name='Reverse', callback=partial(call_simpler_function, 'reverse')) - self.one_shot_sustain_mode_option = DeviceSwitchOption(name='Trigger Mode', default_label='Trigger', second_label='Gate', parameter=self.get_parameter_by_name('Trigger Mode')) + self.one_shot_sustain_mode_option = DeviceSwitchOption(name='Trigger Mode', default_label='Trigger', second_label='Gate', parameter=get_parameter_by_name(self, 'Trigger Mode')) self.retrigger_option = DeviceOnOffOption(name='Retrigger', property_host=self._live_object, property_name='retrigger') self.warp_as_x_bars_option = DeviceTriggerOption(name='Warp as X Bars', default_label=self.get_warp_as_option_label(), callback=lambda : call_simpler_function('warp_as', call_simpler_function('guess_playback_length')), is_active=lambda : get_simpler_flag('can_warp_as')) self.warp_half_option = DeviceTriggerOption(name=':2', callback=partial(call_simpler_function, 'warp_half'), is_active=lambda : get_simpler_flag('can_warp_half')) self.warp_double_option = DeviceTriggerOption(name='x2', callback=partial(call_simpler_function, 'warp_double'), is_active=lambda : get_simpler_flag('can_warp_double')) - self.lfo_sync_option = DeviceSwitchOption(name='LFO Sync Type', default_label='Free', second_label='Sync', parameter=self.get_parameter_by_name('L Sync')) - self.loop_option = DeviceOnOffOption(name='Loop', property_host=self.get_parameter_by_name('S Loop On'), property_name='value') - self.filter_slope_option = DeviceSwitchOption(name='Filter Slope', default_label='12dB', second_label='24dB', parameter=self.get_parameter_by_name('Filter Slope')) + self.lfo_sync_option = DeviceSwitchOption(name='LFO Sync Type', default_label='Free', second_label='Sync', parameter=get_parameter_by_name(self, 'L Sync')) + self.loop_option = DeviceOnOffOption(name='Loop', property_host=get_parameter_by_name(self, 'S Loop On'), property_name='value') + self.filter_slope_option = DeviceSwitchOption(name='Filter Slope', default_label='12dB', second_label='24dB', parameter=get_parameter_by_name(self, 'Filter Slope')) def get_parameter_by_name(self, name): - return find_if(lambda p: p.name == name, self._live_object.parameters) - - @property - def available_resolutions(self): - return ('1 Bar', '1/2', '1/4', '1/8', '1/16', '1/32', 'Transients') - - @property - def available_transient_loop_modes(self): - return ('Off', 'Forward', 'Alternate') - - @property - def parameters(self): - return tuple(self._live_object.parameters) + self._additional_parameters + return find_if(lambda p: p.name == name, self.parameters) @property def options(self): @@ -212,68 +194,26 @@ def options(self): self.filter_slope_option) @listenable_property - def current_playback_mode(self): - return str(self._live_object.playback_mode) - - @property - def available_voice_numbers(self): - return list(Live.SimplerDevice.get_available_voice_numbers()) - - @property - def available_playback_modes(self): - return ['Classic', 'One-Shot', 'Slicing'] + def waveform_navigation(self): + return self.zoom.waveform_navigation @property - def available_warp_modes(self): - return SimplerWarpModes.values() - - @property - def available_slicing_playback_modes(self): - return ['Mono', 'Poly', 'Thru'] + def available_resolutions(self): + return (u'1 Bar', u'\xbd', u'\xbc', u'\u215b', u'\ue001', u'\ue002', u'Transients') @listens('parameters') def __on_parameters_changed(self): - self.lfo_sync_option.set_parameter(self.get_parameter_by_name('L Sync')) - self.filter_slope_option.set_parameter(self.get_parameter_by_name('Filter Slope')) + self.lfo_sync_option.set_parameter(get_parameter_by_name(self, 'L Sync')) + self.filter_slope_option.set_parameter(get_parameter_by_name(self, 'Filter Slope')) - @listens('sample_file_path') - def __on_sample_changed(self): - self.start.connect() - self.end.connect() - self.sensitivity.connect() - self.warp.connect() - self.warp_mode_param.connect() - self.granulation_resolution.connect() - self.transient_loop_mode.connect() - self.transient_envelope.connect() - self.tones_grain_size_param.connect() - self.texture_grain_size_param.connect() - self.flux.connect() - self.formants.connect() - self.complex_pro_envelope_param.connect() - self.gain_param.connect() - self._reconnect_to_slices() + def _reconnect_sample_listeners(self): + super(_SimplerDeviceDecorator, self)._reconnect_sample_listeners() self._reconnect_to_markers() self._update_warp_as_label() - def _reconnect_to_slices(self): - self.__on_slices_changed.subject = None - self.__on_slices_changed.subject = self._live_object - self.notify_slices() - def _reconnect_to_markers(self): - self.__on_start_marker_changed.subject = None - self.__on_start_marker_changed.subject = self._live_object - self.__on_end_marker_changed.subject = None - self.__on_end_marker_changed.subject = self._live_object - - @listens('playback_mode') - def __on_playback_mode_changed(self): - self.notify_current_playback_mode() - - @listens('slices') - def __on_slices_changed(self): - self.notify_slices() + self.__on_start_marker_changed.subject = self._live_object.sample + self.__on_end_marker_changed.subject = self._live_object.sample def _update_warp_as_label(self): self.warp_as_x_bars_option.default_label = self.get_warp_as_option_label() @@ -310,24 +250,69 @@ def get_warp_as_option_label(self): return 'Warp as X Bars' -class _OperatorDeviceDecorator(LiveObjectDecorator): +class _OperatorDeviceDecorator(SlotManager, LiveObjectDecorator): def __init__(self, song = None, osc_types_provider = None, *a, **k): super(_OperatorDeviceDecorator, self).__init__(*a, **k) self._osc_types_provider = osc_types_provider if osc_types_provider is not None else OscillatorTypesList() - self.oscillator = EnumWrappingParameter(name='Oscillator', parent=self._osc_types_provider, values_property='available_values', index_property='index', value_type=OscillatorType) + self.__on_parameters_changed.subject = self._live_object + self.oscillator = EnumWrappingParameter(name='Oscillator', parent=self, values_property_host=self._osc_types_provider, index_property_host=self._osc_types_provider, values_property='available_values', index_property='index', value_type=OscillatorType) + self.filter_slope_option = DeviceSwitchOption(name='Filter Slope', default_label='12dB', second_label='24dB', parameter=get_parameter_by_name(self, 'Filter Slope')) + self.register_disconnectables(self.options) @property def parameters(self): return tuple(self._live_object.parameters) + (self.oscillator,) + @property + def options(self): + return (self.filter_slope_option,) + + @listens('parameters') + def __on_parameters_changed(self): + self.filter_slope_option.set_parameter(get_parameter_by_name(self, 'Filter Slope')) + + +class _SamplerDeviceDecorator(SlotManager, LiveObjectDecorator): + + def __init__(self, song = None, *a, **k): + super(_SamplerDeviceDecorator, self).__init__(*a, **k) + self.__on_parameters_changed.subject = self._live_object + self.filter_slope_option = DeviceSwitchOption(name='Filter Slope', default_label='12dB', second_label='24dB', parameter=get_parameter_by_name(self, 'Filter Slope')) + self.register_disconnectables(self.options) + + @property + def options(self): + return (self.filter_slope_option,) + + @listens('parameters') + def __on_parameters_changed(self): + self.filter_slope_option.set_parameter(get_parameter_by_name(self, 'Filter Slope')) + + +class _AutoFilterDeviceDecorator(SlotManager, LiveObjectDecorator): + + def __init__(self, song = None, *a, **k): + super(_AutoFilterDeviceDecorator, self).__init__(*a, **k) + self.__on_parameters_changed.subject = self._live_object + self.slope_option = DeviceSwitchOption(name='Slope', default_label='12dB', second_label='24dB', parameter=get_parameter_by_name(self, 'Slope')) + self.register_disconnectables(self.options) + + @property + def options(self): + return (self.slope_option,) + + @listens('parameters') + def __on_parameters_changed(self): + self.slope_option.set_parameter(get_parameter_by_name(self, 'Slope')) + class _Eq8DeviceDecorator(LiveObjectDecorator): def __init__(self, song = None, band_types_provider = None, *a, **k): super(_Eq8DeviceDecorator, self).__init__(*a, **k) self._band_types_provider = band_types_provider if band_types_provider is not None else BandTypesList() - self.band = EnumWrappingParameter(name='Band', parent=self._band_types_provider, values_property='available_values', index_property='index') + self.band = EnumWrappingParameter(name='Band', parent=self, values_property_host=self._band_types_provider, index_property_host=self._band_types_provider, values_property='available_values', index_property='index') @property def parameters(self): @@ -337,6 +322,8 @@ def parameters(self): class DeviceDecoratorFactory(DecoratorFactory): DECORATOR_CLASSES = {'OriginalSimpler': _SimplerDeviceDecorator, 'Operator': _OperatorDeviceDecorator, + 'MultiSampler': _SamplerDeviceDecorator, + 'AutoFilter': _AutoFilterDeviceDecorator, 'Eq8': _Eq8DeviceDecorator} @classmethod @@ -348,8 +335,9 @@ def generate_decorated_device(cls, device, additional_properties = {}, song = No def _should_be_decorated(cls, device): return liveobj_valid(device) and device.class_name in cls.DECORATOR_CLASSES - def _get_decorated_object(self, device, additional_properties, *a, **k): - return self.generate_decorated_device(device, additional_properties=additional_properties, *a, **k) + @depends(song=None) + def _get_decorated_object(self, device, additional_properties, song = None, *a, **k): + return self.generate_decorated_device(device, additional_properties=additional_properties, song=song, *a, **k) class SimplerDecoratedPropertiesCopier(object): diff --git a/Push2/device_navigation.py b/Push2/device_navigation.py index 119e4ed8..d59f9df4 100644 --- a/Push2/device_navigation.py +++ b/Push2/device_navigation.py @@ -1,15 +1,16 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/device_navigation.py -from __future__ import absolute_import, with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/device_navigation.py +from __future__ import absolute_import, print_function from contextlib import contextmanager from itertools import ifilter, imap, chain from functools import partial -from _Tools.multipledispatch import dispatch +from multipledispatch import dispatch import Live from ableton.v2.base import find_if, first, index_if, listenable_property, listens, listens_group, liveobj_changed, liveobj_valid, SlotGroup, SlotManager, Subject, task -from ableton.v2.control_surface.control import control_list, forward_control, StepEncoderControl +from ableton.v2.control_surface.components import device_to_appoint +from ableton.v2.control_surface.control import control_list, StepEncoderControl from ableton.v2.control_surface.mode import Component, ModesComponent +from pushbase.decoration import DecoratorFactory from pushbase.device_chain_utils import is_first_device_on_pad -from .decoration import DecoratorFactory from .item_lister_component import ItemListerComponent, ItemProvider def find_drum_pad(items): @@ -31,8 +32,17 @@ def is_active_element(device): return device.is_active +def set_enabled(device, is_on): + device.parameters[0].value = int(is_on) + + +def is_on(device): + return bool(device.parameters[0].value) + + def nested_device_parent(device): - return device.view.selected_chain if device.can_have_chains and device.view.is_showing_chain_devices and not device.view.is_collapsed else None + if device.can_have_chains and device.view.is_showing_chain_devices and not device.view.is_collapsed: + return device.view.selected_chain def collect_devices(track_or_chain, nesting_level = 0): @@ -235,15 +245,15 @@ def _move_in(self, rack, move_to_end = False): class DeviceNavigationComponent(ItemListerComponent): - __events__ = ('drum_pad_selection',) - select_buttons = forward_control(ItemListerComponent.select_buttons) + __events__ = ('drum_pad_selection', 'mute_solo_stop_cancel_action_performed') - def __init__(self, device_bank_registry = None, device_component = None, delete_handler = None, chain_selection = None, bank_selection = None, move_device = None, track_selection = None, *a, **k): + def __init__(self, device_bank_registry = None, banking_info = None, device_component = None, delete_handler = None, chain_selection = None, bank_selection = None, move_device = None, track_list_component = None, *a, **k): raise device_bank_registry is not None or AssertionError raise device_component is not None or AssertionError raise chain_selection is not None or AssertionError raise bank_selection is not None or AssertionError raise move_device is not None or AssertionError + raise track_list_component is not None or AssertionError self._flattened_chain = FlattenedDeviceChain() super(DeviceNavigationComponent, self).__init__(item_provider=self._flattened_chain, *a, **k) self._track_decorator = DecoratorFactory() @@ -258,7 +268,7 @@ def __init__(self, device_bank_registry = None, device_component = None, delete_ self._last_pressed_button_index = -1 self._selected_on_previous_press = None self._modes = self.register_component(ModesComponent()) - self._modes.add_mode('default', [track_selection, partial(self._chain_selection.set_parent, None), partial(self._bank_selection.set_device, None)]) + self._modes.add_mode('default', [partial(self._chain_selection.set_parent, None), partial(self._bank_selection.set_device, None)]) self._modes.add_mode('chain_selection', [self._chain_selection]) self._modes.add_mode('bank_selection', [self._bank_selection]) self._modes.selected_mode = 'default' @@ -267,6 +277,7 @@ def __init__(self, device_bank_registry = None, device_component = None, delete_ self.__on_bank_selection_closed.subject = self._bank_selection self._on_selected_track_changed() self._on_selected_track_changed.subject = self.song.view + self._track_list = track_list_component watcher = self.register_disconnectable(DeviceChainEnabledStateWatcher(device_navigation=self)) self.__on_enabled_state_changed.subject = watcher self._update_button_colors() @@ -275,35 +286,50 @@ def __init__(self, device_bank_registry = None, device_component = None, delete_ def modes(self): return self._modes - @select_buttons.pressed - def select_buttons(self, button): - self._last_pressed_button_index = button.index - device_or_pad = self.items[button.index].item - if not self._delete_handler or not self._delete_handler.is_deleting: - self._selected_on_previous_press = device_or_pad if self.selected_object != device_or_pad else None - self._select_item(device_or_pad) + def _in_device_enabling_mode(self): + return self._track_list.selected_mode == 'mute' - @select_buttons.released_immediately - def select_buttons(self, button): - self._last_pressed_button_index = -1 + def _on_select_button_pressed(self, button): device_or_pad = self.items[button.index].item - if self._delete_handler and self._delete_handler.is_deleting: - self._delete_item(device_or_pad) - elif self.selected_object == device_or_pad and device_or_pad != self._selected_on_previous_press: - self._on_reselecting_object(device_or_pad) - self._selected_on_previous_press = None - - @select_buttons.pressed_delayed - def select_buttons(self, button): - self._on_pressed_delayed(self.items[button.index].item) + if self._in_device_enabling_mode(): + self._toggle_device(device_or_pad) + self.notify_mute_solo_stop_cancel_action_performed() + else: + self._last_pressed_button_index = button.index + if not self._delete_handler or not self._delete_handler.is_deleting: + self._selected_on_previous_press = device_or_pad if self.selected_object != device_or_pad else None + self._select_item(device_or_pad) - @select_buttons.released - def select_buttons(self, button): + def _on_select_button_released_immediately(self, button): + if not self._in_device_enabling_mode(): + self._last_pressed_button_index = -1 + device_or_pad = self.items[button.index].item + if self._delete_handler and self._delete_handler.is_deleting: + self._delete_item(device_or_pad) + elif self.selected_object == device_or_pad and device_or_pad != self._selected_on_previous_press: + self._on_reselecting_object(device_or_pad) + self._selected_on_previous_press = None + + def _on_select_button_pressed_delayed(self, button): + if not self._in_device_enabling_mode(): + self._on_pressed_delayed(self.items[button.index].item) + + def _on_select_button_released(self, button): if button.index == self._last_pressed_button_index: self._modes.selected_mode = 'default' self._last_pressed_button_index = -1 self._end_move_device() + @dispatch(Live.DrumPad.DrumPad) + def _toggle_device(self, drum_pad): + if liveobj_valid(drum_pad): + drum_pad.mute = not drum_pad.mute + + @dispatch(object) + def _toggle_device(self, device): + if liveobj_valid(device) and device.parameters[0].is_enabled: + set_enabled(device, not is_on(device)) + @listens('enabled_state') def __on_enabled_state_changed(self): self._update_button_colors() @@ -311,11 +337,11 @@ def __on_enabled_state_changed(self): @listens('items') def __on_items_changed(self): new_items = map(lambda x: x.item, self.items) - if new_items and is_drum_pad(new_items[-1]): - lost_selection_on_empty_pad = self._flattened_chain.selected_item not in new_items - if self._should_select_drum_pad() or lost_selection_on_empty_pad: - self._select_item(self._current_drum_pad()) - self.moving and self._show_selected_item() + lost_selection_on_empty_pad = new_items and is_drum_pad(new_items[-1]) and self._flattened_chain.selected_item not in new_items + if self._should_select_drum_pad() or lost_selection_on_empty_pad: + self._select_item(self._current_drum_pad()) + if self.moving: + self._show_selected_item() self.notify_drum_pad_selection() @listenable_property @@ -326,12 +352,13 @@ def moving(self): def device_selection_update_allowed(self): return not self._should_select_drum_pad() - def _update_button_colors(self): - for button in self.select_buttons: - item = self.items[button.index] - device_or_pad = item.item - is_active = liveobj_valid(device_or_pad) and is_active_element(device_or_pad) - button.unchecked_color = 'ItemNavigation.ItemNotSelected' if is_active else 'DefaultButton.Off' + def _color_for_button(self, button_index, is_selected): + item = self.items[button_index] + device_or_pad = item.item + is_active = liveobj_valid(device_or_pad) and is_active_element(device_or_pad) + if not is_active: + return 'DefaultButton.Off' + return super(DeviceNavigationComponent, self)._color_for_button(button_index, is_selected) def _begin_move_device(self, device): if not self._move_device.is_enabled() and device.type != Live.Device.DeviceType.instrument: @@ -365,6 +392,9 @@ def unfold_current_drum_pad(self): self._current_track().drum_pad_selected = False self._current_drum_pad().canonical_parent.view.is_showing_chain_devices = True + def sync_selection_to_selected_device(self): + self._update_item_provider(self.song.view.selected_track.view.selected_device) + @property def is_drum_pad_selected(self): return is_drum_pad(self._flattened_chain.selected_item) @@ -434,9 +464,10 @@ def _appoint_device(self, device): @dispatch(object) def _do_select_item(self, device): self._current_track().drum_pad_selected = False - self.song.view.select_device(device) - if device.can_be_appointed: - self._appoint_device(device) + appointed_device = device_to_appoint(device) + self._appoint_device(appointed_device) + self.song.view.select_device(device, False) + self.song.appointed_device = appointed_device @dispatch(Live.DrumPad.DrumPad) def _on_reselecting_object(self, drum_pad): @@ -505,12 +536,12 @@ def _toggle(self, item): def _can_update_device_selection(self, new_selection): can_update = liveobj_valid(new_selection) - if not self.is_drum_pad_selected: - drum_pad_selected_or_requested = self._should_select_drum_pad() - if can_update and drum_pad_selected_or_requested: - if is_empty_rack(new_selection): - can_update = False - can_update = can_update and self.is_drum_pad_selected and not is_first_device_on_pad(new_selection, self._flattened_chain.selected_item) + drum_pad_selected_or_requested = self.is_drum_pad_selected or self._should_select_drum_pad() + if can_update and drum_pad_selected_or_requested: + if is_empty_rack(new_selection): + can_update = False + if can_update and self.is_drum_pad_selected: + can_update = not is_first_device_on_pad(new_selection, self._flattened_chain.selected_item) elif not can_update and not drum_pad_selected_or_requested: can_update = True return can_update diff --git a/Push2/device_options.py b/Push2/device_options.py index 248e6e1e..09ee851a 100644 --- a/Push2/device_options.py +++ b/Push2/device_options.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/device_options.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/device_options.py +from __future__ import absolute_import, print_function from ableton.v2.base import liveobj_valid, listenable_property, listens, const, Subject, Slot, SlotManager class DeviceTriggerOption(Subject): @@ -51,7 +51,9 @@ def _is_active(self): @listenable_property def active_index(self): - return int(bool(self._parameter.value)) if liveobj_valid(self._parameter) else 0 + if liveobj_valid(self._parameter): + return int(bool(self._parameter.value)) + return 0 @listens('value') def __on_value_changed(self): @@ -82,7 +84,9 @@ def notify_index_and_default_label(): self._property_slot = self.register_slot(Slot(subject=property_host, event=property_name, listener=notify_index_and_default_label)) def _property_value(self): - return getattr(self._property_host, self._property_name, False) if liveobj_valid(self._property_host) else False + if liveobj_valid(self._property_host): + return getattr(self._property_host, self._property_name, False) + return False def _is_active(self): return super(DeviceOnOffOption, self)._is_active() and liveobj_valid(self._property_host) diff --git a/Push2/device_parameter_bank_with_options.py b/Push2/device_parameter_bank_with_options.py index 3cb1dfa9..b8debab0 100644 --- a/Push2/device_parameter_bank_with_options.py +++ b/Push2/device_parameter_bank_with_options.py @@ -1,8 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/device_parameter_bank_with_options.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/device_parameter_bank_with_options.py +from __future__ import absolute_import, print_function from ableton.v2.base import listenable_property, liveobj_valid, find_if +from pushbase.device_parameter_bank import create_device_bank, DescribedDeviceParameterBank from .custom_bank_definitions import OPTIONS_KEY, SHOW_WAVEFORM_KEY -from .device_parameter_bank import create_device_bank, DescribedDeviceParameterBank OPTIONS_PER_BANK = 7 class DescribedDeviceParameterBankWithOptions(DescribedDeviceParameterBank): diff --git a/Push2/device_view_component.py b/Push2/device_view_component.py index 4ce9a098..1be5b735 100644 --- a/Push2/device_view_component.py +++ b/Push2/device_view_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/device_view_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/device_view_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import const, listens, liveobj_valid from ableton.v2.control_surface import Component from ableton.v2.control_surface.mode import ModesComponent @@ -12,6 +13,7 @@ def __init__(self, parameter_provider = None, device_type_provider = const('defa self._parameter_provider = parameter_provider self._view = view self._parameters = None + self._parameter_names = [] self._device_type_provider = device_type_provider def update(self): @@ -19,9 +21,10 @@ def update(self): if self.is_enabled(): self._view.deviceType = self._device_type_provider() parameters = self._value_for_state(map(lambda p: p and p.parameter, self._parameter_provider.parameters), []) - if parameters != self._parameters: + if self._parameters_changed(parameters): self._view.parameters = parameters self._parameters = parameters + self._parameter_names = self._extract_names(parameters) def on_enabled_changed(self): self._view.visible = self.is_enabled() @@ -32,8 +35,16 @@ def on_enabled_changed(self): def _on_parameters_changed(self): self.update() + def _extract_names(self, parameters): + return [ (p.name if p else None) for p in parameters ] + + def _parameters_changed(self, new_parameters): + return new_parameters != self._parameters or self._extract_names(new_parameters) != self._parameter_names + def _value_for_state(self, enabled_value, disabled_value): - return enabled_value if self.is_enabled() else disabled_value + if self.is_enabled(): + return enabled_value + return disabled_value class SimplerDeviceViewConnector(DeviceViewConnector): @@ -72,17 +83,21 @@ def __init__(self, device_component = None, view_model = None, *a, **k): self.add_mode('default', DeviceViewConnector(parameter_provider=device_component, device_type_provider=self._device_type, view=view_model.deviceParameterView, is_enabled=False)) self.add_mode('OriginalSimpler', SimplerDeviceViewConnector(parameter_provider=device_component, device_component=device_component, device_type_provider=self._device_type, view=view_model.simplerDeviceView, is_enabled=False)) - self.selected_mode = 'default' self._on_parameters_changed.subject = device_component + self._on_parameters_changed() def _device_type(self): device = self._get_device() - return device.class_name if liveobj_valid(device) else '' + if liveobj_valid(device): + return device.class_name + return '' def _mode_to_select(self): device = self._get_device() device_type = device and device.class_name - return device_type if self.get_mode(device_type) != None else 'default' + if self.get_mode(device_type) != None: + return device_type + return 'default' @listens('parameters') def _on_parameters_changed(self): diff --git a/Push2/drum_group_component.py b/Push2/drum_group_component.py index ff18d5ab..d9c65e5b 100644 --- a/Push2/drum_group_component.py +++ b/Push2/drum_group_component.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/drum_group_component.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/drum_group_component.py +from __future__ import absolute_import, print_function from itertools import ifilter, izip from ableton.v2.base import flatten, liveobj_valid from pushbase.device_chain_utils import find_instrument_devices @@ -44,6 +44,7 @@ def _copy_simpler_properties(self, source_simpler, destination_simpler): class DrumGroupComponent(DrumGroupComponentBase): + __events__ = ('mute_solo_stop_cancel_action_performed',) def __init__(self, tracks_provider = None, device_decorator_factory = None, *a, **k): raise tracks_provider is not None or AssertionError @@ -57,6 +58,10 @@ def select_drum_pad(self, drum_pad): if len(drum_pad.chains) > 0 and self.song.view.selected_track.is_showing_chains: self._tracks_provider.scroll_into_view(drum_pad.chains[0]) + def _on_matrix_pressed(self, pad): + super(DrumGroupComponent, self)._on_matrix_pressed(pad) + self.notify_mute_solo_stop_cancel_action_performed() + def _on_selected_drum_pad_changed(self): super(DrumGroupComponent, self)._on_selected_drum_pad_changed() chain = self._selected_drum_pad.chains[0] if self._selected_drum_pad and len(self._selected_drum_pad.chains) > 0 else None diff --git a/Push2/drum_pad_parameter_component.py b/Push2/drum_pad_parameter_component.py index ab9a5313..669257f5 100644 --- a/Push2/drum_pad_parameter_component.py +++ b/Push2/drum_pad_parameter_component.py @@ -1,11 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/drum_pad_parameter_component.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/drum_pad_parameter_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import clamp, listenable_property, listens, liveobj_valid, SlotManager from ableton.v2.control_surface import CompoundComponent from ableton.v2.control_surface.control import StepEncoderControl +from pushbase.internal_parameter import InternalParameterBase from pushbase.parameter_provider import generate_info, ParameterProvider from .device_view_component import DeviceViewConnector -from .internal_parameter import InternalParameterBase NO_CHOKE_GROUP = u'None' MAX_CHOKE_GROUP = 16 NUM_CHOKE_GROUPS = MAX_CHOKE_GROUP + 1 @@ -28,7 +28,9 @@ def _on_pad_updated(self): @listenable_property def value(self): - return self._pad.choke_group if len(self._pad.chains) > 0 else 0 + if len(self._pad.chains) > 0: + return self._pad.choke_group + return 0 @value.setter def value(self, value): diff --git a/Push2/elements.py b/Push2/elements.py index ca584a6b..79127167 100644 --- a/Push2/elements.py +++ b/Push2/elements.py @@ -1,8 +1,10 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/elements.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/elements.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface.elements import SysexElement from pushbase.control_element_factory import create_button, create_note_button from pushbase.elements import Elements as ElementsBase from pushbase.touch_strip_element import TouchStripElement +from .parameter_mapping_sensitivities import CONTINUOUS_MAPPING_SENSITIVITY, FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY from . import sysex class Elements(ElementsBase): @@ -10,7 +12,7 @@ class Elements(ElementsBase): def __init__(self, model = None, *a, **k): raise model is not None or AssertionError self._model = model - super(Elements, self).__init__(*a, **k) + super(Elements, self).__init__(continuous_mapping_sensitivity=CONTINUOUS_MAPPING_SENSITIVITY, fine_grained_continuous_mapping_sensitivity=FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY, *a, **k) for button in self.select_buttons_raw: button.is_rgb = True diff --git a/Push2/firmware.py b/Push2/firmware.py index 9bf1c7e7..9f6eb89b 100644 --- a/Push2/firmware.py +++ b/Push2/firmware.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/firmware.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/firmware.py +from __future__ import absolute_import, print_function import fnmatch import logging import os @@ -18,10 +19,11 @@ def __init__(self, major = 0, minor = 0, build = 0, *a, **k): self.build = build def __cmp__(self, other): - if self.major == other.major and self.minor == other.minor: - if self.build == other.build: - return 0 - return 1 if self.major > other.major or self.major == other.major and self.minor > other.minor or self.major == other.major and self.minor == other.minor and self.build > other.build else -1 + if self.major == other.major and self.minor == other.minor and self.build == other.build: + return 0 + if self.major > other.major or self.major == other.major and self.minor > other.minor or self.major == other.major and self.minor == other.minor and self.build > other.build: + return 1 + return -1 def __repr__(self): return '' % (self.major, self.minor, self.build) diff --git a/Push2/firmware/app_push2_1.0.47.upgrade b/Push2/firmware/app_push2_1.0.47.upgrade new file mode 100644 index 00000000..a1b0c927 Binary files /dev/null and b/Push2/firmware/app_push2_1.0.47.upgrade differ diff --git a/Push2/hardware_settings_component.py b/Push2/hardware_settings_component.py index d5f98e8a..79110ca8 100644 --- a/Push2/hardware_settings_component.py +++ b/Push2/hardware_settings_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/hardware_settings_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/hardware_settings_component.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import clamp, listens, task from ableton.v2.control_surface import Component diff --git a/Push2/item_lister_component.py b/Push2/item_lister_component.py index 8019519b..55e41b3c 100644 --- a/Push2/item_lister_component.py +++ b/Push2/item_lister_component.py @@ -1,6 +1,7 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/item_lister_component.py -from __future__ import absolute_import -from ableton.v2.base import forward_property, index_if, listens, SlotManager, Subject +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/item_lister_component.py +from __future__ import absolute_import, print_function +from itertools import izip +from ableton.v2.base import forward_property, listens, SlotManager, Subject from ableton.v2.control_surface import Component, CompoundComponent from ableton.v2.control_surface.control import control_list, ButtonControl, RadioButtonControl @@ -207,7 +208,7 @@ def update(self): class ItemListerComponent(ItemListerComponentBase): - select_buttons = control_list(RadioButtonControl, checked_color='ItemNavigation.ItemSelected', unchecked_color='ItemNavigation.ItemNotSelected', unavailable_color='ItemNavigation.NoItem') + select_buttons = control_list(ButtonControl, unavailable_color='ItemNavigation.NoItem') def __init__(self, *a, **k): super(ItemListerComponent, self).__init__(*a, **k) @@ -225,17 +226,48 @@ def __init__(self, *a, **k): @listens('items') def __on_items_changed(self): self.select_buttons.control_count = len(self.items) - self._update_button_selection() + self._update_button_colors() self._scroll_overlay.update_scroll_buttons() @listens('selected_item') def __on_selection_changed(self): - self._update_button_selection() + self._update_button_colors() - def _update_button_selection(self): + def _update_button_colors(self): selected_item = self._item_provider.selected_item - items = self.items - selected_index = index_if(lambda item: item == selected_item, items) - if selected_index >= len(items): - selected_index = -1 - self.select_buttons.checked_index = selected_index \ No newline at end of file + for button, item in izip(self.select_buttons, self.items): + is_selected = item == selected_item + button.color = self._color_for_button(button.index, is_selected) + + def _color_for_button(self, button_index, is_selected): + if is_selected: + return 'ItemNavigation.ItemSelected' + return 'ItemNavigation.ItemNotSelected' + + @select_buttons.pressed + def select_buttons(self, button): + self._on_select_button_pressed(button) + + @select_buttons.pressed_delayed + def select_buttons(self, button): + self._on_select_button_pressed_delayed(button) + + @select_buttons.released + def select_buttons(self, button): + self._on_select_button_released(button) + + @select_buttons.released_immediately + def select_buttons(self, button): + self._on_select_button_released_immediately(button) + + def _on_select_button_pressed(self, button): + pass + + def _on_select_button_pressed_delayed(self, button): + pass + + def _on_select_button_released(self, button): + pass + + def _on_select_button_released_immediately(self, button): + pass \ No newline at end of file diff --git a/Push2/master_track.py b/Push2/master_track.py index 5e3acc08..b86d7139 100644 --- a/Push2/master_track.py +++ b/Push2/master_track.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/master_track.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/master_track.py +from __future__ import absolute_import, print_function from ableton.v2.base import listens from ableton.v2.control_surface import Component from ableton.v2.control_surface.control import ToggleButtonControl diff --git a/Push2/mixable_utilities.py b/Push2/mixable_utilities.py index 0945758e..8e4fa7fb 100644 --- a/Push2/mixable_utilities.py +++ b/Push2/mixable_utilities.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/mixable_utilities.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/mixable_utilities.py +from __future__ import absolute_import, print_function import Live from pushbase.device_chain_utils import find_instrument_meeting_requirement diff --git a/Push2/mixer_control_component.py b/Push2/mixer_control_component.py index 40a24319..2b41d737 100644 --- a/Push2/mixer_control_component.py +++ b/Push2/mixer_control_component.py @@ -1,13 +1,13 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/mixer_control_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/mixer_control_component.py +from __future__ import absolute_import, print_function from contextlib import contextmanager from functools import partial -from itertools import izip +from itertools import izip, izip_longest from math import ceil from ableton.v2.base import clamp, depends, listens, liveobj_valid, NamedTuple from ableton.v2.control_surface.control import control_list, ButtonControl from ableton.v2.control_surface.mode import ModesComponent -from .mapped_control import MappedControl +from pushbase.mapped_control import MappedControl from .real_time_channel import RealTimeDataComponent from .item_lister_component import SimpleItemSlot MIXER_SECTIONS = ('Volumes', 'Pans') @@ -69,7 +69,7 @@ def _setup_modes(self, view_model): self._add_mode('panning', view_model.panControlListView, lambda mixer: mixer.panning) def add_send_mode(index): - self._add_mode(SEND_MODE_NAMES[index], view_model.sendControlListView, lambda mixer: mixer.sends[self._send_offset + index] if len(mixer.sends) > self._send_offset + index else None) + self._add_mode(SEND_MODE_NAMES[index], view_model.sendControlListView, lambda mixer: (mixer.sends[self._send_offset + index] if len(mixer.sends) > self._send_offset + index else None)) for i in xrange(SEND_LIST_LENGTH): add_send_mode(i) @@ -170,7 +170,7 @@ def _update_controls(self, parameter_getter, control_view): parameters = self._get_parameter_for_tracks(parameter_getter) control_view.parameters = parameters self._update_realtime_ids() - for control, parameter in map(None, self.controls, parameters): + for control, parameter in izip_longest(self.controls, parameters): control.mapped_parameter = parameter def _update_realtime_ids(self): @@ -181,7 +181,7 @@ def _update_realtime_ids(self): def _get_parameter_for_tracks(self, parameter_getter): tracks = self._track_provider.items self.controls.control_count = len(tracks) - return map(lambda t: parameter_getter(t.mixer_device) if t else None, tracks) + return map(lambda t: (parameter_getter(t.mixer_device) if t else None), tracks) def mode_can_be_used(self, mode): return mode not in SEND_MODE_NAMES or SEND_MODE_NAMES.index(mode) + self._send_offset < self.number_sends diff --git a/Push2/mode_collector.py b/Push2/mode_collector.py index 28a3f768..20a4badf 100644 --- a/Push2/mode_collector.py +++ b/Push2/mode_collector.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/mode_collector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/mode_collector.py +from __future__ import absolute_import, print_function from ableton.v2.base import listenable_property, listens, Subject, SlotManager class ModeCollector(SlotManager, Subject): diff --git a/Push2/model/__init__.py b/Push2/model/__init__.py index 2fc6f962..709f0290 100644 --- a/Push2/model/__init__.py +++ b/Push2/model/__init__.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/model/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/model/__init__.py +from __future__ import absolute_import, print_function from .declaration import Binding, custom_property, id_property, listmodel, listof, view_property, ViewModel, ModelVisitor from .repr import BrowserItemAdapter, BrowserListWrapper, ClipAdapter, DeviceAdapter, DeviceParameterAdapter, EditModeOptionAdapter, ItemListAdapter, ItemSlotAdapter, LiveDialogAdapter, OptionsListAdapter, SimplerDeviceAdapter, TrackAdapter, TrackControlAdapter, TrackListAdapter, VisibleAdapter __all__ = (ModelVisitor,) @@ -20,6 +21,7 @@ class Track(Binding): parentColorIndex = view_property(int, -1) arm = view_property(bool, False) isMaster = view_property(bool, False) + isAudio = view_property(bool, False) id = id_property() @@ -121,11 +123,6 @@ class DeviceParameter(Binding): isActive = view_property(bool, True) -class MixerButtonState(Binding): - id = id_property() - is_pressed = view_property(bool, False) - - class Encoder(Binding): id = id_property() touched = view_property(bool, False) @@ -140,9 +137,37 @@ class Slice(Binding): time = view_property(int, -1) +class Sample(Binding): + start_marker = view_property(int, 0) + end_marker = view_property(int, 0) + length = view_property(int, 0) + + +class SimplerView(Binding): + sample_start = view_property(int, 0) + sample_end = view_property(int, 0) + sample_loop_start = view_property(int, 0) + sample_loop_end = view_property(int, 0) + sample_loop_fade = view_property(int, 0) + sample_env_fade_in = view_property(int, 0) + sample_env_fade_out = view_property(int, 0) + + +class WaveformNavigationFocusMarker(Binding): + name = view_property(unicode, u'') + position = view_property(int, -1) + + +class WaveformNavigation(Binding): + animate_visible_region = view_property(bool, False) + visible_start = view_property(float, 0.0, depends=animate_visible_region) + visible_end = view_property(float, 0.0, depends=animate_visible_region) + show_focus = view_property(bool, False) + focus_marker = view_property(WaveformNavigationFocusMarker) + + class SimplerProperties(Binding): ADAPTER = SimplerDeviceAdapter - sample_file_path = view_property(unicode, '') sample_start = view_property(DeviceParameter) sample_length = view_property(DeviceParameter) loop_length = view_property(DeviceParameter) @@ -152,11 +177,14 @@ class SimplerProperties(Binding): start_marker = view_property(int, 0) end_marker = view_property(int, 0) multi_sample_mode = view_property(bool, False) - current_playback_mode = view_property(unicode, '') + current_playback_mode = view_property(int, 0) slices = view_property(listmodel(Slice)) selected_slice = view_property(Slice) playhead_real_time_channel_id = view_property(unicode, '') waveform_real_time_channel_id = view_property(unicode, '') + sample = view_property(Sample) + view = view_property(SimplerView) + waveform_navigation = view_property(WaveformNavigation) class DeviceParameterListModel(ViewModel): @@ -258,6 +286,7 @@ class ScalesModel(Binding): root_note_names = view_property(listof(unicode), '') selected_root_note_index = view_property(int, -1) note_layout = view_property(NoteLayout) + horizontal_navigation = view_property(bool, False) class QuantizeSettingsModel(Binding): @@ -315,6 +344,7 @@ class LoopSettingsModel(Binding): loop_parameters = view_property(listof(DeviceParameter)) zoom = view_property(DeviceParameter) processed_zoom_requests = view_property(int, 0) + waveform_navigation = view_property(WaveformNavigation) class AudioClipSettingsModel(Binding): @@ -325,11 +355,21 @@ class AudioClipSettingsModel(Binding): playhead_real_time_channel_id = view_property(unicode, '') +class ClipViewModel(Binding): + sample_length = view_property(int, -1) + sample_start_marker = view_property(int, -1) + sample_end_marker = view_property(int, -1) + sample_loop_start = view_property(int, -1) + sample_loop_end = view_property(int, -1) + + class ClipModel(Binding): ADAPTER = ClipAdapter id = id_property() name = view_property(unicode, '') color_index = view_property(int, -1) + is_recording = view_property(bool, False) + view = view_property(ClipViewModel) class ClipControlModel(Binding): @@ -395,12 +435,17 @@ class ProfilingSettingsModel(Binding): show_realtime_ipc_stats = view_property(bool, False) +class ExperimentalSettingsModel(Binding): + new_waveform_navigation = view_property(bool, False) + + class SettingsModel(Binding): general = view_property(GeneralSettingsModel) pad_settings = view_property(PadSettingsModel) hardware = view_property(HardwareSettingsModel) display_debug = view_property(DisplayDebugSettingsModel) profiling = view_property(ProfilingSettingsModel) + experimental = view_property(ExperimentalSettingsModel) class VelocityCurveModel(Binding): @@ -456,7 +501,6 @@ class RootModel(ViewModel): realTimeClient = view_property(RealTimeClient) modeState = view_property(ModeState) controls = view_property(Controls) - mixerButtonState = view_property(MixerButtonState) liveDialogView = view_property(LiveDialogViewModel) mixerSelectView = view_property(MixerSelectionListModel) trackMixerSelectView = view_property(TrackMixerSelectionListModel) diff --git a/Push2/model/declaration.py b/Push2/model/declaration.py index a2526dee..f5bf18d8 100644 --- a/Push2/model/declaration.py +++ b/Push2/model/declaration.py @@ -1,5 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/model/declaration.py - +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/model/declaration.py +from __future__ import absolute_import, print_function +from itertools import count class ModelDeclarationException(Exception): pass @@ -17,10 +18,14 @@ class UndeclaredReferenceClass(ModelDeclarationException): pass +class ViewModelCantContainListModels(ModelDeclarationException): + pass + + def is_view_model_property_decl(decl): try: - return ViewModel in decl.property_type.__mro__ - except AttributeError: + return issubclass(decl.property_type, ViewModel) + except TypeError: return False @@ -34,8 +39,8 @@ def is_list_model_property_decl(decl): def is_binding_property_decl(decl): try: - return Binding in decl.property_type.__mro__ - except AttributeError: + return issubclass(decl.property_type, Binding) + except TypeError: return False @@ -52,23 +57,32 @@ def is_value_property_type(decl): bool) +def is_custom_property(decl): + return isinstance(decl, custom_property) + + class property_declaration(object): pass class view_property(property_declaration): sentinel = object() + GLOBAL_ORDER = count() - def __init__(self, property_type, default_value = sentinel, *a, **k): + def __init__(self, property_type, default_value = sentinel, depends = (), *a, **k): super(view_property, self).__init__(*a, **k) self.property_type = property_type self.default_value = default_value + self.order = self.GLOBAL_ORDER.next() raise default_value is not self.sentinel or is_view_model_property_decl(self) or is_list_property_decl(self) or is_binding_property_decl(self) or is_reference_property_decl(self) or AssertionError + depends = depends def __repr__(self): return '<%s %r>' % (self.__class__.__name__, self.property_type) def visit(self, name, visitor): + if name == 'id': + raise WrongIdPropertyDeclaration visitor.visit_view_property(name, self) @@ -79,20 +93,28 @@ def __init__(self, property_type, wrapper_class = None, *a, **k): super(custom_property, self).__init__(property_type=property_type, *a, **k) self.wrapper_class = wrapper_class + def visit(self, name, visitor): + if name == 'id': + raise WrongIdPropertyDeclaration + visitor.visit_custom_property(name, self) + class id_property(property_declaration): property_type = int default_value = -1 + order = -1 @staticmethod def id_attribute_getter(obj): if hasattr(obj, '__id__'): return unicode(obj.__id__) - elif hasattr(obj, '_live_ptr'): + if hasattr(obj, '_live_ptr'): return unicode(obj._live_ptr) return unicode(id(obj)) def visit(self, name, visitor): + if name != 'id': + raise WrongIdPropertyDeclaration visitor.visit_id_property(name, self) @@ -113,29 +135,55 @@ class listmodel(listof): class ModelVisitor(object): def visit_class(self, class_): - for name, decl in class_.__dict__.iteritems(): - if isinstance(decl, property_declaration): - decl.visit(name, self) + if issubclass(class_, Binding): + self.visit_binding_class(class_) + else: + self.visit_viewmodel_class(class_) + + def visit_binding_class(self, class_): + self.visit_class_declarations(class_) + + def visit_viewmodel_class(self, class_): + self.visit_class_declarations(class_) + + def visit_class_declarations(self, class_): + view_properties = ((name, decl) for name, decl in class_.__dict__.iteritems() if isinstance(decl, property_declaration)) + for name, decl in sorted(view_properties, key=lambda item: item[1].order): + decl.visit(name, self) def visit_id_property(self, name, decl): pass def visit_view_property(self, name, decl): - if is_value_property_type(decl): + if is_reference_property_decl(decl): + self.visit_reference_property(name, decl) + elif is_binding_property_decl(decl): + self.visit_binding_property(name, decl) + elif is_value_property_type(decl): self.visit_value_property(name, decl) elif is_view_model_property_decl(decl): self.visit_view_model_property(name, decl) elif is_list_property_decl(decl): self.visit_list_property(name, decl) + else: + raise Exception('Invalid property declaration') + + def visit_reference_property(self, name, decl): + pass def visit_value_property(self, name, decl): pass - def visit_view_model_property(self, name, decl): + def visit_binding_property(self, _name, decl): + self.visit_class(decl.property_type) + + def visit_view_model_property(self, _name, decl): self.visit_class(decl.property_type) def visit_list_property(self, name, decl): - if is_value_property_type(decl.property_type): + if is_reference_property_decl(decl.property_type): + self.visit_reference_list_property(name, decl, decl.property_type.property_type) + elif is_value_property_type(decl.property_type): self.visit_value_list_property(name, decl, decl.property_type.property_type) elif is_list_model_property_decl(decl): self.visit_list_model_property(name, decl, decl.property_type.property_type) @@ -147,12 +195,18 @@ def visit_list_property(self, name, decl): def visit_value_list_property(self, name, decl, value_type): pass - def visit_list_model_property(self, name, decl, value_type): + def visit_custom_property(self, name, decl): + pass + + def visit_list_model_property(self, _name, _decl, value_type): self.visit_class(value_type) - def visit_complex_list_property(self, name, decl, value_type): + def visit_complex_list_property(self, _name, _decl, value_type): self.visit_class(value_type) + def visit_reference_list_property(self, name, decl, reference_name): + pass + class ModelMeta(type): diff --git a/Push2/model/generation.py b/Push2/model/generation.py index 419b39cb..7a49d7be 100644 --- a/Push2/model/generation.py +++ b/Push2/model/generation.py @@ -1,9 +1,13 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/model/generation.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/model/generation.py +from __future__ import absolute_import, print_function +from hashlib import md5 +from contextlib import contextmanager +from collections import namedtuple from operator import attrgetter from functools import partial -from ableton.v2.base import Disconnectable, memoize, SlotManager, Slot, has_event +from ableton.v2.base import Disconnectable, SlotManager, Slot, has_event from .repr import ModelAdapter -from .declaration import custom_property, id_property, is_binding_property_decl, is_list_property_decl, is_list_model_property_decl, is_reference_property_decl, is_view_model_property_decl, view_property, WrongIdPropertyDeclaration, ViewModelsCantContainRefs, UndeclaredReferenceClass +from .declaration import ViewModelsCantContainRefs, ViewModelCantContainListModels, UndeclaredReferenceClass, ModelVisitor class AdapterAwareSlot(Slot): """ @@ -19,7 +23,7 @@ def subject_valid(self, adapter): class ModelUpdateNotifier(object): def __init__(self, step = None, parent = None, delegate = None): - raise parent is not None or step is None or AssertionError, (parent, step) + raise parent is not None or step is None or AssertionError((parent, step)) self._step = step self._delegate = delegate self.path = [] if self._step is None else parent.path + [self._step] @@ -97,8 +101,8 @@ def _update_list(self): for value in self._value: self.register_disconnectable(value) - if not (self._verify_unique_ids and len(self._value) == len(set((item.values['id'].get() for item in self._value)))): - raise AssertionError, 'BoundListWrapper requires unique ids for items' + if self._verify_unique_ids: + raise len(self._value) == len(set((item.values['id'].get() for item in self._value))) or AssertionError('BoundListWrapper requires unique ids for items') def to_json(self): return [ v.to_json() for v in self._value ] @@ -290,86 +294,221 @@ def apply_wrapper(bound_object, name = None, wrapper = None, notifier = None): return partial(apply_wrapper, name=name, wrapper=wrapper) +ClassInfo = namedtuple('ClassInfo', ['class_', + 'd', + 'default_data', + 'wrappers', + 'children']) + +@contextmanager +def pushpop(collection, item): + collection.append(item) + yield item + collection.pop() + + +class BindingModelVisitor(ModelVisitor): + + def __init__(self, decl2class, references, name2class): + self._class_stack = [] + self._decl2class = decl2class + self._references = references + self._name2class = name2class + + @property + def current_class_info(self): + return self._class_stack[-1] + + @contextmanager + def __call__(self, class_info): + self._class_stack.append(class_info) + yield class_info + self._class_stack.pop() + + def visit_binding_class(self, class_): + if class_ not in self._decl2class: + with self(ClassInfo(class_=class_, d=None, default_data=None, wrappers={}, children=None)) as ci: + super(BindingModelVisitor, self).visit_binding_class(class_) + self._decl2class[class_] = partial(BoundObjectWrapper, wrappers=ci.wrappers, adapter=class_.__dict__.get('ADAPTER', ModelAdapter)) + self._name2class[class_.__name__] = self._decl2class[class_] + return self._decl2class[class_] + + def visit_value_property(self, name, decl): + super(BindingModelVisitor, self).visit_value_property(name, decl) + self.current_class_info.wrappers[name] = partial(BoundAttributeWrapper, attr_getter=attrgetter(name)) + + def visit_id_property(self, name, decl): + super(BindingModelVisitor, self).visit_id_property(name, decl) + self.current_class_info.wrappers[name] = partial(BoundAttributeWrapper, attr_getter=decl.id_attribute_getter) + + def visit_binding_property(self, name, decl): + super(BindingModelVisitor, self).visit_binding_property(name, decl) + self.current_class_info.wrappers[name] = make_bound_child_wrapper(name=name, wrapper=self._decl2class[decl.property_type]) + + def visit_value_list_property(self, name, decl, value_type): + super(BindingModelVisitor, self).visit_value_list_property(name, decl, value_type) + self.current_class_info.wrappers[name] = partial(BoundListWrapper, name=name, wrapper=SimpleWrapper, verify_unique_ids=False) + + def visit_complex_list_property(self, name, decl, value_type): + super(BindingModelVisitor, self).visit_complex_list_property(name, decl, value_type) + self.current_class_info.wrappers[name] = partial(BoundListWrapper, name=name, wrapper=self._decl2class[value_type], verify_unique_ids=False) + + def visit_custom_property(self, name, decl): + super(BindingModelVisitor, self).visit_custom_property(name, decl) + self.current_class_info.wrappers[name] = decl.wrapper_class + + def visit_list_model_property(self, name, decl, value_type): + super(BindingModelVisitor, self).visit_list_model_property(name, decl, value_type) + self.current_class_info.wrappers[name] = partial(BoundListWrapper, name=name, wrapper=self._decl2class[value_type], verify_unique_ids=True) + + def visit_reference_property(self, name, decl): + super(BindingModelVisitor, self).visit_reference_property(name, decl) + self._references.append(partial(self._resolve_reference, decl.property_type.class_name, self.current_class_info.wrappers, name, self._name2class)) + + def visit_reference_list_property(self, name, decl, reference_name): + self._references.append(partial(self._resolve_reference_list, decl.property_type.property_type.class_name, self.current_class_info.wrappers, name, self._name2class)) + + @staticmethod + def _resolve_reference(class_name, wrappers, name, decl2class): + generated_class = decl2class[class_name] + wrappers[name] = partial(DeferredWrapper, name=name, bound_object_wrapper=generated_class) + + @staticmethod + def _resolve_reference_list(class_name, wrappers, name, decl2class): + generated_class = decl2class[class_name] + wrappers[name] = partial(BoundListWrapper, name=name, wrapper=generated_class, verify_unique_ids=False) + + +class ViewModelVisitor(ModelVisitor): + + def __init__(self, *a, **k): + super(ViewModelVisitor, self).__init__(*a, **k) + self._class_stack = [] + self._decl2class = {} + self._name2class = {} + self._references = [] + + def resolve_references(self): + for r in self._references: + try: + r() + except KeyError: + raise UndeclaredReferenceClass + + @property + def current_class_info(self): + return self._class_stack[-1] + + @contextmanager + def __call__(self, class_info): + self._class_stack.append(class_info) + yield class_info + self._class_stack.pop() + + def visit_viewmodel_class(self, class_): + with self(ClassInfo(class_=class_, d={}, default_data={}, wrappers={}, children={})) as ci: + super(ViewModelVisitor, self).visit_viewmodel_class(class_) + ci.d['default_data'] = ci.default_data + ci.d['wrappers'] = ci.wrappers + ci.d['children'] = ci.children + generated_class = type('P2' + class_.__name__, (ModelMixin,), ci.d) + self._decl2class[class_] = generated_class + return generated_class + + def visit_binding_class(self, class_): + BindingModelVisitor(self._decl2class, self._references, self._name2class).visit_class(class_) + + def visit_value_property(self, name, decl): + super(ViewModelVisitor, self).visit_value_property(name, decl) + ci = self.current_class_info + ci.d[name] = _generate_model_mixin_property(name) + ci.default_data[name] = decl.default_value + ci.wrappers[name] = SimpleWrapper + + def visit_view_model_property(self, name, decl): + super(ViewModelVisitor, self).visit_view_model_property(name, decl) + ci = self.current_class_info + ci.d[name] = _generate_model_mixin_property(name) + ci.children[name] = self._decl2class[decl.property_type] + + def visit_value_list_property(self, name, decl, value_type): + super(ViewModelVisitor, self).visit_value_list_property(name, decl, value_type) + ci = self.current_class_info + ci.d[name] = _generate_model_mixin_property(name) + ci.default_data[name] = [] + ci.wrappers[name] = partial(NotifyingList, wrapper=SimpleWrapper) + + def visit_binding_property(self, name, decl): + super(ViewModelVisitor, self).visit_binding_property(name, decl) + ci = self.current_class_info + ci.d[name] = _generate_model_mixin_property(name) + ci.default_data[name] = None + ci.wrappers[name] = self._decl2class[decl.property_type] + + def visit_complex_list_property(self, name, decl, value_type): + super(ViewModelVisitor, self).visit_complex_list_property(name, decl, value_type) + ci = self.current_class_info + ci.d[name] = _generate_model_mixin_property(name) + ci.default_data[name] = [] + ci.wrappers[name] = partial(NotifyingList, wrapper=self._decl2class[value_type]) + + def visit_reference_property(self, name, decl): + raise ViewModelsCantContainRefs + + def visit_list_model_property(self, name, decl, value_type): + raise ViewModelCantContainListModels + + +class ModelFingerprintVisitor(ModelVisitor): + + def __init__(self, class_): + self._fingerprint = None + self._class2proplist = {} + self._property_prints = [] + self.visit_class(class_) + + @property + def property_prints(self): + return self._property_prints[-1] + + @property + def fingerprint(self): + if self._fingerprint is None: + self._fingerprint = ';'.join(('%s(%s)' % (classname, ','.join(property_prints)) for classname, property_prints in sorted(self._class2proplist.iteritems(), key=lambda item: item[0]))) + return self._fingerprint + + def visit_class(self, class_): + with pushpop(self._property_prints, []) as property_prints: + super(ModelFingerprintVisitor, self).visit_class(class_) + self._class2proplist[class_.__name__] = property_prints + + def visit_id_property(self, *_a): + self.property_prints.append('id') + + def visit_value_property(self, name, decl): + super(ModelFingerprintVisitor, self).visit_value_property(name, decl) + self.property_prints.append('%s:%s' % (name, decl.property_type.__name__)) + + def visit_view_model_property(self, name, decl): + super(ModelFingerprintVisitor, self).visit_view_model_property(name, decl) + self.property_prints.append('%s:%s' % (name, decl.property_type.__name__)) + + def visit_value_list_property(self, name, decl, property_type): + super(ModelFingerprintVisitor, self).visit_value_list_property(name, decl, property_type) + self.property_prints.append('%s:listof(%s)' % (name, property_type.__name__)) + + def visit_list_model_property(self, name, decl, property_type): + super(ModelFingerprintVisitor, self).visit_list_model_property(name, decl, property_type) + self.property_prints.append('%s:listmodel(%s)' % (name, property_type.__name__)) + + +def generate_model_fingerprint(cls): + return md5(ModelFingerprintVisitor(cls).fingerprint).hexdigest() + + def generate_mrs_model(cls): - name2bound_class = {} - references = [] - - def lookp_class_by_name(name): - try: - return name2bound_class[name] - except KeyError as e: - raise UndeclaredReferenceClass(e) - - @memoize - def _generate_mrs_model(cls): - d = {} - default_data = {} - wrappers = {} - children = {} - - @memoize - def binding_wrapper(cls): - raise cls.__name__ not in name2bound_class or AssertionError - name2bound_class[cls.__name__] = cls - wrappers = {} - adapter = cls.__dict__.get('ADAPTER', ModelAdapter) - for name, decl in cls.__dict__.iteritems(): - if name == 'id' and not isinstance(decl, id_property): - raise WrongIdPropertyDeclaration(cls) - if isinstance(decl, custom_property): - wrappers[name] = decl.wrapper_class - elif isinstance(decl, view_property): - if is_reference_property_decl(decl): - - def resolve_reference(decl, wrappers, name): - wrappers[name] = partial(DeferredWrapper, name=name, bound_object_wrapper=binding_wrapper(lookp_class_by_name(decl.property_type.class_name))) - - references.append(partial(resolve_reference, decl, wrappers, name)) - elif is_list_property_decl(decl): - is_list_model = is_list_model_property_decl(decl) - if is_reference_property_decl(decl.property_type): - - def resolve_reference(decl, wrappers, name): - wrappers[name] = partial(BoundListWrapper, name=name, wrapper=binding_wrapper(lookp_class_by_name(decl.property_type.class_name)), verify_unique_ids=is_list_model) - - references.append(partial(resolve_reference, decl.property_type, wrappers, name)) - else: - wrapper = binding_wrapper(decl.property_type.property_type) if is_binding_property_decl(decl.property_type) else SimpleWrapper - wrappers[name] = partial(BoundListWrapper, name=name, wrapper=wrapper, verify_unique_ids=is_list_model) - elif is_binding_property_decl(decl): - wrappers[name] = make_bound_child_wrapper(name=name, wrapper=binding_wrapper(decl.property_type)) - else: - wrappers[name] = partial(BoundAttributeWrapper, attr_getter=attrgetter(name)) - elif isinstance(decl, id_property): - wrappers[name] = partial(BoundAttributeWrapper, attr_getter=decl.id_attribute_getter) - - return partial(BoundObjectWrapper, wrappers=wrappers, adapter=adapter) - - for name, decl in cls.__dict__.iteritems(): - if isinstance(decl, view_property): - d[name] = _generate_model_mixin_property(name) - if is_reference_property_decl(decl): - raise ViewModelsCantContainRefs - elif is_binding_property_decl(decl): - default_data[name] = None - wrappers[name] = binding_wrapper(decl.property_type) - elif is_view_model_property_decl(decl): - children[name] = generate_mrs_model(decl.property_type) - elif is_list_property_decl(decl): - default_data[name] = [] - wrapper = binding_wrapper(decl.property_type.property_type) if is_binding_property_decl(decl.property_type) else SimpleWrapper - wrappers[name] = partial(NotifyingList, wrapper=wrapper) - else: - default_data[name] = decl.default_value - wrappers[name] = SimpleWrapper - - d['default_data'] = default_data - d['wrappers'] = wrappers - d['children'] = children - return type('P2' + cls.__name__, (ModelMixin,), d) - - model_class = _generate_mrs_model(cls) - for refdecl in references: - refdecl() - - return model_class \ No newline at end of file + visitor = ViewModelVisitor() + root_class = visitor.visit_viewmodel_class(cls) + visitor.resolve_references() + root_class.__fingerprint__ = generate_model_fingerprint(cls) + return root_class \ No newline at end of file diff --git a/Push2/model/repr.py b/Push2/model/repr.py index 0ea82767..d2a25c48 100644 --- a/Push2/model/repr.py +++ b/Push2/model/repr.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/model/repr.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/model/repr.py +from __future__ import absolute_import, print_function import re from functools import partial from ableton.v2.base import Slot, SlotError, SlotManager, Subject, find_if, listenable_property, listens, liveobj_valid @@ -52,18 +53,9 @@ def get_parameter_display_value(parameter): def get_parameter_unit(parameter): parameter_string = unicode(parameter) value = unit_pattern.findall(parameter_string) - return ''.join(string_pattern.findall(value[0])) if value else '' - - -def get_file_url(path_provider): - path = path_provider.sample_file_path - url = '' - if path != '': - normalized_path = path.replace('\\', '/') - if not normalized_path.startswith('/'): - normalized_path = '/' + normalized_path - url = 'file://' + normalized_path - return url + if value: + return ''.join(string_pattern.findall(value[0])) + return '' def strip_formatted_string(str): @@ -85,11 +77,15 @@ def is_valid(self): return liveobj_valid(self._adaptee) def __getattr__(self, name): - return object.__getattribute__(self, name) if name in self.__dict__ else getattr(self._adaptee, name) + if name in self.__dict__: + return object.__getattribute__(self, name) + return getattr(self._adaptee, name) @property def _live_ptr(self): - return self._adaptee._live_ptr if hasattr(self._adaptee, '_live_ptr') else id(self._adaptee) + if hasattr(self._adaptee, '_live_ptr'): + return self._adaptee._live_ptr + return id(self._adaptee) def _alias_observable_property(self, prop_name, alias_name, getter = None): default_getter = lambda self_: getattr(self_._adaptee, prop_name) @@ -130,7 +126,9 @@ def __init__(self, *a, **k): @listenable_property def valueItems(self): - return self._adaptee.value_items if self._adaptee.is_quantized else [] + if self._adaptee.is_quantized: + return self._adaptee.value_items + return [] @listenable_property def displayValue(self): @@ -189,34 +187,31 @@ def __init__(self, *a, **k): self.loop_length = get_parameter('S Loop Length') self.loop_on = get_parameter('S Loop On') self.zoom = get_parameter('Zoom') - - def get_raising_property(self_, name, default_value): - try: - return getattr(self_._adaptee, name) - except RuntimeError: - return default_value - - for prop, value in [('start_marker', 0), - ('end_marker', 0), - ('slicing_sensitivity', 0.0), - ('gain', 0.0)]: - getter = partial(get_raising_property, name=prop, default_value=value) - setattr(self.__class__, prop, property(getter)) + self.__on_sample_changed.subject = self._adaptee + self.__on_sample_changed() def _is_slicing(self): return self._adaptee.playback_mode == 2 def _get_slice_times(self): slice_times = [] - if self._is_slicing(): + if self._is_slicing() and liveobj_valid(self._adaptee.sample): try: - slice_times = self._adaptee.slices + slice_times = self._adaptee.sample.slices except RuntimeError: pass return slice_times - @property + @listens('sample') + def __on_sample_changed(self): + self.register_slot(self._adaptee.sample, self.notify_start_marker, 'start_marker') + self.register_slot(self._adaptee.sample, self.notify_end_marker, 'end_marker') + self.register_slot(self._adaptee.sample, self.notify_slices, 'slices') + self.register_slot(self._adaptee.sample, self.notify_slicing_sensitivity, 'slicing_sensitivity') + self.register_slot(self._adaptee.sample, self.notify_gain, 'gain') + + @listenable_property def slices(self): def unique_id(id_, existing = set()): @@ -234,14 +229,34 @@ def __init__(self, __id__, time): return [ SlicePoint(unique_id(time), time) for time in self._get_slice_times() ] - @property - def sample_file_path(self): - return get_file_url(self._adaptee) - @listenable_property def selected_slice(self): return find_if(lambda s: s.time == self.view.selected_slice, self.slices) + @listenable_property + def start_marker(self): + if liveobj_valid(self._adaptee) and liveobj_valid(self._adaptee.sample): + return self._adaptee.sample.start_marker + return 0 + + @listenable_property + def end_marker(self): + if liveobj_valid(self._adaptee) and liveobj_valid(self._adaptee.sample): + return self._adaptee.sample.end_marker + return 0 + + @listenable_property + def slicing_sensitivity(self): + if liveobj_valid(self._adaptee) and liveobj_valid(self._adaptee.sample): + return self._adaptee.sample.slicing_sensitivity + return 0.0 + + @listenable_property + def gain(self): + if liveobj_valid(self._adaptee) and liveobj_valid(self._adaptee.sample): + return self._adaptee.sample.gain + return 0.0 + class VisibleAdapter(ModelAdapter): @@ -410,7 +425,7 @@ def nestingLevel(self): @property def activated(self): try: - return self._adaptee.muted_via_solo or self._adaptee.mute and not not self._adaptee.solo + return not (self._adaptee.muted_via_solo or self._adaptee.mute and not self._adaptee.solo) except RuntimeError: return True @@ -424,7 +439,9 @@ def isFrozen(self): @listenable_property def arm(self): try: - return self._adaptee.arm if self._adaptee.can_be_armed else False + if self._adaptee.can_be_armed: + return self._adaptee.arm + return False except AttributeError: return False @@ -443,7 +460,9 @@ def __on_muted_via_solo_changed(self): @staticmethod def _convert_color_index(color_index): from ..colors import UNCOLORED_INDEX - return UNCOLORED_INDEX if color_index is None else color_index + if color_index is None: + return UNCOLORED_INDEX + return color_index @listenable_property def colorIndex(self): @@ -466,6 +485,13 @@ def isMaster(self): except AttributeError: return False + @property + def isAudio(self): + try: + return not self._adaptee.has_midi_input + except AttributeError: + return False + class TrackListAdapter(VisibleAdapter): __events__ = ('selectedTrack',) @@ -520,4 +546,6 @@ class LiveDialogAdapter(VisibleAdapter): @property def text(self): text = self._adaptee.text - return strip_formatted_string(text) if text is not None else '' \ No newline at end of file + if text is not None: + return strip_formatted_string(text) + return '' \ No newline at end of file diff --git a/Push2/model/uniqueid.py b/Push2/model/uniqueid.py index 9d7a5ca2..83b8608b 100644 --- a/Push2/model/uniqueid.py +++ b/Push2/model/uniqueid.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/model/uniqueid.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/model/uniqueid.py +from __future__ import absolute_import, print_function from itertools import count class UniqueIdMixin(object): diff --git a/Push2/mute_solo_stop.py b/Push2/mute_solo_stop.py new file mode 100644 index 00000000..426e6e0a --- /dev/null +++ b/Push2/mute_solo_stop.py @@ -0,0 +1,176 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/mute_solo_stop.py +from __future__ import absolute_import, print_function +from functools import partial +from ableton.v2.base import listenable_property, listens, listens_group, liveobj_valid, MultiSlot, SlotManager, Subject +from ableton.v2.control_surface import Component, CompoundComponent, Layer +from ableton.v2.control_surface.control import ButtonControl +from pushbase.message_box_component import Messenger +from .track_list import toggle_mixable_mute, toggle_mixable_solo +GLOBAL_ACTION_LOCK_MODE_DELAY = 0.6 + +def stop_clip_in_selected_track(song): + selected_track = song.view.selected_track + if selected_track != song.master_track and selected_track not in song.return_tracks: + selected_track.stop_all_clips() + + +class TrackStateColorIndicator(Subject, SlotManager): + color = listenable_property.managed('DefaultButton.On') + + def __init__(self, item_provider = None, track_property = None, property_active_color = None, song = None, *a, **k): + super(TrackStateColorIndicator, self).__init__(*a, **k) + self._provider = item_provider + self._active_color = property_active_color + self._property = track_property + self._song = song + self.__on_items_changed.subject = item_provider + self.register_slot(MultiSlot(listener=self.__on_property_changed, event=('selected_item', track_property), subject=item_provider)) + self._update_color() + + @listens('items') + def __on_items_changed(self): + self._update_color() + + def __on_property_changed(self): + self._update_color() + + def _update_color(self): + selected_mixable = self._provider.selected_item + use_active_color = liveobj_valid(selected_mixable) and selected_mixable != self._song.master_track and getattr(selected_mixable, self._property) + self.color = self._active_color if use_active_color else 'DefaultButton.On' + + +class GlobalMixerActionComponent(Component): + action_button = ButtonControl(delay_time=GLOBAL_ACTION_LOCK_MODE_DELAY) + + def __init__(self, track_list_component = None, mode = None, immediate_action = None, default_color_indicator = None, mode_locked_color = None, mode_active_color = None, *a, **k): + if not track_list_component is not None: + raise AssertionError + raise mode is not None or AssertionError + raise mode in track_list_component.modes or AssertionError + super(GlobalMixerActionComponent, self).__init__(*a, **k) + self._mode = mode + self._immediate_action = immediate_action + self._mode_locked = False + self._default_color_indicator = None + self._locked_color = mode_locked_color + self._active_color = mode_active_color if mode_active_color is not None else 'DefaultButton.On' + self._allow_released_immediately_action = True + self._track_list_component = track_list_component + self._default_color_indicator = default_color_indicator is not None and self.register_disconnectable(default_color_indicator) + self.__on_default_color_changed.subject = default_color_indicator + self._update_default_color() + + @listenable_property + def mode_locked(self): + return self._mode_locked + + @property + def mode(self): + return self._mode + + def cancel_release_action(self): + self._allow_released_immediately_action = False + + def cancel_locked_mode(self): + self._track_list_component.pop_mode(self._mode) + self._mode_locked = False + self._update_default_color() + + @listens('color') + def __on_default_color_changed(self, _): + self._update_default_color() + + @action_button.released_immediately + def action_button(self, button): + if self._allow_released_immediately_action: + self._immediate_action() + + @action_button.pressed + def action_button(self, button): + if self._mode_locked: + self._allow_released_immediately_action = False + self._unlock_mode() + else: + self._allow_released_immediately_action = True + self._track_list_component.push_mode(self._mode) + self.action_button.color = self._active_color + + @action_button.pressed_delayed + def action_button(self, button): + if self._allow_released_immediately_action: + self._lock_mode() + + @action_button.released + def action_button(self, button): + if not self._mode_locked: + self._track_list_component.pop_mode(self._mode) + self._update_default_color() + + def _lock_mode(self): + self._mode_locked = True + self.action_button.color = self._locked_color + self.notify_mode_locked(self._mode_locked) + + def _unlock_mode(self): + self.cancel_locked_mode() + self.notify_mode_locked(self._mode_locked) + + def _update_default_color(self): + if self._mode not in self._track_list_component.active_modes: + self.action_button.color = self._default_color_indicator.color if self._default_color_indicator else 'DefaultButton.On' + + +class MuteSoloStopClipComponent(CompoundComponent, Messenger): + MESSAGE_FOR_MODE = {'mute': 'Mute: %s', + 'solo': 'Solo: %s', + 'stop': 'Stop Clips: %s'} + stop_all_clips_button = ButtonControl() + + def __init__(self, item_provider = None, solo_track_button = None, mute_track_button = None, stop_clips_button = None, track_list_component = None, cancellation_action_performers = [], *a, **k): + super(MuteSoloStopClipComponent, self).__init__(*a, **k) + self._currently_locked_button_handler = None + self._track_list = track_list_component + self._solo_button_handler = self.register_component(GlobalMixerActionComponent(track_list_component=track_list_component, mode='solo', mode_active_color='Mixer.SoloOn', mode_locked_color='Mixer.LockedSoloMode', default_color_indicator=TrackStateColorIndicator(item_provider=item_provider, track_property='solo', property_active_color='Mixer.SoloOn', song=self.song), immediate_action=lambda : toggle_mixable_solo(item_provider.selected_item, self.song))) + self._solo_button_handler.layer = Layer(action_button=solo_track_button) + self._mute_button_handler = self.register_component(GlobalMixerActionComponent(track_list_component=track_list_component, mode='mute', mode_active_color='Mixer.MuteOff', mode_locked_color='Mixer.LockedMuteMode', default_color_indicator=TrackStateColorIndicator(item_provider=item_provider, track_property='mute', property_active_color='Mixer.MuteOff', song=self.song), immediate_action=lambda : toggle_mixable_mute(item_provider.selected_item, self.song))) + self._mute_button_handler.layer = Layer(action_button=mute_track_button) + self._stop_button_handler = self.register_component(GlobalMixerActionComponent(track_list_component=track_list_component, mode='stop', immediate_action=partial(stop_clip_in_selected_track, self.song), mode_locked_color='StopClips.LockedStopMode')) + self._stop_button_handler.layer = Layer(action_button=stop_clips_button) + self.__on_mute_solo_stop_cancel_action_performed.replace_subjects([track_list_component] + cancellation_action_performers) + button_handlers = (self._mute_button_handler, self._solo_button_handler, self._stop_button_handler) + self.__on_mode_locked_changed.replace_subjects(button_handlers, button_handlers) + self.__on_selected_item_changed.subject = item_provider + + @stop_all_clips_button.pressed + def stop_all_clips_button(self, button): + self.song.stop_all_clips() + + @listens_group('mute_solo_stop_cancel_action_performed') + def __on_mute_solo_stop_cancel_action_performed(self, _): + self.cancel_release_actions() + + @listens_group('mode_locked') + def __on_mode_locked_changed(self, is_locked, button_handler): + if is_locked: + if self._currently_locked_button_handler: + self._currently_locked_button_handler.cancel_locked_mode() + self._currently_locked_button_handler = button_handler + else: + self._currently_locked_button_handler = None + self._track_list.locked_mode = self._currently_locked_button_handler.mode if is_locked else None + self._show_mode_lock_change_notification(is_locked, button_handler.mode) + + @listens('selected_item') + def __on_selected_item_changed(self): + self.cancel_release_actions() + + def _show_mode_lock_change_notification(self, is_locked, mode): + message_template = self.MESSAGE_FOR_MODE[mode] + message_part = 'Locked' if is_locked else 'Unlocked' + self.show_notification(message_template % message_part) + + def cancel_release_actions(self): + self._solo_button_handler.cancel_release_action() + self._mute_button_handler.cancel_release_action() + self._stop_button_handler.cancel_release_action() \ No newline at end of file diff --git a/Push2/note_editor.py b/Push2/note_editor.py new file mode 100644 index 00000000..3680b3b6 --- /dev/null +++ b/Push2/note_editor.py @@ -0,0 +1,10 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/note_editor.py +from __future__ import absolute_import, print_function +from pushbase.note_editor_component import NoteEditorComponent + +class Push2NoteEditorComponent(NoteEditorComponent): + __events__ = ('mute_solo_stop_cancel_action_performed',) + + def _on_pad_pressed(self, value, x, y, is_momentary): + super(Push2NoteEditorComponent, self)._on_pad_pressed(value, x, y, is_momentary) + self.notify_mute_solo_stop_cancel_action_performed() \ No newline at end of file diff --git a/Push2/note_settings.py b/Push2/note_settings.py index aff99ef8..8c3d7e4d 100644 --- a/Push2/note_settings.py +++ b/Push2/note_settings.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/note_settings.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/note_settings.py +from __future__ import absolute_import, print_function from ableton.v2.base import listenable_property, listens, liveobj_valid from ableton.v2.control_surface.control import StepEncoderControl from pushbase.note_settings_component import NoteSettingBase, NoteSettingsComponentBase, step_offset_percentage @@ -103,7 +104,9 @@ def velocity(self): @listenable_property def color_index(self): clip = self.song.view.detail_clip - return clip.color_index if liveobj_valid(clip) else -1 + if liveobj_valid(clip): + return clip.color_index + return -1 @listens('detail_clip.color_index') def __on_color_index_changed(self, *a): diff --git a/Push2/notification_component.py b/Push2/notification_component.py index 430f4c2e..55125251 100644 --- a/Push2/notification_component.py +++ b/Push2/notification_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/notification_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/notification_component.py +from __future__ import absolute_import, print_function from weakref import ref import time from ableton.v2.base import nop, task, listenable_property diff --git a/Push2/observable_property_alias.py b/Push2/observable_property_alias.py index 28fce409..2e3d81d9 100644 --- a/Push2/observable_property_alias.py +++ b/Push2/observable_property_alias.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/observable_property_alias.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/observable_property_alias.py +from __future__ import absolute_import, print_function from ableton.v2.base import SlotManager, Slot class ObservablePropertyAlias(SlotManager): diff --git a/Push2/pad_velocity_curve.py b/Push2/pad_velocity_curve.py index fc546a93..2bf0a514 100644 --- a/Push2/pad_velocity_curve.py +++ b/Push2/pad_velocity_curve.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/pad_velocity_curve.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/pad_velocity_curve.py +from __future__ import absolute_import, print_function import math from ableton.v2.base import SerializableListenableProperties, chunks, clamp, listenable_property, task from ableton.v2.control_surface import Component diff --git a/Push2/parameter_mapping_sensitivities.py b/Push2/parameter_mapping_sensitivities.py index 42db20fa..c95b2dc9 100644 --- a/Push2/parameter_mapping_sensitivities.py +++ b/Push2/parameter_mapping_sensitivities.py @@ -1,9 +1,10 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/parameter_mapping_sensitivities.py -from pushbase import consts +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/parameter_mapping_sensitivities.py +from __future__ import absolute_import, print_function DEFAULT_SENSITIVITY_KEY = 'normal_sensitivity' FINE_GRAINED_SENSITIVITY_KEY = 'fine_grained_sensitivity' -DEFAULT_SENSITIVITY = consts.CONTINUOUS_MAPPING_SENSITIVITY -DEFAULT_FG_SENSITIVITY = consts.FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY +CONTINUOUS_MAPPING_SENSITIVITY = 1.0 +FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY = 0.01 +QUANTIZED_MAPPING_SENSITIVITY = 1.0 / 15.0 PARAMETER_SENSITIVITIES = {'Analog': {'OSC1 Octave': {DEFAULT_SENSITIVITY_KEY: 0.1}, 'OSC2 Octave': {DEFAULT_SENSITIVITY_KEY: 0.1}, 'OSC1 Semi': {DEFAULT_SENSITIVITY_KEY: 0.5}, diff --git a/Push2/push2.py b/Push2/push2.py index 8665dc03..098fa59b 100644 --- a/Push2/push2.py +++ b/Push2/push2.py @@ -1,20 +1,20 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/push2.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/push2.py +from __future__ import absolute_import, print_function from contextlib import contextmanager from functools import partial +import json import logging -import os -import sys +import weakref import Live import MidiRemoteScript -from ableton.v2.base import const, inject, listens, listens_group, liveobj_valid, Subject, NamedTuple, Disconnectable +from ableton.v2.base import const, inject, listens, listens_group, task, Subject, NamedTuple from ableton.v2.control_surface import BackgroundLayer, Component, IdentifiableControlSurface, Layer, get_element -from ableton.v2.control_surface.control import ButtonControl, DoubleClickContext +from ableton.v2.control_surface.control import ButtonControl from ableton.v2.control_surface.elements import ButtonMatrixElement, ComboElement, SysexElement -from ableton.v2.control_surface.mode import EnablingModesComponent, ModeButtonBehaviour, ModesComponent, LayerMode, LazyComponentMode, ReenterBehaviour, SetAttributeMode +from ableton.v2.control_surface.mode import EnablingModesComponent, ModesComponent, LayerMode, LazyComponentMode, ReenterBehaviour, SetAttributeMode from pushbase.actions import select_clip_and_get_name_from_slot, select_scene_and_get_name -from pushbase.browser_modes import BrowserHotswapMode -from pushbase.quantization_component import QuantizationComponent, QuantizationSettingsComponent +from pushbase.device_parameter_component import DeviceParameterComponentBase as DeviceParameterComponent +from pushbase.quantization_component import QUANTIZATION_NAMES_UNICODE, QuantizationComponent, QuantizationSettingsComponent from pushbase.selection import PushSelection from pushbase.percussion_instrument_finder_component import find_drum_group_device from pushbase import consts @@ -25,11 +25,11 @@ from .automation import AutomationComponent from .elements import Elements from .browser_component import BrowserComponent, NewTrackBrowserComponent +from .browser_modes import AddDeviceMode, AddTrackMode, BrowseMode, BrowserComponentMode, BrowserModeBehaviour from .device_decoration import DeviceDecoratorFactory from .skin_default import make_default_skin -from .mixer_component import MixerComponent -from .device_component import DeviceComponent -from .device_parameter_component import DeviceParameterComponent +from .mute_solo_stop import MuteSoloStopClipComponent +from .device_component import Push2DeviceProvider, DeviceComponent from .device_view_component import DeviceViewComponent from .device_navigation import is_empty_rack, DeviceNavigationComponent, MoveDeviceComponent from .drum_group_component import DrumGroupComponent @@ -44,6 +44,7 @@ from .hardware_settings_component import HardwareSettingsComponent from .master_track import MasterTrackComponent from .mixer_control_component import MixerControlComponent +from .note_editor import Push2NoteEditorComponent from .note_settings import NoteSettingsComponent from .notification_component import NotificationComponent from .pad_velocity_curve import PadVelocityCurveSender @@ -52,20 +53,16 @@ from .session_recording import SessionRecordingComponent from .session_ring_selection_linking import SessionRingSelectionLinking from .settings import create_settings -from .stop_clip_component import StopClipComponent from .track_mixer_control_component import TrackMixerControlComponent from .mode_collector import ModeCollector +from .real_time_channel import update_real_time_attachments from .setup_component import SetupComponent, Settings -from .device_enabling import DeviceEnablingComponent -from .track_selection import MixerTrackListComponent, SessionRingTrackProvider, ViewControlComponent -from .user_component import UserComponent -from .banking_util import BankingInfo +from .track_list import TrackListComponent +from .track_selection import SessionRingTrackProvider, ViewControlComponent +from .user_component import UserButtonBehavior, UserComponent from .custom_bank_definitions import BANK_DEFINITIONS -j = os.path.join -dn = os.path.dirname -sys.path.append(j(dn(dn(__file__)), '_Tools')) -import simplejson as json logger = logging.getLogger(__name__) +VELOCITY_RANGE_THRESHOLDS = [120, 60, 0] class QmlError(Exception): pass @@ -107,16 +104,22 @@ class Push2(IdentifiableControlSurface, PushBase): session_component_type = SessionComponent drum_group_note_editor_skin = 'DrumGroupNoteEditor' input_target_name_for_auto_arm = 'Push2 Input' + note_editor_velocity_range_thresholds = VELOCITY_RANGE_THRESHOLDS + device_component_class = DeviceComponent + device_provider_class = Push2DeviceProvider + bank_definitions = BANK_DEFINITIONS + note_editor_class = Push2NoteEditorComponent RESEND_MODEL_DATA_TIMEOUT = 5.0 - - def __init__(self, c_instance = None, model = None, *a, **k): - raise model is not None or AssertionError - self._model = model - self._double_click_context = DoubleClickContext() - self._real_time_mapper = c_instance.real_time_mapper - self._device_decorator_factory = DeviceDecoratorFactory() - self._clip_decorator_factory = ClipDecoratorFactory() - self._real_time_data_list = [] + DEFUNCT_EXTERNAL_PROCESS_RELAUNCH_TIMEOUT = 2.0 + + def __init__(self, c_instance = None, model = None, bank_definitions = None, *a, **k): + if not model is not None: + raise AssertionError + self._model = model + self._real_time_mapper = c_instance.real_time_mapper + self._clip_decorator_factory = ClipDecoratorFactory() + self._real_time_data_list = [] + self.bank_definitions = bank_definitions is not None and bank_definitions super(Push2, self).__init__(c_instance=c_instance, product_id_bytes=sysex.IDENTITY_RESPONSE_PRODUCT_ID_BYTES, *a, **k) self._board_revision = 0 self._firmware_version = FirmwareVersion(0, 0, 0) @@ -125,7 +128,7 @@ def __init__(self, c_instance = None, model = None, *a, **k): self._identified = False self._initialized = False self.register_disconnectable(model) - self.register_disconnectable(self._device_decorator_factory) + self.register_disconnectable(self._clip_decorator_factory) with self.component_guard(): self._model.realTimeClient = self._real_time_client self._real_time_client.clientId = self._real_time_mapper.client_id @@ -143,7 +146,6 @@ def initialize(self): self.__on_selected_track_frozen_changed.subject = self.song.view self.__on_selected_track_frozen_changed() self._switch_to_live_mode() - self._user.defer_sysex_sending = True self.update() if self._firmware_update.provided_version > self._firmware_version and self._board_revision > 0 and self._identified: self._firmware_update.start() @@ -157,10 +159,12 @@ def on_process_state_changed(self, state): self._connected = state == StateEnum.connected if state == StateEnum.died: self._c_instance.launch_external_process() - if state == StateEnum.connected: + elif state == StateEnum.connected: with self.component_guard(): self._try_initialize() self._model.commit_changes(send_all=True) + elif state in (StateEnum.defunct_process_terminated, StateEnum.defunct_process_killed): + self._tasks.add(task.sequence(task.wait(self.DEFUNCT_EXTERNAL_PROCESS_RELAUNCH_TIMEOUT), task.run(self._c_instance.launch_external_process))) def on_user_data_arrived(self, message): if self._initialized: @@ -174,7 +178,6 @@ def _process_qml_errors(self, data): raise QmlError('\n'.join(qmlerrors)) def disconnect(self): - self.__on_before_push_mode_sent.subject = None super(Push2, self).disconnect() self.__dict__.clear() logger.info('Push 2 script unloaded') @@ -183,14 +186,16 @@ def register_real_time_data(self, real_time_data): self._real_time_data_list.append(real_time_data) def _commit_real_time_data_changes(self): - for d in self._real_time_data_list: - d.update_attachment() + update_real_time_attachments(self._real_time_data_list) + + def _create_device_decorator_factory(self): + return DeviceDecoratorFactory() def _create_skin(self): return self.register_disconnectable(make_default_skin()) def _create_injector(self): - return inject(double_press_context=const(self._double_press_context), double_click_context=const(self._double_click_context), expect_dialog=const(self.expect_dialog), show_notification=const(self.show_notification), commit_model_changes=const(self._model.commit_changes), register_real_time_data=const(self.register_real_time_data), selection=lambda : PushSelection(application=self.application(), device_component=self._device_component, navigation_component=self._device_navigation)) + return inject(double_press_context=const(self._double_press_context), expect_dialog=const(self.expect_dialog), show_notification=const(self.show_notification), commit_model_changes=const(self._model.commit_changes), register_real_time_data=const(self.register_real_time_data), selection=lambda : PushSelection(application=self.application(), device_component=self._device_component, navigation_component=self._device_navigation)) def _create_components(self): self._init_dialog_modes() @@ -200,6 +205,7 @@ def _create_components(self): self._init_setup_component() self._init_firmware_update() self._init_convert_enabler() + self._init_mute_solo_stop() @contextmanager def _component_guard(self): @@ -227,12 +233,10 @@ def _init_message_box(self): super(Push2, self)._init_message_box() self._model.liveDialogView = self._dialog._message_box - def _create_mixer(self): - return MixerComponent(is_root=True, tracks_provider=self._session_ring, solo_layer=Layer(solo_buttons='select_buttons'), mute_layer=Layer(mute_buttons='select_buttons')) - def _create_convert(self): convert = ConvertComponent(decorator_factory=self._device_decorator_factory, name='Convert', tracks_provider=self._session_ring, is_enabled=False, layer=make_dialog_layer(action_buttons='select_buttons', cancel_button='track_state_buttons_raw[0]')) self.__on_convert_closed.subject = convert + self.__on_convert_suceeded.subject = convert self._model.convertView = convert return convert @@ -256,9 +260,14 @@ def _init_convert_enabler(self): def __on_convert_closed(self): self._dialog_modes.selected_mode = None + @listens('success') + def __on_convert_suceeded(self, action_name): + if action_name == 'audio_clip_to_simpler': + self._main_modes.selected_mode = 'device' + def _init_main_modes(self): super(Push2, self)._init_main_modes() - self._main_modes.add_mode('user', [self._user_mode_ui_blocker]) + self._main_modes.add_mode('user', [self._user_mode_ui_blocker, SetAttributeMode(obj=self._user, attribute='mode', value=sysex.USER_MODE)], behaviour=UserButtonBehavior(user_component=self._user)) self._model.modeState = self.register_disconnectable(ModeCollector(main_modes=self._main_modes, mix_modes=self._mix_modes, global_mix_modes=self._mixer_control, device_modes=self._device_navigation.modes)) self.__on_main_mode_button_value.replace_subjects([self.elements.vol_mix_mode_button, self.elements.pan_send_mix_mode_button, @@ -281,23 +290,11 @@ def _exit_modal_modes(self): def _create_capture_and_insert_scene_component(self): return CaptureAndInsertSceneComponent(name='Capture_And_Insert_Scene', decorator_factory=self._clip_decorator_factory, is_root=True) - def _init_stop_clips_action(self): - stop_clips_buttons = ButtonMatrixElement(rows=[wrap_button('select_buttons_raw', 'global_track_stop_button')]) - self._stop_clips = StopClipComponent(session_ring=self._session_ring, name='Stop_Clip', is_root=True) - self._stop_clips.layer = Layer(stop_all_clips_button=self._with_shift('global_track_stop_button'), stop_selected_track_clip_button='global_track_stop_button', stop_track_clips_buttons=stop_clips_buttons) - - def _init_mixer(self): - self._mixer = self._create_mixer() - self._mixer.add_mode('stop', self._stop_clips) - self._mixer.stop_button.mode_unselected_color = 'DefaultButton.On' - self._mixer.layer = Layer(solo_track_button='global_solo_button', mute_track_button='global_mute_button', stop_button='global_track_stop_button') - self._mixer_solo_layer = self._create_mixer_solo_layer() - self._mixer_mute_layer = self._create_mixer_mute_layer() - self._mixer.master_strip().name = 'Master_Channel_strip' + def _init_mute_solo_stop(self): + self._mute_solo_stop = MuteSoloStopClipComponent(is_root=True, item_provider=self._session_ring, track_list_component=self._track_list_component, cancellation_action_performers=[self._device_navigation, self._drum_component] + self._note_editor_settings_component.editors, solo_track_button='global_solo_button', mute_track_button='global_mute_button', stop_clips_button='global_track_stop_button') + self._mute_solo_stop.layer = Layer(stop_all_clips_button=self._with_shift('global_track_stop_button')) self._master_selector = MasterTrackComponent(tracks_provider=self._session_ring, is_enabled=False, layer=Layer(toggle_button='master_select_button')) self._master_selector.set_enabled(True) - self._model.mixerButtonState = self._mixer.mixer_button_state - self._mixer.set_enabled(True) def _create_instrument_layer(self): return super(Push2, self)._create_instrument_layer() + Layer(prev_loop_page_button='page_left_button', next_loop_page_button='page_right_button') @@ -346,7 +343,6 @@ def _create_device_mode(self): self._device_or_pad_parameter_chooser.selected_mode = 'device' return [partial(self._view_control.show_view, 'Detail/DeviceChain'), self._device_or_pad_parameter_chooser, - make_freeze_aware(self._device_enabling, self._device_enabling.layer), self._setup_freeze_aware_device_navigation(), self._device_note_editor_mode, SetAttributeMode(obj=self._note_editor_settings_component, attribute='parameter_provider', value=self._device_component)] @@ -360,71 +356,30 @@ def create_layer_setter(layer_name, layer): @listens('drum_pad_selection') def __on_drum_pad_selection_changed(self): - if self._device_navigation.is_drum_pad_selected: - show_pad_parameters = self._device_navigation.is_drum_pad_unfolded - new_mode = 'drum_pad' if show_pad_parameters else 'device' - selected_pad = show_pad_parameters and self._device_navigation.item_provider.selected_item + show_pad_parameters = self._device_navigation.is_drum_pad_selected and self._device_navigation.is_drum_pad_unfolded + new_mode = 'drum_pad' if show_pad_parameters else 'device' + if show_pad_parameters: + selected_pad = self._device_navigation.item_provider.selected_item self._drum_pad_parameter_component.drum_pad = selected_pad self._device_or_pad_parameter_chooser.selected_mode = new_mode self._automation_component.set_drum_pad_selected(self._device_navigation.is_drum_pad_selected) def _init_browser(self): - - class BrowserMode(LazyComponentMode, Disconnectable): - - def __init__(self, model = None, *a, **k): - raise model is not None or AssertionError - super(BrowserMode, self).__init__(*a, **k) - self._model = model - - def enter_mode(self): - self._model.browserView = self.component - self._model.browserData = self.component - super(BrowserMode, self).enter_mode() - - def disconnect(self): - super(BrowserMode, self).disconnect() - self._model = None - - self._browser_mode = BrowserMode(self._model, self._create_browser) - self._new_track_browser_mode = BrowserMode(self._model, self._create_new_track_browser) - self.register_disconnectable(self._browser_mode) - self.register_disconnectable(self._new_track_browser_mode) + self._browser_component_mode = BrowserComponentMode(weakref.ref(self._model), self._create_browser) + self._new_track_browser_component_mode = BrowserComponentMode(weakref.ref(self._model), self._create_new_track_browser) def _init_browse_mode(self): - - class BrowserModeBehaviour(ModeButtonBehaviour): - - def press_immediate(self, component, mode): - if mode == component.selected_mode: - component.selected_mode = component.active_modes[0] - else: - component.push_mode(mode) - - browser = Live.Application.get_application().browser - - def clear_hotswap_target(): - browser.hotswap_target = None - - def select_filter_type_for_track(): - has_midi_support = self.song.view.selected_track.has_midi_input - browser.filter_type = Live.Browser.FilterType.midi_track_devices if has_midi_support else Live.Browser.FilterType.audio_effect_hotswap - - def select_filter_type_for_hotswapping(): - if liveobj_valid(browser.hotswap_target): - browser.filter_type = Live.Browser.FilterType.disabled - else: - select_filter_type_for_track() - - self._main_modes.add_mode('browse', [BrowserHotswapMode(application=self.application()), select_filter_type_for_hotswapping, self._browser_mode], behaviour=BrowserModeBehaviour()) - self._main_modes.add_mode('add_device', [clear_hotswap_target, select_filter_type_for_track, self._browser_mode], behaviour=BrowserModeBehaviour()) - self._main_modes.add_mode('add_track', [clear_hotswap_target, self._new_track_browser_mode], behaviour=BrowserModeBehaviour()) + application = Live.Application.get_application() + browser = application.browser + self._main_modes.add_mode('browse', [BrowseMode(application=application, song=self.song, browser=browser, component_mode=self._browser_component_mode)], behaviour=BrowserModeBehaviour()) + self._main_modes.add_mode('add_device', [AddDeviceMode(application=application, song=self.song, browser=browser, component_mode=self._browser_component_mode)], behaviour=BrowserModeBehaviour()) + self._main_modes.add_mode('add_track', [AddTrackMode(browser=browser, component_mode=self._new_track_browser_component_mode)], behaviour=BrowserModeBehaviour()) def _create_browser_layer(self): - return Layer(up_button='nav_up_button', down_button='nav_down_button', right_button='nav_right_button', left_button='nav_left_button', back_button='track_state_buttons_raw[-2]', open_button='track_state_buttons_raw[-1]', load_button='select_buttons_raw[-1]', scroll_encoders=self.elements.global_param_controls.submatrix[:-1, :], scroll_focused_encoder='parameter_controls_raw[-1]', close_button='track_state_buttons_raw[0]', prehear_button='track_state_buttons_raw[1]') + return (BackgroundLayer('select_buttons', 'track_state_buttons', priority=consts.DIALOG_PRIORITY), Layer(up_button='nav_up_button', down_button='nav_down_button', right_button='nav_right_button', left_button='nav_left_button', back_button='track_state_buttons_raw[-2]', open_button='track_state_buttons_raw[-1]', load_button='select_buttons_raw[-1]', scroll_encoders=self.elements.global_param_controls.submatrix[:-1, :], scroll_focused_encoder='parameter_controls_raw[-1]', close_button='track_state_buttons_raw[0]', prehear_button='track_state_buttons_raw[1]', priority=consts.DIALOG_PRIORITY)) def _create_browser(self): - browser = BrowserComponent(name='Browser', is_enabled=False, preferences=self.preferences, layer=self._create_browser_layer()) + browser = BrowserComponent(name='Browser', is_enabled=False, preferences=self.preferences, main_modes_ref=weakref.ref(self._main_modes), layer=self._create_browser_layer()) self._on_browser_loaded.add_subject(browser) self._on_browser_closed.add_subject(browser) return browser @@ -437,18 +392,25 @@ def _create_new_track_browser(self): @listens_group('loaded') def _on_browser_loaded(self, sender): - browser = Live.Application.get_application().browser - if browser.hotswap_target is None: - self._main_modes.selected_mode = 'device' - drum_rack = find_drum_group_device(self.song.view.selected_track) - if drum_rack and is_empty_rack(drum_rack): - self._device_navigation.request_drum_pad_selection() - if drum_rack and self._device_navigation.is_drum_pad_selected and not self._device_navigation.is_drum_pad_unfolded: - self._device_navigation.unfold_current_drum_pad() + if sender.browse_for_audio_clip: + self._main_modes.selected_mode = 'clip' + else: + browser = Live.Application.get_application().browser + if browser.hotswap_target is None: + self._main_modes.selected_mode = 'device' + drum_rack = find_drum_group_device(self.song.view.selected_track) + if drum_rack and is_empty_rack(drum_rack): + self._device_navigation.request_drum_pad_selection() + if drum_rack and self._device_navigation.is_drum_pad_selected: + if not self._device_navigation.is_drum_pad_unfolded: + self._device_navigation.unfold_current_drum_pad() + self._device_navigation.sync_selection_to_selected_device() @listens_group('close') def _on_browser_closed(self, sender): - if self._main_modes.selected_mode == 'add_track': + if sender.browse_for_audio_clip: + self._main_modes.selected_mode = 'clip' + elif self._main_modes.selected_mode == 'add_track': self._main_modes.selected_mode = self._main_modes.active_modes[0] else: self._main_modes.selected_mode = 'device' @@ -483,30 +445,27 @@ def __on_selected_track_frozen_changed(self): self._main_modes.browse_button.enabled = self._main_modes.add_track_button.enabled = self._main_modes.add_device_button.enabled = not frozen self._close_browse_mode() - def _create_device_component(self): - return DeviceComponent(device_decorator_factory=self._device_decorator_factory, device_bank_registry=self._device_bank_registry, banking_info=BankingInfo(bank_definitions=BANK_DEFINITIONS), name='DeviceComponent', is_enabled=True, is_root=True) - def _create_device_parameter_component(self): return DeviceParameterComponent(parameter_provider=self._device_component, is_enabled=False, layer=Layer(parameter_controls='fine_grain_param_controls')) def _create_device_navigation(self): - self._chain_selection = ChainSelectionComponent(is_enabled=False, layer=Layer(select_buttons='select_buttons')) - self._chain_selection.scroll_left_layer = Layer(button='select_buttons_raw[0]') - self._chain_selection.scroll_right_layer = Layer(button='select_buttons_raw[-1]') - self._bank_selection = BankSelectionComponent(bank_registry=self._device_bank_registry, banking_info=BankingInfo(bank_definitions=BANK_DEFINITIONS), device_options_provider=self._device_component, is_enabled=False, layer=Layer(option_buttons='track_state_buttons', select_buttons='select_buttons', priority=consts.DIALOG_PRIORITY)) + self._chain_selection = ChainSelectionComponent(is_enabled=False, layer=Layer(select_buttons='select_buttons', priority=consts.DIALOG_PRIORITY)) + self._chain_selection.scroll_left_layer = Layer(button='select_buttons_raw[0]', priority=consts.DIALOG_PRIORITY) + self._chain_selection.scroll_right_layer = Layer(button='select_buttons_raw[-1]', priority=consts.DIALOG_PRIORITY) + self._bank_selection = BankSelectionComponent(bank_registry=self._device_bank_registry, banking_info=self._banking_info, device_options_provider=self._device_component, is_enabled=False, layer=Layer(option_buttons='track_state_buttons', select_buttons='select_buttons', priority=consts.DIALOG_PRIORITY)) self._bank_selection.scroll_left_layer = Layer(button='select_buttons_raw[0]', priority=consts.DIALOG_PRIORITY) self._bank_selection.scroll_right_layer = Layer(button='select_buttons_raw[-1]', priority=consts.DIALOG_PRIORITY) move_device = MoveDeviceComponent(is_enabled=False, layer=Layer(move_encoders='global_param_controls')) - device_navigation = DeviceNavigationComponent(name='DeviceNavigation', device_bank_registry=self._device_bank_registry, device_component=self._device_component, delete_handler=self._delete_component, chain_selection=self._chain_selection, bank_selection=self._bank_selection, move_device=move_device, track_selection=self._track_list_component, is_enabled=False, layer=Layer(select_buttons='track_state_buttons')) + device_navigation = DeviceNavigationComponent(name='DeviceNavigation', device_bank_registry=self._device_bank_registry, banking_info=self._banking_info, device_component=self._device_component, delete_handler=self._delete_component, chain_selection=self._chain_selection, bank_selection=self._bank_selection, move_device=move_device, track_list_component=self._track_list_component, is_enabled=False, layer=Layer(select_buttons='track_state_buttons')) device_navigation.scroll_left_layer = Layer(button='track_state_buttons_raw[0]') device_navigation.scroll_right_layer = Layer(button='track_state_buttons_raw[-1]') - self._device_enabling = DeviceEnablingComponent(device_navigation=device_navigation, is_enabled=False, layer=Layer(toggle_buttons=ButtonMatrixElement(rows=[wrap_button('track_state_buttons_raw', 'global_mute_button')]))) self.__on_drum_pad_selection_changed.subject = device_navigation - self._device_component.allow_update_callback = lambda : device_navigation.device_selection_update_allowed + self.device_provider.allow_update_callback = lambda : device_navigation.device_selection_update_allowed return device_navigation def _init_device(self): super(Push2, self)._init_device() + self._device_component.layer = Layer(parameter_touch_buttons=ButtonMatrixElement(rows=[self.elements.global_param_touch_buttons_raw])) self._device_view = DeviceViewComponent(name='DeviceView', device_component=self._device_component, view_model=self._model, is_enabled=False) self._model.devicelistView = self._device_navigation self._model.chainListView = self._chain_selection @@ -523,16 +482,14 @@ def _create_session_recording(self): return SessionRecordingComponent(fixed_length_setting=self._fixed_length_setting, clip_creator=self._clip_creator, view_controller=self._view_control, name='Session_Recording', is_root=True) def _init_session_ring(self): - self._session_ring = SessionRingTrackProvider(num_tracks=NUM_TRACKS, num_scenes=NUM_SCENES, tracks_to_use=partial(tracks_to_use_from_song, self.song), is_enabled=True, is_root=True) + self._session_ring = SessionRingTrackProvider(name='Session_Ring', num_tracks=NUM_TRACKS, num_scenes=NUM_SCENES, tracks_to_use=partial(tracks_to_use_from_song, self.song), is_enabled=True, is_root=True) def _init_session_ring_selection_linking(self): self._sessionring_link = self.register_disconnectable(SessionRingSelectionLinking(session_ring=self._session_ring, selection_changed_notifier=self._view_control)) def _init_track_list(self): - track_delete_buttons = ButtonMatrixElement(rows=[wrap_button('select_buttons_raw', 'delete_button')]) - track_duplicate_buttons = ButtonMatrixElement(rows=[wrap_button('select_buttons_raw', 'duplicate_button')]) - track_arm_buttons = ButtonMatrixElement(rows=[wrap_button('select_buttons_raw', 'record_button')]) - self._track_list_component = MixerTrackListComponent(tracks_provider=self._session_ring, trigger_recording_on_release_callback=self._session_recording.set_trigger_recording_on_release, is_enabled=False, layer=Layer(select_buttons='select_buttons', delete_buttons=track_delete_buttons, duplicate_buttons=track_duplicate_buttons, arm_buttons=track_arm_buttons)) + self._track_list_component = TrackListComponent(tracks_provider=self._session_ring, trigger_recording_on_release_callback=self._session_recording.set_trigger_recording_on_release, is_enabled=False, is_root=True, layer=Layer(track_action_buttons='select_buttons', lock_override_button='select_button', delete_button='delete_button', duplicate_button='duplicate_button', arm_button='record_button')) + self._track_list_component.set_enabled(True) self._model.tracklistView = self._track_list_component def _create_main_mixer_modes(self): @@ -558,7 +515,7 @@ def on_reenter(behaviour_self): if not self._is_on_master(): self._mix_modes.cycle_mode() - self._main_modes.add_mode('mix', [self._mix_modes, SetAttributeMode(obj=self._note_editor_settings_component, attribute='parameter_provider', value=self._track_parameter_provider), self._track_list_component], behaviour=MixModeBehaviour()) + self._main_modes.add_mode('mix', [self._mix_modes, SetAttributeMode(obj=self._note_editor_settings_component, attribute='parameter_provider', value=self._track_parameter_provider)], behaviour=MixModeBehaviour()) def _init_dialog_modes(self): self._dialog_modes = ModesComponent(is_root=True) @@ -579,7 +536,7 @@ def _exit_dialog_mode(self, mode_name): def _create_scales(self): root_note_buttons = ButtonMatrixElement(rows=[self.elements.track_state_buttons_raw[1:-1], self.elements.select_buttons_raw[1:-1]]) - scales = ScalesComponent(note_layout=self._note_layout, is_enabled=False, layer=make_dialog_layer(root_note_buttons=root_note_buttons, in_key_toggle_button='select_buttons_raw[0]', fixed_toggle_button='select_buttons_raw[-1]', scale_encoders=self.elements.global_param_controls.submatrix[1:-1, :], close_button='track_state_buttons_raw[0]')) + scales = ScalesComponent(note_layout=self._note_layout, is_enabled=False, layer=make_dialog_layer(root_note_buttons=root_note_buttons, in_key_toggle_button='select_buttons_raw[0]', fixed_toggle_button='select_buttons_raw[-1]', scale_encoders=self.elements.global_param_controls.submatrix[1:-1, :], close_button='track_state_buttons_raw[0]', up_button='nav_up_button', down_button='nav_down_button', right_button='nav_right_button', left_button='nav_left_button')) self.__on_scales_closed.subject = scales self._model.scalesView = scales return scales @@ -612,11 +569,10 @@ def _create_clip_mode(self): return [clip_control_mode_selector, make_freeze_aware(self._loop_controller, base_loop_layer), make_freeze_aware(audio_clip_controller, audio_clip_layer), - clip_control, - self._track_list_component] + clip_control] def _init_quantize_actions(self): - self._quantize_settings = QuantizationSettingsComponent(name='Quantization_Settings', is_enabled=False, layer=make_dialog_layer(swing_amount_encoder='parameter_controls_raw[0]', quantize_to_encoder='parameter_controls_raw[1]', quantize_amount_encoder='parameter_controls_raw[2]', record_quantization_encoder='parameter_controls_raw[4]', record_quantization_toggle_button='track_state_buttons_raw[4]', priority=consts.MOMENTARY_DIALOG_PRIORITY)) + self._quantize_settings = QuantizationSettingsComponent(name='Quantization_Settings', quantization_names=QUANTIZATION_NAMES_UNICODE, is_enabled=False, layer=make_dialog_layer(swing_amount_encoder='parameter_controls_raw[0]', quantize_to_encoder='parameter_controls_raw[1]', quantize_amount_encoder='parameter_controls_raw[2]', record_quantization_encoder='parameter_controls_raw[4]', record_quantization_toggle_button='track_state_buttons_raw[4]', priority=consts.MOMENTARY_DIALOG_PRIORITY)) self._model.quantizeSettingsView = self._quantize_settings self._quantize = self._for_non_frozen_tracks(QuantizationComponent(name='Selected_Clip_Quantize', settings=self._quantize_settings, is_enabled=False, layer=Layer(action_button='quantize_button')), is_root=True) @@ -634,7 +590,7 @@ def _init_value_components(self): self._model.importantGlobals.cueVolume = self._master_cue_vol.display def _create_main_modes_layer(self): - return Layer(mix_button='mix_button', clip_button='clip_mode_button', device_button='device_mode_button', browse_button='browse_mode_button', add_device_button='create_device_button', add_track_button='create_track_button') + return Layer(mix_button='mix_button', clip_button='clip_mode_button', device_button='device_mode_button', browse_button='browse_mode_button', add_device_button='create_device_button', add_track_button='create_track_button') + Layer(user_button='user_button', priority=consts.USER_BUTTON_PRIORITY) def _should_send_palette(self): return self._firmware_version <= FirmwareVersion(0, 5, 28) @@ -656,22 +612,8 @@ def _create_user_component(self): self._user_mode_ui_blocker = Component(is_enabled=False, layer=self._create_message_box_background_layer()) sysex_control = SysexElement(send_message_generator=sysex.make_mode_switch_messsage, sysex_identifier=sysex.make_message_identifier(sysex.MODE_SWITCH_MESSAGE_ID)) user = UserComponent(value_control=sysex_control, is_enabled=True, is_root=True) - user.layer = Layer(user_mode_toggle_button='user_button', priority=consts.USER_BUTTON_PRIORITY) - self.__on_before_push_mode_sent.subject = user - self.__on_after_push_mode_sent.subject = user return user - @listens('before_mode_sent') - def __on_before_push_mode_sent(self, mode): - if mode == sysex.USER_MODE and self._main_modes.selected_mode != 'user': - self._main_modes.push_mode('user') - - @listens('after_mode_sent') - def __on_after_push_mode_sent(self, mode): - if mode == sysex.LIVE_MODE and self._main_modes.selected_mode == 'user': - self._main_modes.pop_mode('user') - self._user.defer_sysex_sending = mode == sysex.LIVE_MODE - def _create_settings(self): return create_settings(preferences=self.preferences) @@ -682,11 +624,14 @@ def _init_hardware_settings(self): def _init_setup_component(self): self._setup_settings.general.workflow = 'scene' if self._settings['workflow'].value else 'clip' self.__on_workflow_setting_changed.subject = self._setup_settings.general + self.__on_new_waveform_navigation_setting_changed.subject = self._setup_settings.experimental + self.__on_new_waveform_navigation_setting_changed(self._setup_settings.experimental.new_waveform_navigation) setup = SetupComponent(name='Setup', settings=self._setup_settings, pad_curve_sender=self._pad_curve_sender, in_developer_mode=self._c_instance.in_developer_mode, is_enabled=False, layer=make_dialog_layer(category_radio_buttons='select_buttons', priority=consts.SETUP_DIALOG_PRIORITY)) setup.general.layer = Layer(workflow_encoder='parameter_controls_raw[0]', display_brightness_encoder='parameter_controls_raw[1]', led_brightness_encoder='parameter_controls_raw[2]', priority=consts.SETUP_DIALOG_PRIORITY) setup.pad_settings.layer = Layer(sensitivity_encoder='parameter_controls_raw[4]', gain_encoder='parameter_controls_raw[5]', dynamics_encoder='parameter_controls_raw[6]', priority=consts.SETUP_DIALOG_PRIORITY) setup.display_debug.layer = Layer(show_row_spaces_button='track_state_buttons_raw[0]', show_row_margins_button='track_state_buttons_raw[1]', show_row_middle_button='track_state_buttons_raw[2]', show_button_spaces_button='track_state_buttons_raw[3]', show_unlit_button_button='track_state_buttons_raw[4]', show_lit_button_button='track_state_buttons_raw[5]', priority=consts.SETUP_DIALOG_PRIORITY) setup.profiling.layer = Layer(show_qml_stats_button='track_state_buttons_raw[0]', show_usb_stats_button='track_state_buttons_raw[1]', show_realtime_ipc_stats_button='track_state_buttons_raw[2]', priority=consts.SETUP_DIALOG_PRIORITY) + setup.experimental.layer = Layer(new_waveform_navigation_button='track_state_buttons_raw[0]', priority=consts.SETUP_DIALOG_PRIORITY) self._model.setupView = setup self._setup_enabler = EnablingModesComponent(component=setup, enabled_color='DefaultButton.On', disabled_color='DefaultButton.On') self._setup_enabler.layer = Layer(cycle_mode_button='setup_button') @@ -699,6 +644,10 @@ def _init_firmware_update(self): def __on_workflow_setting_changed(self, value): self._settings['workflow'].value = value == 'scene' + @listens('new_waveform_navigation') + def __on_new_waveform_navigation_setting_changed(self, value): + self._device_component.use_waveform_navigation = value + def _create_note_mode(self): class NoteLayoutSwitcher(Component): diff --git a/Push2/push2_model.py b/Push2/push2_model.py index 0314393e..5f4e36d7 100644 --- a/Push2/push2_model.py +++ b/Push2/push2_model.py @@ -1,12 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/push2_model.py -import os -import sys +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/push2_model.py +from __future__ import absolute_import, print_function from pprint import pformat import logging -j = os.path.join -dn = os.path.dirname -sys.path.append(j(dn(dn(__file__)), '_Tools')) -import simplejson as json +import json from .model import RootModel from .model.generation import generate_mrs_model, ModelUpdateNotifier logger = logging.getLogger(__name__) @@ -34,6 +30,8 @@ def attribute_changed(self, path, value): def send(self, root_model, send_all = False): def send_data(data): + if data['command'] == 'full-model-update': + data['fingerprint'] = root_model.__fingerprint__ raw = json.dumps(data) self._message_sink(raw) if logger.isEnabledFor(logging.DEBUG): diff --git a/Push2/real_time_channel.py b/Push2/real_time_channel.py index e97b979f..00863496 100644 --- a/Push2/real_time_channel.py +++ b/Push2/real_time_channel.py @@ -1,7 +1,21 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/real_time_channel.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/real_time_channel.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface import Component from ableton.v2.base import depends, listenable_property, liveobj_changed, liveobj_valid +def update_real_time_attachments(real_time_data_components): + """ + Updates all the real-time channels. We need to explicitly detach all + channels before attaching them again, otherwise we could end up in a situation + where we try to attach to a channel that's already occupied. + """ + for d in real_time_data_components: + d.detach() + + for d in real_time_data_components: + d.attach() + + class RealTimeDataComponent(Component): @depends(real_time_mapper=None, register_real_time_data=None) @@ -28,7 +42,11 @@ def object_id(self): def on_enabled_changed(self): super(RealTimeDataComponent, self).on_enabled_changed() self.invalidate() - self.update_attachment() + self._update_attachment() + + def _update_attachment(self): + self.detach() + self.attach() def set_data(self, data): if liveobj_changed(data, self._data): @@ -38,11 +56,13 @@ def set_data(self, data): def invalidate(self): self._valid = False - def update_attachment(self): + def detach(self): + if not self._valid and self._real_time_channel_id != '': + self._real_time_mapper.detach_channel(self._real_time_channel_id) + self._real_time_channel_id = '' + + def attach(self): if not self._valid: - if self._real_time_channel_id != '': - self._real_time_mapper.detach_channel(self._real_time_channel_id) - self._real_time_channel_id = '' data = self._data if self.is_enabled() else None if data != None: self._real_time_channel_id, self._object_id = self._real_time_mapper.attach_object(data, self._channel_type) diff --git a/Push2/scales_component.py b/Push2/scales_component.py index 0c5072d9..7cd28f20 100644 --- a/Push2/scales_component.py +++ b/Push2/scales_component.py @@ -1,4 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/scales_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/scales_component.py +from __future__ import absolute_import, print_function +from math import ceil from functools import partial from ableton.v2.base import clamp, listens, listenable_property from ableton.v2.control_surface import Component @@ -7,11 +9,19 @@ class ScalesComponent(Component): __events__ = ('close',) + navigation_colors = dict(color='Scales.Navigation', disabled_color='Scales.NavigationDisabled') + up_button = ButtonControl(repeat=True, **navigation_colors) + down_button = ButtonControl(repeat=True, **navigation_colors) + right_button = ButtonControl(repeat=True, **navigation_colors) + left_button = ButtonControl(repeat=True, **navigation_colors) root_note_buttons = control_list(RadioButtonControl, control_count=len(ROOT_NOTES), checked_color='Scales.OptionOn', unchecked_color='Scales.OptionOff') in_key_toggle_button = ToggleButtonControl(toggled_color='Scales.OptionOn', untoggled_color='Scales.OptionOn') fixed_toggle_button = ToggleButtonControl(toggled_color='Scales.OptionOn', untoggled_color='Scales.OptionOff') scale_encoders = control_list(StepEncoderControl) close_button = ButtonControl(color='Scales.Close') + horizontal_navigation = listenable_property.managed(False) + NUM_DISPLAY_ROWS = 4 + NUM_DISPLAY_COLUMNS = int(ceil(float(len(SCALES)) / NUM_DISPLAY_ROWS)) def __init__(self, note_layout = None, *a, **k): raise note_layout is not None or AssertionError @@ -28,6 +38,30 @@ def __init__(self, note_layout = None, *a, **k): self.__on_root_note_changed(note_layout.root_note) self.__on_scale_changed(note_layout.scale) + def _set_selected_scale_index(self, index): + index = clamp(index, 0, len(self._scale_list) - 1) + self._note_layout.scale = self._scale_list[index] + + @down_button.pressed + def down_button(self, button): + self._update_horizontal_navigation() + self._set_selected_scale_index(self._selected_scale_index + 1) + + @up_button.pressed + def up_button(self, button): + self._update_horizontal_navigation() + self._set_selected_scale_index(self._selected_scale_index - 1) + + @left_button.pressed + def left_button(self, button): + self._update_horizontal_navigation() + self._set_selected_scale_index(self._selected_scale_index - self.NUM_DISPLAY_ROWS) + + @right_button.pressed + def right_button(self, button): + self._update_horizontal_navigation() + self._set_selected_scale_index(self._selected_scale_index + self.NUM_DISPLAY_ROWS) + @root_note_buttons.pressed def root_note_buttons(self, button): self._note_layout.root_note = ROOT_NOTES[button.index] @@ -48,8 +82,8 @@ def selected_root_note_index(self): @scale_encoders.value def scale_encoders(self, value, encoder): - index = clamp(self._selected_scale_index + value, 0, len(self._scale_list) - 1) - self._note_layout.scale = self._scale_list[index] + self._update_horizontal_navigation() + self._set_selected_scale_index(self._selected_scale_index + value) @property def scale_names(self): @@ -64,6 +98,10 @@ def __on_scale_changed(self, scale): index = self._scale_list.index(scale) if scale in self._scale_list else -1 if index != self._selected_scale_index: self._selected_scale_index = index + self.up_button.enabled = index > 0 + self.left_button.enabled = index > 0 + self.down_button.enabled = index < len(self._scale_list) - 1 + self.right_button.enabled = index < len(self._scale_list) - 1 self.notify_selected_scale_index() @close_button.pressed @@ -74,6 +112,9 @@ def close_button(self, button): def note_layout(self): return self._note_layout + def _update_horizontal_navigation(self): + self.horizontal_navigation = self.right_button.is_pressed or self.left_button.is_pressed + class ScalesEnabler(Component): toggle_button = ButtonControl(color='DefaultButton.On') @@ -89,6 +130,10 @@ def __init__(self, enter_dialog_mode = None, exit_dialog_mode = None, *a, **k): def toggle_button(self, button): self._enable_dialog_mode() + @toggle_button.released_delayed + def toggle_button(self, button): + self._exit_dialog_mode() + def on_enabled_changed(self): super(ScalesEnabler, self).on_enabled_changed() if not self.is_enabled(): diff --git a/Push2/session_component.py b/Push2/session_component.py index 836e2cdb..e093af4a 100644 --- a/Push2/session_component.py +++ b/Push2/session_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/session_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/session_component.py +from __future__ import absolute_import, print_function from itertools import imap from pushbase.special_session_component import SpecialClipSlotComponent, SpecialSceneComponent, SpecialSessionComponent from .clip_decoration import ClipDecoratedPropertiesCopier @@ -8,7 +9,9 @@ class ClipSlotComponent(SpecialClipSlotComponent): _decorator_factory = None def _color_value(self, slot_or_clip): - return WHITE_MIDI_VALUE if slot_or_clip.color_index == WHITE_COLOR_INDEX_FROM_LIVE else translate_color_index(slot_or_clip.color_index) + if slot_or_clip.color_index == WHITE_COLOR_INDEX_FROM_LIVE: + return WHITE_MIDI_VALUE + return translate_color_index(slot_or_clip.color_index) def _do_duplicate_clip(self): @@ -16,11 +19,11 @@ def get_destination_clip(destination_slot_ix): track = self._clip_slot.canonical_parent return track.clip_slots[destination_slot_ix].clip - if self._clip_slot: - if not self._clip_slot.has_clip: - return - destination_slot_ix = super(ClipSlotComponent, self)._do_duplicate_clip() - destination_slot_ix is not None and self._decorator_factory and ClipDecoratedPropertiesCopier(target_clip=self._clip_slot.clip, destination_clip=get_destination_clip(destination_slot_ix), decorator_factory=self._decorator_factory).post_duplication_action() + if not (self._clip_slot and self._clip_slot.has_clip): + return + destination_slot_ix = super(ClipSlotComponent, self)._do_duplicate_clip() + if destination_slot_ix is not None and self._decorator_factory: + ClipDecoratedPropertiesCopier(target_clip=self._clip_slot.clip, destination_clip=get_destination_clip(destination_slot_ix), decorator_factory=self._decorator_factory).post_duplication_action() return destination_slot_ix def set_decorator_factory(self, factory): diff --git a/Push2/session_recording.py b/Push2/session_recording.py index 99e489a3..016d29c1 100644 --- a/Push2/session_recording.py +++ b/Push2/session_recording.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/session_recording.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/session_recording.py +from __future__ import absolute_import, print_function from pushbase.session_recording_component import FixedLengthSessionRecordingComponent class SessionRecordingComponent(FixedLengthSessionRecordingComponent): diff --git a/Push2/session_ring_selection_linking.py b/Push2/session_ring_selection_linking.py index 663b7726..c163c0d7 100644 --- a/Push2/session_ring_selection_linking.py +++ b/Push2/session_ring_selection_linking.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/session_ring_selection_linking.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/session_ring_selection_linking.py +from __future__ import absolute_import, print_function from ableton.v2.base.slot import SlotManager, listens from ableton.v2.base.dependency import depends from ableton.v2.base.util import index_if diff --git a/Push2/settings.py b/Push2/settings.py index 8d6ebb31..260a5f2c 100644 --- a/Push2/settings.py +++ b/Push2/settings.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/settings.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/settings.py +from __future__ import absolute_import, print_function from pushbase.setting import OnOffSetting def create_settings(preferences = None): diff --git a/Push2/setup_component.py b/Push2/setup_component.py index 98cd1706..cfa83886 100644 --- a/Push2/setup_component.py +++ b/Push2/setup_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/setup_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/setup_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import CompoundDisconnectable, SerializableListenableProperties, Subject, clamp, listenable_property from ableton.v2.control_surface import Component from ableton.v2.control_surface.control import RadioButtonControl, StepEncoderControl, ToggleButtonControl, control_list @@ -36,6 +37,10 @@ class ProfilingSettings(SerializableListenableProperties): show_realtime_ipc_stats = listenable_property.managed(False) +class ExperimentalSettings(SerializableListenableProperties): + new_waveform_navigation = listenable_property.managed(False) + + class Settings(CompoundDisconnectable): def __init__(self, preferences = None, *a, **k): @@ -46,6 +51,7 @@ def __init__(self, preferences = None, *a, **k): self._hardware = self.register_disconnectable(preferences.setdefault('settings_hardware', HardwareSettings())) self._display_debug = self.register_disconnectable(preferences.setdefault('settings_display_debug', DisplayDebugSettings())) self._profiling = self.register_disconnectable(preferences.setdefault('settings_profiling', ProfilingSettings())) + self._experimental = self.register_disconnectable(preferences.setdefault('experimental', ExperimentalSettings())) @property def general(self): @@ -67,6 +73,10 @@ def display_debug(self): def profiling(self): return self._profiling + @property + def experimental(self): + return self._experimental + class GeneralSettingsComponent(Component): workflow_encoder = StepEncoderControl() @@ -79,7 +89,7 @@ def __init__(self, settings = None, hardware_settings = None, *a, **k): super(GeneralSettingsComponent, self).__init__(*a, **k) self._settings = settings self._hardware_settings = hardware_settings - self.workflow_encoder.connect_property(settings, 'workflow', lambda v: 'clip' if v > 0 else 'scene') + self.workflow_encoder.connect_property(settings, 'workflow', lambda v: ('clip' if v > 0 else 'scene')) @led_brightness_encoder.value def led_brightness_encoder(self, value, encoder): @@ -145,6 +155,15 @@ def __init__(self, settings = None, *a, **k): self.show_realtime_ipc_stats_button.connect_property(settings, 'show_realtime_ipc_stats') +class ExperimentalSettingsComponent(Component): + new_waveform_navigation_button = ToggleButtonControl() + + def __init__(self, settings = None, *a, **k): + raise settings is not None or AssertionError + super(ExperimentalSettingsComponent, self).__init__(*a, **k) + self.new_waveform_navigation_button.connect_property(settings, 'new_waveform_navigation') + + class SetupComponent(ModesComponent): category_radio_buttons = control_list(RadioButtonControl, checked_color='Option.Selected', unchecked_color='Option.Unselected') @@ -158,10 +177,12 @@ def __init__(self, settings = None, pad_curve_sender = None, in_developer_mode = self._pad_settings = self.register_component(PadSettingsComponent(pad_settings=settings.pad_settings, is_enabled=False)) self._display_debug = self.register_component(DisplayDebugSettingsComponent(settings=settings.display_debug, is_enabled=False)) self._profiling = self.register_component(ProfilingSettingsComponent(settings=settings.profiling, is_enabled=False)) + self._experimental = self.register_component(ExperimentalSettingsComponent(settings=settings.experimental, is_enabled=False)) self.add_mode('Settings', [self._general, self._pad_settings]) self.add_mode('Info', []) in_developer_mode and self.add_mode('Display Debug', [self._display_debug]) self.add_mode('Profiling', [self._profiling]) + self.add_mode('Experimental', [self._experimental]) self.selected_mode = 'Settings' self.category_radio_buttons.control_count = len(self.modes) self.category_radio_buttons.checked_index = 0 @@ -182,6 +203,10 @@ def display_debug(self): def profiling(self): return self._profiling + @property + def experimental(self): + return self._experimental + @property def settings(self): return self._settings diff --git a/Push2/simpler_zoom.py b/Push2/simpler_zoom.py index 01cde3cf..4a6b165e 100644 --- a/Push2/simpler_zoom.py +++ b/Push2/simpler_zoom.py @@ -1,16 +1,14 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/simpler_zoom.py -from __future__ import absolute_import, with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/simpler_zoom.py +from __future__ import absolute_import, print_function from contextlib import contextmanager from ableton.v2.base import clamp, linear, SlotManager, Subject, listens, liveobj_valid, liveobj_changed - -def is_simpler(device): - return device and device.class_name == 'OriginalSimpler' - +from pushbase.device_chain_utils import is_simpler def get_zoom_parameter(parameter_host): parameters = parameter_host.parameters if liveobj_valid(parameter_host) else [] results = filter(lambda p: p.name == 'Zoom', parameters) - return results[0] if len(results) > 0 else None + if len(results) > 0: + return results[0] class ZoomHandling(SlotManager, Subject): @@ -23,7 +21,9 @@ class ZoomHandling(SlotManager, Subject): @property def zoom(self): - return self._zoom_parameter.value if self._zoom_parameter else 0.0 + if self._zoom_parameter: + return self._zoom_parameter.value + return 0.0 @property def max_zoom(self): @@ -58,7 +58,9 @@ def _get_zoom_start_fudge(self): def _internal_to_zoom(self, value, _parent): fudge = self._get_zoom_start_fudge() ** 10 ** (1.0 / self.ZOOM_EXP) - return (value * (1.0 - fudge) + fudge) ** self.ZOOM_EXP if value > 0.0 else 0.0 + if value > 0.0: + return (value * (1.0 - fudge) + fudge) ** self.ZOOM_EXP + return 0.0 def _zoom_to_internal(self, value, _parent): fudge = self._get_zoom_start_fudge() ** 10 ** (1.0 / self.ZOOM_EXP) @@ -97,7 +99,7 @@ def set_parameter_host(self, parameter_host): def _set_zoom_parameter(self): self._zoom_parameter = get_zoom_parameter(self._parameter_host) - @listens('sample_file_path') + @listens('sample') def _on_sample_changed(self): if self._zoom_parameter: self._zoom_parameter.value = self._zoom_parameter.default_value @@ -112,13 +114,13 @@ def _updating_zoom_scaling(self): @property def max_zoom(self): - has_sample = liveobj_valid(self._parameter_host) and self._parameter_host.sample_length > 0 - length = float(self._parameter_host.sample_length if has_sample else self.SCREEN_WIDTH) + has_sample = liveobj_valid(self._parameter_host) and liveobj_valid(self._parameter_host.sample) + length = float(self._parameter_host.sample.length if has_sample else self.SCREEN_WIDTH) return float(length / self.SCREEN_WIDTH) def _get_zoom_start_fudge(self): - if liveobj_valid(self._parameter_host): - sample_length = self._parameter_host.sample_length + if liveobj_valid(self._parameter_host) and liveobj_valid(self._parameter_host.sample): + sample_length = self._parameter_host.sample.length fudge_length_a = 200000 fudge_factor_a = 0.4 fudge_length_b = 2500000 diff --git a/Push2/skin_default.py b/Push2/skin_default.py index a581753a..264bcd4e 100644 --- a/Push2/skin_default.py +++ b/Push2/skin_default.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/skin_default.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/skin_default.py +from __future__ import absolute_import, print_function from functools import partial from ableton.v2.control_surface import Skin from ableton.v2.control_surface.elements import SelectedTrackColorFactory, SelectedClipColorFactory @@ -113,6 +114,8 @@ class Mixer: MuteOff = Rgb.YELLOW SoloOn = TRACK_SOLOED_COLOR SoloOff = Rgb.DEEP_OCEAN + LockedMuteMode = Pulse(Rgb.BLACK, Rgb.YELLOW, 48) + LockedSoloMode = Pulse(Rgb.BLACK, TRACK_SOLOED_COLOR, 48) class MixerControlView: SectionSelected = Rgb.WHITE @@ -135,6 +138,8 @@ class Browser: OptionDisabled = Rgb.DARK_GREY class Scales: + Navigation = FallbackColor(Rgb.WHITE, Basic.ON) + NavigationDisabled = FallbackColor(Rgb.DARK_GREY, Basic.OFF) OptionOn = Rgb.WHITE OptionOff = Rgb.DARK_GREY NoOption = Rgb.BLACK @@ -152,6 +157,7 @@ class Recording: On = RECORDING_COLOR Off = Rgb.WHITE Transition = Blink(RECORDING_COLOR, Rgb.BLACK, 48) + ArrangementRecordingOn = Pulse(RECORDING_COLOR, Rgb.BLACK, 48) FixedLengthRecordingOn = Rgb.WHITE FixedLengthRecordingOff = Rgb.DARK_GREY @@ -177,6 +183,7 @@ class Session: class StopClips: SoloedTrack = Pulse(Rgb.BLACK, TRACK_SOLOED_COLOR, 48) MutedTrack = Pulse(Rgb.BLACK, Rgb.DARK_GREY, 48) + LockedStopMode = Pulse(Rgb.BLACK, Rgb.RED, 48) class Zooming: Selected = Rgb.WHITE diff --git a/Push2/sysex.py b/Push2/sysex.py index 3df42477..df71ffad 100644 --- a/Push2/sysex.py +++ b/Push2/sysex.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/sysex.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/sysex.py +from __future__ import absolute_import, print_function from ableton.v2.base import chunks from ableton.v2.control_surface import midi from pushbase.sysex import LIVE_MODE, USER_MODE @@ -75,7 +76,9 @@ def make_touch_strip_mode_message(mode): TouchStripStates.STATE_FULL: 6} def _make_touch_strip_light(state): - return state[0] | state[1] << 3 if len(state) == 2 else state[0] + if len(state) == 2: + return state[0] | state[1] << 3 + return state[0] def make_touch_strip_light_message(states): diff --git a/Push2/track_list.py b/Push2/track_list.py new file mode 100644 index 00000000..7251a4d8 --- /dev/null +++ b/Push2/track_list.py @@ -0,0 +1,272 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/track_list.py +from __future__ import absolute_import, print_function +from functools import partial +from itertools import chain, izip +import Live +from ableton.v2.base import nop, listenable_property, listens, listens_group, liveobj_valid +from ableton.v2.control_surface.control import ButtonControl, control_list +from ableton.v2.control_surface.mode import ModeButtonBehaviour, ModesComponent +from pushbase.actions import is_clip_stop_pending +from pushbase.consts import MessageBoxText +from pushbase.message_box_component import Messenger +from pushbase.special_chan_strip_component import toggle_arm +from .colors import make_blinking_track_color, make_pulsing_track_color, translate_color_index +from .mixable_utilities import can_play_clips, is_chain +from .skin_default import RECORDING_COLOR, UNLIT_COLOR +from .track_selection import get_all_mixer_tracks, SelectedMixerTrackProvider +DeviceType = Live.Device.DeviceType + +def track_color_with_pending_stop(track): + return make_blinking_track_color(track, UNLIT_COLOR) + + +def mixable_button_color(mixer_track, song, selected_track = None): + color = 'Mixer.NoTrack' + if mixer_track: + if can_play_clips(mixer_track) and is_clip_stop_pending(mixer_track): + color = track_color_with_pending_stop(mixer_track) + elif mixer_track.solo: + color = 'Mixer.SoloOn' + elif mixer_track == selected_track and not mixer_track.mute: + color = 'Mixer.TrackSelected' + elif mixer_track.mute or mixer_track.muted_via_solo: + color = 'Mixer.MutedTrack' + else: + color = translate_color_index(mixer_track.color_index) + return color + + +def stop_clip_button_color(track, song, _): + if liveobj_valid(track) and not is_chain(track) and bool(track.clip_slots): + if is_clip_stop_pending(track): + return track_color_with_pending_stop(track) + elif track.playing_slot_index >= 0: + if track.solo: + return 'StopClips.SoloedTrack' + if track.mute: + return 'StopClips.MutedTrack' + if track.clip_slots[track.playing_slot_index].is_recording: + pulse_to = RECORDING_COLOR + else: + pulse_to = UNLIT_COLOR + return make_pulsing_track_color(track, pulse_to) + else: + return 'Session.StoppedClip' + else: + return 'Mixer.NoTrack' + + +def toggle_mixable_mute(mixable, song): + if mixable != song.master_track: + mixable.mute = not mixable.mute + + +def toggle_mixable_solo(mixable, song): + if mixable != song.master_track: + tracks = get_all_mixer_tracks(song) + other_solos = any([ track.solo for track in tracks ]) + if other_solos and song.exclusive_solo and not mixable.solo: + for track in tracks: + track.solo = False + + mixable.solo = not mixable.solo + + +class TrackListBehaviour(ModeButtonBehaviour): + + def press_immediate(self, component, mode): + component.push_mode(mode) + + def release_delayed(self, component, mode): + self.release_immediate(component, mode) + + def release_immediate(self, component, mode): + component.pop_mode(mode) + + +class TrackListComponent(ModesComponent, Messenger): + """ + Notifies whenever a track action is executed, e.g. deleting or duplicating. But + selection does *not* count as an action. + """ + __events__ = ('mute_solo_stop_cancel_action_performed',) + track_action_buttons = control_list(ButtonControl, control_count=8) + + def __init__(self, tracks_provider = None, trigger_recording_on_release_callback = nop, *a, **k): + raise tracks_provider is not None or AssertionError + super(TrackListComponent, self).__init__(*a, **k) + self.locked_mode = None + self._button_handler = self._select_mixable + self._button_feedback_provider = mixable_button_color + self._setup_action_mode('select', handler=self._select_mixable) + self._setup_action_mode('lock_override', handler=self._select_mixable) + self._setup_action_mode('delete', handler=self._delete_mixable) + self._setup_action_mode('duplicate', handler=self._duplicate_mixable) + self._setup_action_mode('arm', handler=self._arm_track) + self._setup_action_mode('mute', handler=partial(toggle_mixable_mute, song=self.song)) + self._setup_action_mode('solo', handler=partial(toggle_mixable_solo, song=self.song)) + self._setup_action_mode('stop', handler=self._stop_track_clip, feedback_provider=stop_clip_button_color) + self.selected_mode = 'select' + self._can_trigger_recording_callback = trigger_recording_on_release_callback + self._track_provider = tracks_provider + self._selected_track = self.register_disconnectable(SelectedMixerTrackProvider()) + self.__on_items_changed.subject = self._track_provider + self.__on_selected_item_changed.subject = self._track_provider + self.__on_tracks_changed.subject = self.song + self.__on_selected_track_changed.subject = self.song.view + self._update_track_and_chain_listeners() + self._update_button_enabled_state() + self._update_all_button_colors() + + @listenable_property + def tracks(self): + return self._track_provider.items + + @listenable_property + def selected_track(self): + return self._track_provider.selected_item + + @listenable_property + def absolute_selected_track_index(self): + song = self.song + tracks = song.tracks + song.return_tracks + (song.master_track,) + selected_track = song.view.selected_track + return list(tracks).index(selected_track) + + def _setup_action_mode(self, name, handler, feedback_provider = mixable_button_color): + self.add_mode(name, partial(self._enter_action_mode, handler=handler, feedback_provider=feedback_provider), behaviour=TrackListBehaviour()) + self.get_mode_button(name).mode_selected_color = 'DefaultButton.Transparent' + self.get_mode_button(name).mode_unselected_color = 'DefaultButton.Transparent' + + def _enter_action_mode(self, handler, feedback_provider): + self._button_handler = handler + if feedback_provider != self._button_feedback_provider: + self._button_feedback_provider = feedback_provider + self._update_all_button_colors() + + @listens('tracks') + def __on_tracks_changed(self): + self._update_track_and_chain_listeners() + self._update_button_enabled_state() + + @listens_group('mute') + def __on_track_mute_state_changed(self, track): + self._update_all_button_colors() + + @listens_group('solo') + def __on_track_solo_state_changed(self, track): + self._update_all_button_colors() + + @listens_group('fired_slot_index') + def __on_track_fired_slot_changed(self, track): + self._update_all_button_colors() + + @listens_group('playing_slot_index') + def __on_track_playing_slot_changed(self, _): + self._update_all_button_colors() + + @listens('items') + def __on_items_changed(self): + self._update_track_and_chain_listeners() + self._update_button_enabled_state() + + def _update_track_and_chain_listeners(self): + self.notify_tracks() + self.__on_track_color_index_changed.replace_subjects(self.tracks) + tracks_without_chains = filter(can_play_clips, self.tracks) + self.__on_track_fired_slot_changed.replace_subjects(tracks_without_chains) + self.__on_track_playing_slot_changed.replace_subjects(tracks_without_chains) + all_tracks = [ _ for _ in chain(self.song.tracks, self.tracks) ] + self.__on_track_mute_state_changed.replace_subjects(all_tracks) + self.__on_track_solo_state_changed.replace_subjects(all_tracks) + self.__on_track_muted_via_solo_changed.replace_subjects(all_tracks) + self._update_button_enabled_state() + self._update_all_button_colors() + + def _update_button_enabled_state(self): + tracks = self.tracks + for track, control in izip(tracks, self.track_action_buttons): + control.enabled = liveobj_valid(track) + + @listens_group('color_index') + def __on_track_color_index_changed(self, _): + self._update_all_button_colors() + + @listens('selected_item') + def __on_selected_item_changed(self): + self.notify_selected_track() + self._update_all_button_colors() + + @listens('selected_track') + def __on_selected_track_changed(self): + self.notify_absolute_selected_track_index() + + @listens_group('muted_via_solo') + def __on_track_muted_via_solo_changed(self, mixable): + self._update_all_button_colors() + + def _update_all_button_colors(self): + for index, mixer_track in enumerate(self.tracks): + color = self._button_feedback_provider(mixer_track, self.song, self.selected_track) + self.track_action_buttons[index].color = color + + @track_action_buttons.pressed + def track_action_buttons(self, button): + self._button_handler(self.tracks[button.index]) + if self.selected_mode != 'select': + self.notify_mute_solo_stop_cancel_action_performed() + + def _select_mixable(self, track): + if track: + if self._track_provider.selected_item != track: + self._track_provider.selected_item = track + else: + if hasattr(track, 'is_foldable') and track.is_foldable: + track.fold_state = not track.fold_state + if hasattr(track, 'is_showing_chains') and track.can_show_chains: + track.is_showing_chains = not track.is_showing_chains + + @staticmethod + def can_duplicate_or_delete(track_or_chain, return_tracks): + unwrapped = track_or_chain.proxied_object + return isinstance(unwrapped, Live.Track.Track) and unwrapped not in list(return_tracks) + + def _delete_mixable(self, track_or_chain): + if self.can_duplicate_or_delete(track_or_chain, self.song.return_tracks): + try: + track_index = list(self.song.tracks).index(track_or_chain) + name = track_or_chain.name + self.song.delete_track(track_index) + self.show_notification(MessageBoxText.DELETE_TRACK % name) + except RuntimeError: + self.show_notification(MessageBoxText.TRACK_DELETE_FAILED) + + def _duplicate_mixable(self, track_or_chain): + if self.can_duplicate_or_delete(track_or_chain, self.song.return_tracks): + try: + track_index = list(self.song.tracks).index(track_or_chain) + self.song.duplicate_track(track_index) + self.show_notification(MessageBoxText.DUPLICATE_TRACK % track_or_chain.name) + self._update_all_button_colors() + except Live.Base.LimitationError: + self.show_notification(MessageBoxText.TRACK_LIMIT_REACHED) + except RuntimeError: + self.show_notification(MessageBoxText.TRACK_DUPLICATION_FAILED) + + def _arm_track(self, track_or_chain): + if not is_chain(track_or_chain) and track_or_chain.can_be_armed: + song = self.song + toggle_arm(track_or_chain, song, exclusive=song.exclusive_arm) + self._can_trigger_recording_callback(False) + + def _stop_track_clip(self, mixable): + if not is_chain(mixable): + mixable.stop_all_clips() + + def on_enabled_changed(self): + super(TrackListComponent, self).on_enabled_changed() + if not self.is_enabled(): + self.selected_mode = 'select' + self.pop_unselected_modes() + elif self.locked_mode is not None: + self.push_mode(self.locked_mode) \ No newline at end of file diff --git a/Push2/track_mixer_control_component.py b/Push2/track_mixer_control_component.py index 08d69691..7861922a 100644 --- a/Push2/track_mixer_control_component.py +++ b/Push2/track_mixer_control_component.py @@ -1,8 +1,10 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/track_mixer_control_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/track_mixer_control_component.py +from __future__ import absolute_import, print_function +from itertools import izip_longest from ableton.v2.base import clamp, depends, listens, liveobj_valid from ableton.v2.control_surface import CompoundComponent from ableton.v2.control_surface.control import control_list, ButtonControl -from .mapped_control import MappedControl +from pushbase.mapped_control import MappedControl from .real_time_channel import RealTimeDataComponent from .item_lister_component import SimpleItemSlot MAX_RETURN_TRACKS = 6 @@ -49,7 +51,7 @@ def _update_real_time_channel_id(self): def _update_controls(self): if self.is_enabled(): - for control, parameter in map(None, self.controls, self.parameters[self.scroll_offset:]): + for control, parameter in izip_longest(self.controls, self.parameters[self.scroll_offset:]): if control: control.mapped_parameter = parameter @@ -70,7 +72,9 @@ def _on_return_tracks_changed(self): def _number_sends(self): mixable = self._tracks_provider.selected_item - return len(mixable.mixer_device.sends) if mixable != self.song.master_track else 0 + if mixable != self.song.master_track: + return len(mixable.mixer_device.sends) + return 0 def _update_scroll_offset(self): new_number_return_tracks = self._number_sends() diff --git a/Push2/track_selection.py b/Push2/track_selection.py index 2faf5718..3b452059 100644 --- a/Push2/track_selection.py +++ b/Push2/track_selection.py @@ -1,39 +1,33 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/track_selection.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/track_selection.py +from __future__ import absolute_import, print_function from functools import partial -from itertools import chain, ifilter, izip import Live from ableton.v2.base import SlotManager, Subject, const, depends, flatten, nop, listenable_property, listens, listens_group, liveobj_changed, liveobj_valid -from ableton.v2.control_surface import Component from ableton.v2.control_surface.components import SessionRingComponent, right_align_return_tracks_track_assigner -from ableton.v2.control_surface.control import ButtonControl, control_list from ableton.v2.control_surface.components.view_control import has_next_item, next_item, TrackScroller as TrackScrollerBase, ViewControlComponent as ViewControlComponentBase from pushbase.device_chain_utils import find_instrument_devices -from pushbase.actions import is_clip_stop_pending -from pushbase.consts import MessageBoxText -from pushbase.message_box_component import Messenger -from pushbase.special_chan_strip_component import toggle_arm -from .colors import translate_color_index from .decoration import TrackDecoratorFactory from .item_lister_component import ItemProvider -from .mixable_utilities import can_play_clips, is_chain from .observable_property_alias import ObservablePropertyAlias -from .stop_clip_component import track_color_with_pending_stop -DeviceType = Live.Device.DeviceType - -def mixable_button_color(mixer_track, song, selected_track = None): - color = 'Mixer.NoTrack' - if mixer_track: - if can_play_clips(mixer_track) and is_clip_stop_pending(mixer_track): - color = track_color_with_pending_stop(mixer_track) - elif mixer_track.solo: - color = 'Mixer.SoloOn' - elif mixer_track == selected_track and not mixer_track.mute: - color = 'Mixer.TrackSelected' - elif mixer_track.mute or mixer_track.muted_via_solo: - color = 'Mixer.MutedTrack' - else: - color = translate_color_index(mixer_track.color_index) - return color + +def get_flattened_track(track): + """ + Returns a flat list of a track with its instrument chains (when visible), or just the + original track + """ + flat_track = [track] + if track.can_show_chains and track.is_showing_chains: + instruments = list(find_instrument_devices(track)) + flat_track.extend([ c for c in instruments[0].chains ]) + return flat_track + + +def get_all_mixer_tracks(song): + tracks = [] + for track in song.visible_tracks: + tracks.extend(get_flattened_track(track)) + + return tracks + list(song.return_tracks) class SelectedMixerTrackProvider(Subject, SlotManager): @@ -79,27 +73,9 @@ def _on_selected_mixer_track_changed(self): def _get_selected_chain_or_track(self): selected_chain = self._view.selected_chain - return selected_chain if selected_chain else self._view.selected_track - - -def get_flattened_track(track): - """ - Returns a flat list of a track with its instrument chains (when visible), or just the - original track - """ - flat_track = [track] - if track.can_show_chains and track.is_showing_chains: - instruments = list(find_instrument_devices(track)) - flat_track.extend([ c for c in instruments[0].chains ]) - return flat_track - - -def get_all_mixer_tracks(song): - tracks = [] - for track in song.visible_tracks: - tracks.extend(get_flattened_track(track)) - - return tracks + list(song.return_tracks) + if selected_chain: + return selected_chain + return self._view.selected_track class SessionRingTrackProvider(SessionRingComponent, ItemProvider): @@ -194,9 +170,10 @@ def flattened_list_of_instruments(instruments): self._on_devices_changed.replace_subjects(tracks) chain_listenable_tracks = [ track for track in tracks if isinstance(track, Live.Track.Track) and track ] instruments = flattened_list_of_instruments([ find_instrument_devices(track) for track in chain_listenable_tracks if track ]) + instruments_with_chains = filter(lambda i: i.can_have_chains, instruments) self._on_is_showing_chains_changed.replace_subjects(chain_listenable_tracks) - self._on_chains_changed.replace_subjects(instruments) - self._on_instrument_return_chains_changed.replace_subjects(instruments) + self._on_chains_changed.replace_subjects(instruments_with_chains) + self._on_instrument_return_chains_changed.replace_subjects(instruments_with_chains) def _ensure_valid_track_offset(self): max_index = len(self.tracks_to_use()) - 1 @@ -213,161 +190,6 @@ def _on_selected_item_changed(self, _): self.notify_selected_item() -def number_of_solos(song): - return len([ track for track in get_all_mixer_tracks(song) if track.solo ]) - - -class MixerTrackListComponent(Component, Messenger): - select_buttons = control_list(ButtonControl, control_count=8) - delete_buttons = control_list(ButtonControl, control_count=8) - duplicate_buttons = control_list(ButtonControl, control_count=8) - arm_buttons = control_list(ButtonControl, control_count=8) - - def __init__(self, tracks_provider = None, trigger_recording_on_release_callback = nop, *a, **k): - raise tracks_provider is not None or AssertionError - super(MixerTrackListComponent, self).__init__(*a, **k) - self._can_trigger_recording_callback = trigger_recording_on_release_callback - self._track_provider = tracks_provider - self._selected_track = self.register_disconnectable(SelectedMixerTrackProvider()) - self.__on_items_changed.subject = self._track_provider - self.__on_selected_item_changed.subject = self._track_provider - self.__on_tracks_changed.subject = self.song - self.__on_selected_track_changed.subject = self.song.view - self._update_track_and_chain_listeners() - self._update_button_enabled_state() - self._update_all_button_colors() - - @listenable_property - def tracks(self): - return self._track_provider.items - - @listenable_property - def selected_track(self): - return self._track_provider.selected_item - - @listenable_property - def absolute_selected_track_index(self): - song = self.song - tracks = song.tracks + song.return_tracks + (song.master_track,) - selected_track = song.view.selected_track - return list(tracks).index(selected_track) - - @listens('tracks') - def __on_tracks_changed(self): - self._update_track_and_chain_listeners() - self._update_button_enabled_state() - - @listens_group('mute') - def __on_track_mute_state_changed(self, track): - self._update_all_button_colors() - - @listens_group('solo') - def __on_track_solo_state_changed(self, track): - self._update_all_button_colors() - - @listens_group('fired_slot_index') - def __on_track_fired_slot_changed(self, track): - self._update_all_button_colors() - - @listens('items') - def __on_items_changed(self): - self._update_track_and_chain_listeners() - self._update_button_enabled_state() - - def _update_track_and_chain_listeners(self): - self.notify_tracks() - self.__on_track_color_index_changed.replace_subjects(self.tracks) - tracks_without_chains = ifilter(can_play_clips, self.tracks) - self.__on_track_fired_slot_changed.replace_subjects(tracks_without_chains) - all_tracks = [ _ for _ in chain(self.song.tracks, self.tracks) ] - self.__on_track_mute_state_changed.replace_subjects(all_tracks) - self.__on_track_solo_state_changed.replace_subjects(all_tracks) - self.__on_track_muted_via_solo_changed.replace_subjects(all_tracks) - self._update_button_enabled_state() - self._update_all_button_colors() - - def _update_button_enabled_state(self): - tracks = self.tracks - for track, control in chain(izip(tracks, self.select_buttons), izip(tracks, self.delete_buttons), izip(tracks, self.arm_buttons), izip(tracks, self.duplicate_buttons)): - control.enabled = liveobj_valid(track) - - @listens_group('color_index') - def __on_track_color_index_changed(self, _): - self._update_all_button_colors() - - @listens('selected_item') - def __on_selected_item_changed(self): - self.notify_selected_track() - self._update_all_button_colors() - - @listens('selected_track') - def __on_selected_track_changed(self): - self.notify_absolute_selected_track_index() - - @listens_group('muted_via_solo') - def __on_track_muted_via_solo_changed(self, mixable): - self._update_all_button_colors() - - def _update_all_button_colors(self): - for index, mixer_track in enumerate(self.tracks): - color = mixable_button_color(mixer_track, self.song, self.selected_track) - self.select_buttons[index].color = color - self.duplicate_buttons[index].color = color - self.delete_buttons[index].color = color - self.arm_buttons[index].color = color - - @select_buttons.pressed - def select_buttons(self, button): - track = self.tracks[button.index] - if track: - if self._track_provider.selected_item != track: - self._track_provider.selected_item = track - else: - if hasattr(track, 'is_foldable') and track.is_foldable: - track.fold_state = not track.fold_state - if hasattr(track, 'is_showing_chains') and track.can_show_chains: - track.is_showing_chains = not track.is_showing_chains - - @staticmethod - def can_duplicate_or_delete(track_or_chain, return_tracks): - unwrapped = track_or_chain.proxied_object - return isinstance(unwrapped, Live.Track.Track) and unwrapped not in list(return_tracks) - - @delete_buttons.pressed - def delete_buttons(self, button): - track_or_chain = self.tracks[button.index] - if self.can_duplicate_or_delete(track_or_chain, self.song.return_tracks): - try: - track_index = list(self.song.tracks).index(track_or_chain) - name = track_or_chain.name - self.song.delete_track(track_index) - self.show_notification(MessageBoxText.DELETE_TRACK % name) - except RuntimeError: - self.show_notification(MessageBoxText.TRACK_DELETE_FAILED) - - @duplicate_buttons.pressed - def duplicate_buttons(self, button): - track_or_chain = self.tracks[button.index] - if self.can_duplicate_or_delete(track_or_chain, self.song.return_tracks): - try: - track_index = list(self.song.tracks).index(track_or_chain) - self.song.duplicate_track(track_index) - self.show_notification(MessageBoxText.DUPLICATE_TRACK % track_or_chain.name) - self._update_all_button_colors() - except Live.Base.LimitationError: - self.show_notification(MessageBoxText.TRACK_LIMIT_REACHED) - except RuntimeError: - self.show_notification(MessageBoxText.TRACK_DUPLICATION_FAILED) - - @arm_buttons.pressed - def arm_buttons(self, button): - track_or_chain = self.tracks[button.index] - if not is_chain(track_or_chain) and track_or_chain.can_be_armed: - song = self.song - toggle_arm(track_or_chain, song, exclusive=song.exclusive_arm) - self._can_trigger_recording_callback(False) - - class TrackScroller(TrackScrollerBase, Subject): __events__ = ('scrolled',) diff --git a/Push2/user_component.py b/Push2/user_component.py index ca6a190d..848b239d 100644 --- a/Push2/user_component.py +++ b/Push2/user_component.py @@ -1,10 +1,46 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Push2/user_component.py -from ableton.v2.control_surface.control import ToggleButtonControl +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/user_component.py +from __future__ import absolute_import, print_function +from contextlib import contextmanager +from ableton.v2.control_surface.mode import ModeButtonBehaviour from pushbase.user_component import UserComponentBase +from . import sysex + +class UserButtonBehavior(ModeButtonBehaviour): + + def __init__(self, user_component = None, *a, **k): + raise user_component is not None or AssertionError + super(UserButtonBehavior, self).__init__(*a, **k) + self._previous_mode = None + self._user_component = user_component + + def press_immediate(self, component, mode): + if component.selected_mode != 'user' and self._user_component.mode == sysex.LIVE_MODE: + self._previous_mode = component.selected_mode + component.selected_mode = 'user' + else: + self._leave_user_mode(component) + + def release_delayed(self, component, mode): + self._leave_user_mode(component) + + def _leave_user_mode(self, component): + if not (component.selected_mode == 'user' and self._user_component.mode == sysex.USER_MODE and self._previous_mode is not None): + raise AssertionError + component.selected_mode = self._previous_mode + self._previous_mode = None + class UserComponent(UserComponentBase): - user_mode_toggle_button = ToggleButtonControl() - @user_mode_toggle_button.toggled - def user_mode_toggle_button(self, toggled, button): - self.toggle_mode() \ No newline at end of file + @contextmanager + def _deferring_sysex(self): + self.defer_sysex_sending = True + yield + self.defer_sysex_sending = False + + def _do_set_mode(self, mode): + if mode == sysex.USER_MODE: + with self._deferring_sysex(): + super(UserComponent, self)._do_set_mode(mode) + else: + super(UserComponent, self)._do_set_mode(mode) \ No newline at end of file diff --git a/Push2/waveform_navigation.py b/Push2/waveform_navigation.py new file mode 100644 index 00000000..cd3fec9c --- /dev/null +++ b/Push2/waveform_navigation.py @@ -0,0 +1,458 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Push2/waveform_navigation.py +from __future__ import absolute_import, print_function +import math +from collections import namedtuple, OrderedDict +from functools import partial +from itertools import imap +from ableton.v2.base import SlotManager, Subject, const, clamp, depends, find_if, index_if, lazy_attribute, listenable_property, listens, listens_group, liveobj_changed, task +from ableton.v2.control_surface.control import EncoderControl +FocusMarker = namedtuple('FocusMarker', ['name', 'position']) + +def ease_out(t, degree): + return 1 - (1 - t) ** degree + + +def inverse_ease_out(t, degree): + if t < 1.0: + return 1.0 - (1.0 - t) ** (1.0 / degree) + return 1.0 + + +def interpolate(from_value, to_value, t, ease_out_degree): + """ + Interpolate between from_value and to_value given the value t [0..1] + ease_out_degree alters the interpolation curve to ease out more, the higher + the value, where 1 is no easing. + """ + t = ease_out(t, ease_out_degree) + return (1.0 - t) * from_value + t * to_value + + +def interpolate_inverse(from_value, to_value, current_value, ease_out_degree): + """ + The inverse function of interpolate solved to t + """ + t = 0.0 if from_value - to_value == 0 else -float(current_value - from_value) / float(from_value - to_value) + return inverse_ease_out(t, ease_out_degree) + + +def calc_easing_degree_for_proportion(proportion): + """ + Calculates a reasonable easing degree for a given proportion. + """ + return -math.log10(proportion) + 1 + + +def compare_region_length(r1, r2): + """ + Returns a negative, zero or positive number, depending on whether r1 is considered + smaller than, equal to, or larger than r2 + """ + r1 = r1() + r2 = r2() + s1 = r1[1] - r1[0] + s2 = r2[1] - r2[0] + return int(s2 - s1) + + +class WaveformNavigation(SlotManager, Subject): + """ Class for managing a visible area of a waveform """ + visible_start = listenable_property.managed(0) + visible_end = listenable_property.managed(0) + animate_visible_region = listenable_property.managed(False) + show_focus = listenable_property.managed(False) + ZOOM_SENSITIVITY = 1.5 + MIN_VISIBLE_LENGTH = 1000 + WAVEFORM_WIDTH_IN_PX = 933 + MARGIN_IN_PX = 121 + RELATIVE_FOCUS_MARGIN = float(MARGIN_IN_PX) / WAVEFORM_WIDTH_IN_PX + + def __init__(self, waveform_length = None, *a, **k): + raise waveform_length is not None or AssertionError + raise waveform_length > 0 or AssertionError + super(WaveformNavigation, self).__init__(*a, **k) + self._length = waveform_length + self._focused_object = None + self._focus_marker = FocusMarker('', 0) + self._touched_objects = set() + self._has_tasks = False + self._target_region_getter = self.get_start_end_region + self._source_region_getter = lambda : (0, self._length) + self._request_select_region = False + self.set_visible_region(0, self._length) + + def disconnect(self): + super(WaveformNavigation, self).disconnect() + if self._has_tasks: + self._tasks.kill() + self._tasks.clear() + + def get_object_identifier(self, obj): + raise NotImplementedError + + def get_zoom_object(self): + raise NotImplementedError + + def get_start_object_identifier(self): + raise NotImplementedError + + def get_end_object_identifier(self): + raise NotImplementedError + + def get_start_end_region(self): + return self._make_region_from_region_identifiers(self.get_start_object_identifier(), self.get_end_object_identifier()) + + @lazy_attribute + def focusable_object_connections(self): + return {} + + @property + def visible_length(self): + """ Returns the length of the visible area """ + return self.visible_end - self.visible_start + + @property + def visible_proportion(self): + """ Returns the proportion between the visible length and the sample length """ + return self.visible_length / float(self._length) + + def set_visible_region(self, start, end, animate = False): + self.animate_visible_region = animate + self.visible_start = clamp(start, 0, self._length) + self.visible_end = clamp(end, 0, self._length) + + def zoom(self, value): + """ Zooms in or out of the waveform start + value should be between -1.0 and 1.0, where 1.0 will zoom in as much as + possible and -1.0 will zoom out completely. + """ + animate = self._request_select_region + if self._request_select_region: + self._select_region(value > 0) + source = self._source_region_getter() + target = self._target_region_getter() + source_length = float(source[1] - source[0]) + target_length = float(target[1] - target[0]) + easing_degree = calc_easing_degree_for_proportion(target_length / source_length) + if source[0] != target[0]: + t = interpolate_inverse(source[0], target[0], self.visible_start, easing_degree) + else: + t = interpolate_inverse(source[1], target[1], self.visible_end, easing_degree) + t = clamp(t + value * self.ZOOM_SENSITIVITY, 0.0, 1.0) + self.set_visible_region(interpolate(source[0], target[0], t, easing_degree), interpolate(source[1], target[1], t, easing_degree), animate=animate) + self.show_focus = True + self.try_hide_focus_delayed() + + def focus_object(self, obj): + if obj != self.get_zoom_object(): + identifier = self.get_object_identifier(obj) + if identifier in self.focusable_object_connections: + connection = self.focusable_object_connections[identifier] + animate = liveobj_changed(self._focused_object, obj) + self._focused_object = obj + self._focus_connection(connection, animate=animate) + return True + return False + + def _focus_connection(self, connection, animate = False): + """ Focuses the connection in the waveform and brings it into the visible range. + The visible length is preserved. The position is aligned to the left or right + of the visible range, with a certain margin defined by RELATIVE_FOCUS_MARGIN. + If the connections boundary is already in the visible range, the visible + position is not changing. + :connection: the object connection to focus + :align_right: focuses the position on the left or right side of the + :animate: should be set to True if, if it should animate to the new position + """ + position = connection.getter() + visible_length = self.visible_length + visible_margin = visible_length * self.RELATIVE_FOCUS_MARGIN + length = self._length + if connection.align_right: + start = min(connection.boundary_getter() - visible_margin, self.visible_start) if connection else 0 + right = max(position + visible_margin, start + visible_length) + self.set_visible_region(clamp(right - visible_length, 0, length - visible_length), clamp(right, visible_length, length), animate) + else: + end = max(connection.boundary_getter() + visible_margin, self.visible_end) if connection else length + left = min(position - visible_margin, end - visible_length) + self.set_visible_region(clamp(left, 0, length - visible_length), clamp(left + visible_length, visible_length, length), animate) + self._focus_marker = FocusMarker(connection.focus_name, position) + self.notify_focus_marker() + self._request_select_region = True + + @listenable_property + def focus_marker(self): + return self._focus_marker + + def touch_object(self, obj): + is_zoom_object = obj == self.get_zoom_object() + if is_zoom_object: + if self._visible_region_reaches(self._target_region_getter()) or self._visible_region_reaches(self._source_region_getter()): + self._request_select_region = True + if self.focus_object(obj) or is_zoom_object: + self._touched_objects.add(obj) + self.show_focus = True + + def release_object(self, obj): + if obj in self._touched_objects: + self._touched_objects.remove(obj) + self.try_hide_focus() + + def change_object(self, obj): + if self.focus_object(obj) or obj == self.get_zoom_object(): + self.show_focus = True + self.try_hide_focus_delayed() + + def try_hide_focus(self): + """ Hides the focus, if the focused object is not longer touched """ + if self._should_hide_focus(): + self.show_focus = False + + def try_hide_focus_delayed(self): + """ Hides the focus after some time, if the focused object is not + longer touched + """ + if self._hide_focus_task and self._should_hide_focus(): + self._hide_focus_task.restart() + + def _should_hide_focus(self): + return self.get_zoom_object() not in self._touched_objects and self._focused_object not in self._touched_objects + + def reset_focus_and_animation(self): + self.show_focus = False + self.animate_visible_region = False + self._touched_objects = set() + + @lazy_attribute + @depends(parent_task_group=const(None)) + def _tasks(self, parent_task_group = None): + if parent_task_group is not None: + tasks = parent_task_group.add(task.TaskGroup()) + self._has_tasks = True + return tasks + + @lazy_attribute + def _hide_focus_task(self): + tasks = self._tasks + if tasks is not None: + return tasks.add(task.sequence(task.wait(EncoderControl.TOUCH_TIME), task.run(self.try_hide_focus))) + + def _add_margin_to_region(self, start, end): + margin = self.RELATIVE_FOCUS_MARGIN + start1 = (margin * start + end * margin - start) / (2 * margin - 1) + end1 = (end - margin * start1) / (1 - margin) + start1 = clamp(start1, 0, self._length) + end1 = clamp(end1, 0, self._length) + return (start1, end1) + + def _get_position_for_identifier(self, identifier): + return self.focusable_object_connections[identifier].getter() + + def _make_region_from_region_identifiers(self, start_identifier, end_identifier): + return self._add_margin_to_region(self._get_position_for_identifier(start_identifier), self._get_position_for_identifier(end_identifier)) + + def _make_region_from_position_identifier(self, identifier): + connection = self.focusable_object_connections[identifier] + align_right = connection.align_right + position = connection.getter() + length = self.MIN_VISIBLE_LENGTH + margin = self.RELATIVE_FOCUS_MARGIN * length + if align_right: + right = min(position + margin, self._length) + left = max(right - length, 0) + else: + left = max(position - margin, 0) + right = min(left + length, self._length) + return (left, right) + + def _make_region_for_focused_object(self): + if self._focused_object is not None: + return self._make_region_from_position_identifier(self.get_object_identifier(self._focused_object)) + return (0, 0) + + def _region_inside(self, inner_region, outer_region): + outer_region = (int(outer_region[0]), int(outer_region[1])) + inner_region = (int(inner_region[0]), int(inner_region[1])) + return inner_region[0] >= outer_region[0] and inner_region[1] <= outer_region[1] and outer_region != inner_region + + def _visible_region_reaches(self, region): + region = (int(region[0]), int(region[1])) + visible_region = (int(self.visible_start), int(self.visible_end)) + return region == visible_region + + def _visible_region_inside(self, region): + return self._region_inside((self.visible_start, self.visible_end), region) + + def _get_region_getters_for_focused_identifier(self): + focused_identifier = self.get_object_identifier(self._focused_object) + return self.focusable_object_connections[focused_identifier].region_getters + + def _get_unique_region_getters(self): + """ + Eliminates duplicates of the current regions and returns the remaining getters + sorted by the length of the regions. + """ + getters = OrderedDict() + for region_getter in self._get_region_getters_for_focused_identifier(): + getters[region_getter()] = region_getter + + return sorted(getters.values(), cmp=compare_region_length) + + def _select_region_around_visible_region(self): + region_getters = self._get_unique_region_getters() + source_getter = find_if(lambda g: self._visible_region_inside(g()), region_getters[1::-1]) + if source_getter is not None: + self._source_region_getter = source_getter + self._target_region_getter = region_getters[region_getters.index(source_getter) + 1] + + def _select_reached_region(self, zoom_in): + region_getters = self._get_unique_region_getters() + i = index_if(self._visible_region_reaches, imap(apply, region_getters)) + if i != len(region_getters): + if zoom_in: + if i < len(region_getters) - 1: + self._source_region_getter = region_getters[i] + self._target_region_getter = region_getters[i + 1] + elif i > 0: + self._source_region_getter = region_getters[i - 1] + self._target_region_getter = region_getters[i] + return True + return False + + def _select_region(self, zoom_in): + if not self._select_reached_region(zoom_in): + self._select_region_around_visible_region() + self._request_select_region = False + + +ObjectConnection = namedtuple('ObjectConnection', ['getter', + 'align_right', + 'focus_name', + 'region_getters', + 'boundary_getter']) + +class SimplerWaveformNavigation(WaveformNavigation): + """ Extends the WaveformNavigation class by the concept of focusing parameters + and slices. + """ + selected_slice_focus = object() + + def __init__(self, simpler = None, *a, **k): + super(SimplerWaveformNavigation, self).__init__(*a, **k) + self._simpler = simpler + focusable_parameters = [ self._simpler.get_parameter_by_name(n) for n in self.focusable_object_connections ] + self.__on_selected_slice_changed.subject = simpler.view + self.__on_parameter_value_changed.replace_subjects(focusable_parameters) + + @lazy_attribute + def focusable_object_connections(self): + return {'Start': ObjectConnection(lambda : self._simpler.sample.start_marker, False, 'start_marker', (lambda : (0, self._length), self.get_start_end_region, self._make_region_for_focused_object), partial(self._get_position_for_identifier, 'End')), + 'End': ObjectConnection(lambda : self._simpler.sample.end_marker, True, 'end_marker', (lambda : (0, self._length), self.get_start_end_region, self._make_region_for_focused_object), partial(self._get_position_for_identifier, 'Start')), + 'S Start': ObjectConnection(lambda : self._simpler.view.sample_start, False, 'position', (lambda : (0, self._length), + self.get_start_end_region, + self.get_sample_start_end_region, + self._make_region_for_focused_object), partial(self._get_position_for_identifier, 'S Length')), + 'S Length': ObjectConnection(lambda : self._simpler.view.sample_end, True, 'position', (lambda : (0, self._length), + self.get_start_end_region, + self.get_sample_start_end_region, + self._make_region_for_focused_object), partial(self._get_position_for_identifier, 'S Start')), + 'S Loop Length': ObjectConnection(lambda : self._simpler.view.sample_loop_start, False, 'position', (lambda : (0, self._length), + self.get_start_end_region, + self.get_sample_start_end_region, + self.get_sample_loop_start_end_region, + self._make_region_for_focused_object), partial(self._get_position_for_identifier, 'S Length')), + self.selected_slice_focus: ObjectConnection(lambda : self._simpler.view.selected_slice, False, '', (lambda : (0, self._length), + self.get_start_end_region, + self.get_slice_region, + self._make_region_for_focused_object), self.get_next_slice_position)} + + def get_object_identifier(self, obj): + if hasattr(obj, 'name'): + return obj.name + return self.selected_slice_focus + + def get_zoom_object(self): + return self._simpler.zoom + + def get_start_object_identifier(self): + return 'Start' + + def get_end_object_identifier(self): + return 'End' + + def get_sample_start_end_region(self): + return self._make_region_from_region_identifiers('S Start', 'S Length') + + def get_sample_loop_start_end_region(self): + return self._make_region_from_region_identifiers('S Loop Length', 'S Length') + + def get_next_slice_position(self): + selected_slice = self._get_selected_slice_index() + if selected_slice < 0 or selected_slice + 1 >= len(self._simpler.sample.slices): + return self._get_position_for_identifier(self.get_end_object_identifier()) + return self._simpler.sample.slices[selected_slice + 1] + + def get_slice_region(self): + return self._add_margin_to_region(self._get_position_for_identifier(self.selected_slice_focus), self.get_next_slice_position()) + + @listens_group('value') + def __on_parameter_value_changed(self, parameter): + self.change_object(parameter) + + @listens('selected_slice') + def __on_selected_slice_changed(self): + slice_index = self._get_selected_slice_index() + if slice_index != -1: + self.focus_object(slice_index) + + def _get_selected_slice_index(self): + try: + return self._simpler.sample.slices.index(self._simpler.view.selected_slice) + except ValueError: + pass + + return -1 + + +class AudioClipWaveformNavigation(WaveformNavigation): + """ WaveformNavigation that adds the concept of focus for audio clips to the. """ + zoom_focus = object() + start_marker_focus = object() + loop_start_focus = object() + loop_end_focus = object() + + def __init__(self, clip = None, *a, **k): + super(AudioClipWaveformNavigation, self).__init__(*a, **k) + self._clip = clip + self.__on_is_recording_changed.subject = clip + + @lazy_attribute + def focusable_object_connections(self): + return {self.start_marker_focus: ObjectConnection(lambda : self._clip.view.sample_start_marker, False, 'start_marker', (lambda : (0, self._length), self.get_start_end_region, self._make_region_for_focused_object), partial(self._get_position_for_identifier, self.loop_end_focus)), + self.loop_start_focus: ObjectConnection(lambda : self._clip.view.sample_loop_start, False, 'position', (lambda : (0, self._length), self.get_start_end_region, self._make_region_for_focused_object), partial(self._get_position_for_identifier, self.loop_end_focus)), + self.loop_end_focus: ObjectConnection(lambda : self._clip.view.sample_loop_end, True, 'end_marker', (lambda : (0, self._length), self.get_start_end_region, self._make_region_for_focused_object), self._get_start_position)} + + def get_object_identifier(self, obj): + return obj + + def get_zoom_object(self): + return self.zoom_focus + + def get_start_object_identifier(self): + return self.loop_start_focus + + def get_end_object_identifier(self): + return self.loop_end_focus + + def _get_start_position(self): + start_marker_position = self._get_position_for_identifier(self.start_marker_focus) + loop_start_position = self._get_position_for_identifier(self.loop_start_focus) + return min(start_marker_position, loop_start_position) + + def get_start_end_region(self): + return self._add_margin_to_region(self._get_start_position(), self._get_position_for_identifier(self.loop_end_focus)) + + @listens('is_recording') + def __on_is_recording_changed(self): + self._length = self._clip.view.sample_length + self.set_visible_region(0, self._length) \ No newline at end of file diff --git a/Radium49_61/__init__.py b/Radium49_61/__init__.py index bf47f9ec..62a05c22 100644 --- a/Radium49_61/__init__.py +++ b/Radium49_61/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Radium49_61/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Radium49_61/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/Radium49_61/config.py b/Radium49_61/config.py index 2940945a..65ef4aab 100644 --- a/Radium49_61/config.py +++ b/Radium49_61/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Radium49_61/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Radium49_61/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/Radium49_61/consts.py b/Radium49_61/consts.py index 8272b4a7..f76f221d 100644 --- a/Radium49_61/consts.py +++ b/Radium49_61/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Radium49_61/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Radium49_61/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/RemoteSL/DisplayController.py b/RemoteSL/DisplayController.py index bb7249be..0956ce9f 100644 --- a/RemoteSL/DisplayController.py +++ b/RemoteSL/DisplayController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL/DisplayController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL/DisplayController.py from RemoteSLComponent import RemoteSLComponent from consts import * diff --git a/RemoteSL/EffectController.py b/RemoteSL/EffectController.py index c5e05c34..9f8645f4 100644 --- a/RemoteSL/EffectController.py +++ b/RemoteSL/EffectController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL/EffectController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL/EffectController.py import Live from RemoteSLComponent import RemoteSLComponent from consts import * @@ -45,18 +45,18 @@ def receive_midi_cc(self, cc_no, cc_value): elif cc_no in fx_encoder_row_ccs: strip = self.__strips[cc_no - FX_ENCODER_ROW_BASE_CC] strip.on_encoder_moved(cc_value) - elif not (cc_no in fx_lower_button_row_ccs and False): - raise AssertionError, 'Lower Button CCS should be passed to Live!' - elif not (cc_no in fx_poti_row_ccs and False): - raise AssertionError, 'Poti CCS should be passed to Live!' + elif cc_no in fx_lower_button_row_ccs: + raise False or AssertionError('Lower Button CCS should be passed to Live!') + elif cc_no in fx_poti_row_ccs: + raise False or AssertionError('Poti CCS should be passed to Live!') else: - raise False or AssertionError, 'unknown FX midi message' + raise False or AssertionError('unknown FX midi message') def receive_midi_note(self, note, velocity): - if not (note in fx_drum_pad_row_notes and False): - raise AssertionError, 'DrumPad CCS should be passed to Live!' + if note in fx_drum_pad_row_notes: + raise False or AssertionError('DrumPad CCS should be passed to Live!') else: - raise False or AssertionError, 'unknown FX midi message' + raise False or AssertionError('unknown FX midi message') def build_midi_map(self, script_handle, midi_map_handle): needs_takeover = True @@ -156,7 +156,7 @@ def __handle_page_up_down_ccs(self, cc_no, cc_value): new_bank = max(self.__bank - 1, 0) else: if not False: - raise AssertionError, 'unknown Display midi message' + raise AssertionError('unknown Display midi message') if not self.__bank == new_bank: self.__show_bank = True if not self.__assigned_device_is_locked: @@ -184,7 +184,7 @@ def __handle_select_button_ccs(self, cc_no, cc_value): if cc_value == CC_VAL_BUTTON_PRESSED: self.song().stop_all_clips() else: - raise False or AssertionError, 'unknown select row midi message' + raise False or AssertionError('unknown select row midi message') def __update_select_row_leds(self): if self.__assigned_device_is_locked: @@ -276,4 +276,4 @@ def on_button_pressed(self): self.__assigned_parameter.value = self.__assigned_parameter.default_value def on_encoder_moved(self, cc_value): - raise self.__assigned_parameter == None or AssertionError, 'should only be reached when the encoder was not realtime mapped ' \ No newline at end of file + raise self.__assigned_parameter == None or AssertionError('should only be reached when the encoder was not realtime mapped ') \ No newline at end of file diff --git a/RemoteSL/MixerController.py b/RemoteSL/MixerController.py index 9f2bbc43..6cce695c 100644 --- a/RemoteSL/MixerController.py +++ b/RemoteSL/MixerController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL/MixerController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL/MixerController.py import Live from RemoteSLComponent import RemoteSLComponent from consts import * @@ -70,7 +70,7 @@ def receive_midi_cc(self, cc_no, cc_value): elif cc_no in ts_ccs: self.__handle_transport_ccs(cc_no, cc_value) else: - raise False or AssertionError, 'unknown FX midi message' + raise False or AssertionError('unknown FX midi message') def build_midi_map(self, script_handle, midi_map_handle): needs_takeover = True @@ -155,7 +155,7 @@ def __handle_page_up_down_ccs(self, cc_no, cc_value): self.__validate_strip_offset() self.__reassign_strips() else: - raise False or AssertionError, 'unknown Display midi message' + raise False or AssertionError('unknown Display midi message') def __handle_select_button_ccs(self, cc_no, cc_value): if cc_no == MX_SELECT_SLIDER_ROW: @@ -168,7 +168,7 @@ def __handle_select_button_ccs(self, cc_no, cc_value): if cc_value == CC_VAL_BUTTON_PRESSED: self.__set_slider_mode(SLIDER_MODE_SEND) else: - raise False or AssertionError, 'unknown select row midi message' + raise False or AssertionError('unknown select row midi message') def __handle_transport_ccs(self, cc_no, cc_value): if cc_no == TS_REWIND_CC: @@ -199,7 +199,7 @@ def __handle_transport_ccs(self, cc_no, cc_value): self.__transport_locked = cc_value != CC_VAL_BUTTON_RELEASED self.__on_transport_lock_changed() else: - raise False or AssertionError, 'unknown Transport CC ' + str(cc_no) + raise False or AssertionError('unknown Transport CC ' + str(cc_no)) def __on_transport_lock_changed(self): for strip in self.__strips: @@ -331,9 +331,9 @@ def slider_parameter(self): if self.__assigned_track: if slider_mode == SLIDER_MODE_VOLUME: return self.__assigned_track.mixer_device.volume - elif slider_mode == SLIDER_MODE_PAN: + if slider_mode == SLIDER_MODE_PAN: return self.__assigned_track.mixer_device.panning - elif slider_mode >= SLIDER_MODE_SEND: + if slider_mode >= SLIDER_MODE_SEND: send_index = slider_mode - SLIDER_MODE_SEND if send_index < len(self.__assigned_track.mixer_device.sends): return self.__assigned_track.mixer_device.sends[send_index] @@ -343,7 +343,7 @@ def slider_parameter(self): return None def slider_moved(self, cc_value): - raise self.__assigned_track == None or self.slider_parameter() == None or AssertionError, 'should only be reached when the slider was not realtime mapped ' + raise self.__assigned_track == None or self.slider_parameter() == None or AssertionError('should only be reached when the slider was not realtime mapped ') def take_control_of_second_button(self, take_control): if self.__mixer_controller.support_mkII(): @@ -358,12 +358,12 @@ def first_button_pressed(self): self.__assigned_track.mute = not self.__assigned_track.mute def second_button_pressed(self): - if self.__assigned_track in self.song().visible_tracks: - if self.__assigned_track.can_be_armed: - self.__mixer_controller.track_about_to_arm(self.__assigned_track) - self.__assigned_track.arm = not self.__assigned_track.arm - if self.__assigned_track.arm: - self.__assigned_track.view.select_instrument() and self.__mixer_controller.set_selected_track(self.__assigned_track) + if self.__assigned_track in self.song().visible_tracks and self.__assigned_track.can_be_armed: + self.__mixer_controller.track_about_to_arm(self.__assigned_track) + self.__assigned_track.arm = not self.__assigned_track.arm + if self.__assigned_track.arm: + if self.__assigned_track.view.select_instrument(): + self.__mixer_controller.set_selected_track(self.__assigned_track) def _on_mute_changed(self): if self.__mixer_controller.support_mkII(): diff --git a/RemoteSL/RemoteSL.py b/RemoteSL/RemoteSL.py index 46b2eba5..749b2f9e 100644 --- a/RemoteSL/RemoteSL.py +++ b/RemoteSL/RemoteSL.py @@ -1,10 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL/RemoteSL.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL/RemoteSL.py import Live import MidiRemoteScript from EffectController import EffectController from MixerController import MixerController from DisplayController import DisplayController from consts import * +from _Generic.util import DeviceAppointer class RemoteSL: """ Automap script for the Novation Remote SL. @@ -19,6 +20,7 @@ def __init__(self, c_instance): self.__mixer_controller = MixerController(self, self.__display_controller) self.__components = [self.__effect_controller, self.__mixer_controller, self.__display_controller] self.__update_hardware_delay = -1 + self._device_appointer = DeviceAppointer(song=self.song(), appointed_device_setter=self._set_appointed_device) def disconnect(self): """Called right before we get disconnected from Live @@ -26,6 +28,7 @@ def disconnect(self): for c in self.__components: c.disconnect() + self._device_appointer.disconnect() self.send_midi(ALL_LEDS_OFF_MESSAGE) self.send_midi(GOOD_BYE_SYSEX_MESSAGE) @@ -69,7 +72,7 @@ def unlock_from_device(self, device): """ self.__effect_controller.unlock_from_device(device) - def set_appointed_device(self, device): + def _set_appointed_device(self, device): """Live -> Script Live can tell the script which device to use if it is not locked This is a substitute mechanism for the listeners used by older scripts diff --git a/RemoteSL/RemoteSLComponent.py b/RemoteSL/RemoteSLComponent.py index 10024cc7..13157886 100644 --- a/RemoteSL/RemoteSLComponent.py +++ b/RemoteSL/RemoteSLComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL/RemoteSLComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL/RemoteSLComponent.py from consts import * class RemoteSLComponent: diff --git a/RemoteSL/__init__.py b/RemoteSL/__init__.py index 6683d4c7..fc5f2154 100644 --- a/RemoteSL/__init__.py +++ b/RemoteSL/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL/__init__.py from RemoteSL import RemoteSL def create_instance(c_instance): diff --git a/RemoteSL/consts.py b/RemoteSL/consts.py index d60bae71..9dd99df4 100644 --- a/RemoteSL/consts.py +++ b/RemoteSL/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL/consts.py NOTE_OFF_STATUS = 128 NOTE_ON_STATUS = 144 CC_STATUS = 176 diff --git a/RemoteSL_Classic/DisplayController.py b/RemoteSL_Classic/DisplayController.py index ca9d63ac..26096f6e 100644 --- a/RemoteSL_Classic/DisplayController.py +++ b/RemoteSL_Classic/DisplayController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL_Classic/DisplayController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL_Classic/DisplayController.py from RemoteSLComponent import RemoteSLComponent from consts import * diff --git a/RemoteSL_Classic/EffectController.py b/RemoteSL_Classic/EffectController.py index 5d881923..6a4e415b 100644 --- a/RemoteSL_Classic/EffectController.py +++ b/RemoteSL_Classic/EffectController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL_Classic/EffectController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL_Classic/EffectController.py import Live from RemoteSLComponent import RemoteSLComponent from consts import * @@ -44,18 +44,18 @@ def receive_midi_cc(self, cc_no, cc_value): elif cc_no in fx_encoder_row_ccs: strip = self.__strips[cc_no - FX_ENCODER_ROW_BASE_CC] strip.on_encoder_moved(cc_value) - elif not (cc_no in fx_lower_button_row_ccs and False): - raise AssertionError, 'Lower Button CCS should be passed to Live!' - elif not (cc_no in fx_poti_row_ccs and False): - raise AssertionError, 'Poti CCS should be passed to Live!' + elif cc_no in fx_lower_button_row_ccs: + raise False or AssertionError('Lower Button CCS should be passed to Live!') + elif cc_no in fx_poti_row_ccs: + raise False or AssertionError('Poti CCS should be passed to Live!') else: - raise False or AssertionError, 'unknown FX midi message' + raise False or AssertionError('unknown FX midi message') def receive_midi_note(self, note, velocity): - if not (note in fx_drum_pad_row_notes and False): - raise AssertionError, 'DrumPad CCS should be passed to Live!' + if note in fx_drum_pad_row_notes: + raise False or AssertionError('DrumPad CCS should be passed to Live!') else: - raise False or AssertionError, 'unknown FX midi message' + raise False or AssertionError('unknown FX midi message') def build_midi_map(self, script_handle, midi_map_handle): needs_takeover = True @@ -146,7 +146,7 @@ def __handle_page_up_down_ccs(self, cc_no, cc_value): new_bank = max(self.__bank - 1, 0) else: if not False: - raise AssertionError, 'unknown Display midi message' + raise AssertionError('unknown Display midi message') if not self.__bank == new_bank: self.__show_bank = True if not self.__assigned_device_is_locked: @@ -174,7 +174,7 @@ def __handle_select_button_ccs(self, cc_no, cc_value): if cc_value == CC_VAL_BUTTON_PRESSED: self.song().stop_all_clips() else: - raise False or AssertionError, 'unknown select row midi message' + raise False or AssertionError('unknown select row midi message') def __update_select_row_leds(self): if self.__assigned_device_is_locked: @@ -264,4 +264,4 @@ def on_button_pressed(self): self.__assigned_parameter.value = self.__assigned_parameter.default_value def on_encoder_moved(self, cc_value): - raise self.__assigned_parameter == None or AssertionError, 'should only be reached when the encoder was not realtime mapped ' \ No newline at end of file + raise self.__assigned_parameter == None or AssertionError('should only be reached when the encoder was not realtime mapped ') \ No newline at end of file diff --git a/RemoteSL_Classic/MixerController.py b/RemoteSL_Classic/MixerController.py index b2f67710..3d4512d8 100644 --- a/RemoteSL_Classic/MixerController.py +++ b/RemoteSL_Classic/MixerController.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL_Classic/MixerController.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL_Classic/MixerController.py import Live from RemoteSLComponent import RemoteSLComponent from consts import * @@ -70,7 +70,7 @@ def receive_midi_cc(self, cc_no, cc_value): elif cc_no in ts_ccs: self.__handle_transport_ccs(cc_no, cc_value) else: - raise False or AssertionError, 'unknown FX midi message' + raise False or AssertionError('unknown FX midi message') def build_midi_map(self, script_handle, midi_map_handle): needs_takeover = True @@ -155,7 +155,7 @@ def __handle_page_up_down_ccs(self, cc_no, cc_value): self.__validate_strip_offset() self.__reassign_strips() else: - raise False or AssertionError, 'unknown Display midi message' + raise False or AssertionError('unknown Display midi message') def __handle_select_button_ccs(self, cc_no, cc_value): if cc_no == MX_SELECT_SLIDER_ROW: @@ -168,7 +168,7 @@ def __handle_select_button_ccs(self, cc_no, cc_value): if cc_value == CC_VAL_BUTTON_PRESSED: self.__set_slider_mode(SLIDER_MODE_SEND) else: - raise False or AssertionError, 'unknown select row midi message' + raise False or AssertionError('unknown select row midi message') def __handle_transport_ccs(self, cc_no, cc_value): if cc_no == TS_REWIND_CC: @@ -199,7 +199,7 @@ def __handle_transport_ccs(self, cc_no, cc_value): self.__transport_locked = cc_value != CC_VAL_BUTTON_RELEASED self.__on_transport_lock_changed() else: - raise False or AssertionError, 'unknown Transport CC ' + str(cc_no) + raise False or AssertionError('unknown Transport CC ' + str(cc_no)) def __on_transport_lock_changed(self): for strip in self.__strips: @@ -331,9 +331,9 @@ def slider_parameter(self): if self.__assigned_track: if slider_mode == SLIDER_MODE_VOLUME: return self.__assigned_track.mixer_device.volume - elif slider_mode == SLIDER_MODE_PAN: + if slider_mode == SLIDER_MODE_PAN: return self.__assigned_track.mixer_device.panning - elif slider_mode >= SLIDER_MODE_SEND: + if slider_mode >= SLIDER_MODE_SEND: send_index = slider_mode - SLIDER_MODE_SEND if send_index < len(self.__assigned_track.mixer_device.sends): return self.__assigned_track.mixer_device.sends[send_index] @@ -343,7 +343,7 @@ def slider_parameter(self): return None def slider_moved(self, cc_value): - raise self.__assigned_track == None or self.slider_parameter() == None or AssertionError, 'should only be reached when the slider was not realtime mapped ' + raise self.__assigned_track == None or self.slider_parameter() == None or AssertionError('should only be reached when the slider was not realtime mapped ') def take_control_of_second_button(self, take_control): if self.__mixer_controller.support_mkII(): @@ -358,12 +358,12 @@ def first_button_pressed(self): self.__assigned_track.mute = not self.__assigned_track.mute def second_button_pressed(self): - if self.__assigned_track in self.song().visible_tracks: - if self.__assigned_track.can_be_armed: - self.__mixer_controller.track_about_to_arm(self.__assigned_track) - self.__assigned_track.arm = not self.__assigned_track.arm - if self.__assigned_track.arm: - self.__assigned_track.view.select_instrument() and self.__mixer_controller.set_selected_track(self.__assigned_track) + if self.__assigned_track in self.song().visible_tracks and self.__assigned_track.can_be_armed: + self.__mixer_controller.track_about_to_arm(self.__assigned_track) + self.__assigned_track.arm = not self.__assigned_track.arm + if self.__assigned_track.arm: + if self.__assigned_track.view.select_instrument(): + self.__mixer_controller.set_selected_track(self.__assigned_track) def _on_mute_changed(self): if self.__mixer_controller.support_mkII(): diff --git a/RemoteSL_Classic/RemoteSL.py b/RemoteSL_Classic/RemoteSL.py index 5164f01e..650cda41 100644 --- a/RemoteSL_Classic/RemoteSL.py +++ b/RemoteSL_Classic/RemoteSL.py @@ -1,10 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL_Classic/RemoteSL.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL_Classic/RemoteSL.py import Live import MidiRemoteScript from EffectController import EffectController from MixerController import MixerController from DisplayController import DisplayController from consts import * +from _Generic.util import DeviceAppointer class RemoteSL: """ Automap script for the Novation Remote SL. @@ -19,6 +20,7 @@ def __init__(self, c_instance): self.__mixer_controller = MixerController(self, self.__display_controller) self.__components = [self.__effect_controller, self.__mixer_controller, self.__display_controller] self.__update_hardware_delay = -1 + self._device_appointer = DeviceAppointer(song=self.song(), appointed_device_setter=self._set_appointed_device) def disconnect(self): """Called right before we get disconnected from Live @@ -26,6 +28,7 @@ def disconnect(self): for c in self.__components: c.disconnect() + self._device_appointer.disconnect() self.send_midi(ALL_LEDS_OFF_MESSAGE) self.send_midi(GOOD_BYE_SYSEX_MESSAGE) @@ -69,7 +72,7 @@ def unlock_from_device(self, device): """ self.__effect_controller.unlock_from_device(device) - def set_appointed_device(self, device): + def _set_appointed_device(self, device): """Live -> Script Live can tell the script which device to use if it is not locked This is a substitute mechanism for the listeners used by older scripts diff --git a/RemoteSL_Classic/RemoteSLComponent.py b/RemoteSL_Classic/RemoteSLComponent.py index 255b464e..82805e7c 100644 --- a/RemoteSL_Classic/RemoteSLComponent.py +++ b/RemoteSL_Classic/RemoteSLComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL_Classic/RemoteSLComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL_Classic/RemoteSLComponent.py from consts import * class RemoteSLComponent: diff --git a/RemoteSL_Classic/__init__.py b/RemoteSL_Classic/__init__.py index 56b05fe4..9f107452 100644 --- a/RemoteSL_Classic/__init__.py +++ b/RemoteSL_Classic/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL_Classic/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL_Classic/__init__.py from RemoteSL import RemoteSL def create_instance(c_instance): diff --git a/RemoteSL_Classic/consts.py b/RemoteSL_Classic/consts.py index 8682c7bf..350f3b36 100644 --- a/RemoteSL_Classic/consts.py +++ b/RemoteSL_Classic/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/RemoteSL_Classic/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/RemoteSL_Classic/consts.py NOTE_OFF_STATUS = 128 NOTE_ON_STATUS = 144 CC_STATUS = 176 diff --git a/Roland_A_PRO/DeviceNavigationComponent.py b/Roland_A_PRO/DeviceNavigationComponent.py index a4a4b64a..0768c744 100644 --- a/Roland_A_PRO/DeviceNavigationComponent.py +++ b/Roland_A_PRO/DeviceNavigationComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Roland_A_PRO/DeviceNavigationComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Roland_A_PRO/DeviceNavigationComponent.py import Live from _Framework.ControlSurfaceComponent import ControlSurfaceComponent from _Framework.Control import ButtonControl diff --git a/Roland_A_PRO/MixerComponent.py b/Roland_A_PRO/MixerComponent.py index 2686d83c..db55f628 100644 --- a/Roland_A_PRO/MixerComponent.py +++ b/Roland_A_PRO/MixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Roland_A_PRO/MixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Roland_A_PRO/MixerComponent.py from _Framework.MixerComponent import MixerComponent as MixerComponentBase from _Framework.Control import ButtonControl diff --git a/Roland_A_PRO/Roland_A_PRO.py b/Roland_A_PRO/Roland_A_PRO.py index 7bef4260..5895c62b 100644 --- a/Roland_A_PRO/Roland_A_PRO.py +++ b/Roland_A_PRO/Roland_A_PRO.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Roland_A_PRO/Roland_A_PRO.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Roland_A_PRO/Roland_A_PRO.py from __future__ import with_statement from functools import partial import Live diff --git a/Roland_A_PRO/__init__.py b/Roland_A_PRO/__init__.py index 7b3ad8ad..cf01d826 100644 --- a/Roland_A_PRO/__init__.py +++ b/Roland_A_PRO/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Roland_A_PRO/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Roland_A_PRO/__init__.py from .Roland_A_PRO import Roland_A_PRO from _Framework.Capabilities import controller_id, inport, outport, CONTROLLER_ID_KEY, PORTS_KEY, NOTES_CC, SCRIPT, REMOTE diff --git a/Tranzport/Tranzport.py b/Tranzport/Tranzport.py index e85ef560..160e4ed9 100644 --- a/Tranzport/Tranzport.py +++ b/Tranzport/Tranzport.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Tranzport/Tranzport.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Tranzport/Tranzport.py import Live from consts import * from itertools import chain @@ -296,8 +296,8 @@ def __on_track_button_pressed(self, button, status): i.mute = False elif button == TRANZ_SOLO_TRACK: - if status > 0: - if (list(self.song().visible_tracks) + list(self.song().return_tracks)).count(self.__current_track) > 0 and (self.song().exclusive_solo and not self.__shift_pressed or self.__shift_pressed and not self.song().exclusive_solo): + if status > 0 and (list(self.song().visible_tracks) + list(self.song().return_tracks)).count(self.__current_track) > 0: + if self.song().exclusive_solo and not self.__shift_pressed or self.__shift_pressed and not self.song().exclusive_solo: for i in chain(self.song().tracks, self.song().return_tracks): if i.solo and not i == self.__current_track: i.solo = False diff --git a/Tranzport/__init__.py b/Tranzport/__init__.py index e0a85021..fde86836 100644 --- a/Tranzport/__init__.py +++ b/Tranzport/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Tranzport/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Tranzport/__init__.py from Tranzport import Tranzport def create_instance(c_instance): diff --git a/Tranzport/consts.py b/Tranzport/consts.py index 0511951d..fd854e7e 100644 --- a/Tranzport/consts.py +++ b/Tranzport/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/Tranzport/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/Tranzport/consts.py NOTE_OFF_STATUS = 128 NOTE_ON_STATUS = 144 CC_STATUS = 176 diff --git a/TriggerFinger/__init__.py b/TriggerFinger/__init__.py index 489abe32..1773c3cc 100644 --- a/TriggerFinger/__init__.py +++ b/TriggerFinger/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/TriggerFinger/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/TriggerFinger/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/TriggerFinger/config.py b/TriggerFinger/config.py index 6476ca8a..5a7c15d1 100644 --- a/TriggerFinger/config.py +++ b/TriggerFinger/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/TriggerFinger/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/TriggerFinger/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/TriggerFinger/consts.py b/TriggerFinger/consts.py index 4e93d51a..079a4b90 100644 --- a/TriggerFinger/consts.py +++ b/TriggerFinger/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/TriggerFinger/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/TriggerFinger/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/UC33e/__init__.py b/UC33e/__init__.py index a1f8b41e..bee0300b 100644 --- a/UC33e/__init__.py +++ b/UC33e/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/UC33e/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/UC33e/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/UC33e/config.py b/UC33e/config.py index ff612d9c..b0ea2ac2 100644 --- a/UC33e/config.py +++ b/UC33e/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/UC33e/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/UC33e/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/UC33e/consts.py b/UC33e/consts.py index a5bff2b5..b24d2b26 100644 --- a/UC33e/consts.py +++ b/UC33e/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/UC33e/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/UC33e/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/VCM600/MixerComponent.py b/VCM600/MixerComponent.py index 4331ec7d..e1f0b6ca 100644 --- a/VCM600/MixerComponent.py +++ b/VCM600/MixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/VCM600/MixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/VCM600/MixerComponent.py from _Framework.MixerComponent import MixerComponent as MixerComponentBase from .TrackEQComponent import TrackEQComponent from .TrackFilterComponent import TrackFilterComponent diff --git a/VCM600/TrackEQComponent.py b/VCM600/TrackEQComponent.py index b3ee1c6b..7d6ccf70 100644 --- a/VCM600/TrackEQComponent.py +++ b/VCM600/TrackEQComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/VCM600/TrackEQComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/VCM600/TrackEQComponent.py import Live from _Framework.ControlSurfaceComponent import ControlSurfaceComponent from _Framework.EncoderElement import EncoderElement diff --git a/VCM600/TrackFilterComponent.py b/VCM600/TrackFilterComponent.py index e039a904..ceb8b1bd 100644 --- a/VCM600/TrackFilterComponent.py +++ b/VCM600/TrackFilterComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/VCM600/TrackFilterComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/VCM600/TrackFilterComponent.py import Live from _Framework.ControlSurfaceComponent import ControlSurfaceComponent from _Framework.EncoderElement import EncoderElement diff --git a/VCM600/TransportComponent.py b/VCM600/TransportComponent.py index 2bc3e36d..4c44ffb5 100644 --- a/VCM600/TransportComponent.py +++ b/VCM600/TransportComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/VCM600/TransportComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/VCM600/TransportComponent.py from _Framework.TransportComponent import TransportComponent as TransportComponentBase class TransportComponent(TransportComponentBase): diff --git a/VCM600/VCM600.py b/VCM600/VCM600.py index 72e37da1..a9e16c08 100644 --- a/VCM600/VCM600.py +++ b/VCM600/VCM600.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/VCM600/VCM600.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/VCM600/VCM600.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/VCM600/ViewTogglerComponent.py b/VCM600/ViewTogglerComponent.py index 287dfa5c..b10d1b81 100644 --- a/VCM600/ViewTogglerComponent.py +++ b/VCM600/ViewTogglerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/VCM600/ViewTogglerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/VCM600/ViewTogglerComponent.py import Live from _Framework.ControlSurfaceComponent import ControlSurfaceComponent from _Framework.ButtonElement import ButtonElement diff --git a/VCM600/__init__.py b/VCM600/__init__.py index 567a52b4..bc6f806c 100644 --- a/VCM600/__init__.py +++ b/VCM600/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/VCM600/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/VCM600/__init__.py from VCM600 import VCM600 def create_instance(c_instance): diff --git a/ZERO8/__init__.py b/ZERO8/__init__.py index 466acc90..36d657e6 100644 --- a/ZERO8/__init__.py +++ b/ZERO8/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ZERO8/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ZERO8/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/ZERO8/config.py b/ZERO8/config.py index 58dbec62..41ba4154 100644 --- a/ZERO8/config.py +++ b/ZERO8/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ZERO8/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ZERO8/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/ZERO8/consts.py b/ZERO8/consts.py index adf30ef8..96abdd1b 100644 --- a/ZERO8/consts.py +++ b/ZERO8/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ZERO8/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ZERO8/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/_APC/APC.py b/_APC/APC.py index ed10391c..c4760753 100644 --- a/_APC/APC.py +++ b/_APC/APC.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/APC.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/APC.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface @@ -56,15 +56,15 @@ def _on_identity_response(self, midi_bytes): self._log_version(version_bytes) def _on_dongle_response(self, midi_bytes): - if midi_bytes[1] == MANUFACTURER_ID and midi_bytes[3] == self._product_model_id_byte() and midi_bytes[2] == self._device_id and midi_bytes[5] == 0: - if midi_bytes[6] == 16: - response = [long(0), long(0)] - for index in range(8): - response[0] += long(midi_bytes[7 + index] & 15) << 4 * (7 - index) - response[1] += long(midi_bytes[15 + index] & 15) << 4 * (7 - index) - - expected_response = Live.Application.encrypt_challenge(self._dongle_challenge[0], self._dongle_challenge[1]) - [long(expected_response[0]), long(expected_response[1])] == response and self._on_handshake_successful() + if midi_bytes[1] == MANUFACTURER_ID and midi_bytes[3] == self._product_model_id_byte() and midi_bytes[2] == self._device_id and midi_bytes[5] == 0 and midi_bytes[6] == 16: + response = [long(0), long(0)] + for index in range(8): + response[0] += long(midi_bytes[7 + index] & 15) << 4 * (7 - index) + response[1] += long(midi_bytes[15 + index] & 15) << 4 * (7 - index) + + expected_response = Live.Application.encrypt_challenge(self._dongle_challenge[0], self._dongle_challenge[1]) + if [long(expected_response[0]), long(expected_response[1])] == response: + self._on_handshake_successful() def _on_handshake_successful(self): self._suppress_session_highlight = False diff --git a/_APC/ControlElementUtils.py b/_APC/ControlElementUtils.py index a16a02f9..a36953f4 100644 --- a/_APC/ControlElementUtils.py +++ b/_APC/ControlElementUtils.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/ControlElementUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/ControlElementUtils.py import Live MapMode = Live.MidiMap.MapMode from _Framework.EncoderElement import EncoderElement diff --git a/_APC/DetailViewCntrlComponent.py b/_APC/DetailViewCntrlComponent.py index c7efd271..98a7a436 100644 --- a/_APC/DetailViewCntrlComponent.py +++ b/_APC/DetailViewCntrlComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/DetailViewCntrlComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/DetailViewCntrlComponent.py import Live NavDirection = Live.Application.Application.View.NavDirection from _Framework.Control import ButtonControl, ToggleButtonControl diff --git a/_APC/DeviceBankButtonElement.py b/_APC/DeviceBankButtonElement.py index cfee87c9..7673a260 100644 --- a/_APC/DeviceBankButtonElement.py +++ b/_APC/DeviceBankButtonElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/DeviceBankButtonElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/DeviceBankButtonElement.py from _Framework.ComboElement import ComboElement class DeviceBankButtonElement(ComboElement): diff --git a/_APC/DeviceComponent.py b/_APC/DeviceComponent.py index 3d29d03a..dccd6856 100644 --- a/_APC/DeviceComponent.py +++ b/_APC/DeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/DeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/DeviceComponent.py from itertools import ifilter from _Framework.CompoundComponent import CompoundComponent from _Framework.DeviceComponent import DeviceComponent as DeviceComponentBase @@ -22,7 +22,9 @@ def _current_bank_details(self): def _number_of_parameter_banks(self): num = super(DeviceComponent, self)._number_of_parameter_banks() - return max(num, 8) if self._use_fake_banks else num + if self._use_fake_banks: + return max(num, 8) + return num def _on_device_bank_changed(self, device, bank): super(DeviceComponent, self)._on_device_bank_changed(device, bank) diff --git a/_APC/MixerComponent.py b/_APC/MixerComponent.py index cebad07f..7cfc5b04 100644 --- a/_APC/MixerComponent.py +++ b/_APC/MixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/MixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/MixerComponent.py from _Framework.ChannelStripComponent import ChannelStripComponent as ChannelStripComponentBase from _Framework.MixerComponent import MixerComponent as MixerComponentBase TRACK_FOLD_DELAY = 5 diff --git a/_APC/RingedEncoderElement.py b/_APC/RingedEncoderElement.py index e6c8c9d9..8c749d3d 100644 --- a/_APC/RingedEncoderElement.py +++ b/_APC/RingedEncoderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/RingedEncoderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/RingedEncoderElement.py from _Framework.EncoderElement import EncoderElement from _Framework.ButtonElement import ButtonElement RING_OFF_VALUE = 0 diff --git a/_APC/SessionComponent.py b/_APC/SessionComponent.py index d72b78e9..46a2e826 100644 --- a/_APC/SessionComponent.py +++ b/_APC/SessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/SessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/SessionComponent.py from _Framework.SessionComponent import SessionComponent as SessionComponentBase class SessionComponent(SessionComponentBase): diff --git a/_APC/SkinDefault.py b/_APC/SkinDefault.py index 20a5bb11..fb06f4a0 100644 --- a/_APC/SkinDefault.py +++ b/_APC/SkinDefault.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/SkinDefault.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/SkinDefault.py from _Framework.Skin import Skin from _Framework.ButtonElement import Color from pushbase.colors import Rgb, Pulse, Blink diff --git a/_APC/__init__.py b/_APC/__init__.py index aa90ff4b..f519e475 100644 --- a/_APC/__init__.py +++ b/_APC/__init__.py @@ -1,2 +1,2 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_APC/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_APC/__init__.py pass \ No newline at end of file diff --git a/_Arturia/ArturiaControlSurface.py b/_Arturia/ArturiaControlSurface.py new file mode 100644 index 00000000..83f568ae --- /dev/null +++ b/_Arturia/ArturiaControlSurface.py @@ -0,0 +1,126 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Arturia/ArturiaControlSurface.py +from __future__ import with_statement +from functools import partial +from _Framework import Task +from _Framework.ControlSurface import ControlSurface +SETUP_MSG_PREFIX = (240, 0, 32, 107, 127, 66) +SETUP_MSG_SUFFIX = (247,) +WRITE_COMMAND = 2 +WORKING_MEMORY_ID = 0 +MODE_PROPERTY = 1 +CHANNEL_PROPERTY = 2 +IDENTIFIER_PROPERTY = 3 +MINIMUM_PROPERTY = 4 +MAXIMUM_PROPERTY = 5 +MODE_OPTION_PROPERTY = 6 +ENCODER_CC_MODE = 1 +ENCODER_RELATIVE_CC_MODE = 2 +BUTTON_CC_MODE = 8 +BUTTON_NOTE_MODE = 9 +BUTTON_MOMENTARY_MODE_OPTION = 1 +ENCODER_BINARY_OFFSET_MODE_OPTION = 1 +ENCODER_TWOS_COMPLEMENT_MODE_OPTION = 2 +BUTTON_MSG_TYPES = {'note': BUTTON_NOTE_MODE, + 'cc': BUTTON_CC_MODE} +SETUP_HARDWARE_DELAY = 1.0 +INDIVIDUAL_MESSAGE_DELAY = 0.001 + +def split_list(l, size): + for i in xrange(0, len(l), size): + yield l[i:i + size] + + +class ArturiaControlSurface(ControlSurface): + + def __init__(self, *a, **k): + super(ArturiaControlSurface, self).__init__(*a, **k) + self._messages_to_send = [] + self._setup_hardware_task = self._tasks.add(Task.sequence(Task.run(self._collect_setup_messages), Task.wait(SETUP_HARDWARE_DELAY), Task.run(self._setup_hardware))) + self._setup_hardware_task.kill() + with self.component_guard(): + self._collect_setup_messages() + self._setup_hardware() + + def _collect_setup_messages(self): + """ + Override to set up controls on the hardware + """ + raise NotImplementedError + + def _setup_hardware_encoder(self, hardware_id, identifier, channel = 0): + """ + Set up a relative encoder using a twos complement coding scheme + """ + self._set_encoder_cc_msg_type(hardware_id) + self._set_identifier(hardware_id, identifier) + self._set_channel(hardware_id, channel) + self._set_twos_complement_mode(hardware_id) + + def _setup_hardware_slider(self, hardware_id, identifier, channel = 0): + """ + Set up a simple hardware fader + """ + self._set_encoder_cc_msg_type(hardware_id) + self._set_identifier(hardware_id, identifier) + self._set_channel(hardware_id, channel) + + def _setup_hardware_button(self, hardware_id, identifier, channel = 0, is_momentary = True, msg_type = 'note'): + """ + Set up a momentary button sending MIDI notes + """ + raise msg_type in BUTTON_MSG_TYPES.keys() or AssertionError + self._set_button_msg_type(hardware_id, msg_type) + self._set_identifier(hardware_id, identifier) + self._set_channel(hardware_id, channel) + self._set_momentary_mode(hardware_id, is_momentary) + + def _set_encoder_cc_msg_type(self, hardware_id, is_relative = False): + self._collect_setup_message(MODE_PROPERTY, hardware_id, ENCODER_CC_MODE if not is_relative else ENCODER_RELATIVE_CC_MODE) + + def _set_button_msg_type(self, hardware_id, msg_type): + self._collect_setup_message(MODE_PROPERTY, hardware_id, BUTTON_MSG_TYPES[msg_type]) + + def _set_identifier(self, hardware_id, identifier): + self._collect_setup_message(IDENTIFIER_PROPERTY, hardware_id, identifier) + + def _set_momentary_mode(self, hardware_id, is_momentary): + self._collect_setup_message(MODE_OPTION_PROPERTY, hardware_id, int(is_momentary)) + + def _set_channel(self, hardware_id, channel): + self._collect_setup_message(CHANNEL_PROPERTY, hardware_id, channel) + + def _set_binary_offset_mode(self, hardware_id): + self._collect_setup_message(MODE_OPTION_PROPERTY, hardware_id, ENCODER_BINARY_OFFSET_MODE_OPTION) + + def _set_twos_complement_mode(self, hardware_id): + self._collect_setup_message(MODE_OPTION_PROPERTY, hardware_id, ENCODER_TWOS_COMPLEMENT_MODE_OPTION) + + def _set_value_minimum(self, hardware_id): + self._collect_setup_message(MINIMUM_PROPERTY, hardware_id, 0) + + def _set_value_maximum(self, hardware_id): + self._collect_setup_message(MAXIMUM_PROPERTY, hardware_id, 127) + + def _collect_setup_message(self, property, hardware_id, value): + raise property is not None or AssertionError + raise hardware_id is not None or AssertionError + raise value is not None or AssertionError + msg = SETUP_MSG_PREFIX + (WRITE_COMMAND, + WORKING_MEMORY_ID, + property, + hardware_id, + value) + SETUP_MSG_SUFFIX + self._messages_to_send.append(msg) + + def _setup_hardware(self): + sequence_to_run = [None] * (len(self._messages_to_send) * 2) + sequence_to_run[::2] = [ Task.run(partial(self._send_midi, msg)) for msg in self._messages_to_send ] + sequence_to_run[1::2] = [ Task.wait(INDIVIDUAL_MESSAGE_DELAY) for _ in self._messages_to_send ] + for subsequence in split_list(sequence_to_run, 40): + self._tasks.add(Task.sequence(*subsequence)) + + self._messages_to_send = [] + + def port_settings_changed(self): + super(ArturiaControlSurface, self).port_settings_changed() + self._setup_hardware_task.restart() \ No newline at end of file diff --git a/_Arturia/MixerComponent.py b/_Arturia/MixerComponent.py new file mode 100644 index 00000000..9f49c9a4 --- /dev/null +++ b/_Arturia/MixerComponent.py @@ -0,0 +1,55 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Arturia/MixerComponent.py +from _Framework.MixerComponent import MixerComponent as MixerComponentBase +from .ScrollComponent import ScrollComponent + +class MixerComponent(MixerComponentBase): + + def __init__(self, *a, **k): + super(MixerComponent, self).__init__(*a, **k) + self._track_selection = self.register_component(ScrollComponent()) + self._track_selection.can_scroll_up = self._can_select_prev_track + self._track_selection.can_scroll_down = self._can_select_next_track + self._track_selection.scroll_up = self._select_prev_track + self._track_selection.scroll_down = self._select_next_track + + def set_selected_track_volume_control(self, control): + self.selected_strip().set_volume_control(control) + + def set_selected_track_pan_control(self, control): + self.selected_strip().set_pan_control(control) + + def set_selected_track_send_controls(self, controls): + self.selected_strip().set_send_controls(controls) + + def set_return_volume_controls(self, controls): + for strip, control in map(None, self._return_strips, controls or []): + strip.set_volume_control(control) + + def set_track_select_encoder(self, encoder): + self._track_selection.set_scroll_encoder(encoder) + + def all_tracks(self): + return self.tracks_to_use() + (self.song().master_track,) + + def tracks_to_use(self): + return tuple(self.song().visible_tracks) + tuple(self.song().return_tracks) + + def _can_select_prev_track(self): + return self.song().view.selected_track != self.song().tracks[0] + + def _can_select_next_track(self): + return self.song().view.selected_track != self.song().master_track + + def _select_prev_track(self): + selected_track = self.song().view.selected_track + all_tracks = self.all_tracks() + raise selected_track in all_tracks or AssertionError + index = list(all_tracks).index(selected_track) + self.song().view.selected_track = all_tracks[index - 1] + + def _select_next_track(self): + selected_track = self.song().view.selected_track + all_tracks = self.all_tracks() + raise selected_track in all_tracks or AssertionError + index = list(all_tracks).index(selected_track) + self.song().view.selected_track = all_tracks[index + 1] \ No newline at end of file diff --git a/_Arturia/ScrollComponent.py b/_Arturia/ScrollComponent.py new file mode 100644 index 00000000..f1381fd9 --- /dev/null +++ b/_Arturia/ScrollComponent.py @@ -0,0 +1,20 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Arturia/ScrollComponent.py +from _Framework.ScrollComponent import ScrollComponent as ScrollComponentBase +from _Framework.Control import EncoderControl + +class ScrollComponent(ScrollComponentBase): + scroll_encoder = EncoderControl() + + def set_scroll_encoder(self, encoder): + self.scroll_encoder.set_control_element(encoder) + self.update() + + @scroll_encoder.value + def scroll_encoder(self, value, encoder): + scroll_step = None + if value > 0 and self.can_scroll_down(): + scroll_step = self._do_scroll_down + elif value < 0 and self.can_scroll_up(): + scroll_step = self._do_scroll_up + if scroll_step is not None: + scroll_step() \ No newline at end of file diff --git a/_Arturia/SessionComponent.py b/_Arturia/SessionComponent.py new file mode 100644 index 00000000..5533b42b --- /dev/null +++ b/_Arturia/SessionComponent.py @@ -0,0 +1,42 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Arturia/SessionComponent.py +from _Framework.SessionComponent import SessionComponent as SessionComponentBase +from _Framework.Control import EncoderControl + +class SessionComponent(SessionComponentBase): + scene_select_encoder = EncoderControl() + _session_component_ends_initialisation = False + + def __init__(self, *a, **k): + super(SessionComponent, self).__init__(*a, **k) + self.set_offsets(0, 0) + self.on_selected_scene_changed() + self.on_selected_track_changed() + + def set_scene_select_control(self, control): + self.scene_select_encoder.set_control_element(control) + + @scene_select_encoder.value + def scene_select_encoder(self, value, encoder): + selected_scene = self.song().view.selected_scene + all_scenes = self.song().scenes + current_index = list(all_scenes).index(selected_scene) + if value > 0 and selected_scene != all_scenes[-1]: + self.song().view.selected_scene = all_scenes[current_index + 1] + elif value < 0 and selected_scene != all_scenes[0]: + self.song().view.selected_scene = all_scenes[current_index - 1] + + def on_selected_scene_changed(self): + super(SessionComponent, self).on_selected_scene_changed() + all_scenes = list(self.song().scenes) + selected_scene = self.song().view.selected_scene + new_scene_offset = all_scenes.index(selected_scene) + self.set_offsets(self.track_offset(), new_scene_offset) + + def on_selected_track_changed(self): + super(SessionComponent, self).on_selected_track_changed() + tracks = list(self.song().tracks) + selected_track = self.song().view.selected_track + if selected_track in tracks: + track_index = tracks.index(selected_track) + new_track_offset = track_index - track_index % self.width() + self.set_offsets(new_track_offset, self.scene_offset()) \ No newline at end of file diff --git a/_Arturia/__init__.py b/_Arturia/__init__.py new file mode 100644 index 00000000..e8db9347 --- /dev/null +++ b/_Arturia/__init__.py @@ -0,0 +1,2 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Arturia/__init__.py +pass \ No newline at end of file diff --git a/_Axiom/Encoders.py b/_Axiom/Encoders.py index 9700120b..7a0ed2c2 100644 --- a/_Axiom/Encoders.py +++ b/_Axiom/Encoders.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Axiom/Encoders.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Axiom/Encoders.py import Live from consts import * from _Generic.Devices import * diff --git a/_Axiom/Pads.py b/_Axiom/Pads.py index d6fcefc7..22a80ec3 100644 --- a/_Axiom/Pads.py +++ b/_Axiom/Pads.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Axiom/Pads.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Axiom/Pads.py import Live from consts import * diff --git a/_Axiom/Transport.py b/_Axiom/Transport.py index fa713651..9ae639eb 100644 --- a/_Axiom/Transport.py +++ b/_Axiom/Transport.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Axiom/Transport.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Axiom/Transport.py import Live from consts import * diff --git a/_Axiom/__init__.py b/_Axiom/__init__.py index 6dd96f47..3bb62d4d 100644 --- a/_Axiom/__init__.py +++ b/_Axiom/__init__.py @@ -1,2 +1,2 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Axiom/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Axiom/__init__.py pass \ No newline at end of file diff --git a/_Axiom/consts.py b/_Axiom/consts.py index ec3c5858..0fc8ff25 100644 --- a/_Axiom/consts.py +++ b/_Axiom/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Axiom/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Axiom/consts.py NOTE_OFF_STATUS = 128 NOTE_ON_STATUS = 144 CC_STATUS = 176 diff --git a/_Framework/BackgroundComponent.py b/_Framework/BackgroundComponent.py index 07758772..8f9e9e26 100644 --- a/_Framework/BackgroundComponent.py +++ b/_Framework/BackgroundComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/BackgroundComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/BackgroundComponent.py from __future__ import absolute_import from functools import partial from .ControlSurfaceComponent import ControlSurfaceComponent diff --git a/_Framework/ButtonElement.py b/_Framework/ButtonElement.py index 825297c7..03a7e36a 100644 --- a/_Framework/ButtonElement.py +++ b/_Framework/ButtonElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ButtonElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ButtonElement.py from __future__ import absolute_import import Live from .InputControlElement import InputControlElement, MIDI_CC_TYPE diff --git a/_Framework/ButtonMatrixElement.py b/_Framework/ButtonMatrixElement.py index 7f64b9ab..471e7178 100644 --- a/_Framework/ButtonMatrixElement.py +++ b/_Framework/ButtonMatrixElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ButtonMatrixElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ButtonMatrixElement.py from __future__ import absolute_import from .CompoundElement import CompoundElement from .Util import in_range, product, const, slicer, to_slice @@ -88,7 +88,7 @@ def __getitem__(self, index): return self._do_get_item(index) def _do_get_item(self, index): - raise in_range(index, 0, len(self)) or AssertionError, 'Index out of range' + raise in_range(index, 0, len(self)) or AssertionError('Index out of range') row, col = divmod(index, self.width()) return self.get_button(col, row) diff --git a/_Framework/ButtonSliderElement.py b/_Framework/ButtonSliderElement.py index 1e4b5933..7dc0c4d5 100644 --- a/_Framework/ButtonSliderElement.py +++ b/_Framework/ButtonSliderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ButtonSliderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ButtonSliderElement.py from __future__ import absolute_import from .ButtonElement import ButtonElement from .InputControlElement import InputControlElement, MIDI_INVALID_TYPE diff --git a/_Framework/Capabilities.py b/_Framework/Capabilities.py index bc4bc0a5..73996473 100644 --- a/_Framework/Capabilities.py +++ b/_Framework/Capabilities.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Capabilities.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Capabilities.py PORTS_KEY = 'ports' CONTROLLER_ID_KEY = 'controller_id' TYPE_KEY = 'surface_type' diff --git a/_Framework/ChannelStripComponent.py b/_Framework/ChannelStripComponent.py index 51af6304..6e3e01bc 100644 --- a/_Framework/ChannelStripComponent.py +++ b/_Framework/ChannelStripComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ChannelStripComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ChannelStripComponent.py from __future__ import absolute_import from itertools import chain import Live diff --git a/_Framework/ChannelTranslationSelector.py b/_Framework/ChannelTranslationSelector.py index 6203109e..c01e13af 100644 --- a/_Framework/ChannelTranslationSelector.py +++ b/_Framework/ChannelTranslationSelector.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ChannelTranslationSelector.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ChannelTranslationSelector.py from __future__ import absolute_import from .InputControlElement import InputControlElement from .ModeSelectorComponent import ModeSelectorComponent diff --git a/_Framework/ClipCreator.py b/_Framework/ClipCreator.py index a5646f94..05130a5a 100644 --- a/_Framework/ClipCreator.py +++ b/_Framework/ClipCreator.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ClipCreator.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ClipCreator.py from __future__ import absolute_import import Live _Q = Live.Song.Quantization diff --git a/_Framework/ClipSlotComponent.py b/_Framework/ClipSlotComponent.py index 68b946f8..b65d3d3d 100644 --- a/_Framework/ClipSlotComponent.py +++ b/_Framework/ClipSlotComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ClipSlotComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ClipSlotComponent.py from __future__ import absolute_import import Live from .ControlSurfaceComponent import ControlSurfaceComponent @@ -134,16 +134,19 @@ def _feedback_value(self): track = self._clip_slot.canonical_parent slot_or_clip = self._clip_slot.clip if self.has_clip() else self._clip_slot if slot_or_clip.is_triggered: - return self._triggered_to_record_value if slot_or_clip.will_record_on_start else self._triggered_to_play_value - elif slot_or_clip.is_playing: - return self._recording_value if slot_or_clip.is_recording else self._started_value - elif slot_or_clip.color != None: + if slot_or_clip.will_record_on_start: + return self._triggered_to_record_value + return self._triggered_to_play_value + if slot_or_clip.is_playing: + if slot_or_clip.is_recording: + return self._recording_value + return self._started_value + if slot_or_clip.color != None: return self._color_value(slot_or_clip.color) - elif getattr(slot_or_clip, 'controls_other_clips', True) and self._stopped_value != None: + if getattr(slot_or_clip, 'controls_other_clips', True) and self._stopped_value != None: return self._stopped_value - elif self._track_is_armed(track) and self._clip_slot.has_stop_button: - if self._record_button_value != None: - return self._record_button_value + if self._track_is_armed(track) and self._clip_slot.has_stop_button and self._record_button_value != None: + return self._record_button_value def _update_clip_property_slots(self): clip = self._clip_slot.clip if self._clip_slot else None @@ -239,14 +242,14 @@ def _do_duplicate_clip(self): def _do_launch_clip(self, value): button = self._launch_button_value.subject object_to_launch = self._clip_slot - if not value: - launch_pressed = not button.is_momentary() - if self.has_clip(): - object_to_launch = self._clip_slot.clip - else: - self._has_fired_slot = True - if button.is_momentary(): - object_to_launch.set_fire_button_state(value != 0) - elif launch_pressed: - object_to_launch.fire() - self.song().view.highlighted_clip_slot = launch_pressed and self.has_clip() and self.song().select_on_launch and self._clip_slot \ No newline at end of file + launch_pressed = value or not button.is_momentary() + if self.has_clip(): + object_to_launch = self._clip_slot.clip + else: + self._has_fired_slot = True + if button.is_momentary(): + object_to_launch.set_fire_button_state(value != 0) + elif launch_pressed: + object_to_launch.fire() + if launch_pressed and self.has_clip() and self.song().select_on_launch: + self.song().view.highlighted_clip_slot = self._clip_slot \ No newline at end of file diff --git a/_Framework/ComboElement.py b/_Framework/ComboElement.py index 9e8089d2..147196a0 100644 --- a/_Framework/ComboElement.py +++ b/_Framework/ComboElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ComboElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ComboElement.py from __future__ import absolute_import, with_statement from itertools import imap from contextlib import contextmanager @@ -109,8 +109,8 @@ def reset(self): self._wrapped_control.reset() def get_control_element_priority(self, element, priority): - if not (element == self._wrapped_control and (priority is None or 1 - priority + int(priority) > self.priority_increment)): - raise AssertionError, 'Attempting to increase the priority over a whole unit. ' + 'Make sure the combo element is not inside another combo element' + if element == self._wrapped_control: + raise priority is None or 1 - priority + int(priority) > self.priority_increment or AssertionError('Attempting to increase the priority over a whole unit. ' + 'Make sure the combo element is not inside another combo element') priority = DEFAULT_PRIORITY if priority is None else priority return priority + self.priority_increment return priority diff --git a/_Framework/CompoundComponent.py b/_Framework/CompoundComponent.py index f2fdaf45..8958ddfc 100644 --- a/_Framework/CompoundComponent.py +++ b/_Framework/CompoundComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/CompoundComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/CompoundComponent.py from __future__ import absolute_import from .ControlSurfaceComponent import ControlSurfaceComponent diff --git a/_Framework/CompoundElement.py b/_Framework/CompoundElement.py index 154ef9a4..7263e738 100644 --- a/_Framework/CompoundElement.py +++ b/_Framework/CompoundElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/CompoundElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/CompoundElement.py from __future__ import absolute_import, with_statement from itertools import ifilter from .ControlElement import ControlElementClient diff --git a/_Framework/Control.py b/_Framework/Control.py index 914854b5..71727adc 100644 --- a/_Framework/Control.py +++ b/_Framework/Control.py @@ -1,6 +1,7 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Control.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Control.py from __future__ import absolute_import, with_statement from functools import partial +from itertools import izip_longest from . import Task from .Defaults import MOMENTARY_DELAY from .SubjectSlot import SlotManager @@ -449,9 +450,9 @@ def _is_momentary(self): def _on_value(self, value, *a, **k): if self._notifications_enabled(): - if not value: - checked = self._is_momentary() - self.is_checked = checked and not self._checked and True + checked = value or self._is_momentary() + if checked and not self._checked: + self.is_checked = True super(RadioButtonControl.State, self)._on_value(value, *a, **k) def _notify_checked(self): @@ -619,7 +620,7 @@ def _get_unavailable_color(self): def _set_unavailable_color(self, value): self._unavailable_color = value control_elements = self._control_elements or [] - for control, element in map(None, self._controls, control_elements): + for control, element in izip_longest(self._controls, control_elements): if not control and element: self._send_unavailable_color(element) @@ -652,7 +653,7 @@ def set_control_element(self, control_elements): def _update_controls(self): control_elements = self._control_elements or [] - for control, element in map(None, self._controls, control_elements): + for control, element in izip_longest(self._controls, control_elements): if control: control._get_state(self._manager).set_control_element(element) elif element: diff --git a/_Framework/ControlElement.py b/_Framework/ControlElement.py index 1138177b..1ec39192 100644 --- a/_Framework/ControlElement.py +++ b/_Framework/ControlElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ControlElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ControlElement.py from __future__ import absolute_import import traceback from . import Task diff --git a/_Framework/ControlSurface.py b/_Framework/ControlSurface.py index 49afd469..11e91a0c 100644 --- a/_Framework/ControlSurface.py +++ b/_Framework/ControlSurface.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ControlSurface.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ControlSurface.py from __future__ import absolute_import, with_statement from functools import partial, wraps from itertools import chain, ifilter, imap @@ -178,15 +178,6 @@ def restore_bank(self, bank_index): with self.component_guard(): self._device_component.restore_bank(bank_index) - @_scheduled_method - def set_appointed_device(self, device): - """ - Live -> Script - Live tells the script to unlock from a certain device - """ - with self.component_guard(): - self._device_component.set_device(device) - def suggest_input_port(self): """ Live -> Script: Live can ask for the name of the script's prefered input port""" @@ -473,7 +464,7 @@ def _register_control(self, control): """ puts control into the list of controls for triggering updates """ if not control != None: raise AssertionError - raise control not in self.controls or AssertionError, 'Control registered twice' + raise control not in self.controls or AssertionError('Control registered twice') self.controls.append(control) control.canonical_parent = self isinstance(control, PhysicalDisplayElement) and self._displays.append(control) @@ -481,7 +472,7 @@ def _register_control(self, control): def _register_component(self, component): """ puts component into the list of controls for triggering updates """ raise component != None or AssertionError - raise component not in self._components or AssertionError, 'Component registered twice' + raise component not in self._components or AssertionError('Component registered twice') self._components.append(component) component.canonical_parent = self @@ -629,7 +620,7 @@ def _install_forwarding(self, midi_map_handle, control): forwarding_keys = success and control.identifier_bytes() for key in forwarding_keys: registry = self._forwarding_registry if control.message_type() != MIDI_SYSEX_TYPE else self._forwarding_long_identifier_registry - raise key not in registry.keys() or AssertionError, 'Registry key %s registered twice. Check Midi messages!' % str(key) + raise key not in registry.keys() or AssertionError('Registry key %s registered twice. Check Midi messages!' % str(key)) registry[key] = control return success diff --git a/_Framework/ControlSurfaceComponent.py b/_Framework/ControlSurfaceComponent.py index 9d2efc0c..b0420856 100644 --- a/_Framework/ControlSurfaceComponent.py +++ b/_Framework/ControlSurfaceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ControlSurfaceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ControlSurfaceComponent.py from __future__ import absolute_import import Live from . import Task @@ -50,7 +50,7 @@ def _internal_on_enabled_changed(self): if self.is_enabled(): grabbed = self._layer.grab(self) if not grabbed: - raise AssertionError, 'Only one component can use a layer at atime' + raise AssertionError('Only one component can use a layer at atime') else: self._layer.release(self) if self._has_task_group: @@ -73,9 +73,9 @@ def _set_enabled_recursive(self, enable): self._update_is_enabled() def _update_is_enabled(self): - if self._recursive_is_enabled: - is_enabled = self._explicit_is_enabled - self._is_enabled = is_enabled != self._is_enabled and is_enabled + is_enabled = self._recursive_is_enabled and self._explicit_is_enabled + if is_enabled != self._is_enabled: + self._is_enabled = is_enabled self._internal_on_enabled_changed() self.on_enabled_changed() @@ -110,12 +110,12 @@ def _get_layer(self): def _set_layer(self, new_layer): if self._layer != new_layer: - self._layer and self._layer.release(self) - self._layer = new_layer - if new_layer and self.is_enabled(): - grabbed = new_layer.grab(self) - if not grabbed: - raise AssertionError, 'Only one component can use a layer at atime' + if self._layer: + self._layer.release(self) + self._layer = new_layer + if new_layer and self.is_enabled(): + grabbed = new_layer.grab(self) + raise grabbed or AssertionError('Only one component can use a layer at atime') layer = property(_get_layer, _set_layer) @@ -124,7 +124,9 @@ def is_enabled(self, explicit = False): Returns whether the component is enabled. If 'explicit' is True the parent state is ignored. """ - return self._is_enabled if not explicit else self._explicit_is_enabled + if not explicit: + return self._is_enabled + return self._explicit_is_enabled def on_track_list_changed(self): """ diff --git a/_Framework/Debug.py b/_Framework/Debug.py index 219e6600..c8f68c6c 100644 --- a/_Framework/Debug.py +++ b/_Framework/Debug.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Debug.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Debug.py enable_debug_output = True def debug_print(*a): diff --git a/_Framework/Defaults.py b/_Framework/Defaults.py index 3eb6d9f5..363d0f0e 100644 --- a/_Framework/Defaults.py +++ b/_Framework/Defaults.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Defaults.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Defaults.py TIMER_DELAY = 0.1 MOMENTARY_DELAY = 0.3 MOMENTARY_DELAY_TICKS = int(MOMENTARY_DELAY / TIMER_DELAY) \ No newline at end of file diff --git a/_Framework/Dependency.py b/_Framework/Dependency.py index 5751af43..0350f793 100644 --- a/_Framework/Dependency.py +++ b/_Framework/Dependency.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Dependency.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Dependency.py """ Dependency injection framework. @@ -45,8 +45,7 @@ def get_dependency_for(obj, name, default = None): accessor = _global_injection_registry.get(name, default) if accessor is not None: return accessor() - else: - raise DependencyError('Required dependency %s not provided for %s' % (name, str(obj))) + raise DependencyError('Required dependency %s not provided for %s' % (name, str(obj))) class dependency(object): diff --git a/_Framework/DeviceBankRegistry.py b/_Framework/DeviceBankRegistry.py index 5faf7147..d71a2c5f 100644 --- a/_Framework/DeviceBankRegistry.py +++ b/_Framework/DeviceBankRegistry.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/DeviceBankRegistry.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/DeviceBankRegistry.py """ Classes to keep a global registry of the currently selected bank for given device instances. @@ -22,10 +22,10 @@ def compact_registry(self): self._device_bank_registry = newreg def set_device_bank(self, device, bank): - if not self._find_device_bank_key(device): - key = device - old = self._device_bank_registry[key] if key in self._device_bank_registry else 0 - self._device_bank_registry[key] = old != bank and bank + key = self._find_device_bank_key(device) or device + old = self._device_bank_registry[key] if key in self._device_bank_registry else 0 + if old != bank: + self._device_bank_registry[key] = bank self.notify_device_bank(device, bank) def get_device_bank(self, device): diff --git a/_Framework/DeviceComponent.py b/_Framework/DeviceComponent.py index d0401fa7..b6de006c 100644 --- a/_Framework/DeviceComponent.py +++ b/_Framework/DeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/DeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/DeviceComponent.py from __future__ import absolute_import import Live from _Generic.Devices import device_parameters_to_map, number_of_parameter_banks, parameter_banks, parameter_bank_names, best_of_parameter_bank @@ -6,7 +6,34 @@ from .ControlSurfaceComponent import ControlSurfaceComponent from .DeviceBankRegistry import DeviceBankRegistry from .DisplayDataSource import DisplayDataSource -from .SubjectSlot import subject_slot_group, Subject +from .SubjectSlot import subject_slot, subject_slot_group, Subject + +def device_to_appoint(device): + appointed_device = device + if device != None and device.can_have_drum_pads and not device.has_macro_mappings and len(device.chains) > 0 and device.view.selected_chain != None and len(device.view.selected_chain.devices) > 0: + appointed_device = device_to_appoint(device.view.selected_chain.devices[0]) + return appointed_device + + +def select_and_appoint_device(song, device_to_select, ignore_unmapped_macros = True): + """ + Convenience function for selecting a device for a control surface to control. + + This takes care of selecting the device and appointing it for remote control, which + is important, because these are two concepts, that are not exactly the same. + + The device component always controls the appointed device. It's possible to select + another device, but not appoint it for control. The behaviour in this function + appoints a drum rack's selected chain's first device if none of the macros are mapped + for the drum rack. Though, it's still possible to select the drum rack, we just do + not display its controls in this scenario. + """ + appointed_device = device_to_select + if ignore_unmapped_macros: + appointed_device = device_to_appoint(device_to_select) + song.appointed_device = appointed_device + song.view.select_device(device_to_select, False) + class DeviceComponent(ControlSurfaceComponent, Subject): """ Class representing a device in Live """ @@ -44,7 +71,12 @@ def make_button_slot(name): self._bank_down_button_slot = make_button_slot('bank_down') self._lock_button_slot = make_button_slot('lock') self._on_off_button_slot = make_button_slot('on_off') + song = self.song() + view = song.view self._device_bank_property_slot.subject = self._device_bank_registry + self.__on_appointed_device_changed.subject = song + self.__on_selected_track_changed.subject = view + self.__on_selected_device_changed.subject = view.selected_track.view def disconnect(self): self._device_bank_registry = None @@ -65,6 +97,10 @@ def on_enabled_changed(self): def device(self): return self._device + @subject_slot('appointed_device') + def __on_appointed_device_changed(self): + self.set_device(device_to_appoint(self.song().appointed_device)) + def set_device(self, device): if not self._locked_to_device and (device != self._device or type(device) != type(self._device)): if self._device != None: @@ -81,6 +117,31 @@ def set_device(self, device): self.update() self.notify_device() + @subject_slot('has_macro_mappings') + def __on_has_macro_mappings_changed(self): + self.song().appointed_device = device_to_appoint(self.__on_has_macro_mappings_changed.subject) + + @subject_slot('selected_track') + def __on_selected_track_changed(self): + self.__on_selected_device_changed.subject = self.song().view.selected_track.view + + @subject_slot('chains') + def __on_chains_changed(self): + self._update_appointed_device() + + @subject_slot('selected_device') + def __on_selected_device_changed(self): + self._update_appointed_device() + + def _update_appointed_device(self): + song = self.song() + device = song.view.selected_track.view.selected_device + if device != None: + song.appointed_device = device_to_appoint(device) + rack_device = device if isinstance(device, Live.RackDevice.RackDevice) else None + self.__on_has_macro_mappings_changed.subject = rack_device + self.__on_chains_changed.subject = rack_device + def set_bank_prev_button(self, button): if button != self._bank_down_button: self._bank_down_button = button diff --git a/_Framework/Disconnectable.py b/_Framework/Disconnectable.py index d819d0d5..1240275a 100644 --- a/_Framework/Disconnectable.py +++ b/_Framework/Disconnectable.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Disconnectable.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Disconnectable.py """ Interface for items that adquire resources. """ diff --git a/_Framework/DisplayDataSource.py b/_Framework/DisplayDataSource.py index 10846601..0462c3d1 100644 --- a/_Framework/DisplayDataSource.py +++ b/_Framework/DisplayDataSource.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/DisplayDataSource.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/DisplayDataSource.py from __future__ import absolute_import from functools import partial @@ -16,9 +16,9 @@ def adjust_string(original, length): raise AssertionError resulting_string = original if len(resulting_string) > length: - if resulting_string.endswith('dB'): - unit_db = resulting_string.find('.') != -1 - resulting_string = len(resulting_string.strip()) > length and unit_db and resulting_string[:-2] + unit_db = resulting_string.endswith('dB') and resulting_string.find('.') != -1 + if len(resulting_string.strip()) > length and unit_db: + resulting_string = resulting_string[:-2] if len(resulting_string) > length: for char in (' ', '_', 'i', 'o', 'u', 'e', 'a'): offset = 0 if char == ' ' else 1 diff --git a/_Framework/DrumGroupComponent.py b/_Framework/DrumGroupComponent.py index 6b235813..ac2ab73d 100644 --- a/_Framework/DrumGroupComponent.py +++ b/_Framework/DrumGroupComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/DrumGroupComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/DrumGroupComponent.py from itertools import imap from .Control import PlayableControl, ButtonControl, control_matrix from .Dependency import depends @@ -59,11 +59,15 @@ def _set_position(self, index): @property def width(self): - return self.drum_matrix.width if self.drum_matrix.width else 4 + if self.drum_matrix.width: + return self.drum_matrix.width + return 4 @property def height(self): - return self.drum_matrix.height if self.drum_matrix.height else 4 + if self.drum_matrix.height: + return self.drum_matrix.height + return 4 @property def pressed_pads(self): diff --git a/_Framework/DrumRackComponent.py b/_Framework/DrumRackComponent.py index f89ac649..b869a51a 100644 --- a/_Framework/DrumRackComponent.py +++ b/_Framework/DrumRackComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/DrumRackComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/DrumRackComponent.py from __future__ import absolute_import from itertools import ifilter from .ControlSurfaceComponent import ControlSurfaceComponent diff --git a/_Framework/EncoderElement.py b/_Framework/EncoderElement.py index b5d211b5..d80b5dd2 100644 --- a/_Framework/EncoderElement.py +++ b/_Framework/EncoderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/EncoderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/EncoderElement.py from __future__ import absolute_import import Live from .ComboElement import WrapperElement @@ -12,8 +12,9 @@ def _not_implemented(value): _map_modes = map_modes = Live.MidiMap.MapMode -ENCODER_VALUE_NORMALIZER = {_map_modes.relative_smooth_two_compliment: lambda v: v if v <= 64 else v - 128, - _map_modes.relative_smooth_signed_bit: lambda v: v if v <= 64 else 64 - v} +ENCODER_VALUE_NORMALIZER = {_map_modes.relative_smooth_two_compliment: lambda v: (v if v <= 64 else v - 128), + _map_modes.relative_smooth_signed_bit: lambda v: (v if v <= 64 else 64 - v), + _map_modes.relative_smooth_binary_offset: lambda v: v - 64} class EncoderElement(InputControlElement): """ diff --git a/_Framework/IdentifiableControlSurface.py b/_Framework/IdentifiableControlSurface.py index 26d12f26..428fad6d 100644 --- a/_Framework/IdentifiableControlSurface.py +++ b/_Framework/IdentifiableControlSurface.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/IdentifiableControlSurface.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/IdentifiableControlSurface.py from __future__ import absolute_import from .ControlSurface import ControlSurface from . import Task diff --git a/_Framework/InputControlElement.py b/_Framework/InputControlElement.py index 2bf40cac..e4b3770f 100644 --- a/_Framework/InputControlElement.py +++ b/_Framework/InputControlElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/InputControlElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/InputControlElement.py from __future__ import absolute_import, with_statement import contextlib from . import Task @@ -427,4 +427,6 @@ def _report_value(self, value, is_input): @property def _last_sent_value(self): - return self._last_sent_message[0] if self._last_sent_message else -1 \ No newline at end of file + if self._last_sent_message: + return self._last_sent_message[0] + return -1 \ No newline at end of file diff --git a/_Framework/Layer.py b/_Framework/Layer.py index 57d19b62..acac4da6 100644 --- a/_Framework/Layer.py +++ b/_Framework/Layer.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Layer.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Layer.py """ Module implementing a way to resource-based access to controls in an unified interface dynamic. @@ -47,9 +47,9 @@ def __init__(self, layer = None, layer_client = None, *a, **k): def set_control_element(self, control_element, grabbed): layer = self.layer owner = self.layer_client - raise owner or AssertionError - if not control_element in layer._control_to_names: - raise AssertionError, 'Control not in layer: %s' % (control_element,) + if not owner: + raise AssertionError + raise control_element in layer._control_to_names or AssertionError('Control not in layer: %s' % (control_element,)) names = layer._control_to_names[control_element] control_element = grabbed or None for name in names: diff --git a/_Framework/LogicalDisplaySegment.py b/_Framework/LogicalDisplaySegment.py index a70f7cc2..ad424584 100644 --- a/_Framework/LogicalDisplaySegment.py +++ b/_Framework/LogicalDisplaySegment.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/LogicalDisplaySegment.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/LogicalDisplaySegment.py from __future__ import absolute_import class LogicalDisplaySegment(object): @@ -50,10 +50,10 @@ def update(self): self._update_callback() def _get_display_string(self): - separator = self._data_source != None and self._data_source.separator + self.separator - width = self._width - len(separator) - if not width >= 0: - raise AssertionError + if self._data_source != None: + separator = self._data_source.separator + self.separator + width = self._width - len(separator) + raise width >= 0 or AssertionError return self._data_source.adjust_string(width) + separator else: return ' ' * self._width diff --git a/_Framework/M4LInterfaceComponent.py b/_Framework/M4LInterfaceComponent.py index 133e35c7..4af1768c 100644 --- a/_Framework/M4LInterfaceComponent.py +++ b/_Framework/M4LInterfaceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/M4LInterfaceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/M4LInterfaceComponent.py from __future__ import absolute_import, with_statement from .ControlElement import ControlElementClient from .ControlSurfaceComponent import ControlSurfaceComponent @@ -31,7 +31,8 @@ def get_control_names(self): return self._controls.keys() def get_control(self, control_name): - return self._controls[control_name] if control_name in self._controls else None + if control_name in self._controls: + return self._controls[control_name] def grab_control(self, control): raise control in self._controls.values() or AssertionError diff --git a/_Framework/MidiMap.py b/_Framework/MidiMap.py index ca4758cd..8af37b4c 100644 --- a/_Framework/MidiMap.py +++ b/_Framework/MidiMap.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/MidiMap.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/MidiMap.py from __future__ import absolute_import import Live from .ButtonMatrixElement import ButtonMatrixElement diff --git a/_Framework/MixerComponent.py b/_Framework/MixerComponent.py index 379a7263..4acfa69d 100644 --- a/_Framework/MixerComponent.py +++ b/_Framework/MixerComponent.py @@ -1,5 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/MixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/MixerComponent.py from __future__ import absolute_import +from itertools import izip_longest from .ChannelStripComponent import ChannelStripComponent, release_control from .CompoundComponent import CompoundComponent from .SubjectSlot import subject_slot @@ -120,35 +121,35 @@ def set_crossfader_control(self, control): self.update() def set_volume_controls(self, controls): - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): strip.set_volume_control(control) def set_pan_controls(self, controls): - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): strip.set_pan_control(control) def set_send_controls(self, controls): self._send_controls = controls - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): if self._send_index is None: strip.set_send_controls(None) else: strip.set_send_controls((None,) * self._send_index + (control,)) def set_arm_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): strip.set_arm_button(button) def set_solo_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): strip.set_solo_button(button) def set_mute_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): strip.set_mute_button(button) def set_track_select_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): strip.set_select_button(button) def set_shift_button(self, button): diff --git a/_Framework/ModeSelectorComponent.py b/_Framework/ModeSelectorComponent.py index c1fe35b9..8473e983 100644 --- a/_Framework/ModeSelectorComponent.py +++ b/_Framework/ModeSelectorComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ModeSelectorComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ModeSelectorComponent.py from __future__ import absolute_import from .ButtonElement import ButtonElement from .ControlSurfaceComponent import ControlSurfaceComponent diff --git a/_Framework/ModesComponent.py b/_Framework/ModesComponent.py index 9d177eba..95498206 100644 --- a/_Framework/ModesComponent.py +++ b/_Framework/ModesComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ModesComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ModesComponent.py """ Mode handling components. """ @@ -25,7 +25,7 @@ def tomode(thing): if isinstance(thing, tuple) and len(thing) == 2: if isinstance(thing[0], ControlSurfaceComponent) and isinstance(thing[1], LayerBase): return LayerMode(*thing) - elif callable(thing[0]) and callable(thing[1]): + if callable(thing[0]) and callable(thing[1]): mode = Mode() mode.enter_mode, mode.leave_mode = thing return mode @@ -147,7 +147,9 @@ def __init__(self, component = None, layer = None, *a, **k): self._layer = layer def _get_component(self): - return self._component() if callable(self._component) else self._component + if callable(self._component): + return self._component() + return self._component class LayerMode(LayerModeBase): @@ -240,7 +242,9 @@ def __init__(self, obj = None, attribute = None, value = None, *a, **k): self._value = value def _get_object(self): - return self._obj() if callable(self._obj) else self._obj + if callable(self._obj): + return self._obj() + return self._obj def enter_mode(self): self._old_value = getattr(self._get_object(), self._attribute, None) @@ -370,10 +374,10 @@ class CancellableBehaviour(ModeButtonBehaviour): def press_immediate(self, component, mode): active_modes = component.active_modes groups = component.get_mode_groups(mode) - if not mode in active_modes: - can_cancel_mode = any(imap(lambda other: groups & component.get_mode_groups(other), active_modes)) - if can_cancel_mode: - groups and component.pop_groups(groups) + can_cancel_mode = mode in active_modes or any(imap(lambda other: groups & component.get_mode_groups(other), active_modes)) + if can_cancel_mode: + if groups: + component.pop_groups(groups) else: component.pop_mode(mode) self.restore_previous_mode(component) @@ -593,7 +597,9 @@ def _set_selected_mode(self, mode): @property def selected_groups(self): entry = self._mode_map.get(self.selected_mode, None) - return entry.groups if entry else set() + if entry: + return entry.groups + return set() @property def active_modes(self): @@ -682,7 +688,9 @@ def get_mode(self, name): def get_mode_groups(self, name): entry = self._mode_map.get(name, None) - return entry.groups if entry else set() + if entry: + return entry.groups + return set() def set_toggle_button(self, button): if button and self.is_enabled(): @@ -732,13 +740,13 @@ def _on_mode_button_value(self, name, value, sender): @subject_slot('value') def _on_toggle_value(self, value): - if self._shift_button: - shift = self._shift_button.is_pressed() - if not shift and self.is_enabled() and len(self._mode_list): - is_press = value and not self._last_toggle_value - is_release = not value and self._last_toggle_value - can_latch = self._mode_toggle_task.is_killed and self.selected_mode != self._mode_list[0] - (not self._mode_toggle.is_momentary() or is_press) and self.cycle_mode(1) + shift = self._shift_button and self._shift_button.is_pressed() + if not shift and self.is_enabled() and len(self._mode_list): + is_press = value and not self._last_toggle_value + is_release = not value and self._last_toggle_value + can_latch = self._mode_toggle_task.is_killed and self.selected_mode != self._mode_list[0] + if not self._mode_toggle.is_momentary() or is_press: + self.cycle_mode(1) self._mode_toggle_task.restart() elif is_release and (self.momentary_toggle or can_latch): self.cycle_mode(-1) diff --git a/_Framework/MomentaryModeObserver.py b/_Framework/MomentaryModeObserver.py index fa37c1b0..d368a7cb 100644 --- a/_Framework/MomentaryModeObserver.py +++ b/_Framework/MomentaryModeObserver.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/MomentaryModeObserver.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/MomentaryModeObserver.py from __future__ import absolute_import from . import Defaults diff --git a/_Framework/NotifyingControlElement.py b/_Framework/NotifyingControlElement.py index c5ca48b8..37d72b40 100644 --- a/_Framework/NotifyingControlElement.py +++ b/_Framework/NotifyingControlElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/NotifyingControlElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/NotifyingControlElement.py from __future__ import absolute_import from .SubjectSlot import Subject, SubjectEvent from .ControlElement import ControlElement diff --git a/_Framework/OptionalElement.py b/_Framework/OptionalElement.py index 3d55430b..02affbd9 100644 --- a/_Framework/OptionalElement.py +++ b/_Framework/OptionalElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/OptionalElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/OptionalElement.py from __future__ import absolute_import from .ComboElement import ToggleElement from .SubjectSlot import SlotManager, subject_slot diff --git a/_Framework/PhysicalDisplayElement.py b/_Framework/PhysicalDisplayElement.py index 92557acd..bc7b0c38 100644 --- a/_Framework/PhysicalDisplayElement.py +++ b/_Framework/PhysicalDisplayElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/PhysicalDisplayElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/PhysicalDisplayElement.py from __future__ import absolute_import from itertools import ifilter, izip, starmap, chain, imap from functools import partial diff --git a/_Framework/Profile.py b/_Framework/Profile.py index 87cc0479..13659ab6 100644 --- a/_Framework/Profile.py +++ b/_Framework/Profile.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Profile.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Profile.py from __future__ import absolute_import from functools import wraps, partial ENABLE_PROFILING = False diff --git a/_Framework/Proxy.py b/_Framework/Proxy.py index d55a3b5e..315f1915 100644 --- a/_Framework/Proxy.py +++ b/_Framework/Proxy.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Proxy.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Proxy.py from __future__ import absolute_import, with_statement from .Util import BooleanContext diff --git a/_Framework/Resource.py b/_Framework/Resource.py index 83686e5f..12bfb4db 100644 --- a/_Framework/Resource.py +++ b/_Framework/Resource.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Resource.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Resource.py from __future__ import absolute_import from functools import partial from .Proxy import Proxy @@ -78,7 +78,7 @@ def __init__(self, on_received_callback = None, on_lost_callback = None, *a, **k def grab(self, client, *a, **k): if not client is not None: - raise AssertionError, 'Someone has to adquire resource' + raise AssertionError('Someone has to adquire resource') self._owner == None and self.on_received(client, *a, **k) self._owner = client return self._owner == client @@ -115,7 +115,7 @@ def __init__(self, on_received_callback = None, on_lost_callback = None, *a, **k self._clients = set() def grab(self, client, *a, **k): - raise client is not None or AssertionError, 'Someone has to adquire resource' + raise client is not None or AssertionError('Someone has to adquire resource') self.on_received(client, *a, **k) self._clients.add(client) return True @@ -132,7 +132,7 @@ def release(self, client): return False def get_owner(self): - raise False or AssertionError, 'Shared resource has no owner' + raise False or AssertionError('Shared resource has no owner') def on_received(self, client, *a, **k): raise NotImplemented, 'Override or pass callback' @@ -222,11 +222,15 @@ def _remove_client(self, client): return True def _actual_owners(self): - return [self._clients[-1][0]] if self._clients else [] + if self._clients: + return [self._clients[-1][0]] + return [] @property def max_priority(self): - return self._clients[-1][1] if self._clients else DEFAULT_PRIORITY + if self._clients: + return self._clients[-1][1] + return DEFAULT_PRIORITY @property def stack_size(self): diff --git a/_Framework/SceneComponent.py b/_Framework/SceneComponent.py index 65cfbb64..321d9699 100644 --- a/_Framework/SceneComponent.py +++ b/_Framework/SceneComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/SceneComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/SceneComponent.py from __future__ import absolute_import from .ClipSlotComponent import ClipSlotComponent, find_nearest_color from .CompoundComponent import CompoundComponent diff --git a/_Framework/ScrollComponent.py b/_Framework/ScrollComponent.py index d3cc93c5..c5033fbb 100644 --- a/_Framework/ScrollComponent.py +++ b/_Framework/ScrollComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ScrollComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ScrollComponent.py from __future__ import absolute_import from . import Defaults from . import Task @@ -113,11 +113,11 @@ def update(self): self._update_scroll_buttons() def _on_scroll_pressed(self, button, scroll_step, scroll_task): - if not not self._scroll_task_up.is_killed: - is_scrolling = not self._scroll_task_down.is_killed - if not is_scrolling: - scroll_step() - button.enabled and scroll_task.restart() + is_scrolling = not self._scroll_task_up.is_killed or not self._scroll_task_down.is_killed + if not is_scrolling: + scroll_step() + if button.enabled: + scroll_task.restart() self._ensure_scroll_one_direction() def _on_scroll_released(self, scroll_task): diff --git a/_Framework/SessionComponent.py b/_Framework/SessionComponent.py index 4615f989..ac3b1a98 100644 --- a/_Framework/SessionComponent.py +++ b/_Framework/SessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/SessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/SessionComponent.py from __future__ import absolute_import from itertools import count import Live @@ -57,15 +57,15 @@ def __init__(self, num_tracks = 0, num_scenes = 0, auto_name = False, enable_ski self._stop_clip_triggered_value = 127 self._stop_clip_value = None self._highlighting_callback = None - if num_tracks > 0: - self._show_highlight = num_scenes > 0 - self._mixer = None - self._track_slots = self.register_slot_manager() - self._selected_scene = self.register_component(self._create_scene()) - self._scenes = self.register_components(*[ self._create_scene() for _ in xrange(num_scenes) ]) - if self._session_component_ends_initialisation: - self._end_initialisation() - auto_name and self._auto_name() + self._show_highlight = num_tracks > 0 and num_scenes > 0 + self._mixer = None + self._track_slots = self.register_slot_manager() + self._selected_scene = self.register_component(self._create_scene()) + self._scenes = self.register_components(*[ self._create_scene() for _ in xrange(num_scenes) ]) + if self._session_component_ends_initialisation: + self._end_initialisation() + if auto_name: + self._auto_name() enable_skinning and self._enable_skinning() def _end_initialisation(self): @@ -373,10 +373,14 @@ def tracks_to_use(self): return list_of_tracks def _get_minimal_track_offset(self): - return SessionComponent._minimal_track_offset if self._is_linked() else self.track_offset() + if self._is_linked(): + return SessionComponent._minimal_track_offset + return self.track_offset() def _get_minimal_scene_offset(self): - return SessionComponent._minimal_scene_offset if self._is_linked() else self.scene_offset() + if self._is_linked(): + return SessionComponent._minimal_scene_offset + return self.scene_offset() def _can_bank_down(self): return len(self.song().scenes) > self._get_minimal_scene_offset() + 1 @@ -423,19 +427,19 @@ def _update_scene_offset(self): return offset_corrected def _change_offsets(self, track_increment, scene_increment): - if not track_increment != 0: - offsets_changed = scene_increment != 0 - offsets_changed and self._track_offset += track_increment - self._scene_offset += scene_increment - raise self._track_offset >= 0 or AssertionError - if not self._scene_offset >= 0: - raise AssertionError - if self._mixer != None: - self._mixer.set_track_offset(self.track_offset()) - self._reassign_tracks() - self._reassign_scenes() - self.notify_offset() - self.width() > 0 and self.height() > 0 and self._do_show_highlight() + offsets_changed = track_increment != 0 or scene_increment != 0 + offsets_changed and self._track_offset += track_increment + self._scene_offset += scene_increment + raise self._track_offset >= 0 or AssertionError + if not self._scene_offset >= 0: + raise AssertionError + if self._mixer != None: + self._mixer.set_track_offset(self.track_offset()) + self._reassign_tracks() + self._reassign_scenes() + self.notify_offset() + if self.width() > 0 and self.height() > 0: + self._do_show_highlight() def _reassign_scenes(self): scenes = self.song().scenes @@ -503,9 +507,9 @@ def _on_stop_track_value(self, value, button): def _do_show_highlight(self): if self._highlighting_callback != None: return_tracks = self.song().return_tracks - if len(return_tracks) > 0: - include_returns = return_tracks[0] in self.tracks_to_use() - self._show_highlight and self._highlighting_callback(self._track_offset, self._scene_offset, self.width(), self.height(), include_returns) + include_returns = len(return_tracks) > 0 and return_tracks[0] in self.tracks_to_use() + if self._show_highlight: + self._highlighting_callback(self._track_offset, self._scene_offset, self.width(), self.height(), include_returns) else: self._highlighting_callback(-1, -1, -1, -1, include_returns) @@ -522,11 +526,11 @@ def _on_playing_slot_index_changed(self, track_index): def _update_stop_clips_led(self, index): tracks_to_use = self.tracks_to_use() track_index = index + self.track_offset() - button = self.is_enabled() and self._stop_track_clip_buttons != None and index < len(self._stop_track_clip_buttons) and self._stop_track_clip_buttons[index] - if button != None: - value_to_send = None - if track_index < len(tracks_to_use): - if tracks_to_use[track_index].clip_slots: + if self.is_enabled() and self._stop_track_clip_buttons != None and index < len(self._stop_track_clip_buttons): + button = self._stop_track_clip_buttons[index] + if button != None: + value_to_send = None + if track_index < len(tracks_to_use) and tracks_to_use[track_index].clip_slots: track = tracks_to_use[track_index] if track.fired_slot_index == -2: value_to_send = self._stop_clip_triggered_value diff --git a/_Framework/SessionRecordingComponent.py b/_Framework/SessionRecordingComponent.py index 2c7c4cb6..118ce10e 100644 --- a/_Framework/SessionRecordingComponent.py +++ b/_Framework/SessionRecordingComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/SessionRecordingComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/SessionRecordingComponent.py from __future__ import absolute_import from .CompoundComponent import CompoundComponent from .SubjectSlot import subject_slot @@ -143,9 +143,9 @@ def _on_delete_automation_value(self, value): if self.is_enabled() and value: clip = self._get_playing_clip() selected_track = self.song().view.selected_track - if selected_track: - track_frozen = selected_track.is_frozen - clip and not track_frozen and clip.clear_all_envelopes() + track_frozen = selected_track and selected_track.is_frozen + if clip and not track_frozen: + clip.clear_all_envelopes() def _get_playing_clip(self): playing_clip = None @@ -245,9 +245,9 @@ def _stop_recording(self): was any recording at all """ song = self.song() status = song.session_record_status - if not status != Live.Song.SessionRecordStatus.off: - was_recording = song.session_record - song.session_record = was_recording and False + was_recording = status != Live.Song.SessionRecordStatus.off or song.session_record + if was_recording: + song.session_record = False return was_recording def _start_recording(self): diff --git a/_Framework/SessionZoomingComponent.py b/_Framework/SessionZoomingComponent.py index 62b54664..23db6b95 100644 --- a/_Framework/SessionZoomingComponent.py +++ b/_Framework/SessionZoomingComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/SessionZoomingComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/SessionZoomingComponent.py from __future__ import absolute_import from .CompoundComponent import CompoundComponent from .ScrollComponent import ScrollComponent diff --git a/_Framework/Signal.py b/_Framework/Signal.py index 03682461..8902dc8c 100644 --- a/_Framework/Signal.py +++ b/_Framework/Signal.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Signal.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Signal.py from __future__ import absolute_import from functools import partial from .Util import find_if, nop diff --git a/_Framework/Skin.py b/_Framework/Skin.py index 43c9ce45..b06ab516 100644 --- a/_Framework/Skin.py +++ b/_Framework/Skin.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Skin.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Skin.py from __future__ import absolute_import from itertools import chain diff --git a/_Framework/SlideComponent.py b/_Framework/SlideComponent.py index 52a1c59c..4c6e404c 100644 --- a/_Framework/SlideComponent.py +++ b/_Framework/SlideComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/SlideComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/SlideComponent.py from __future__ import absolute_import from .SubjectSlot import subject_slot, Subject from .CompoundComponent import CompoundComponent diff --git a/_Framework/SliderElement.py b/_Framework/SliderElement.py index 00d75b99..0752c9ae 100644 --- a/_Framework/SliderElement.py +++ b/_Framework/SliderElement.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/SliderElement.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/SliderElement.py from __future__ import absolute_import import Live from .EncoderElement import EncoderElement diff --git a/_Framework/SubjectSlot.py b/_Framework/SubjectSlot.py index 6103102f..f7c557ae 100644 --- a/_Framework/SubjectSlot.py +++ b/_Framework/SubjectSlot.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/SubjectSlot.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/SubjectSlot.py """ Family of classes for maintaining connections with optional subjects. """ diff --git a/_Framework/SysexValueControl.py b/_Framework/SysexValueControl.py index ebe3f51b..eb59c7d5 100644 --- a/_Framework/SysexValueControl.py +++ b/_Framework/SysexValueControl.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/SysexValueControl.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/SysexValueControl.py from __future__ import absolute_import from .InputControlElement import InputControlElement, MIDI_SYSEX_TYPE diff --git a/_Framework/Task.py b/_Framework/Task.py index bb3f5748..d905098c 100644 --- a/_Framework/Task.py +++ b/_Framework/Task.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Task.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Task.py """ Task management. """ @@ -423,7 +423,7 @@ def sinusoid(f, min = 0.0, max = 1.0, *a, **k): pass def run(func, *a, **k): - return FuncTask(lambda t: None if func(*a, **k) else None) + return FuncTask(lambda t: (None if func(*a, **k) else None)) def repeat(task): diff --git a/_Framework/ToggleComponent.py b/_Framework/ToggleComponent.py index 80e41753..0d0dcc30 100644 --- a/_Framework/ToggleComponent.py +++ b/_Framework/ToggleComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ToggleComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ToggleComponent.py from __future__ import absolute_import from .ControlSurfaceComponent import ControlSurfaceComponent from .SubjectSlot import subject_slot @@ -42,7 +42,8 @@ def _set_subject(self, model): subject = property(_get_subject, _set_subject) def _get_value(self): - return getattr(self.subject, self._property_name) if self.subject else None + if self.subject: + return getattr(self.subject, self._property_name) def _set_value(self, value): setattr(self.subject, self._property_name, value) diff --git a/_Framework/TrackArmState.py b/_Framework/TrackArmState.py index 81ab2608..e0a75c6e 100644 --- a/_Framework/TrackArmState.py +++ b/_Framework/TrackArmState.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/TrackArmState.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/TrackArmState.py from __future__ import absolute_import from .SubjectSlot import Subject, subject_slot, SlotManager @@ -25,13 +25,15 @@ def _on_implicit_arm_changed(self): self._on_arm_changed() def _on_arm_changed(self): - if not self._track.arm: - new_state = self._track.implicit_arm - self._arm = self._arm != new_state and new_state + new_state = self._track.arm or self._track.implicit_arm + if self._arm != new_state: + self._arm = new_state self.notify_arm() def _get_arm(self): - return self._arm if self._track.can_be_armed else False + if self._track.can_be_armed: + return self._arm + return False def _set_arm(self, new_state): if self._track.can_be_armed: diff --git a/_Framework/TransportComponent.py b/_Framework/TransportComponent.py index c65b5537..4b3b771b 100644 --- a/_Framework/TransportComponent.py +++ b/_Framework/TransportComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/TransportComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/TransportComponent.py from __future__ import absolute_import from functools import partial import Live diff --git a/_Framework/Util.py b/_Framework/Util.py index d7fa9a7a..97a83077 100644 --- a/_Framework/Util.py +++ b/_Framework/Util.py @@ -1,11 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/Util.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/Util.py """ Various utilities. """ from __future__ import absolute_import from contextlib import contextmanager from functools import wraps, partial -from itertools import chain, imap +from itertools import chain, imap, izip_longest def clamp(val, minv, maxv): return max(minv, min(val, maxv)) @@ -33,11 +33,17 @@ def in_range(value, lower_bound, upper_open_bound): def sign(value): - return 1.0 if value >= 0.0 else -1.0 + if value >= 0.0: + return 1.0 + return -1.0 def to_slice(obj): - return obj if isinstance(obj, slice) else (slice(obj, obj + 1) if obj != -1 else slice(obj, None)) + if isinstance(obj, slice): + return obj + if obj != -1: + return slice(obj, obj + 1) + return slice(obj, None) def slice_size(slice, width): @@ -45,7 +51,7 @@ def slice_size(slice, width): def maybe(fn): - return lambda x: fn(x) if x is not None else None + return lambda x: (fn(x) if x is not None else None) def memoize(function): @@ -204,7 +210,7 @@ def extended(*a, **k): newfunc = extended else: - raise False or AssertionError, 'Must have something to extend' + raise False or AssertionError('Must have something to extend') setattr(target, patchname, newfunc) return func @@ -343,7 +349,7 @@ def group(lst, n): Returns a list of lists with elements from 'lst' grouped in blocks of 'n' elements. """ - return map(None, *[ lst[i::n] for i in range(n) ]) + return list(izip_longest(*[ lst[i::n] for i in range(n) ])) def find_if(predicate, seq): @@ -659,7 +665,7 @@ def __getitem__(self, key): new = key if isinstance(key, tuple) else (key,) keys = self._keys + new if not len(keys) <= self._dimensions: - raise AssertionError, 'Too many dimensions' + raise AssertionError('Too many dimensions') return len(keys) == self._dimensions and self._extractor(*keys) else: return Slicer(dimensions=self._dimensions, extractor=self._extractor, keys=keys) diff --git a/_Framework/ViewControlComponent.py b/_Framework/ViewControlComponent.py index 86d1f222..1367fdce 100644 --- a/_Framework/ViewControlComponent.py +++ b/_Framework/ViewControlComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/ViewControlComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/ViewControlComponent.py from __future__ import absolute_import import Live NavDirection = Live.Application.Application.View.NavDirection diff --git a/_Framework/__init__.py b/_Framework/__init__.py index 436626f8..f21664dc 100644 --- a/_Framework/__init__.py +++ b/_Framework/__init__.py @@ -1,2 +1,2 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Framework/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Framework/__init__.py pass \ No newline at end of file diff --git a/_Generic/Devices.py b/_Generic/Devices.py index ff817018..74a539cf 100644 --- a/_Generic/Devices.py +++ b/_Generic/Devices.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Generic/Devices.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Generic/Devices.py from functools import partial from _Framework.Util import group RCK_BANK1 = ('Macro 1', 'Macro 2', 'Macro 3', 'Macro 4', 'Macro 5', 'Macro 6', 'Macro 7', 'Macro 8') @@ -470,31 +470,30 @@ def parameter_bank_names(device, bank_name_dict = BANK_NAME_DICT): if device != None: if device.class_name in bank_name_dict.keys(): return bank_name_dict[device.class_name] - else: - banks = number_of_parameter_banks(device) + banks = number_of_parameter_banks(device) - def _default_bank_name(bank_index): - return 'Bank ' + str(bank_index + 1) + def _default_bank_name(bank_index): + return 'Bank ' + str(bank_index + 1) - if device.class_name in MAX_DEVICES and banks != 0: + if device.class_name in MAX_DEVICES and banks != 0: - def _is_ascii(c): - return ord(c) < 128 + def _is_ascii(c): + return ord(c) < 128 - def _bank_name(bank_index): - try: - name = device.get_bank_name(bank_index) - except: - name = None + def _bank_name(bank_index): + try: + name = device.get_bank_name(bank_index) + except: + name = None - if name: - return str(filter(_is_ascii, name)) - else: - return _default_bank_name(bank_index) + if name: + return str(filter(_is_ascii, name)) + else: + return _default_bank_name(bank_index) - return map(_bank_name, range(0, banks)) - else: - return map(_default_bank_name, range(0, banks)) + return map(_bank_name, range(0, banks)) + else: + return map(_default_bank_name, range(0, banks)) return [] diff --git a/_Generic/GenericScript.py b/_Generic/GenericScript.py index e404969a..f1d025b5 100644 --- a/_Generic/GenericScript.py +++ b/_Generic/GenericScript.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Generic/GenericScript.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Generic/GenericScript.py from __future__ import with_statement import Live from _Framework.ControlSurface import ControlSurface diff --git a/_Generic/SelectChanStripComponent.py b/_Generic/SelectChanStripComponent.py index e56dc8d0..14760ab4 100644 --- a/_Generic/SelectChanStripComponent.py +++ b/_Generic/SelectChanStripComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Generic/SelectChanStripComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Generic/SelectChanStripComponent.py import Live from _Framework.ChannelStripComponent import ChannelStripComponent diff --git a/_Generic/SpecialMixerComponent.py b/_Generic/SpecialMixerComponent.py index c779bc9d..60a6a9f6 100644 --- a/_Generic/SpecialMixerComponent.py +++ b/_Generic/SpecialMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Generic/SpecialMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Generic/SpecialMixerComponent.py import Live from _Framework.MixerComponent import MixerComponent from SelectChanStripComponent import SelectChanStripComponent diff --git a/_Generic/__init__.py b/_Generic/__init__.py index f5f9c32b..3f0ac23d 100644 --- a/_Generic/__init__.py +++ b/_Generic/__init__.py @@ -1,2 +1,2 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Generic/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Generic/__init__.py pass \ No newline at end of file diff --git a/_Generic/util.py b/_Generic/util.py new file mode 100644 index 00000000..a6707ce0 --- /dev/null +++ b/_Generic/util.py @@ -0,0 +1,39 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Generic/util.py +from __future__ import absolute_import, print_function +from _Framework.SubjectSlot import SlotManager, subject_slot +from _Framework.Util import nop + +class DeviceAppointer(SlotManager): + + def __init__(self, song = None, appointed_device_setter = nop, *a, **k): + super(DeviceAppointer, self).__init__(*a, **k) + self._set_appointed_device = appointed_device_setter + self._appointed_device = None + self._song = song + self.__on_appointed_device_changed.subject = self._song + self.__on_selected_track_changed.subject = self._song.view + self.__on_selected_track_changed() + + @subject_slot('appointed_device') + def __on_appointed_device_changed(self): + if self._appointed_device != self._song.appointed_device: + self._update_appointed_device(self._song.appointed_device) + + @subject_slot('selected_device') + def __on_selected_device_changed(self): + song = self._song + device = song.view.selected_track.view.selected_device + if device != None: + self._update_appointed_device(device) + + @subject_slot('selected_track') + def __on_selected_track_changed(self): + track_view = self._song.view.selected_track.view + self.__on_selected_device_changed.subject = track_view + self._update_appointed_device(track_view.selected_device) + + def _update_appointed_device(self, device): + if device != None: + self._appointed_device = device + self._set_appointed_device(device) + self._song.appointed_device = device \ No newline at end of file diff --git a/_MPDMkIIBase/ControlElementUtils.py b/_MPDMkIIBase/ControlElementUtils.py index 0b998ba2..c3804da0 100644 --- a/_MPDMkIIBase/ControlElementUtils.py +++ b/_MPDMkIIBase/ControlElementUtils.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_MPDMkIIBase/ControlElementUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_MPDMkIIBase/ControlElementUtils.py import Live from _Framework.InputControlElement import MIDI_CC_TYPE from _Framework.EncoderElement import EncoderElement diff --git a/_MPDMkIIBase/MPDMkIIBase.py b/_MPDMkIIBase/MPDMkIIBase.py index 5fdde47b..d91c2bb1 100644 --- a/_MPDMkIIBase/MPDMkIIBase.py +++ b/_MPDMkIIBase/MPDMkIIBase.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_MPDMkIIBase/MPDMkIIBase.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_MPDMkIIBase/MPDMkIIBase.py from __future__ import with_statement from _Framework.ControlSurface import ControlSurface from _Framework.Layer import Layer diff --git a/_MPDMkIIBase/__init__.py b/_MPDMkIIBase/__init__.py index c47ddad9..0c29386b 100644 --- a/_MPDMkIIBase/__init__.py +++ b/_MPDMkIIBase/__init__.py @@ -1,2 +1,2 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_MPDMkIIBase/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_MPDMkIIBase/__init__.py HIDE_SCRIPT = True \ No newline at end of file diff --git a/_MxDCore/LomTypes.py b/_MxDCore/LomTypes.py index 8c1c4b8b..7acb6587 100644 --- a/_MxDCore/LomTypes.py +++ b/_MxDCore/LomTypes.py @@ -1,13 +1,74 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_MxDCore/LomTypes.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_MxDCore/LomTypes.py +import types import Live -from _Tools import types from _Framework.ControlSurface import ControlSurface from _Framework.ControlSurfaceComponent import ControlSurfaceComponent from _Framework.ControlElement import ControlElement from _Framework.Util import is_iterable -HIDDEN_TYPES = (Live.Browser.Browser, Live.Clip.AutomationEnvelope, Live.SimplerDevice.TransientLoopMode) -HIDDEN_PROPERTIES = ('begin_undo_step', 'end_undo_step', 'begin_gesture', 'end_gesture', 'automation_envelope', 'can_be_appointed', 'copy_pad') -HIDDEN_PROPERTIES_FOR_TYPE = {Live.SimplerDevice.SimplerDevice: ('sample_file_path', 'sample_length', 'start_marker', 'end_marker', 'slicing_sensitivity', 'slices', 'warping', 'warp_mode', 'beats_granulation_resolution', 'beats_transient_loop_mode', 'beats_transient_envelope', 'tones_grain_size', 'texture_grain_size', 'texture_flux', 'complex_pro_formants', 'complex_pro_envelope', 'gain', 'gain_display_string', 'remove_slice', 'insert_slice')} +_DEVICE_BASE_PROPS = ['canonical_parent', + 'parameters', + 'view', + 'can_have_chains', + 'can_have_drum_pads', + 'class_display_name', + 'class_name', + 'is_active', + 'name', + 'type', + 'store_chosen_bank'] +_DEVICE_VIEW_BASE_PROPS = ['canonical_parent', 'is_collapsed'] +EXPOSED_TYPE_PROPERTIES = {Live.Application.Application: ('view', 'current_dialog_button_count', 'current_dialog_message', 'open_dialog_count', 'get_bugfix_version', 'get_document', 'get_major_version', 'get_minor_version', 'press_current_dialog_button'), + Live.Application.Application.View: ('canonical_parent', 'browse_mode', 'available_main_views', 'focus_view', 'hide_view', 'is_view_visible', 'scroll_view', 'show_view', 'toggle_browse', 'zoom_view'), + Live.Chain.Chain: ('canonical_parent', 'name', 'devices', 'delete_device', 'mute', 'solo', 'muted_via_solo', 'mixer_device', 'color', 'color_index', 'is_auto_colored', 'has_audio_input', 'has_audio_output', 'has_midi_input', 'has_midi_output'), + Live.ChainMixerDevice.ChainMixerDevice: ('canonical_parent', 'volume', 'panning', 'sends', 'chain_activator'), + Live.Clip.Clip: ('canonical_parent', 'view', 'color', 'color_index', 'end_marker', 'has_envelopes', 'is_arrangement_clip', 'is_audio_clip', 'is_midi_clip', 'is_overdubbing', 'is_playing', 'is_recording', 'is_triggered', 'length', 'loop_end', 'loop_start', 'looping', 'muted', 'name', 'playing_position', 'position', 'signature_denominator', 'signature_numerator', 'start_marker', 'start_time', 'will_record_on_start', 'clear_all_envelopes', 'clear_envelope', 'deselect_all_notes', 'duplicate_loop', 'fire', 'get_notes', 'get_selected_notes', 'move_playing_pos', 'quantize', 'quantize_pitch', 'remove_notes', 'replace_selected_notes', 'scrub', 'select_all_notes', 'set_fire_button_state', 'set_notes', 'stop', 'stop_scrub', 'available_warp_modes', 'file_path', 'gain', 'gain_display_string', 'pitch_coarse', 'pitch_fine', 'ram_mode', 'warp_mode', 'warping'), + Live.Clip.Clip.View: ('canonical_parent', 'grid_is_triplet', 'grid_quantization', 'hide_envelope', 'select_envelope_parameter', 'show_envelope', 'show_loop'), + Live.ClipSlot.ClipSlot: ('canonical_parent', 'clip', 'color', 'color_index', 'controls_other_clips', 'has_clip', 'has_stop_button', 'is_playing', 'is_recording', 'is_triggered', 'playing_status', 'will_record_on_start', 'create_clip', 'delete_clip', 'fire', 'set_fire_button_state', 'stop'), + Live.Device.Device: tuple(_DEVICE_BASE_PROPS), + Live.Device.Device.View: tuple(_DEVICE_VIEW_BASE_PROPS), + Live.DeviceParameter.DeviceParameter: ('canonical_parent', 'automation_state', 'is_enabled', 'is_quantized', 'max', 'min', 'name', 'original_name', 'state', 'value', 'value_items', 're_enable_automation', 'str_for_value', '__str__'), + Live.DrumPad.DrumPad: ('canonical_parent', 'chains', 'mute', 'name', 'note', 'solo', 'delete_all_chains'), + Live.MaxDevice.MaxDevice: tuple(_DEVICE_BASE_PROPS + ['get_bank_count', 'get_bank_name', 'get_bank_parameters']), + Live.MixerDevice.MixerDevice: ('canonical_parent', 'sends', 'panning', 'track_activator', 'volume', 'crossfade_assign'), + Live.PluginDevice.PluginDevice: tuple(_DEVICE_BASE_PROPS + ['presets', 'selected_preset_index']), + Live.RackDevice.RackDevice: tuple(_DEVICE_BASE_PROPS + ['chains', + 'drum_pads', + 'return_chains', + 'visible_drum_pads', + 'has_macro_mappings', + 'copy_pad', + 'has_drum_pads']), + Live.RackDevice.RackDevice.View: tuple(_DEVICE_VIEW_BASE_PROPS + ['selected_chain', + 'is_showing_chain_devices', + 'selected_drum_pad', + 'drum_pads_scroll_position']), + Live.Sample.Sample: ('canonical_parent', 'beats_granulation_resolution', 'beats_transient_envelope', 'beats_transient_loop_mode', 'complex_pro_envelope', 'complex_pro_formants', 'end_marker', 'file_path', 'gain', 'length', 'slicing_sensitivity', 'start_marker', 'texture_flux', 'texture_grain_size', 'tones_grain_size', 'warp_mode', 'warping', 'gain_display_string', 'insert_slice', 'move_slice', 'remove_slice'), + Live.Scene.Scene: ('canonical_parent', 'clip_slots', 'color', 'color_index', 'is_empty', 'is_triggered', 'name', 'tempo', 'fire', 'fire_as_selected', 'set_fire_button_state'), + Live.SimplerDevice.SimplerDevice: tuple(_DEVICE_BASE_PROPS + ['sample', + 'can_warp_as', + 'can_warp_double', + 'can_warp_half', + 'multi_sample_mode', + 'pad_slicing', + 'playback_mode', + 'playing_position', + 'playing_position_enabled', + 'retrigger', + 'slicing_playback_mode', + 'voices', + 'crop', + 'guess_playback_length', + 'reverse', + 'warp_as', + 'warp_double', + 'warp_half']), + Live.SimplerDevice.SimplerDevice.View: tuple(_DEVICE_VIEW_BASE_PROPS + ['selected_slice']), + Live.Song.Song: ('cue_points', 'return_tracks', 'scenes', 'tracks', 'visible_tracks', 'master_track', 'view', 'appointed_device', 'arrangement_overdub', 'back_to_arranger', 'can_jump_to_next_cue', 'can_jump_to_prev_cue', 'can_redo', 'can_undo', 'clip_trigger_quantization', 'current_song_time', 'exclusive_arm', 'exclusive_solo', 'groove_amount', 'is_playing', 'last_event_time', 'loop', 'loop_length', 'loop_start', 'metronome', 'midi_recording_quantization', 'nudge_down', 'overdub', 'punch_in', 'punch_out', 'nudge_up', 're_enable_automation_enabled', 'record_mode', 'root_note', 'scale_name', 'select_on_launch', 'session_automation_record', 'session_record', 'session_record_status', 'signature_denominator', 'signature_numerator', 'song_length', 'swing_amount', 'tempo', 'capture_and_insert_scene', 'continue_playing', 'create_audio_track', 'create_midi_track', 'create_return_track', 'create_scene', 'delete_scene', 'delete_track', 'duplicate_scene', 'duplicate_track', 'find_device_position', 'get_beats_loop_length', 'get_beats_loop_start', 'get_current_beats_song_time', 'get_current_smpte_song_time', 'is_cue_point_selected', 'jump_by', 'jump_to_next_cue', 'jump_to_prev_cue', 'move_device', 'play_selection', 're_enable_automation', 'redo', 'scrub_by', 'set_or_delete_cue', 'start_playing', 'stop_all_clips', 'stop_playing', 'tap_tempo', 'trigger_session_record', 'undo'), + Live.Song.Song.View: ('canonical_parent', 'detail_clip', 'highlighted_clip_slot', 'selected_chain', 'selected_parameter', 'selected_scene', 'selected_track', 'draw_mode', 'follow_song', 'select_device'), + Live.Song.CuePoint: ('canonical_parent', 'name', 'time', 'jump'), + Live.Track.Track: ('clip_slots', 'devices', 'canonical_parent', 'mixer_device', 'view', 'arm', 'can_be_armed', 'can_be_frozen', 'can_show_chains', 'color', 'color_index', 'current_input_routing', 'current_input_sub_routing', 'current_monitoring_state', 'current_output_routing', 'current_output_sub_routing', 'fired_slot_index', 'has_audio_input', 'has_audio_output', 'has_midi_input', 'has_midi_output', 'implicit_arm', 'input_meter_level', 'input_routings', 'input_sub_routings', 'input_meter_left', 'input_meter_right', 'is_foldable', 'is_frozen', 'is_grouped', 'is_part_of_selection', 'is_showing_chains', 'is_visible', 'mute', 'muted_via_solo', 'name', 'output_meter_left', 'output_meter_level', 'output_meter_right', 'output_routings', 'output_sub_routings', 'playing_slot_index', 'solo', 'delete_device', 'duplicate_clip_slot', 'jump_in_running_session_clip', 'stop_all_clips'), + Live.Track.Track.View: ('canonical_parent', 'selected_device', 'device_insert_mode', 'is_collapsed', 'select_instrument')} +HIDDEN_TYPE_PROPERTIES = {Live.Sample.Sample: ('slices',)} ENUM_TYPES = (Live.Song.Quantization, Live.Song.RecordingQuantization, Live.Song.CaptureMode, @@ -46,11 +107,13 @@ 'selected_parameter': Live.DeviceParameter.DeviceParameter, 'selected_chain': Live.Chain.Chain, 'selected_drum_pad': Live.DrumPad.DrumPad, + 'sample': Live.Sample.Sample, 'mixer_device': (Live.MixerDevice.MixerDevice, Live.ChainMixerDevice.ChainMixerDevice), 'view': (Live.Application.Application.View, Live.Song.Song.View, Live.Track.Track.View, Live.Device.Device.View, + Live.RackDevice.RackDevice.View, Live.Clip.Clip.View)} LIVE_APP = 'live_app' LIVE_SET = 'live_set' @@ -96,8 +159,10 @@ def get_root_prop(external_device, prop_key): root_properties = {LIVE_APP: Live.Application.get_application, LIVE_SET: lambda : Live.Application.get_application().get_document(), CONTROL_SURFACES: get_control_surfaces} - raise prop_key in ROOT_KEYS or AssertionError - return external_device if prop_key == THIS_DEVICE else root_properties[prop_key]() + if not prop_key in ROOT_KEYS: + raise AssertionError + return prop_key == THIS_DEVICE and external_device + return root_properties[prop_key]() def cs_base_classes(): @@ -127,6 +192,20 @@ def is_object_iterable(obj): return not isinstance(obj, basestring) and is_iterable(obj) and not isinstance(obj, cs_base_classes()) +def is_property_exposed(lom_object, property_name): + return property_name in EXPOSED_TYPE_PROPERTIES.get(type(lom_object), []) + + +def is_property_hidden(lom_object, property_name): + return property_name in HIDDEN_TYPE_PROPERTIES.get(type(lom_object), []) + + def verify_object_property(lom_object, property_name): - if not hasattr(lom_object, property_name) or property_name in HIDDEN_PROPERTIES: + raise_error = False + if isinstance(lom_object, cs_base_classes()): + if not hasattr(lom_object, property_name): + raise_error = True + elif not (is_property_exposed(lom_object, property_name) or is_property_hidden(lom_object, property_name)): + raise_error = True + if raise_error: raise LomAttributeError("'%s' object has no attribute '%s'" % (lom_object.__class__.__name__, property_name)) \ No newline at end of file diff --git a/_MxDCore/LomUtils.py b/_MxDCore/LomUtils.py index f90ca703..3167d86f 100644 --- a/_MxDCore/LomUtils.py +++ b/_MxDCore/LomUtils.py @@ -1,8 +1,16 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_MxDCore/LomUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_MxDCore/LomUtils.py import sys -from _Tools import types +import types +from itertools import ifilter from MxDUtils import TupleWrapper -from LomTypes import TUPLE_TYPES, PROPERTY_TYPES, ENUM_TYPES, ROOT_KEYS, HIDDEN_TYPES, HIDDEN_PROPERTIES, HIDDEN_PROPERTIES_FOR_TYPE, LomObjectError, LomAttributeError, is_class, get_root_prop, is_lom_object, is_cplusplus_lom_object, is_object_iterable +from LomTypes import cs_base_classes, EXPOSED_TYPE_PROPERTIES, TUPLE_TYPES, PROPERTY_TYPES, ENUM_TYPES, ROOT_KEYS, LomObjectError, LomAttributeError, is_class, get_root_prop, is_lom_object, is_cplusplus_lom_object, is_object_iterable + +def create_lom_doc_string(lom_object): + description = '' + if hasattr(lom_object, '__doc__') and isinstance(lom_object.__doc__, basestring) and len(lom_object.__doc__) > 0: + description = 'description %s' % lom_object.__doc__.replace('\n', ' ').replace(',', '\\,') + return description + class LomInformation(object): """ Class that extracts information from a given LOM object """ @@ -13,7 +21,7 @@ def __init__(self, lom_object, *a, **k): self._children = [] self._functions = [] self._properties = [] - self._description = '' + self._description = create_lom_doc_string(lom_object) self._generate_object_info(lom_object) @property @@ -36,28 +44,32 @@ def functions(self): def properties(self): return tuple(self._properties) - def _generate_object_info(self, lom_object): - if hasattr(lom_object, '__doc__') and isinstance(lom_object.__doc__, basestring) and len(lom_object.__doc__) > 0: - self._description = 'description %s' % lom_object.__doc__.replace('\n', ' ').replace(',', '\\,') + def _add_list_of_children(self, prop_name): + type_name = TUPLE_TYPES[prop_name].__name__ + self._lists_of_children.append((prop_name, type_name)) - def hidden_prop_for_type(prop_name, lom_object): - return prop_name in HIDDEN_PROPERTIES_FOR_TYPE.get(type(lom_object), []) + def _add_child(self, real_prop, prop_name): + type_name = (real_prop.__class__ if real_prop != None else PROPERTY_TYPES[prop_name]).__name__ + self._children.append((prop_name, type_name)) - for prop_name in dir(lom_object): - if not prop_name.startswith('_') and prop_name not in HIDDEN_PROPERTIES and not hidden_prop_for_type(prop_name, lom_object): - self._generate_property_info(prop_name, lom_object) + def _generate_object_info(self, lom_object): + property_names = [] + if isinstance(lom_object, cs_base_classes()): + property_names = ifilter(lambda prop: not prop.startswith('_'), dir(lom_object)) + else: + property_names = EXPOSED_TYPE_PROPERTIES.get(type(lom_object), []) + for name in property_names: + self._generate_property_info(name, lom_object) def _generate_property_info(self, prop_name, lom_object): try: real_prop = getattr(lom_object, prop_name) - if not isinstance(real_prop, HIDDEN_TYPES) and not is_class(real_prop): + if not is_class(real_prop): prop_type = real_prop.__class__.__name__ if prop_name in TUPLE_TYPES: - type_name = TUPLE_TYPES[prop_name].__name__ - self._lists_of_children.append((prop_name, type_name)) + self._add_list_of_children(prop_name) elif prop_name in PROPERTY_TYPES.keys(): - type_name = (real_prop.__class__ if real_prop != None else PROPERTY_TYPES[prop_name]).__name__ - self._children.append((prop_name, type_name)) + self._add_child(real_prop, prop_name) elif prop_name == 'canonical_parent': if real_prop != None: self._children.append((prop_name, prop_type)) @@ -158,9 +170,9 @@ def _find_root_object_path(self, external_device, lom_object): def _find_property_object_path(self, lom_object, parent): component = None for key in PROPERTY_TYPES.keys(): - if isinstance(lom_object, PROPERTY_TYPES[key]): - if hasattr(parent, key): - component = lom_object == getattr(parent, key) and key + if isinstance(lom_object, PROPERTY_TYPES[key]) and hasattr(parent, key): + if lom_object == getattr(parent, key): + component = key break return component @@ -178,7 +190,9 @@ def _find_tuple_element_object_path(self, lom_object, parent): return component def _prepend_path_component(self, component, components): - return [component] + components if component != None else [] + if component != None: + return [component] + components + return [] def _calculate_path(self, lom_object, external_device_getter): components = [] @@ -237,8 +251,6 @@ def _property_object_from_path(self, path_components): lom_object = lom_object[int(component)] else: lom_object = getattr(lom_object, component) - if isinstance(lom_object, HIDDEN_TYPES): - raise AttributeError except IndexError: raise LomAttributeError("invalid index of component '%s'" % prev_component) except AttributeError: diff --git a/_MxDCore/MxDCore.py b/_MxDCore/MxDCore.py index bd083a76..518e1411 100644 --- a/_MxDCore/MxDCore.py +++ b/_MxDCore/MxDCore.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_MxDCore/MxDCore.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_MxDCore/MxDCore.py import Live.Base from functools import partial, wraps import _Framework @@ -6,7 +6,7 @@ from _Framework.Debug import debug_print from MxDUtils import TupleWrapper, StringHandler from LomUtils import LomInformation, LomIntrospection, LomPathCalculator, LomPathResolver -from LomTypes import ENUM_TYPES, PROPERTY_TYPES, CONTROL_SURFACES, ROOT_KEYS, LomNoteOperationWarning, LomNoteOperationError, LomAttributeError, LomObjectError, get_root_prop, is_lom_object, is_cplusplus_lom_object, is_object_iterable, verify_object_property +from LomTypes import ENUM_TYPES, EXPOSED_TYPE_PROPERTIES, CONTROL_SURFACES, PROPERTY_TYPES, ROOT_KEYS, get_root_prop, is_lom_object, is_cplusplus_lom_object, is_object_iterable, LomNoteOperationWarning, LomNoteOperationError, LomAttributeError, LomObjectError, verify_object_property, is_property_hidden def get_current_max_device(device_id): raise MxDCore.instance != None and MxDCore.instance.manager != None or AssertionError @@ -27,6 +27,8 @@ def get_current_max_device(device_id): NOTE_SET_KEY = 'NOTE_SET' CONTAINS_CS_ID_KEY = 'CONTAINS_CS_ID_KEY' LAST_SENT_ID_KEY = 'LAST_SENT_ID' +PRIVATE_PROP_WARNING = 'Warning: Calling private property. This property might change or be removed in the future.' +HIDDEN_PROP_WARNING = 'Warning: Calling hidden property. This property might change or be removed in the future.' def concatenate_strings(string_list, string_format = '%s %s'): return unicode(reduce(lambda s1, s2: string_format % (s1, s2), string_list) if len(string_list) > 0 else '') @@ -52,8 +54,8 @@ class MxDCore(object): """ Central class for the Max-integration """ instance = None - def __init__(self): - object.__init__(self) + def __init__(self, *a, **k): + super(MxDCore, self).__init__(*a, **k) self.device_contexts = {} self.manager = None self.lom_classes = [] @@ -65,8 +67,7 @@ def __init__(self): 'note': self._object_note_handler, 'done': self._object_done_handler, 'get_control_names': self._object_get_control_names_handler} - excluded = (Live.Base, Live.Song.BeatTime, Live.Song.SmptTime) + ENUM_TYPES - self.lom_classes += LomIntrospection(Live, exclude=excluded).lom_classes + self.lom_classes = EXPOSED_TYPE_PROPERTIES.keys() self.lom_classes += LomIntrospection(_Framework).lom_classes self.appointed_lom_ids = {0: None} @@ -402,6 +403,13 @@ def _set_property_value(self, lom_object, property_name, value): raise LomAttributeError('set: unsupported property type') setattr(lom_object, property_name, value) + def _warn_if_using_private_property(self, device_id, object_id, property_name): + if property_name.startswith('_'): + self._warn(device_id, object_id, PRIVATE_PROP_WARNING) + lom_object = self._get_current_lom_object(device_id, object_id) + if is_property_hidden(lom_object, property_name): + self._warn(device_id, object_id, HIDDEN_PROP_WARNING) + def obj_set(self, device_id, object_id, parameters): if not isinstance(parameters, (str, unicode)): raise AssertionError @@ -412,6 +420,7 @@ def obj_set(self, device_id, object_id, parameters): value = property_values[0] try: self._set_property_value(current_object, property_name, value) + self._warn_if_using_private_property(device_id, object_id, property_name) except LomAttributeError as e: self._raise(device_id, object_id, e.message) @@ -430,6 +439,7 @@ def obj_get(self, device_id, object_id, parameters): result_value = current_object[int(parameters)] else: verify_object_property(current_object, parameters) + self._warn_if_using_private_property(device_id, object_id, parameters) result_value = getattr(current_object, parameters) if isinstance(result_value, ENUM_TYPES): result_value = int(result_value) @@ -618,6 +628,7 @@ def _goto_path(self, device_id, object_id, parameters): def _object_default_call_handler(self, device_id, object_id, lom_object, parameters): verify_object_property(lom_object, parameters[0]) + self._warn_if_using_private_property(device_id, object_id, parameters[0]) function = getattr(lom_object, parameters[0]) result = function(*parameters[1:]) result_str = self._str_representation_for_object(result) @@ -672,7 +683,9 @@ def _object_note_handler(self, device_id, object_id, lom_object, parameters): def _selector_for_note_operation(self, note_operation): if note_operation not in (NOTE_REPLACE_KEY, NOTE_SET_KEY): raise LomNoteOperationWarning('invalid note operation') - return 'set_notes' if note_operation == NOTE_SET_KEY else 'replace_selected_notes' + if note_operation == NOTE_SET_KEY: + return 'set_notes' + return 'replace_selected_notes' def _object_done_handler(self, device_id, object_id, lom_object, parameters): if not (isinstance(lom_object, Live.Clip.Clip) and lom_object.is_midi_clip): @@ -755,6 +768,7 @@ def _observer_install_listener(self, device_id, object_id): raise AssertionError current_object = self._get_current_lom_object(device_id, object_id) property_name = self._get_current_property(device_id, object_id) + self._warn_if_using_private_property(device_id, object_id, property_name) property_name == u'id' and self._observer_id_callback(device_id, object_id) else: object_context = current_object != None and property_name != '' and self.device_contexts[device_id][object_id] @@ -858,7 +872,9 @@ def _disambiguate_object(self, object): return result def _listenable_property_for(self, prop_name): - return 'has_clip' if prop_name == 'clip' else prop_name + if prop_name == 'clip': + return 'has_clip' + return prop_name def _parse(self, device_id, object_id, string): return StringHandler.parse(string, self._object_for_id(device_id)) diff --git a/_MxDCore/MxDUtils.py b/_MxDCore/MxDUtils.py index 5c1c3bce..9ea60035 100644 --- a/_MxDCore/MxDUtils.py +++ b/_MxDCore/MxDUtils.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_MxDCore/MxDUtils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_MxDCore/MxDUtils.py class TupleWrapper(object): diff --git a/_MxDCore/__init__.py b/_MxDCore/__init__.py index c9c61b38..caaa34ea 100644 --- a/_MxDCore/__init__.py +++ b/_MxDCore/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_MxDCore/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_MxDCore/__init__.py from MxDCore import MxDCore as _MxDCore import sys diff --git a/_Serato/PySCAClipControl.py b/_Serato/PySCAClipControl.py index a02dd6c0..e5dabd62 100644 --- a/_Serato/PySCAClipControl.py +++ b/_Serato/PySCAClipControl.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Serato/PySCAClipControl.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Serato/PySCAClipControl.py import libInterprocessCommsAPIPython class PySCAClipControl: diff --git a/_Serato/Serato.py b/_Serato/Serato.py index 7f9d9ddb..44ac5dfe 100644 --- a/_Serato/Serato.py +++ b/_Serato/Serato.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Serato/Serato.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Serato/Serato.py from __future__ import with_statement import Live import libInterprocessCommsAPIPython diff --git a/_Serato/SpecialChanStripComponent.py b/_Serato/SpecialChanStripComponent.py index 67cddb89..be07b3b9 100644 --- a/_Serato/SpecialChanStripComponent.py +++ b/_Serato/SpecialChanStripComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Serato/SpecialChanStripComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Serato/SpecialChanStripComponent.py from _Framework.ChannelStripComponent import ChannelStripComponent class SpecialChanStripComponent(ChannelStripComponent): diff --git a/_Serato/SpecialClipSlotComponent.py b/_Serato/SpecialClipSlotComponent.py index e83a2192..33bb56a0 100644 --- a/_Serato/SpecialClipSlotComponent.py +++ b/_Serato/SpecialClipSlotComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Serato/SpecialClipSlotComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Serato/SpecialClipSlotComponent.py import Live import libInterprocessCommsAPIPython from _Framework.ClipSlotComponent import ClipSlotComponent diff --git a/_Serato/SpecialDeviceComponent.py b/_Serato/SpecialDeviceComponent.py index 51dbdb9b..9f2f9d43 100644 --- a/_Serato/SpecialDeviceComponent.py +++ b/_Serato/SpecialDeviceComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Serato/SpecialDeviceComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Serato/SpecialDeviceComponent.py import Live import libInterprocessCommsAPIPython from PySCAClipControl import * diff --git a/_Serato/SpecialMixerComponent.py b/_Serato/SpecialMixerComponent.py index 3ee3d415..4bbb345f 100644 --- a/_Serato/SpecialMixerComponent.py +++ b/_Serato/SpecialMixerComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Serato/SpecialMixerComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Serato/SpecialMixerComponent.py import Live from _Framework.MixerComponent import MixerComponent from SpecialChanStripComponent import SpecialChanStripComponent diff --git a/_Serato/SpecialSceneComponent.py b/_Serato/SpecialSceneComponent.py index 98d0e0ca..2cd5423a 100644 --- a/_Serato/SpecialSceneComponent.py +++ b/_Serato/SpecialSceneComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Serato/SpecialSceneComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Serato/SpecialSceneComponent.py import Live from _Framework.SceneComponent import SceneComponent from _Framework.InputControlElement import * diff --git a/_Serato/SpecialSessionComponent.py b/_Serato/SpecialSessionComponent.py index 60747087..9624cbf4 100644 --- a/_Serato/SpecialSessionComponent.py +++ b/_Serato/SpecialSessionComponent.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Serato/SpecialSessionComponent.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Serato/SpecialSessionComponent.py import Live from _Framework.SessionComponent import SessionComponent from _Framework.InputControlElement import * diff --git a/_Serato/__init__.py b/_Serato/__init__.py index d9b0ffb2..881b2279 100644 --- a/_Serato/__init__.py +++ b/_Serato/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Serato/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Serato/__init__.py from Serato import Serato HIDE_SCRIPT = True diff --git a/_Tools/__init__.py b/_Tools/__init__.py index 31759ee9..a96ef3f6 100644 --- a/_Tools/__init__.py +++ b/_Tools/__init__.py @@ -1,2 +1,2 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_Tools/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_Tools/__init__.py pass \ No newline at end of file diff --git a/_UserScript/__init__.py b/_UserScript/__init__.py index 0c8fce62..7aea307a 100644 --- a/_UserScript/__init__.py +++ b/_UserScript/__init__.py @@ -1,7 +1,7 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/_UserScript/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/_UserScript/__init__.py +from ConfigParser import ConfigParser from _Generic.GenericScript import GenericScript import Live -from _Tools.ConfigParser import ConfigParser HIDE_SCRIPT = True def interpret_map_mode(map_mode_name): diff --git a/ableton/__init__.py b/ableton/__init__.py index 1a785784..d2b32b79 100644 --- a/ableton/__init__.py +++ b/ableton/__init__.py @@ -1,2 +1,2 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/__init__.py -pass \ No newline at end of file +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/__init__.py +from __future__ import absolute_import, print_function \ No newline at end of file diff --git a/ableton/v2/.DS_Store_failed_failed b/ableton/v2/.DS_Store_failed_failed new file mode 100644 index 00000000..e69de29b diff --git a/ableton/v2/__init__.pyc b/ableton/v2/__init__.pyc index 7f5f9edd..746f445f 100644 Binary files a/ableton/v2/__init__.pyc and b/ableton/v2/__init__.pyc differ diff --git a/ableton/v2/base/.DS_Store_failed_failed b/ableton/v2/base/.DS_Store_failed_failed new file mode 100644 index 00000000..e69de29b diff --git a/ableton/v2/base/collection/__init__.py b/ableton/v2/base/collection/__init__.py index 6366f319..006ecd38 100644 --- a/ableton/v2/base/collection/__init__.py +++ b/ableton/v2/base/collection/__init__.py @@ -1,3 +1,83 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/collection/__init__.py -from ordered_dict import OrderedDict -from indexed_dict import IndexedDict \ No newline at end of file +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/__init__.py +from __future__ import absolute_import, print_function +from .live_api_utils import liveobj_changed, liveobj_valid +from .proxy import Proxy, ProxyBase +from .slot import Event, has_event, listenable_property, listens, listens_group, MultiSlot, SerializableListenableProperties, Slot, SlotError, SlotGroup, SlotManager, Subject +from .signal import Signal +from .dependency import DependencyError, depends, inject +from .disconnectable import disconnectable, Disconnectable, CompoundDisconnectable +from .util import Bindable, BooleanContext, chunks, clamp, compose, const, dict_diff, find_if, first, flatten, forward_property, get_slice, group, index_if, infinite_context_manager, instance_decorator, in_range, is_contextmanager, is_iterable, is_matrix, lazy_attribute, linear, maybe, memoize, mixin, monkeypatch, monkeypatch_extend, NamedTuple, negate, next, nop, overlaymap, partial, print_message, product, recursive_map, remove_if, second, sign, Slicer, slicer, slice_size, third, to_slice, trace_value, union, wraps +from .gcutil import histogram, instances_by_name, refget +__all__ = (Bindable, + BooleanContext, + chunks, + clamp, + compose, + CompoundDisconnectable, + const, + DependencyError, + depends, + dict_diff, + Disconnectable, + disconnectable, + Event, + find_if, + first, + flatten, + forward_property, + get_slice, + group, + has_event, + histogram, + index_if, + infinite_context_manager, + inject, + instances_by_name, + instance_decorator, + in_range, + is_contextmanager, + is_iterable, + is_matrix, + lazy_attribute, + linear, + listenable_property, + listens, + listens_group, + liveobj_changed, + liveobj_valid, + maybe, + memoize, + mixin, + monkeypatch, + monkeypatch_extend, + MultiSlot, + NamedTuple, + negate, + next, + nop, + overlaymap, + partial, + print_message, + product, + Proxy, + ProxyBase, + recursive_map, + refget, + remove_if, + second, + SerializableListenableProperties, + sign, + Signal, + Slicer, + slicer, + slice_size, + Slot, + SlotError, + SlotGroup, + SlotManager, + Subject, + third, + to_slice, + trace_value, + union, + wraps) \ No newline at end of file diff --git a/ableton/v2/base/collection/indexed_dict.py b/ableton/v2/base/collection/indexed_dict.py index d2ae6e4c..b58b3ca5 100644 --- a/ableton/v2/base/collection/indexed_dict.py +++ b/ableton/v2/base/collection/indexed_dict.py @@ -1,5 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/collection/indexed_dict.py -from . import OrderedDict +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/collection/indexed_dict.py +from __future__ import absolute_import, print_function +from collections import OrderedDict class IndexedDict(OrderedDict): """ Dictionary whose values are accessible by indices """ diff --git a/ableton/v2/base/dependency.py b/ableton/v2/base/dependency.py index 471c77f1..702618d6 100644 --- a/ableton/v2/base/dependency.py +++ b/ableton/v2/base/dependency.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/dependency.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/dependency.py """ Dependency injection framework. @@ -9,7 +9,7 @@ identifiers. Dependencies are provided via accessor functions, that in general will be called whenever they are needed. """ -from __future__ import absolute_import +from __future__ import absolute_import, print_function from functools import wraps from .util import union __all__ = ('inject', 'depends', 'dependency') @@ -48,8 +48,7 @@ def get_dependency_for(name, default = None): accessor = _global_injection_registry.get(name, default) if accessor is not None: return accessor() - else: - raise DependencyError('Required dependency %s not provided' % name) + raise DependencyError('Required dependency %s not provided' % name) class dependency(object): diff --git a/ableton/v2/base/disconnectable.py b/ableton/v2/base/disconnectable.py index e0b236bd..a6b2ff74 100644 --- a/ableton/v2/base/disconnectable.py +++ b/ableton/v2/base/disconnectable.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/disconnectable.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/disconnectable.py +from __future__ import absolute_import, print_function from .util import find_if class Disconnectable(object): @@ -23,6 +23,12 @@ def __init__(self, *a, **k): super(CompoundDisconnectable, self).__init__(*a, **k) self._registered_disconnectables = [] + def register_disconnectables(self, disconnectables): + for disconnectable in disconnectables: + self.register_disconnectable(disconnectable) + + return disconnectables + def register_disconnectable(self, slot): if slot not in self._registered_disconnectables: self._registered_disconnectables.append(slot) diff --git a/ableton/v2/base/gcutil.py b/ableton/v2/base/gcutil.py index 5be4e750..26853a0e 100644 --- a/ableton/v2/base/gcutil.py +++ b/ableton/v2/base/gcutil.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/gcutil.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/gcutil.py +from __future__ import absolute_import, print_function from collections import defaultdict import gc @@ -8,7 +9,7 @@ def typename(obj): """ if hasattr(obj, '__class__'): return obj.__class__.__name__ - elif hasattr(obj, '__name__'): + if hasattr(obj, '__name__'): return obj.__name__ return '' diff --git a/ableton/v2/base/live_api_utils.py b/ableton/v2/base/live_api_utils.py index d44e3b1b..b83ce498 100644 --- a/ableton/v2/base/live_api_utils.py +++ b/ableton/v2/base/live_api_utils.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/live_api_utils.py - +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/live_api_utils.py +from __future__ import absolute_import, print_function def liveobj_changed(obj, other): """ diff --git a/ableton/v2/base/proxy.py b/ableton/v2/base/proxy.py index f39d97d1..37e0c042 100644 --- a/ableton/v2/base/proxy.py +++ b/ableton/v2/base/proxy.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/proxy.py -from __future__ import absolute_import, with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/proxy.py +from __future__ import absolute_import, print_function from .util import BooleanContext class ProxyBase(object): diff --git a/ableton/v2/base/signal.py b/ableton/v2/base/signal.py index a86907d1..0d9855cd 100644 --- a/ableton/v2/base/signal.py +++ b/ableton/v2/base/signal.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/signal.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/signal.py +from __future__ import absolute_import, print_function from functools import partial from .util import find_if, nop diff --git a/ableton/v2/base/slot.py b/ableton/v2/base/slot.py index 54bd5c27..2a8c6c9c 100644 --- a/ableton/v2/base/slot.py +++ b/ableton/v2/base/slot.py @@ -1,8 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/slot.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/slot.py """ Family of classes for maintaining connections with optional subjects. """ -from __future__ import absolute_import +from __future__ import absolute_import, print_function from itertools import izip, repeat, chain from functools import partial, wraps from .disconnectable import Disconnectable, CompoundDisconnectable @@ -49,7 +49,7 @@ def set_property_name(self, property_name): self._member_name = '__listenable_property_%s' % property_name def _get_value(self, obj): - raise self._member_name is not None or AssertionError, 'Cannot get member for managed listenable property. Listenable property might be used without inheriting from Subject.' + raise self._member_name is not None or AssertionError('Cannot get member for managed listenable property. Listenable property might be used without inheriting from Subject.') return getattr(obj, self._member_name, self._default_value) def __get__(self, obj, owner): @@ -136,9 +136,9 @@ def __new__(cls, name, bases, dct): events = dct.get('__events__', []) property_events = [ event_name for event_name, obj in listenable_properties ] - if not events: - has_events = property_events - dct['disconnect'] = has_events and 'disconnect' not in dct and (lambda self: super(cls, self).disconnect()) + has_events = events or property_events + if has_events and 'disconnect' not in dct: + dct['disconnect'] = lambda self: super(cls, self).disconnect() cls = super(SubjectMeta, cls).__new__(cls, name, bases, dct) raise not has_events or hasattr(cls, 'disconnect') or AssertionError for lst in chain(events, property_events): @@ -289,10 +289,12 @@ def is_connected(self): return connected - def _get_subject(self): + @property + def subject(self): return self._subject - def _set_subject(self, subject): + @subject.setter + def subject(self, subject): if subject != self._subject: if self.subject_valid(subject): validate_subject_interface(subject, self._event) @@ -300,8 +302,6 @@ def _set_subject(self, subject): self._subject = subject self.connect() - subject = property(_get_subject, _set_subject) - def _get_listener(self): return self._listener @@ -383,15 +383,17 @@ def __init__(self, subject = None, listener = None, event = None, extra_kws = No self._nested_slot = None super(MultiSlot, self).__init__(event=event[0], listener=self._event_fired, subject=subject, function=function, extra_kws=extra_kws, extra_args=extra_args) if len(event) > 1: - self._nested_slot = self.register_disconnectable(MultiSlot(event=event[1:], listener=listener, subject=subject, function=function, extra_kws=extra_kws, extra_args=extra_args)) + self._nested_slot = self.register_disconnectable(MultiSlot(event=event[1:], listener=listener, function=function, extra_kws=extra_kws, extra_args=extra_args)) self._update_nested_subject() - def _get_subject(self): - return super(MultiSlot, self)._get_subject() + @property + def subject(self): + return super(MultiSlot, self).subject - def _set_subject(self, subject): + @subject.setter + def subject(self, subject): try: - super(MultiSlot, self)._set_subject(subject) + super(MultiSlot, MultiSlot).subject.fset(self, subject) except SlotError: if self._nested_slot == None: raise @@ -399,8 +401,6 @@ def _set_subject(self, subject): self._slot_subject = subject self._update_nested_subject() - subject = property(_get_subject, _set_subject) - def _event_fired(self, *a, **k): self._update_nested_subject() self._original_listener(*a, **k) diff --git a/ableton/v2/base/task.py b/ableton/v2/base/task.py index 112ff8e4..1c4c491b 100644 --- a/ableton/v2/base/task.py +++ b/ableton/v2/base/task.py @@ -1,7 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/task.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/task.py """ Task management. """ +from __future__ import absolute_import, print_function import functools import logging import traceback @@ -130,12 +131,14 @@ def __init__(self, func = None, equivalent = None, *a, **k): self._func = func self._equivalent = equivalent - def _set_func(self, func): - self._func = func - - def _get_func(self): + @property + def func(self): return self._orig + @func.setter + def func(self, func): + self._func = func + def do_update(self, timer): super(FuncTask, self).do_update(timer) action = self._func(timer) @@ -147,8 +150,6 @@ def do_update(self, timer): def _task_equivalent(self, other): return self == other or self._func == other or self._equivalent == other - func = property(_get_func, _set_func) - class GeneratorTask(Task): @@ -159,16 +160,18 @@ def __init__(self, generator = None, equivalent = None, *a, **k): raise generator is not None and callable(generator) or AssertionError super(GeneratorTask, self).__init__(*a, **k) self._param = GeneratorTask.Param() - self._set_generator(generator) + self.generator = generator self._equivalent = equivalent - def _set_generator(self, generator): + @property + def generator(self): + return self._orig + + @generator.setter + def generator(self, generator): self._orig = generator self._iter = generator(self._param) - def _get_generator(self): - return self._orig - def do_update(self, delta): super(GeneratorTask, self).do_update(delta) self._param.delta = delta @@ -185,8 +188,6 @@ def do_update(self, delta): def _task_equivalent(self, other): return self == other or self._orig == other or self._equivalent == other - generator = property(_get_generator, _set_generator) - class TaskGroup(Task): auto_kill = True @@ -425,7 +426,7 @@ def sinusoid(f, min = 0.0, max = 1.0, *a, **k): pass def run(func, *a, **k): - return FuncTask(lambda t: None if func(*a, **k) else None) + return FuncTask(lambda t: (None if func(*a, **k) else None)) def repeat(task): diff --git a/ableton/v2/base/util.py b/ableton/v2/base/util.py index 014a5647..bc8c2ba0 100644 --- a/ableton/v2/base/util.py +++ b/ableton/v2/base/util.py @@ -1,11 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/base/util.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/base/util.py """ Various utilities. """ -from __future__ import absolute_import +from __future__ import absolute_import, print_function from contextlib import contextmanager from functools import wraps, partial -from itertools import chain, imap +from itertools import chain, imap, izip_longest def clamp(val, minv, maxv): return max(minv, min(val, maxv)) @@ -33,11 +33,17 @@ def in_range(value, lower_bound, upper_open_bound): def sign(value): - return 1.0 if value >= 0.0 else -1.0 + if value >= 0.0: + return 1.0 + return -1.0 def to_slice(obj): - return obj if isinstance(obj, slice) else (slice(obj, obj + 1) if obj != -1 else slice(obj, None)) + if isinstance(obj, slice): + return obj + if obj != -1: + return slice(obj, obj + 1) + return slice(obj, None) def slice_size(slice, width): @@ -50,7 +56,7 @@ def chunks(l, chunk_size): def maybe(fn): - return lambda x: fn(x) if x is not None else None + return lambda x: (fn(x) if x is not None else None) def memoize(function): @@ -209,7 +215,7 @@ def extended(*a, **k): newfunc = extended else: - raise False or AssertionError, 'Must have something to extend' + raise False or AssertionError('Must have something to extend') setattr(target, patchname, newfunc) return func @@ -348,7 +354,7 @@ def group(lst, n): Returns a list of lists with elements from 'lst' grouped in blocks of 'n' elements. """ - return map(None, *[ lst[i::n] for i in range(n) ]) + return list(izip_longest(*[ lst[i::n] for i in range(n) ])) def find_if(predicate, seq): @@ -435,16 +441,6 @@ def recursive_map(fn, element, sequence_type = None): return fn(element) -def chain_from_iterable(iterables): - """ - Alternate constructor for chain(). Gets chained inputs from a single iterable - argument that is evaluated lazily. - """ - for it in iterables: - for element in it: - yield element - - def is_matrix(iterable): """ Returns True if 'iterable' is a two dimensional iterable where each iterable is @@ -664,7 +660,7 @@ def __getitem__(self, key): new = key if isinstance(key, tuple) else (key,) keys = self._keys + new if not len(keys) <= self._dimensions: - raise AssertionError, 'Too many dimensions' + raise AssertionError('Too many dimensions') return len(keys) == self._dimensions and self._extractor(*keys) else: return Slicer(dimensions=self._dimensions, extractor=self._extractor, keys=keys) @@ -693,7 +689,7 @@ def make_slicer(*a, **k): def print_message(*messages): - print ' '.join(map(str, messages)) + print(' '.join(map(str, messages))) class overlaymap(object): @@ -719,7 +715,7 @@ def __getitem__(self, key): def keys(self): res = set() - for key in chain_from_iterable(self._maps): + for key in chain.from_iterable(self._maps): res.add(key) return list(res) @@ -737,7 +733,7 @@ def trace_value(value, msg = 'Value: '): Prints value and returns value. Useful when debugging the results of sub-expressions. """ - print msg, value + print(msg, value) return value diff --git a/ableton/v2/control_surface/.DS_Store_failed_failed b/ableton/v2/control_surface/.DS_Store_failed_failed new file mode 100644 index 00000000..e69de29b diff --git a/ableton/v2/control_surface/__init__.py b/ableton/v2/control_surface/__init__.py index c24eb96f..760e33b3 100644 --- a/ableton/v2/control_surface/__init__.py +++ b/ableton/v2/control_surface/__init__.py @@ -1,11 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/__init__.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/__init__.py +from __future__ import absolute_import, print_function from .clip_creator import ClipCreator from .component import Component from .compound_component import CompoundComponent from .compound_element import NestedElementClient, CompoundElement from .control_element import ControlElement, ControlElementClient, ElementOwnershipHandler, get_element, NotifyingControlElement, OptimizedOwnershipHandler -from .control_surface import ControlSurface +from .control_surface import ControlSurface, SimpleControlSurface from .device_bank_registry import DeviceBankRegistry from .identifiable_control_surface import IdentifiableControlSurface from .input_control_element import InputControlElement, InputSignal, ParameterSlot, MIDI_CC_TYPE, MIDI_INVALID_TYPE, MIDI_NOTE_TYPE, MIDI_PB_TYPE, MIDI_SYSEX_TYPE @@ -13,44 +13,45 @@ from .midi_map import MidiMap from .resource import Resource, CompoundResource, ExclusiveResource, SharedResource, StackingResource, PrioritizedResource, ProxyResource, DEFAULT_PRIORITY from .skin import SkinColorMissingError, Skin, merge_skins -__all__ = (ClipCreator, +__all__ = (BackgroundLayer, + ClipCreator, Component, CompoundComponent, - NestedElementClient, CompoundElement, + CompoundLayer, + CompoundResource, ControlElement, ControlElementClient, - ElementOwnershipHandler, - get_element, - NotifyingControlElement, - OptimizedOwnershipHandler, ControlSurface, + DEFAULT_PRIORITY, DeviceBankRegistry, + ElementOwnershipHandler, + ExclusiveResource, + get_element, IdentifiableControlSurface, InputControlElement, InputSignal, - ParameterSlot, + Layer, + LayerClient, + LayerError, + merge_skins, + MidiMap, MIDI_CC_TYPE, MIDI_INVALID_TYPE, MIDI_NOTE_TYPE, MIDI_PB_TYPE, MIDI_SYSEX_TYPE, - BackgroundLayer, - CompoundLayer, - Layer, - LayerClient, - LayerError, - SimpleLayerOwner, - UnhandledElementError, - MidiMap, - Resource, - CompoundResource, - ExclusiveResource, - SharedResource, - StackingResource, + NestedElementClient, + NotifyingControlElement, + OptimizedOwnershipHandler, + ParameterSlot, PrioritizedResource, ProxyResource, - DEFAULT_PRIORITY, - SkinColorMissingError, + Resource, + SharedResource, + SimpleControlSurface, + SimpleLayerOwner, Skin, - merge_skins) \ No newline at end of file + SkinColorMissingError, + StackingResource, + UnhandledElementError) \ No newline at end of file diff --git a/ableton/v2/control_surface/capabilities.py b/ableton/v2/control_surface/capabilities.py index ea9982ab..aeb17450 100644 --- a/ableton/v2/control_surface/capabilities.py +++ b/ableton/v2/control_surface/capabilities.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/capabilities.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/capabilities.py +from __future__ import absolute_import, print_function PORTS_KEY = 'ports' CONTROLLER_ID_KEY = 'controller_id' TYPE_KEY = 'surface_type' diff --git a/ableton/v2/control_surface/clip_creator.py b/ableton/v2/control_surface/clip_creator.py index 7fbad1a8..d5ebe262 100644 --- a/ableton/v2/control_surface/clip_creator.py +++ b/ableton/v2/control_surface/clip_creator.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/clip_creator.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/clip_creator.py +from __future__ import absolute_import, print_function import Live _Q = Live.Song.Quantization diff --git a/ableton/v2/control_surface/component.py b/ableton/v2/control_surface/component.py index 4480a877..fa7e4f65 100644 --- a/ableton/v2/control_surface/component.py +++ b/ableton/v2/control_surface/component.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/component.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/component.py +from __future__ import absolute_import, print_function import Live from .control import ControlManager from ..base import depends, lazy_attribute, Subject, task, is_iterable @@ -69,9 +69,9 @@ def _set_enabled_recursive(self, enable): self._update_is_enabled() def _update_is_enabled(self): - if self._recursive_is_enabled: - is_enabled = self._explicit_is_enabled - self._is_enabled = is_enabled != self._is_enabled and is_enabled + is_enabled = self._recursive_is_enabled and self._explicit_is_enabled + if is_enabled != self._is_enabled: + self._is_enabled = is_enabled self._internal_on_enabled_changed() self.on_enabled_changed() self.notify_enabled(is_enabled) @@ -103,22 +103,22 @@ def _tasks(self, parent_task_group = None): self._has_task_group = True return tasks - def _get_layer(self): + @property + def layer(self): return self._layer - def _set_layer(self, new_layer): + @layer.setter + def layer(self, new_layer): if self._layer != new_layer: self._release_all_layers() self._layer = new_layer if self.is_enabled(): self._grab_all_layers() - layer = property(_get_layer, _set_layer) - def _grab_all_layers(self): for layer in self._get_layer_iterable(): grabbed = layer.grab(self) - raise grabbed or AssertionError, 'Only one component can use a layer at atime' + raise grabbed or AssertionError('Only one component can use a layer at atime') def _release_all_layers(self): for layer in self._get_layer_iterable(): @@ -127,14 +127,18 @@ def _release_all_layers(self): def _get_layer_iterable(self): if self._layer is None: return tuple() - return self._layer if is_iterable(self._layer) else (self._layer,) + if is_iterable(self._layer): + return self._layer + return (self._layer,) def is_enabled(self, explicit = False): """ Returns whether the component is enabled. If 'explicit' is True the parent state is ignored. """ - return self._is_enabled if not explicit else self._explicit_is_enabled + if not explicit: + return self._is_enabled + return self._explicit_is_enabled @depends(parent_task_group=None) def _register_timer_callback(self, callback, parent_task_group = None): diff --git a/ableton/v2/control_surface/components/__init__.py b/ableton/v2/control_surface/components/__init__.py index 018075b9..e707556f 100644 --- a/ableton/v2/control_surface/components/__init__.py +++ b/ableton/v2/control_surface/components/__init__.py @@ -1,8 +1,9 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/__init__.py +from __future__ import absolute_import, print_function from .background import BackgroundComponent, ModifierBackgroundComponent from .channel_strip import ChannelStripComponent from .clip_slot import ClipSlotComponent, find_nearest_color -from .device import DeviceComponent +from .device import DeviceComponent, device_to_appoint, select_and_appoint_device from .drum_group import DrumGroupComponent from .m4l_interface import M4LInterfaceComponent from .mixer import MixerComponent, right_align_return_tracks_track_assigner @@ -23,6 +24,7 @@ ChannelStripComponent, ClipSlotComponent, find_nearest_color, + device_to_appoint, DeviceComponent, DrumGroupComponent, M4LInterfaceComponent, @@ -32,6 +34,7 @@ SceneComponent, Scrollable, ScrollComponent, + select_and_appoint_device, SessionComponent, SessionNavigationComponent, SessionRecordingComponent, diff --git a/ableton/v2/control_surface/components/background.py b/ableton/v2/control_surface/components/background.py index 5b8b694b..915f0e4f 100644 --- a/ableton/v2/control_surface/components/background.py +++ b/ableton/v2/control_surface/components/background.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/background.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/background.py +from __future__ import absolute_import, print_function from functools import partial from ..component import Component diff --git a/ableton/v2/control_surface/components/channel_strip.py b/ableton/v2/control_surface/components/channel_strip.py index 686acc74..50c5f0b3 100644 --- a/ableton/v2/control_surface/components/channel_strip.py +++ b/ableton/v2/control_surface/components/channel_strip.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/channel_strip.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/channel_strip.py +from __future__ import absolute_import, print_function from itertools import chain import Live from ...base import nop, listens, liveobj_valid diff --git a/ableton/v2/control_surface/components/clip_slot.py b/ableton/v2/control_surface/components/clip_slot.py index 1d7b995e..f9cf2e5f 100644 --- a/ableton/v2/control_surface/components/clip_slot.py +++ b/ableton/v2/control_surface/components/clip_slot.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/clip_slot.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/clip_slot.py +from __future__ import absolute_import, print_function import Live from ...base import in_range, listens, liveobj_valid from ..component import Component @@ -134,16 +134,19 @@ def _feedback_value(self): track = self._clip_slot.canonical_parent slot_or_clip = self._clip_slot.clip if self.has_clip() else self._clip_slot if slot_or_clip.is_triggered: - return self._triggered_to_record_value if slot_or_clip.will_record_on_start else self._triggered_to_play_value - elif slot_or_clip.is_playing: - return self._recording_value if slot_or_clip.is_recording else self._started_value - elif slot_or_clip.color != None: + if slot_or_clip.will_record_on_start: + return self._triggered_to_record_value + return self._triggered_to_play_value + if slot_or_clip.is_playing: + if slot_or_clip.is_recording: + return self._recording_value + return self._started_value + if slot_or_clip.color != None: return self._color_value(slot_or_clip) - elif getattr(slot_or_clip, 'controls_other_clips', True) and self._stopped_value != None: + if getattr(slot_or_clip, 'controls_other_clips', True) and self._stopped_value != None: return self._stopped_value - elif self._track_is_armed(track) and self._clip_slot.has_stop_button: - if self._record_button_value != None: - return self._record_button_value + if self._track_is_armed(track) and self._clip_slot.has_stop_button and self._record_button_value != None: + return self._record_button_value def _update_clip_property_slots(self): clip = self._clip_slot.clip if self._clip_slot else None @@ -239,14 +242,14 @@ def _do_duplicate_clip(self): def _do_launch_clip(self, value): button = self.__launch_button_value.subject object_to_launch = self._clip_slot - if not value: - launch_pressed = not button.is_momentary() - if self.has_clip(): - object_to_launch = self._clip_slot.clip - else: - self._has_fired_slot = True - if button.is_momentary(): - object_to_launch.set_fire_button_state(value != 0) - elif launch_pressed: - object_to_launch.fire() - self.song.view.highlighted_clip_slot = launch_pressed and self.has_clip() and self.song.select_on_launch and self._clip_slot \ No newline at end of file + launch_pressed = value or not button.is_momentary() + if self.has_clip(): + object_to_launch = self._clip_slot.clip + else: + self._has_fired_slot = True + if button.is_momentary(): + object_to_launch.set_fire_button_state(value != 0) + elif launch_pressed: + object_to_launch.fire() + if launch_pressed and self.has_clip() and self.song.select_on_launch: + self.song.view.highlighted_clip_slot = self._clip_slot \ No newline at end of file diff --git a/ableton/v2/control_surface/components/device.py b/ableton/v2/control_surface/components/device.py index 3c23f7ed..e5a14bce 100644 --- a/ableton/v2/control_surface/components/device.py +++ b/ableton/v2/control_surface/components/device.py @@ -1,89 +1,198 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/device.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/device.py +from __future__ import absolute_import, print_function import Live from _Generic.Devices import best_of_parameter_bank, device_parameters_to_map, number_of_parameter_banks, parameter_bank_names, parameter_banks -from ...base import listens, listens_group, liveobj_changed, liveobj_valid, Subject +from ...base import depends, listenable_property, listens, listens_group, liveobj_changed, liveobj_valid, SlotManager, Subject from ..component import Component -from ..device_bank_registry import DeviceBankRegistry -from ..elements import ButtonElement, DisplayDataSource +from ..elements import DisplayDataSource + +def device_to_appoint(device): + appointed_device = device + if liveobj_valid(device) and device.can_have_drum_pads and not device.has_macro_mappings and len(device.chains) > 0 and liveobj_valid(device.view.selected_chain) and len(device.view.selected_chain.devices) > 0: + appointed_device = device_to_appoint(device.view.selected_chain.devices[0]) + return appointed_device + + +def select_and_appoint_device(song, device_to_select, ignore_unmapped_macros = True): + """ + Convenience function for selecting a device for a control surface to control. + + This takes care of selecting the device and appointing it for remote control, which + is important, because these are two concepts, that are not exactly the same. + + The device component always controls the appointed device. It's possible to select + another device, but not appoint it for control. The behaviour in this function + appoints a drum rack's selected chain's first device if none of the macros are mapped + for the drum rack. Though, it's still possible to select the drum rack, we just do + not display its controls in this scenario. + """ + appointed_device = device_to_select + if ignore_unmapped_macros: + appointed_device = device_to_appoint(device_to_select) + song.view.select_device(device_to_select, False) + song.appointed_device = appointed_device + + +class DeviceProvider(Subject, SlotManager): + """ + Provide "controlled device" to device component + + This class abstracts the logic required to provide a controlled device to be used + by the device component. In most cases, this is the same as the appointed device, but + not always, e.g. when a surface is locked to a device (there is only one global + appointed device per Song). + + This class also takes care of appointing the right device when switching between + tracks etc. + """ + device_selection_follows_track_selection = True + + def __init__(self, song = None, *a, **k): + super(DeviceProvider, self).__init__(*a, **k) + self._device = None + self._locked_to_device = False + self.song = song + self.__on_appointed_device_changed.subject = song + self.__on_selected_track_changed.subject = song.view + self.__on_selected_device_changed.subject = song.view.selected_track.view + + @listenable_property + def device(self): + return self._device + + @device.setter + def device(self, device): + if liveobj_changed(self._device, device) and not self.is_locked_to_device: + self._device = device + self.notify_device() + + @listenable_property + def is_locked_to_device(self): + """ + Indicates whether the provider is currently locked to a device. + """ + return self._locked_to_device + + def lock_to_device(self, device): + self.device = device + self._locked_to_device = True + self.notify_is_locked_to_device() + + def unlock_from_device(self): + self._locked_to_device = False + self.notify_is_locked_to_device() + + def update_device_selection(self): + view = self.song.view + track_or_chain = view.selected_chain if view.selected_chain else view.selected_track + device_to_select = None + if isinstance(track_or_chain, Live.Track.Track): + device_to_select = track_or_chain.view.selected_device + if device_to_select == None and len(track_or_chain.devices) > 0: + device_to_select = track_or_chain.devices[0] + if liveobj_valid(device_to_select): + appointed_device = device_to_appoint(device_to_select) + self.song.view.select_device(device_to_select, False) + self.song.appointed_device = appointed_device + self.device = appointed_device + else: + self.song.appointed_device = None + self.device = None + + @listens('appointed_device') + def __on_appointed_device_changed(self): + self.device = device_to_appoint(self.song.appointed_device) + + @listens('has_macro_mappings') + def __on_has_macro_mappings_changed(self): + self.song.appointed_device = device_to_appoint(self.song.view.selected_track.view.selected_device) + + @listens('selected_track') + def __on_selected_track_changed(self): + self.__on_selected_device_changed.subject = self.song.view.selected_track.view + if self.device_selection_follows_track_selection: + self.update_device_selection() -class DeviceComponent(Component, Subject): + @listens('selected_device') + def __on_selected_device_changed(self): + self._update_appointed_device() + + @listens('chains') + def __on_chains_changed(self): + self._update_appointed_device() + + def _update_appointed_device(self): + song = self.song + device = song.view.selected_track.view.selected_device + if liveobj_valid(device): + self.song.appointed_device = device_to_appoint(device) + rack_device = device if isinstance(device, Live.RackDevice.RackDevice) else None + self.__on_has_macro_mappings_changed.subject = rack_device + self.__on_chains_changed.subject = rack_device + + +class DeviceComponent(Component): """ Class representing a device in Live """ - __events__ = ('device',) - def __init__(self, device_bank_registry = None, *a, **k): + @depends(device_bank_registry=None) + @depends(device_provider=None) + def __init__(self, device_provider = None, device_bank_registry = None, *a, **k): + raise device_bank_registry is not None or AssertionError super(DeviceComponent, self).__init__(*a, **k) - self._device_bank_registry = device_bank_registry or DeviceBankRegistry() - self._device = None + self._device_bank_registry = device_bank_registry + self._device_provider = device_provider self._parameter_controls = None self._bank_up_button = None self._bank_down_button = None self._bank_buttons = None self._on_off_button = None - self._lock_button = None - self._lock_callback = None self._device_name_data_source = None self._bank_index = 0 self._bank_name = '' - self._locked_to_device = False - - def make_property_slot(name, alias = None): - alias = alias or name - return self.register_slot(None, getattr(self, '_on_%s_changed' % alias), name) - - self._on_off_property_slot = make_property_slot('value', alias='device_on_off') - self._name_property_slot = make_property_slot('name', alias='device_name') - self._parameters_property_slot = make_property_slot('parameters') - self._device_bank_property_slot = make_property_slot('device_bank') def make_button_slot(name): return self.register_slot(None, getattr(self, '_%s_value' % name), 'value') self._bank_up_button_slot = make_button_slot('bank_up') self._bank_down_button_slot = make_button_slot('bank_down') - self._lock_button_slot = make_button_slot('lock') self._on_off_button_slot = make_button_slot('on_off') - self._device_bank_property_slot.subject = self._device_bank_registry - self._device_selection_follows_track_selection = False - self.__on_selected_track_changed.subject = self.song.view + self.__on_device_bank_changed.subject = self._device_bank_registry + self.__on_provided_device_changed.subject = self._device_provider + self.__on_provided_device_changed() def disconnect(self): self._device_bank_registry = None - self._lock_callback = None self._release_parameters(self._parameter_controls) self._parameter_controls = None self._bank_up_button = None self._bank_down_button = None self._bank_buttons = None self._on_off_button = None - self._lock_button = None - self._device = None + self._device_provider = None super(DeviceComponent, self).disconnect() + def _get_device(self): + return self._device_provider.device + def on_enabled_changed(self): self.update() - def device(self): - return self._device - - def set_device(self, device): - if self._device_changed(device): - if liveobj_valid(device): - self._release_parameters(self._parameter_controls) - self._device = device - self._name_property_slot.subject = device - self._parameters_property_slot.subject = device - self._on_off_property_slot.subject = self._on_off_parameter() - if liveobj_valid(self._device): - self._bank_index = 0 - self._bank_index = self._device_bank_registry.get_device_bank(self._device) - self._bank_name = '' - self._on_device_name_changed() - self.update() - self.notify_device() + @listens('device') + def __on_provided_device_changed(self): + self._on_device_changed(self._get_device()) - def _device_changed(self, device): - return not self._locked_to_device and liveobj_changed(self._device, device) + def _on_device_changed(self, device): + if liveobj_valid(device): + self._release_parameters(self._parameter_controls) + self.__on_device_name_changed.subject = device + self.__on_parameters_changed.subject = device + self.__on_device_on_off_changed.subject = self._on_off_parameter() + if liveobj_valid(device): + self._bank_index = 0 + self._bank_index = self._device_bank_registry.get_device_bank(device) + self._bank_name = '' + self.__on_device_name_changed() + self.update() def set_bank_prev_button(self, button): if button != self._bank_down_button: @@ -111,51 +220,30 @@ def set_parameter_controls(self, controls): self._parameter_controls = controls self.update() - def set_lock_to_device(self, lock, device): - if lock: - self.set_device(device) - self._locked_to_device = lock - self._update_lock_button() - - def set_lock_button(self, button): - raise button == None or isinstance(button, ButtonElement) or AssertionError - self._lock_button = button - self._lock_button_slot.subject = button - self._update_lock_button() - def set_on_off_button(self, button): self._on_off_button = button self._on_off_button_slot.subject = button self._update_on_off_button() - def set_lock_callback(self, callback): - self._lock_callback = callback - - def restore_bank(self, bank_index): - if liveobj_valid(self._device) and self._is_banking_enabled() and self._locked_to_device and self._number_of_parameter_banks() > bank_index and self._bank_index != bank_index: - self._bank_index = bank_index - self.update() - def device_name_data_source(self): if self._device_name_data_source == None: self._device_name_data_source = DisplayDataSource() - self._on_device_name_changed() + self.__on_device_name_changed() return self._device_name_data_source def update(self): super(DeviceComponent, self).update() - if self.is_enabled() and liveobj_valid(self._device): - self._device_bank_registry.set_device_bank(self._device, self._bank_index) + if self.is_enabled() and liveobj_valid(self._get_device()): + self._device_bank_registry.set_device_bank(self._get_device(), self._bank_index) if self._parameter_controls != None: old_bank_name = self._bank_name self._assign_parameters() if self._bank_name != old_bank_name: - self._show_msg_callback(self._device.name + ' Bank: ' + self._bank_name) + self._show_msg_callback(self._get_device().name + ' Bank: ' + self._bank_name) elif self._parameter_controls != None: self._release_parameters(self._parameter_controls) if self.is_enabled(): self._update_on_off_button() - self._update_lock_button() self._update_device_bank_buttons() self._update_device_bank_nav_buttons() @@ -165,7 +253,7 @@ def _bank_up_value(self, value): raise isinstance(value, int) or AssertionError if self.is_enabled(): if not self._bank_up_button.is_momentary() or value is not 0: - if liveobj_valid(self._device): + if liveobj_valid(self._get_device()): num_banks = self._number_of_parameter_banks() if self._bank_down_button == None: self._bank_name = '' @@ -183,18 +271,10 @@ def _bank_down_value(self, value): if not isinstance(value, int): raise AssertionError if self.is_enabled(): - self._bank_name = (not self._bank_down_button.is_momentary() or value is not 0) and liveobj_valid(self._device) and (self._bank_index == None or self._bank_index > 0) and '' + self._bank_name = (not self._bank_down_button.is_momentary() or value is not 0) and liveobj_valid(self._get_device()) and (self._bank_index == None or self._bank_index > 0) and '' self._bank_index = self._bank_index - 1 if self._bank_index != None else max(0, self._number_of_parameter_banks() - 1) self.update() - def _lock_value(self, value): - if not self._lock_button != None: - raise AssertionError - raise self._lock_callback != None or AssertionError - raise value != None or AssertionError - raise isinstance(value, int) or AssertionError - (not self._lock_button.is_momentary() or value is not 0) and self._lock_callback() - def _on_off_value(self, value): if not self._on_off_button != None: raise AssertionError @@ -208,7 +288,7 @@ def __on_bank_value(self, value, button): self._bank_value(value, button) def _bank_value(self, value, button): - if self.is_enabled() and liveobj_valid(self._device): + if self.is_enabled() and liveobj_valid(self._get_device()): if not button.is_momentary() or value is not 0: bank = list(self._bank_buttons).index(button) if bank != self._bank_index: @@ -217,7 +297,7 @@ def _bank_value(self, value, button): self._bank_index = bank self.update() else: - self._show_msg_callback(self._device.name + ' Bank: ' + self._bank_name) + self._show_msg_callback(self._get_device().name + ' Bank: ' + self._bank_name) def _is_banking_enabled(self): direct_banking = self._bank_buttons != None @@ -227,7 +307,7 @@ def _is_banking_enabled(self): def _assign_parameters(self): raise self.is_enabled() or AssertionError - raise liveobj_valid(self._device) or AssertionError + raise liveobj_valid(self._get_device()) or AssertionError raise self._parameter_controls != None or AssertionError self._bank_name, bank = self._current_bank_details() for control, parameter in zip(self._parameter_controls, bank): @@ -239,20 +319,23 @@ def _assign_parameters(self): self._release_parameters(self._parameter_controls[len(bank):]) - def _on_device_on_off_changed(self): + @listens('value') + def __on_device_on_off_changed(self): self._update_on_off_button() - def _on_device_name_changed(self): + @listens('name') + def __on_device_name_changed(self): if self._device_name_data_source != None: - self._device_name_data_source.set_display_string(self._device.name if self.is_enabled() and liveobj_valid(self._device) else 'No Device') + self._device_name_data_source.set_display_string(self._get_device().name if self.is_enabled() and liveobj_valid(self._get_device()) else 'No Device') - def _on_parameters_changed(self): + @listens('parameters') + def __on_parameters_changed(self): self.update() def _on_off_parameter(self): result = None - if liveobj_valid(self._device): - for parameter in self._device.parameters: + if liveobj_valid(self._get_device()): + for parameter in self._get_device().parameters: if str(parameter.name).startswith('Device On'): result = parameter break @@ -262,70 +345,39 @@ def _on_off_parameter(self): def _update_on_off_button(self): if self.is_enabled() and self._on_off_button != None: turn_on = False - if liveobj_valid(self._device): + if liveobj_valid(self._get_device()): parameter = self._on_off_parameter() turn_on = parameter != None and parameter.value > 0.0 self._on_off_button.set_light(turn_on) - def _update_lock_button(self): - if self.is_enabled() and self._lock_button != None: - self._lock_button.set_light(self._locked_to_device) - def _update_device_bank_buttons(self): if self.is_enabled(): for index, button in enumerate(self._bank_buttons or []): if button: - button.set_light(index == self._bank_index and self._device) + button.set_light(index == self._bank_index and self._get_device()) def _update_device_bank_nav_buttons(self): if self.is_enabled(): if self._bank_up_button != None and self._bank_down_button != None: can_bank_up = self._bank_index == None or self._number_of_parameter_banks() > self._bank_index + 1 can_bank_down = self._bank_index == None or self._bank_index > 0 - self._bank_up_button.set_light(self._device and can_bank_up) - self._bank_down_button.set_light(self._device and can_bank_down) - - def _get_follow_track_selection(self): - return self._device_selection_follows_track_selection - - def _set_follow_track_selection(self, value): - self._device_selection_follows_track_selection = value - - device_selection_follows_track_selection = property(_get_follow_track_selection, _set_follow_track_selection) - - @listens('selected_track') - def __on_selected_track_changed(self): - if self._device_selection_follows_track_selection: - self.update_device_selection() - - def update_device_selection(self): - view = self.song.view - track_or_chain = view.selected_chain if view.selected_chain else view.selected_track - device_to_select = None - if isinstance(track_or_chain, Live.Track.Track): - device_to_select = track_or_chain.view.selected_device - if device_to_select == None and len(track_or_chain.devices) > 0: - device_to_select = track_or_chain.devices[0] - if liveobj_valid(device_to_select): - self.song.view.select_device(device_to_select) - self.set_device(self.song.appointed_device) - else: - self.set_device(None) + self._bank_up_button.set_light(self._get_device() and can_bank_up) + self._bank_down_button.set_light(self._get_device() and can_bank_down) def _best_of_parameter_bank(self): - return best_of_parameter_bank(self._device) + return best_of_parameter_bank(self._get_device()) def _parameter_banks(self): - return parameter_banks(self._device) + return parameter_banks(self._get_device()) def _parameter_bank_names(self): - return parameter_bank_names(self._device) + return parameter_bank_names(self._get_device()) def _device_parameters_to_map(self): - return device_parameters_to_map(self._device) + return device_parameters_to_map(self._get_device()) def _number_of_parameter_banks(self): - return number_of_parameter_banks(self._device) + return number_of_parameter_banks(self._get_device()) def _current_bank_details(self): bank_name = self._bank_name @@ -342,9 +394,10 @@ def _current_bank_details(self): bank_name = 'Best of Parameters' return (bank_name, bank) - def _on_device_bank_changed(self, device, bank): - if device == self._device: - self._bank_index = bank + @listens('device_bank') + def __on_device_bank_changed(self, device, new_bank_index): + if device == self._get_device() and new_bank_index != self._bank_index and self._number_of_parameter_banks() > new_bank_index: + self._bank_index = new_bank_index self.update() def _release_parameters(self, controls): diff --git a/ableton/v2/control_surface/components/drum_group.py b/ableton/v2/control_surface/components/drum_group.py index 6286e9ec..469ea30d 100644 --- a/ableton/v2/control_surface/components/drum_group.py +++ b/ableton/v2/control_surface/components/drum_group.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/drum_group.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/drum_group.py +from __future__ import absolute_import, print_function from itertools import imap from ...base import depends, find_if, first, clamp, listens_group, listens, liveobj_valid from ..control import ButtonControl @@ -39,18 +39,18 @@ def contents(self, index): return any(imap(lambda pad: pad.chains, drum.drum_pads[index * 4:index * 4 + 4])) return False - def _get_position(self): + @property + def position(self): if liveobj_valid(self._drum_group_device): return self._drum_group_device.view.drum_pads_scroll_position return 0 - def _set_position(self, index): + @position.setter + def position(self, index): if not 0 <= index <= 28: raise AssertionError self._drum_group_device.view.drum_pads_scroll_position = liveobj_valid(self._drum_group_device) and index - position = property(_get_position, _set_position) - @property def assigned_drum_pads(self): return self._assigned_drum_pads @@ -216,7 +216,9 @@ def has_assigned_pads(self): def _pad_for_button(self, button): if self.has_assigned_pads: index = self._button_coordinates_to_pad_index(first(self._assigned_drum_pads).note, button.coordinate) - return self._all_drum_pads[index] if index < 128 else None + if index < 128: + return self._all_drum_pads[index] + return None def _note_translation_for_button(self, button): identifier = None diff --git a/ableton/v2/control_surface/components/m4l_interface.py b/ableton/v2/control_surface/components/m4l_interface.py index 6e061ba9..56fd88b6 100644 --- a/ableton/v2/control_surface/components/m4l_interface.py +++ b/ableton/v2/control_surface/components/m4l_interface.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/m4l_interface.py -from __future__ import absolute_import, with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/m4l_interface.py +from __future__ import absolute_import, print_function from ..control_element import ControlElementClient from ..component import Component @@ -31,7 +31,8 @@ def get_control_names(self): return self._controls.keys() def get_control(self, control_name): - return self._controls[control_name] if control_name in self._controls else None + if control_name in self._controls: + return self._controls[control_name] def grab_control(self, control): raise control in self._controls.values() or AssertionError diff --git a/ableton/v2/control_surface/components/mixer.py b/ableton/v2/control_surface/components/mixer.py index a50074c7..d33c3477 100644 --- a/ableton/v2/control_surface/components/mixer.py +++ b/ableton/v2/control_surface/components/mixer.py @@ -1,6 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/mixer.py -from __future__ import absolute_import -from itertools import izip +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/mixer.py +from __future__ import absolute_import, print_function +from itertools import izip, izip_longest from ...base import clamp, listens, liveobj_valid from ..compound_component import CompoundComponent from .channel_strip import ChannelStripComponent, release_control @@ -78,10 +78,12 @@ def disconnect(self): self._prehear_volume_control = None self._crossfader_control = None - def _get_send_index(self): + @property + def send_index(self): return self._send_index - def _set_send_index(self, index): + @send_index.setter + def send_index(self, index): if 0 <= index < self.num_sends or index is None: if self._send_index != index: self._send_index = index @@ -90,8 +92,6 @@ def _set_send_index(self, index): else: raise IndexError - send_index = property(_get_send_index, _set_send_index) - def on_send_index_changed(self): pass @@ -120,35 +120,35 @@ def set_crossfader_control(self, control): self.update() def set_volume_controls(self, controls): - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): strip.set_volume_control(control) def set_pan_controls(self, controls): - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): strip.set_pan_control(control) def set_send_controls(self, controls): self._send_controls = controls - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): if self._send_index is None: strip.set_send_controls(None) else: strip.set_send_controls((None,) * self._send_index + (control,)) def set_arm_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): strip.set_arm_button(button) def set_solo_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): strip.set_solo_button(button) def set_mute_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): strip.set_mute_button(button) def set_track_select_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): strip.set_select_button(button) def set_shift_button(self, button): diff --git a/ableton/v2/control_surface/components/playable.py b/ableton/v2/control_surface/components/playable.py index 1be05be8..994bc692 100644 --- a/ableton/v2/control_surface/components/playable.py +++ b/ableton/v2/control_surface/components/playable.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/playable.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/playable.py +from __future__ import absolute_import, print_function from .. import Component from ..control import PlayableControl, ButtonControl, control_matrix @@ -100,11 +100,15 @@ def update(self): @property def width(self): - return self.matrix.width if self.matrix.width else 4 + if self.matrix.width: + return self.matrix.width + return 4 @property def height(self): - return self.matrix.height if self.matrix.height else 4 + if self.matrix.height: + return self.matrix.height + return 4 @property def pressed_pads(self): diff --git a/ableton/v2/control_surface/components/scene.py b/ableton/v2/control_surface/components/scene.py index 5bda4e3d..ef837717 100644 --- a/ableton/v2/control_surface/components/scene.py +++ b/ableton/v2/control_surface/components/scene.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/scene.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/scene.py +from __future__ import absolute_import, print_function from itertools import izip from ...base import in_range, listens, liveobj_valid, liveobj_changed from ..compound_component import CompoundComponent diff --git a/ableton/v2/control_surface/components/scroll.py b/ableton/v2/control_surface/components/scroll.py index dacb4dd6..089fbbb9 100644 --- a/ableton/v2/control_surface/components/scroll.py +++ b/ableton/v2/control_surface/components/scroll.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/scroll.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/scroll.py +from __future__ import absolute_import, print_function from ...base import task from .. import defaults from ..control import ButtonControl @@ -50,15 +50,15 @@ def _make_scroll_task(self, scroll_step): t.kill() return t - def _get_scrollable(self): + @property + def scrollable(self): return self._scrollable - def _set_scrollable(self, scrollable): + @scrollable.setter + def scrollable(self, scrollable): self._scrollable = scrollable self._update_scroll_buttons() - scrollable = property(_get_scrollable, _set_scrollable) - def can_scroll_up(self): return self._scrollable.can_scroll_up() @@ -112,11 +112,11 @@ def update(self): self._update_scroll_buttons() def _on_scroll_pressed(self, button, scroll_step, scroll_task): - if not not self._scroll_task_up.is_killed: - is_scrolling = not self._scroll_task_down.is_killed - if not is_scrolling: - scroll_step() - button.enabled and scroll_task.restart() + is_scrolling = not self._scroll_task_up.is_killed or not self._scroll_task_down.is_killed + if not is_scrolling: + scroll_step() + if button.enabled: + scroll_task.restart() self._ensure_scroll_one_direction() def _on_scroll_released(self, scroll_task): diff --git a/ableton/v2/control_surface/components/session.py b/ableton/v2/control_surface/components/session.py index fff462fc..0783c07b 100644 --- a/ableton/v2/control_surface/components/session.py +++ b/ableton/v2/control_surface/components/session.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/session.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/session.py +from __future__ import absolute_import, print_function import Live from itertools import count from ...base import in_range, product, listens, listens_group @@ -201,7 +201,7 @@ def _reassign_scenes(self): def _reassign_tracks(self): tracks_to_use = self._session_ring.tracks_to_use() - tracks = map(lambda t: t if isinstance(t, Live.Track.Track) else None, tracks_to_use) + tracks = map(lambda t: (t if isinstance(t, Live.Track.Track) else None), tracks_to_use) self.__on_fired_slot_index_changed.replace_subjects(tracks, count()) self.__on_playing_slot_index_changed.replace_subjects(tracks, count()) self._update_stop_all_clips_button() @@ -239,11 +239,11 @@ def __on_playing_slot_index_changed(self, track_index): def _update_stop_clips_led(self, index): tracks_to_use = self._session_ring.tracks_to_use() track_index = index + self._session_ring.track_offset - button = self.is_enabled() and self._stop_track_clip_buttons != None and index < len(self._stop_track_clip_buttons) and self._stop_track_clip_buttons[index] - if button != None: - value_to_send = None - if track_index < len(tracks_to_use): - if tracks_to_use[track_index].clip_slots: + if self.is_enabled() and self._stop_track_clip_buttons != None and index < len(self._stop_track_clip_buttons): + button = self._stop_track_clip_buttons[index] + if button != None: + value_to_send = None + if track_index < len(tracks_to_use) and tracks_to_use[track_index].clip_slots: track = tracks_to_use[track_index] if track.fired_slot_index == -2: value_to_send = self._stop_clip_triggered_value diff --git a/ableton/v2/control_surface/components/session_navigation.py b/ableton/v2/control_surface/components/session_navigation.py index 08abd222..9035f990 100644 --- a/ableton/v2/control_surface/components/session_navigation.py +++ b/ableton/v2/control_surface/components/session_navigation.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/session_navigation.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/session_navigation.py +from __future__ import absolute_import, print_function from ...base import listens from ..compound_component import CompoundComponent from .scroll import ScrollComponent diff --git a/ableton/v2/control_surface/components/session_overview.py b/ableton/v2/control_surface/components/session_overview.py index bbeb4cc2..a1cb28fe 100644 --- a/ableton/v2/control_surface/components/session_overview.py +++ b/ableton/v2/control_surface/components/session_overview.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/session_overview.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/session_overview.py +from __future__ import absolute_import, print_function from ...base import in_range, listens, liveobj_valid from ..component import Component @@ -83,12 +83,12 @@ def _update_matrix_buttons(self): playing = False for track in xrange(track_offset, track_offset + width): for scene in xrange(scene_offset, scene_offset + height): - if track in xrange(len(tracks)): - if scene in xrange(len(scenes)): - if not liveobj_valid(slots_registry[scene]): - slots_registry[scene] = scenes[scene].clip_slots - slot = slots_registry[scene][track] if len(slots_registry[scene]) > track else None - value_to_send = liveobj_valid(slot) and slot.has_clip and slot.clip.is_playing and self._playing_value + if track in xrange(len(tracks)) and scene in xrange(len(scenes)): + if not liveobj_valid(slots_registry[scene]): + slots_registry[scene] = scenes[scene].clip_slots + slot = slots_registry[scene][track] if len(slots_registry[scene]) > track else None + if liveobj_valid(slot) and slot.has_clip and slot.clip.is_playing: + value_to_send = self._playing_value playing = True break diff --git a/ableton/v2/control_surface/components/session_recording.py b/ableton/v2/control_surface/components/session_recording.py index 183d14c8..c1057a0b 100644 --- a/ableton/v2/control_surface/components/session_recording.py +++ b/ableton/v2/control_surface/components/session_recording.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/session_recording.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/session_recording.py +from __future__ import absolute_import, print_function import Live from ...base import find_if, listens, liveobj_valid from ..compound_component import CompoundComponent @@ -54,6 +54,7 @@ def __init__(self, clip_creator = None, view_controller = None, *a, **k): self._reconnect_track_listeners() self.register_slot(song, self.update, 'overdub') self.register_slot(song, self.update, 'session_record_status') + self.register_slot(song, self._update_record_button, 'session_record') self.register_slot(song.view, self.update, 'selected_track') self.register_slot(song.view, self.update, 'selected_scene') self.register_slot(song.view, self.update, 'detail_clip') @@ -169,9 +170,9 @@ def _delete_automation_value(self): if self.is_enabled(): clip = self._get_playing_clip() selected_track = self.song.view.selected_track - if selected_track: - track_frozen = selected_track.is_frozen - clip and not track_frozen and clip.clear_all_envelopes() + track_frozen = selected_track and selected_track.is_frozen + if clip and not track_frozen: + clip.clear_all_envelopes() self._update_delete_automation_button_color() def _get_playing_clip(self): @@ -285,9 +286,9 @@ def _stop_recording(self): was any recording at all """ song = self.song status = song.session_record_status - if not status != Live.Song.SessionRecordStatus.off: - was_recording = song.session_record - song.session_record = was_recording and False + was_recording = status != Live.Song.SessionRecordStatus.off or song.session_record + if was_recording: + song.session_record = False return was_recording def _start_recording(self): @@ -322,11 +323,11 @@ def _reconnect_track_listeners(self): manager.register_slot(track, self.update, 'playing_slot_index') manager.register_slot(track, self.update, 'fired_slot_index') - def _set_scene_list_mode(self, scene_list_mode): - self._scene_list_mode = scene_list_mode - self._update_new_button() - - def _get_scene_list_mode(self): + @property + def scene_list_mode(self): return self._scene_list_mode - scene_list_mode = property(_get_scene_list_mode, _set_scene_list_mode) \ No newline at end of file + @scene_list_mode.setter + def scene_list_mode(self, scene_list_mode): + self._scene_list_mode = scene_list_mode + self._update_new_button() \ No newline at end of file diff --git a/ableton/v2/control_surface/components/session_ring.py b/ableton/v2/control_surface/components/session_ring.py index 3a6c29c6..69de4941 100644 --- a/ableton/v2/control_surface/components/session_ring.py +++ b/ableton/v2/control_surface/components/session_ring.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/session_ring.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/session_ring.py +from __future__ import absolute_import, print_function from ...base import const, depends, nop, listens from ..component import Component @@ -90,22 +90,22 @@ def controlled_tracks(self): index = self.track_offset return self.tracks_to_use()[index:index + self.num_tracks] - def _get_track_offset(self): + @property + def track_offset(self): return self._session_ring.track_offset - def _set_track_offset(self, offset): + @track_offset.setter + def track_offset(self, offset): self.set_offsets(offset, self.scene_offset) - track_offset = property(_get_track_offset, _set_track_offset) - - def _get_scene_offset(self): + @property + def scene_offset(self): return self._session_ring.scene_offset - def _set_scene_offset(self, offset): + @scene_offset.setter + def scene_offset(self, offset): self.set_offsets(self.track_offset, offset) - scene_offset = property(_get_scene_offset, _set_scene_offset) - @property def num_tracks(self): return self._session_ring.num_tracks diff --git a/ableton/v2/control_surface/components/slide.py b/ableton/v2/control_surface/components/slide.py index bf832496..1900eae7 100644 --- a/ableton/v2/control_surface/components/slide.py +++ b/ableton/v2/control_surface/components/slide.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/slide.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/slide.py +from __future__ import absolute_import, print_function from ...base import clamp, listens, Subject from ..compound_component import CompoundComponent from .scroll import ScrollComponent, Scrollable diff --git a/ableton/v2/control_surface/components/toggle.py b/ableton/v2/control_surface/components/toggle.py index c8f44c9b..5f768472 100644 --- a/ableton/v2/control_surface/components/toggle.py +++ b/ableton/v2/control_surface/components/toggle.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/toggle.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/toggle.py +from __future__ import absolute_import, print_function from ...base import listens from ..component import Component @@ -32,23 +32,24 @@ def model_transform(self, value): def view_transform(self, value): return value - def _get_subject(self): + @property + def subject(self): return self._property_slot.subject - def _set_subject(self, model): + @subject.setter + def subject(self, model): self._property_slot.subject = model self.update() - subject = property(_get_subject, _set_subject) + @property + def value(self): + if self.subject: + return getattr(self.subject, self._property_name) - def _get_value(self): - return getattr(self.subject, self._property_name) if self.subject else None - - def _set_value(self, value): + @value.setter + def value(self, value): setattr(self.subject, self._property_name, value) - value = property(_get_value, _set_value) - def set_toggle_button(self, button): raise button is None or not self.is_momentary or button.is_momentary() or AssertionError self.__on_button_value.subject = button diff --git a/ableton/v2/control_surface/components/transport.py b/ableton/v2/control_surface/components/transport.py index 7b4dc21e..5e3542f0 100644 --- a/ableton/v2/control_surface/components/transport.py +++ b/ableton/v2/control_surface/components/transport.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/transport.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/transport.py +from __future__ import absolute_import, print_function from functools import partial import Live from ...base import in_range, clamp, listens, task diff --git a/ableton/v2/control_surface/components/view_control.py b/ableton/v2/control_surface/components/view_control.py index ef8599ec..22d97cd4 100644 --- a/ableton/v2/control_surface/components/view_control.py +++ b/ableton/v2/control_surface/components/view_control.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/components/view_control.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/components/view_control.py +from __future__ import absolute_import, print_function import Live from ...base import depends, in_range, liveobj_valid from ..compound_component import CompoundComponent diff --git a/ableton/v2/control_surface/compound_component.py b/ableton/v2/control_surface/compound_component.py index 7b0a28d6..439869eb 100644 --- a/ableton/v2/control_surface/compound_component.py +++ b/ableton/v2/control_surface/compound_component.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/compound_component.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/compound_component.py +from __future__ import absolute_import, print_function from .component import Component class CompoundComponent(Component): diff --git a/ableton/v2/control_surface/compound_element.py b/ableton/v2/control_surface/compound_element.py index ec87abcc..d6992329 100644 --- a/ableton/v2/control_surface/compound_element.py +++ b/ableton/v2/control_surface/compound_element.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/compound_element.py -from __future__ import absolute_import, with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/compound_element.py +from __future__ import absolute_import, print_function from itertools import ifilter from .control_element import ControlElementClient, NotifyingControlElement from ..base import BooleanContext, first, second, SlotManager, listens_group diff --git a/ableton/v2/control_surface/control/__init__.py b/ableton/v2/control_surface/control/__init__.py index 34c962d7..edca84bd 100644 --- a/ableton/v2/control_surface/control/__init__.py +++ b/ableton/v2/control_surface/control/__init__.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control/__init__.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control/__init__.py +from __future__ import absolute_import, print_function from .control import Control, ControlManager, control_color, control_event, forward_control from .mapped import MappedControl from .button import ButtonControl, ButtonControlBase, DoubleClickContext, PlayableControl diff --git a/ableton/v2/control_surface/control/button.py b/ableton/v2/control_surface/control/button.py index 51ad5182..4ff85e73 100644 --- a/ableton/v2/control_surface/control/button.py +++ b/ableton/v2/control_surface/control/button.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control/button.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control/button.py +from __future__ import absolute_import, print_function from ...base import lazy_attribute, partial, task from ..defaults import MOMENTARY_DELAY, DOUBLE_CLICK_DELAY from .control import InputControl, control_event, control_color @@ -33,7 +33,7 @@ class State(InputControl.State): disabled_color = control_color('DefaultButton.Disabled') pressed_color = control_color(None) - def __init__(self, pressed_color = None, disabled_color = None, repeat = False, enabled = True, double_click_context = None, *a, **k): + def __init__(self, pressed_color = None, disabled_color = None, repeat = False, enabled = True, double_click_context = None, delay_time = None, *a, **k): super(ButtonControlBase.State, self).__init__(*a, **k) if disabled_color is not None: self.disabled_color = disabled_color @@ -42,19 +42,20 @@ def __init__(self, pressed_color = None, disabled_color = None, repeat = False, self._is_pressed = False self._enabled = enabled self._double_click_context = double_click_context or DoubleClickContext() + self._delay_time = delay_time if delay_time is not None else ButtonControlBase.DELAY_TIME - def _get_enabled(self): + @property + def enabled(self): return self._enabled - def _set_enabled(self, enabled): + @enabled.setter + def enabled(self, enabled): if self._enabled != enabled: if not enabled: self._release_button() self._enabled = enabled self._send_current_color() - enabled = property(_get_enabled, _set_enabled) - @property def is_momentary(self): return self._control_element and self._control_element.is_momentary() @@ -137,10 +138,10 @@ def _check_double_click_press(self): self._double_click_context.set_new_context(self) def _check_double_click_release(self): - if self._has_listener('double_clicked') and self._double_click_task.is_running: - if self._double_click_context.control_state == self: - self._double_click_context.click_count += 1 - self._double_click_context.click_count == 2 and self._call_listener('double_clicked') + if self._has_listener('double_clicked') and self._double_click_task.is_running and self._double_click_context.control_state == self: + self._double_click_context.click_count += 1 + if self._double_click_context.click_count == 2: + self._call_listener('double_clicked') self._double_click_task.kill() def set_double_click_context(self, context): @@ -148,12 +149,12 @@ def set_double_click_context(self, context): @lazy_attribute def _delay_task(self): - return self.tasks.add(task.sequence(task.wait(ButtonControlBase.DELAY_TIME), task.run(self._on_pressed_delayed))) + return self.tasks.add(task.sequence(task.wait(self._delay_time), task.run(self._on_pressed_delayed))) @lazy_attribute def _repeat_task(self): notify_pressed = partial(self._call_listener, 'pressed') - return self.tasks.add(task.sequence(task.wait(ButtonControlBase.DELAY_TIME), task.loop(task.wait(ButtonControlBase.REPEAT_RATE), task.run(notify_pressed)))) + return self.tasks.add(task.sequence(task.wait(self._delay_time), task.loop(task.wait(ButtonControlBase.REPEAT_RATE), task.run(notify_pressed)))) def _kill_all_tasks(self): if self._repeat: @@ -213,19 +214,19 @@ def _update_script_forwarding(self): if self._control_element and self._enabled: self._control_element.suppress_script_forwarding = self._playable - def _get_enabled(self): + @property + def enabled(self): return self._enabled - def _set_enabled(self, enabled): - super(PlayableControl.State, self)._set_enabled(enabled) + @enabled.setter + def enabled(self, enabled): + super(PlayableControl.State, PlayableControl.State).enabled.fset(self, enabled) if not enabled and self._control_element: self._control_element.reset_state() self._send_current_color() else: self.set_control_element(self._control_element) - enabled = property(_get_enabled, _set_enabled) - def set_playable(self, value): self._playable = value self._update_script_forwarding() diff --git a/ableton/v2/control_surface/control/control.py b/ableton/v2/control_surface/control/control.py index f5462ec1..17f85069 100644 --- a/ableton/v2/control_surface/control/control.py +++ b/ableton/v2/control_surface/control/control.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control/control.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control/control.py +from __future__ import absolute_import, print_function from functools import partial from ...base import lazy_attribute, mixin, nop, task, Disconnectable, NamedTuple, SlotManager @@ -181,26 +181,26 @@ def _register_value_slot(self, manager, control): def _on_value(self, value, *a, **k): self._call_listener('value', value) - def _get_channel(self): + @property + def channel(self): return self._channel - def _set_channel(self, channel): + @channel.setter + def channel(self, channel): self._channel = channel if self._control_element: self._control_element.set_channel(self._channel) - channel = property(_get_channel, _set_channel) - - def _get_identifier(self): + @property + def identifier(self): return self._identifier - def _set_identifier(self, value): + @identifier.setter + def identifier(self, value): self._identifier = value if self._control_element: self._control_element.set_identifier(self._identifier) - identifier = property(_get_identifier, _set_identifier) - class ProxyControl(object): """ @@ -211,7 +211,7 @@ class ProxyControl(object): def __init__(self, control = None, *a, **k): super(ProxyControl, self).__init__(*a, **k) self._control = control - raise not self._control._event_listeners or AssertionError, 'Cannot forward control that already has events.' + raise not self._control._event_listeners or AssertionError('Cannot forward control that already has events.') def _make_control_state(self, manager): """ @@ -261,13 +261,13 @@ def _register_property_slot(self, subject, property_name): else: return NullSlot() - def _set_connected_property_value(self, value): - self._connection.setter(self._connection.transform(value)) - - def _get_connected_property_value(self): + @property + def connected_property_value(self): return self._connection.getter() - connected_property_value = property(_get_connected_property_value, _set_connected_property_value) + @connected_property_value.setter + def connected_property_value(self, value): + self._connection.setter(self._connection.transform(value)) def on_connected_property_changed(self, value): """ diff --git a/ableton/v2/control_surface/control/control_list.py b/ableton/v2/control_surface/control/control_list.py index 3d199ff2..cff84454 100644 --- a/ableton/v2/control_surface/control/control_list.py +++ b/ableton/v2/control_surface/control/control_list.py @@ -1,6 +1,7 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control/control_list.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control/control_list.py +from __future__ import absolute_import, print_function from functools import partial +from itertools import izip_longest from ...base import clamp, first, second, mixin, product, flatten, is_matrix, find_if from .control import Connectable, Control from .radio_button import RadioButtonControl @@ -23,10 +24,12 @@ def __init__(self, control = None, manager = None, unavailable_color = None, ext self._extra_kws = k self.control_count = control.control_count - def _get_control_count(self): + @property + def control_count(self): return len(self._controls) - def _set_control_count(self, count): + @control_count.setter + def control_count(self, count): dynamic_create = count == ControlList.DYNAMIC_CONTROL_COUNT if len(self._controls) != count and not dynamic_create or self._dynamic_create != dynamic_create: self._dynamic_create = count == ControlList.DYNAMIC_CONTROL_COUNT @@ -35,20 +38,18 @@ def _set_control_count(self, count): self._create_controls(count) self._update_controls() - control_count = property(_get_control_count, _set_control_count) - - def _get_unavailable_color(self): + @property + def unavailable_color(self): return self._unavailable_color - def _set_unavailable_color(self, value): + @unavailable_color.setter + def unavailable_color(self, value): self._unavailable_color = value control_elements = self._control_elements or [] - for control, element in map(None, self._controls, control_elements): + for control, element in izip_longest(self._controls, control_elements): if not control and element: self._send_unavailable_color(element) - unavailable_color = property(_get_unavailable_color, _set_unavailable_color) - def _create_controls(self, count): if count > len(self._controls): self._controls.extend([ self._make_control(i) for i in xrange(len(self._controls), count) ]) @@ -79,7 +80,7 @@ def set_control_element(self, control_elements): def _update_controls(self): control_elements = self._control_elements or [] - for control, element in map(None, self._controls, control_elements): + for control, element in izip_longest(self._controls, control_elements): if control: control._get_state(self._manager).set_control_element(element) elif element: @@ -114,10 +115,12 @@ def __init__(self, *a, **k): self._checked_index = -1 super(RadioButtonGroup.State, self).__init__(*a, **k) - def _get_checked_index(self): + @property + def checked_index(self): return self._checked_index - def _set_checked_index(self, index): + @checked_index.setter + def checked_index(self, index): if not -1 <= index < self.control_count: raise AssertionError self[index].is_checked = index != -1 and True @@ -126,8 +129,6 @@ def _set_checked_index(self, index): if checked_control is not None: checked_control.is_checked = False - checked_index = property(_get_checked_index, _set_checked_index) - def connect_property(self, *a): super(RadioButtonGroup.State, self).connect_property(*a) self.checked_index = self.connected_property_value @@ -171,10 +172,12 @@ def __init__(self, control = None, manager = None, *a, **k): self._dimensions = (None, None) super(MatrixControl.State, self).__init__(control, manager, *a, **k) - def _get_dimensions(self): + @property + def dimensions(self): return self._dimensions - def _set_dimensions(self, dimensions): + @dimensions.setter + def dimensions(self, dimensions): if not first(dimensions): raise AssertionError raise second(dimensions) or AssertionError @@ -185,8 +188,6 @@ def _set_dimensions(self, dimensions): self._create_controls(count) self._update_controls() - dimensions = property(_get_dimensions, _set_dimensions) - def _create_controls(self, count): super(MatrixControl.State, self)._create_controls(count) self._update_coordinates() diff --git a/ableton/v2/control_surface/control/encoder.py b/ableton/v2/control_surface/control/encoder.py index 8584f2bd..d451f31d 100644 --- a/ableton/v2/control_surface/control/encoder.py +++ b/ableton/v2/control_surface/control/encoder.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control/encoder.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control/encoder.py +from __future__ import absolute_import, print_function from ...base import lazy_attribute, task, sign from .control import Connectable, InputControl, control_event @@ -11,13 +11,14 @@ class EncoderControl(InputControl): class State(InputControl.State, Connectable): - def __init__(self, control = None, manager = None, *a, **k): + def __init__(self, control = None, manager = None, touch_event_delay = 0, *a, **k): raise control is not None or AssertionError raise manager is not None or AssertionError super(EncoderControl.State, self).__init__(control=control, manager=manager, *a, **k) self._is_touched = False self._touch_value_slot = None self._timer_based = False + self._touch_event_delay = touch_event_delay self._touch_value_slot = self.register_slot(None, self._on_touch_value, 'value') @property @@ -29,12 +30,15 @@ def set_control_element(self, control_element): self._release_encoder() self._kill_all_tasks() super(EncoderControl.State, self).set_control_element(control_element) - self._touch_value_slot.subject = control_element.touch_element if control_element is not None else None + self._touch_value_slot.subject = self._get_touch_element(control_element) if control_element is not None else None if control_element and hasattr(control_element, 'is_pressed') and control_element.is_pressed(): self._touch_encoder() + def _get_touch_element(self, control_element): + return getattr(control_element, 'touch_element', None) + def _lost_touch_element(self, control_element): - return control_element is not None and control_element.touch_element is None + return control_element is not None and self._get_touch_element(control_element) is None def _touch_encoder(self): is_touched = self._is_touched @@ -61,8 +65,11 @@ def _on_value(self, value, *a, **k): if self._notifications_enabled(): if not self._is_touched: self._touch_encoder() - self._timer_based = True - self._timer_based_release_task.restart() + if self._delayed_touch_task.is_running: + self._delayed_touch_task.kill() + else: + self._timer_based = True + self._timer_based_release_task.restart() elif self._timer_based: self._timer_based_release_task.restart() if self._control_element: @@ -71,9 +78,13 @@ def _on_value(self, value, *a, **k): def _on_touch_value(self, value, *a, **k): if self._notifications_enabled(): if value: - self._touch_encoder() + if self._touch_event_delay > 0: + self._delayed_touch_task.restart() + else: + self._touch_encoder() else: self._delayed_release_task.restart() + self._delayed_touch_task.kill() self._cancel_timer_based_events() @lazy_attribute @@ -84,6 +95,10 @@ def _timer_based_release_task(self): def _delayed_release_task(self): return self.tasks.add(task.sequence(task.wait(EncoderControl.RELEASE_DELAY), task.run(self._release_encoder))) + @lazy_attribute + def _delayed_touch_task(self): + return self.tasks.add(task.sequence(task.wait(self._touch_event_delay), task.run(self._touch_encoder))) + def _cancel_timer_based_events(self): if self._timer_based: self._timer_based_release_task.kill() @@ -92,6 +107,10 @@ def _cancel_timer_based_events(self): def _kill_all_tasks(self): self._delayed_release_task.kill() self._timer_based_release_task.kill() + self._delayed_touch_task.kill() + + def __init__(self, *a, **k): + super(EncoderControl, self).__init__(extra_args=a, extra_kws=k) class ValueStepper(object): @@ -152,7 +171,4 @@ def _on_touch_value(self, value, *a, **k): @property def num_steps(self): - return self._stepper._num_steps - - def __init__(self, *a, **k): - super(StepEncoderControl, self).__init__(extra_args=a, extra_kws=k) \ No newline at end of file + return self._stepper._num_steps \ No newline at end of file diff --git a/ableton/v2/control_surface/control/mapped.py b/ableton/v2/control_surface/control/mapped.py index 18a03feb..1c846fae 100644 --- a/ableton/v2/control_surface/control/mapped.py +++ b/ableton/v2/control_surface/control/mapped.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control/mapped.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control/mapped.py +from __future__ import absolute_import, print_function from .control import InputControl class MappedControl(InputControl): @@ -18,15 +18,15 @@ def set_control_element(self, control_element): super(MappedControl.State, self).set_control_element(control_element) self._update_direct_connection() - def _get_direct_mapping(self): + @property + def mapped_parameter(self): return self._direct_mapping - def _set_direct_mapping(self, direct_mapping): + @mapped_parameter.setter + def mapped_parameter(self, direct_mapping): self._direct_mapping = direct_mapping self._update_direct_connection() - mapped_parameter = property(_get_direct_mapping, _set_direct_mapping) - def _update_direct_connection(self): if self._control_element: self._control_element.connect_to(self._direct_mapping) diff --git a/ableton/v2/control_surface/control/radio_button.py b/ableton/v2/control_surface/control/radio_button.py index c35eff3c..29cc2785 100644 --- a/ableton/v2/control_surface/control/radio_button.py +++ b/ableton/v2/control_surface/control/radio_button.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control/radio_button.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control/radio_button.py +from __future__ import absolute_import, print_function from ...base import nop from .control import control_event, control_color from .button import ButtonControlBase @@ -20,18 +20,18 @@ def __init__(self, unchecked_color = None, checked_color = None, *a, **k): self._checked = False self._on_checked = nop - def _get_is_checked(self): + @property + def is_checked(self): return self._checked - def _set_is_checked(self, value): + @is_checked.setter + def is_checked(self, value): if self._checked != value: self._checked = value if self._checked: self._on_checked() self._send_current_color() - is_checked = property(_get_is_checked, _set_is_checked) - def _send_button_color(self): self._control_element.set_light(self.checked_color if self._checked else self.unchecked_color) diff --git a/ableton/v2/control_surface/control/text_display.py b/ableton/v2/control_surface/control/text_display.py index 57fca19f..0d1c28ab 100644 --- a/ableton/v2/control_surface/control/text_display.py +++ b/ableton/v2/control_surface/control/text_display.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control/text_display.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control/text_display.py +from __future__ import absolute_import, print_function from ..elements import DisplayDataSource from .control import Control diff --git a/ableton/v2/control_surface/control/toggle_button.py b/ableton/v2/control_surface/control/toggle_button.py index 2cb917ae..b0c843d5 100644 --- a/ableton/v2/control_surface/control/toggle_button.py +++ b/ableton/v2/control_surface/control/toggle_button.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control/toggle_button.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control/toggle_button.py +from __future__ import absolute_import, print_function from .control import Connectable, control_event, control_color from .button import ButtonControlBase @@ -19,16 +19,16 @@ def __init__(self, untoggled_color = None, toggled_color = None, *a, **k): self.toggled_color = toggled_color self._is_toggled = False - def _get_is_toggled(self): + @property + def is_toggled(self): return self._is_toggled - def _set_is_toggled(self, toggled): + @is_toggled.setter + def is_toggled(self, toggled): if self._is_toggled != toggled: self._is_toggled = toggled self._send_current_color() - is_toggled = property(_get_is_toggled, _set_is_toggled) - def connect_property(self, *a): super(ToggleButtonControl.State, self).connect_property(*a) self.is_toggled = self.connected_property_value diff --git a/ableton/v2/control_surface/control_element.py b/ableton/v2/control_surface/control_element.py index bc92c087..6fcbf1d9 100644 --- a/ableton/v2/control_surface/control_element.py +++ b/ableton/v2/control_surface/control_element.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control_element.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control_element.py +from __future__ import absolute_import, print_function import logging import traceback import re diff --git a/ableton/v2/control_surface/control_surface.py b/ableton/v2/control_surface/control_surface.py index a64adfa1..0cb67ca8 100644 --- a/ableton/v2/control_surface/control_surface.py +++ b/ableton/v2/control_surface/control_surface.py @@ -1,5 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/control_surface.py -from __future__ import absolute_import, with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/control_surface.py +from __future__ import absolute_import, print_function +from collections import OrderedDict from functools import partial from itertools import chain, ifilter, imap from contextlib import contextmanager @@ -9,10 +10,12 @@ import logging import traceback import Live -from ..base import BooleanContext, const, find_if, first, in_range, inject, lazy_attribute, liveobj_valid, SlotManager, task, collection +from ..base import BooleanContext, const, find_if, first, in_range, inject, lazy_attribute, liveobj_valid, SlotManager, task from . import defaults from . import midi +from .components.device import DeviceProvider from .control_element import OptimizedOwnershipHandler +from .device_bank_registry import DeviceBankRegistry from .elements import PhysicalDisplayElement from .input_control_element import InputControlElement, MIDI_CC_TYPE, MIDI_NOTE_TYPE, MIDI_PB_TYPE, MIDI_SYSEX_TYPE from .profile import profile @@ -34,16 +37,19 @@ def get_control_surfaces(): return getattr(__builtins__, CS_LIST_KEY) -class ControlSurface(SlotManager): +class SimpleControlSurface(SlotManager): """ Central base class for scripts based on the new Framework. New scripts need to subclass this class and add special behavior. + + This class does not support device control/locking etc. Use ControlSurface if + you need device support. """ preferences_key = None def __init__(self, c_instance = None, publish_self = True, *a, **k): """ Define and Initialize standard behavior """ - super(ControlSurface, self).__init__(*a, **k) + super(SimpleControlSurface, self).__init__(*a, **k) if not c_instance: raise AssertionError self.canonical_parent = None @@ -55,7 +61,6 @@ def __init__(self, c_instance = None, publish_self = True, *a, **k): self._components = [] self._displays = [] self.controls = [] - self._device_component = None self._forwarding_long_identifier_registry = {} self._forwarding_registry = {} self._is_sending_scheduled_messages = BooleanContext() @@ -109,13 +114,12 @@ def disconnect(self): self._forwarding_registry = None self.controls = None self._displays = None - self._device_component = None self._pad_translations = None cs_list = self._control_surfaces() if self in cs_list: cs_list.remove(self) self._task_group.clear() - super(ControlSurface, self).disconnect() + super(SimpleControlSurface, self).disconnect() def _control_surfaces(self): """ Returns list of registered control surfaces """ @@ -125,42 +129,7 @@ def can_lock_to_devices(self): """ Live -> Script """ - return self._device_component is not None - - def lock_to_device(self, device): - """ - Live -> Script - Live tells the script which device to control - """ - raise self._device_component is not None or AssertionError - with self.component_guard(): - self._device_component.set_lock_to_device(True, device) - - def unlock_from_device(self, device): - """ - Live -> Script - Live tells the script to unlock from a certain device - """ - raise self._device_component is not None or AssertionError - with self.component_guard(): - self._device_component.set_lock_to_device(False, device) - - def restore_bank(self, bank_index): - """ - Live -> Script - Live tells the script which bank to use. - """ - raise self._device_component is not None or AssertionError - with self.component_guard(): - self._device_component.restore_bank(bank_index) - - def set_appointed_device(self, device): - """ - Live -> Script - Live tells the script to unlock from a certain device - """ - with self.component_guard(): - self._device_component.set_device(device) + return False def suggest_input_port(self): """ Live -> Script: Live can ask for the name of the script's @@ -246,12 +215,6 @@ def build_midi_map(self, midi_map_handle): if self._pad_translations is not None: self._c_instance.set_pad_translation(self._pad_translations) - def toggle_lock(self): - """ Script -> Live - Use this function to toggle the script's lock on devices - """ - self._c_instance.toggle_lock() - def port_settings_changed(self): """ Live -> Script Is called when either the user changes the MIDI ports that are assigned @@ -332,7 +295,7 @@ def _do_receive_midi_chunk(self, midi_chunk): recipients allow receiving MIDI in chunks. This would lead to an ordered chunk: [r1.m1, r1.m2], [r2.m1, r2.m2], [r3.m1] """ - midi_data_for_recipient = collection.OrderedDict() + midi_data_for_recipient = OrderedDict() for midi_bytes in midi_chunk: self.process_midi_bytes(midi_bytes, partial(self._merge_midi_data, midi_data=midi_data_for_recipient)) @@ -369,16 +332,6 @@ def get_recipient_for_nonsysex_midi_message(self, midi_bytes): def get_registry_entry_for_sysex_midi_message(self, midi_bytes): return find_if(lambda (identifier, _): midi_bytes[:len(identifier)] == identifier, self._forwarding_long_identifier_registry.iteritems()) - def set_device_component(self, device_component): - if self._device_component is not None: - self._device_component.set_lock_callback(None) - self._device_component = device_component - self._c_instance.update_locks() - if device_component is not None: - device_component.set_lock_callback(self._toggle_lock) - if self._device_component.device_selection_follows_track_selection: - self.schedule_message(1, self._device_component.update_device_selection) - @contextmanager def suppressing_rebuild_requests(self): """ @@ -468,7 +421,7 @@ def _register_control(self, control): if not control != None: raise AssertionError if not control not in self.controls: - raise AssertionError, 'Control registered twice' + raise AssertionError('Control registered twice') self.controls.append(control) control.canonical_parent = self isinstance(control, PhysicalDisplayElement) and self._displays.append(control) @@ -477,7 +430,7 @@ def _register_control(self, control): def _register_component(self, component): """ puts component into the list of controls for triggering updates """ raise component != None or AssertionError - raise component not in self._components or AssertionError, 'Component registered twice' + raise component not in self._components or AssertionError('Component registered twice') self._components.append(component) component.canonical_parent = self @@ -488,7 +441,6 @@ def _disconnect_and_unregister_all_components(self): component.disconnect() self._components = [] - self.set_device_component(None) @contextmanager def component_guard(self): @@ -589,24 +541,24 @@ def _install_mapping(self, midi_map_handle, control, parameter, feedback_delay, raise AssertionError success = False feedback_rule = None - feedback_rule = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.NoteFeedbackRule() + feedback_rule = control.message_type() == MIDI_NOTE_TYPE and Live.MidiMap.NoteFeedbackRule() feedback_rule.note_no = control.message_identifier() feedback_rule.vel_map = feedback_map - elif control.message_type() is MIDI_CC_TYPE: + elif control.message_type() == MIDI_CC_TYPE: feedback_rule = Live.MidiMap.CCFeedbackRule() feedback_rule.cc_no = control.message_identifier() feedback_rule.cc_value_map = feedback_map - elif control.message_type() is MIDI_PB_TYPE: + elif control.message_type() == MIDI_PB_TYPE: feedback_rule = Live.MidiMap.PitchBendFeedbackRule() feedback_rule.value_pair_map = feedback_map if not feedback_rule != None: raise AssertionError feedback_rule.channel = control.message_channel() feedback_rule.delay_in_ms = feedback_delay - success = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.map_midi_note_with_feedback_map(midi_map_handle, parameter, control.message_channel(), control.message_identifier(), feedback_rule) - elif control.message_type() is MIDI_CC_TYPE: + success = control.message_type() == MIDI_NOTE_TYPE and Live.MidiMap.map_midi_note_with_feedback_map(midi_map_handle, parameter, control.message_channel(), control.message_identifier(), feedback_rule) + elif control.message_type() == MIDI_CC_TYPE: success = Live.MidiMap.map_midi_cc_with_feedback_map(midi_map_handle, parameter, control.message_channel(), control.message_identifier(), control.message_map_mode(), feedback_rule, not control.needs_takeover(), control.mapping_sensitivity) - elif control.message_type() is MIDI_PB_TYPE: + elif control.message_type() == MIDI_PB_TYPE: success = Live.MidiMap.map_midi_pitchbend_with_feedback_map(midi_map_handle, parameter, control.message_channel(), feedback_rule, not control.needs_takeover()) success and Live.MidiMap.send_feedback_for_parameter(midi_map_handle, parameter) return success @@ -618,10 +570,10 @@ def _install_forwarding(self, midi_map_handle, control): if not isinstance(control, InputControlElement): raise AssertionError success = False - success = control.message_type() is MIDI_NOTE_TYPE and Live.MidiMap.forward_midi_note(self._c_instance.handle(), midi_map_handle, control.message_channel(), control.message_identifier()) - elif control.message_type() is MIDI_CC_TYPE: + success = control.message_type() == MIDI_NOTE_TYPE and Live.MidiMap.forward_midi_note(self._c_instance.handle(), midi_map_handle, control.message_channel(), control.message_identifier()) + elif control.message_type() == MIDI_CC_TYPE: success = Live.MidiMap.forward_midi_cc(self._c_instance.handle(), midi_map_handle, control.message_channel(), control.message_identifier()) - elif control.message_type() is MIDI_PB_TYPE: + elif control.message_type() == MIDI_PB_TYPE: success = Live.MidiMap.forward_midi_pitchbend(self._c_instance.handle(), midi_map_handle, control.message_channel()) else: raise control.message_type() == MIDI_SYSEX_TYPE or AssertionError @@ -629,7 +581,7 @@ def _install_forwarding(self, midi_map_handle, control): forwarding_keys = success and control.identifier_bytes() for key in forwarding_keys: registry = self._forwarding_registry if control.message_type() != MIDI_SYSEX_TYPE else self._forwarding_long_identifier_registry - raise key not in registry.keys() or AssertionError, 'Registry key %s registered twice. Check Midi messages!' % str(key) + raise key not in registry.keys() or AssertionError('Registry key %s registered twice. Check Midi messages!' % str(key)) registry[key] = control return success @@ -647,10 +599,6 @@ def _translate_message(self, type, from_identifier, from_channel, to_identifier, else: raise False or AssertionError - def _toggle_lock(self): - raise self._device_component is not None or AssertionError - self._c_instance.toggle_lock() - def _refresh_displays(self): """ Make sure the displays of the control surface display current @@ -687,4 +635,83 @@ def _pre_serialize(self): if self.preferences_key is not None: preferences = self._c_instance.preferences(self.preferences_key) dump = dumps(self.preferences) - preferences.set_serializer(lambda : dump) \ No newline at end of file + preferences.set_serializer(lambda : dump) + + +class ControlSurface(SimpleControlSurface): + """ + Central base class for scripts based on the new Framework. New + scripts need to subclass this class and add special behavior. + + This class supports device control, i.e. it supports locking to a device, and + appoints devices when the selected track/device changes etc. The appointing behavior + can be customized by overriding device_provider_class. + """ + device_provider_class = DeviceProvider + + def __init__(self, *a, **k): + super(ControlSurface, self).__init__(*a, **k) + self._device_provider = None + self._device_bank_registry = None + if self.device_provider_class: + self._init_device_provider() + self._device_support_injector = inject(device_provider=const(self.device_provider), device_bank_registry=const(self._device_bank_registry)).everywhere() + + def _init_device_provider(self): + self._device_provider = self.register_disconnectable(self.device_provider_class(song=self.song)) + self._device_bank_registry = self.register_disconnectable(DeviceBankRegistry()) + self._c_instance.update_locks() + self._device_provider.update_device_selection() + + @property + def device_provider(self): + return self._device_provider + + def disconnect(self): + self._device_provider = None + self._device_bank_registry = None + super(ControlSurface, self).disconnect() + + def can_lock_to_devices(self): + return True + + def lock_to_device(self, device): + """ + Live -> Script + Live tells the script which device to control + """ + raise self._device_provider is not None or AssertionError + with self.component_guard(): + self._device_provider.locked_device = device + + def unlock_from_device(self, device): + """ + Live -> Script + Live tells the script to unlock from a certain device + """ + raise self._device_provider is not None or AssertionError + with self.component_guard(): + self._device_provider.locked_device = None + + def restore_bank(self, bank_index): + """ + Live -> Script + Live tells the script which bank to use. + """ + if not self._device_provider is not None: + raise AssertionError + device = self._device_provider.device + with self._device_provider.is_locked_to_device and liveobj_valid(device) and self.component_guard(): + self._device_bank_registry.set_device_bank(device, bank_index) + + def toggle_lock(self): + """ Script -> Live + Use this function to toggle the script's lock on devices + """ + self._c_instance.toggle_lock() + + @contextmanager + def _component_guard(self): + with super(ControlSurface, self)._component_guard(): + with self._device_support_injector: + yield \ No newline at end of file diff --git a/ableton/v2/control_surface/defaults.py b/ableton/v2/control_surface/defaults.py index d39b1b5d..11c91734 100644 --- a/ableton/v2/control_surface/defaults.py +++ b/ableton/v2/control_surface/defaults.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/defaults.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/defaults.py +from __future__ import absolute_import, print_function TIMER_DELAY = 0.1 MOMENTARY_DELAY = 0.3 MOMENTARY_DELAY_TICKS = int(MOMENTARY_DELAY / TIMER_DELAY) diff --git a/ableton/v2/control_surface/device_bank_registry.py b/ableton/v2/control_surface/device_bank_registry.py index dc6c84a6..8f30c18e 100644 --- a/ableton/v2/control_surface/device_bank_registry.py +++ b/ableton/v2/control_surface/device_bank_registry.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/device_bank_registry.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/device_bank_registry.py """ Classes to keep a global registry of the currently selected bank for given device instances. @@ -6,7 +6,7 @@ [jbo] After some though about this, I personally believe that moving banking to the C++ code is the best mid-term solution. """ -from __future__ import absolute_import +from __future__ import absolute_import, print_function from ..base import Subject class DeviceBankRegistry(Subject): @@ -22,10 +22,10 @@ def compact_registry(self): self._device_bank_registry = newreg def set_device_bank(self, device, bank): - if not self._find_device_bank_key(device): - key = device - old = self._device_bank_registry[key] if key in self._device_bank_registry else 0 - self._device_bank_registry[key] = old != bank and bank + key = self._find_device_bank_key(device) or device + old = self._device_bank_registry[key] if key in self._device_bank_registry else 0 + if old != bank: + self._device_bank_registry[key] = bank self.notify_device_bank(device, bank) def get_device_bank(self, device): diff --git a/ableton/v2/control_surface/elements/__init__.py b/ableton/v2/control_surface/elements/__init__.py index df26f0de..224fe41d 100644 --- a/ableton/v2/control_surface/elements/__init__.py +++ b/ableton/v2/control_surface/elements/__init__.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/__init__.py +from __future__ import absolute_import, print_function from .button import ButtonElement, ButtonElementMixin, ButtonValue, DummyUndoStepHandler, ON_VALUE, OFF_VALUE from .button_matrix import ButtonMatrixElement from .button_slider import ButtonSliderElement diff --git a/ableton/v2/control_surface/elements/button.py b/ableton/v2/control_surface/elements/button.py index e7917c46..56d570a7 100644 --- a/ableton/v2/control_surface/elements/button.py +++ b/ableton/v2/control_surface/elements/button.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/button.py -from __future__ import absolute_import, with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/button.py +from __future__ import absolute_import, print_function import Live from ...base import BooleanContext, const, has_event, listens, SlotManager from ..input_control_element import InputControlElement, MIDI_CC_TYPE diff --git a/ableton/v2/control_surface/elements/button_matrix.py b/ableton/v2/control_surface/elements/button_matrix.py index b5f61f78..07551694 100644 --- a/ableton/v2/control_surface/elements/button_matrix.py +++ b/ableton/v2/control_surface/elements/button_matrix.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/button_matrix.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/button_matrix.py +from __future__ import absolute_import, print_function from ...base import in_range, product, const, slicer, to_slice from ..compound_element import CompoundElement @@ -88,7 +88,7 @@ def __getitem__(self, index): return self._do_get_item(index) def _do_get_item(self, index): - raise in_range(index, 0, len(self)) or AssertionError, 'Index out of range' + raise in_range(index, 0, len(self)) or AssertionError('Index out of range') row, col = divmod(index, self.width()) return self.get_button(col, row) diff --git a/ableton/v2/control_surface/elements/button_slider.py b/ableton/v2/control_surface/elements/button_slider.py index e9e6583c..361d8546 100644 --- a/ableton/v2/control_surface/elements/button_slider.py +++ b/ableton/v2/control_surface/elements/button_slider.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/button_slider.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/button_slider.py +from __future__ import absolute_import, print_function from ...base import SlotManager from ..input_control_element import InputControlElement, MIDI_INVALID_TYPE from .button import ButtonElement diff --git a/ableton/v2/control_surface/elements/color.py b/ableton/v2/control_surface/elements/color.py index ef3868f9..481f1c9b 100644 --- a/ableton/v2/control_surface/elements/color.py +++ b/ableton/v2/control_surface/elements/color.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/color.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/color.py +from __future__ import absolute_import, print_function from ...base import listenable_property, listens, liveobj_valid, nop, Subject, SlotManager def to_midi_value(int_or_color): diff --git a/ableton/v2/control_surface/elements/combo.py b/ableton/v2/control_surface/elements/combo.py index 8d3bf96b..8315c285 100644 --- a/ableton/v2/control_surface/elements/combo.py +++ b/ableton/v2/control_surface/elements/combo.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/combo.py -from __future__ import absolute_import, with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/combo.py +from __future__ import absolute_import, print_function from itertools import imap from contextlib import contextmanager from ...base import const, depends, find_if, is_iterable, lazy_attribute, nop, ProxyBase, SlotManager, Subject, listens, task @@ -106,8 +106,8 @@ def reset(self): self._wrapped_control.reset() def get_control_element_priority(self, element, priority): - if not (element == self._wrapped_control and (priority is None or 1 - priority + int(priority) > self.priority_increment)): - raise AssertionError, 'Attempting to increase the priority over a whole unit. ' + 'Make sure the combo element is not inside another combo element' + if element == self._wrapped_control: + raise priority is None or 1 - priority + int(priority) > self.priority_increment or AssertionError('Attempting to increase the priority over a whole unit. ' + 'Make sure the combo element is not inside another combo element') priority = DEFAULT_PRIORITY if priority is None else priority return priority + self.priority_increment return priority diff --git a/ableton/v2/control_surface/elements/display_data_source.py b/ableton/v2/control_surface/elements/display_data_source.py index 749adeaf..73c15c99 100644 --- a/ableton/v2/control_surface/elements/display_data_source.py +++ b/ableton/v2/control_surface/elements/display_data_source.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/display_data_source.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/display_data_source.py +from __future__ import absolute_import, print_function from functools import partial def adjust_string_crop(original, length): @@ -16,9 +16,9 @@ def adjust_string(original, length): raise AssertionError resulting_string = original if len(resulting_string) > length: - if resulting_string.endswith('dB'): - unit_db = resulting_string.find('.') != -1 - resulting_string = len(resulting_string.strip()) > length and unit_db and resulting_string[:-2] + unit_db = resulting_string.endswith('dB') and resulting_string.find('.') != -1 + if len(resulting_string.strip()) > length and unit_db: + resulting_string = resulting_string[:-2] if len(resulting_string) > length: for char in (' ', '_', 'i', 'o', 'u', 'e', 'a'): offset = 0 if char == ' ' else 1 @@ -49,16 +49,16 @@ def __init__(self, display_string = '', separator = None, adjust_string_fn = adj self._update_callback = None self._in_update = False - def _get_separator(self): + @property + def separator(self): return self._separator - def _set_separator(self, separator): + @separator.setter + def separator(self, separator): if separator != self._separator: self._separator = separator self.update() - separator = property(_get_separator, _set_separator) - def set_update_callback(self, update_callback): if not (not update_callback or callable(update_callback)): raise AssertionError diff --git a/ableton/v2/control_surface/elements/encoder.py b/ableton/v2/control_surface/elements/encoder.py index 7216af42..5415a9c6 100644 --- a/ableton/v2/control_surface/elements/encoder.py +++ b/ableton/v2/control_surface/elements/encoder.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/encoder.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/encoder.py +from __future__ import absolute_import, print_function import Live from ...base import Event, nop, const, clamp, listens from ..input_control_element import InputControlElement, MIDI_CC_TYPE, InputSignal @@ -12,8 +12,9 @@ def _not_implemented(value): raise NotImplementedError -ENCODER_VALUE_NORMALIZER = {_map_modes.relative_smooth_two_compliment: lambda v: v if v <= 64 else v - 128, - _map_modes.relative_smooth_signed_bit: lambda v: v if v <= 64 else 64 - v} +ENCODER_VALUE_NORMALIZER = {_map_modes.relative_smooth_two_compliment: lambda v: (v if v <= 64 else v - 128), + _map_modes.relative_smooth_signed_bit: lambda v: (v if v <= 64 else 64 - v), + _map_modes.relative_smooth_binary_offset: lambda v: v - 64} def accumulate_relative_two_compliment_chunk(chunk): right = 0 @@ -25,7 +26,9 @@ def accumulate_relative_two_compliment_chunk(chunk): left += 128 - value result = clamp(right - left, -63, 64) - return result if result >= 0 else 128 + result + if result >= 0: + return result + return 128 + result ENCODER_VALUE_ACCUMULATOR = {_map_modes.relative_smooth_two_compliment: accumulate_relative_two_compliment_chunk} @@ -117,7 +120,8 @@ def on_nested_control_element_value(self, value, control): @property def touch_element(self): - return self._touch_element if self.owns_control_element(self._touch_element) else None + if self.owns_control_element(self._touch_element): + return self._touch_element def is_pressed(self): return self.owns_control_element(self._touch_element) and self._touch_element.is_pressed() diff --git a/ableton/v2/control_surface/elements/logical_display_segment.py b/ableton/v2/control_surface/elements/logical_display_segment.py index 6e3b3705..a979ccaf 100644 --- a/ableton/v2/control_surface/elements/logical_display_segment.py +++ b/ableton/v2/control_surface/elements/logical_display_segment.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/logical_display_segment.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/logical_display_segment.py +from __future__ import absolute_import, print_function class LogicalDisplaySegment(object): """ @@ -50,10 +50,10 @@ def update(self): self._update_callback() def _get_display_string(self): - separator = self._data_source != None and self._data_source.separator + self.separator - width = self._width - len(separator) - if not width >= 0: - raise AssertionError + if self._data_source != None: + separator = self._data_source.separator + self.separator + width = self._width - len(separator) + raise width >= 0 or AssertionError return self._data_source.adjust_string(width) + separator else: return ' ' * self._width diff --git a/ableton/v2/control_surface/elements/optional.py b/ableton/v2/control_surface/elements/optional.py index a36b6c93..f5e5dd33 100644 --- a/ableton/v2/control_surface/elements/optional.py +++ b/ableton/v2/control_surface/elements/optional.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/optional.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/optional.py +from __future__ import absolute_import, print_function from ...base import SlotManager, listens from .combo import ToggleElement diff --git a/ableton/v2/control_surface/elements/physical_display.py b/ableton/v2/control_surface/elements/physical_display.py index feceb496..56a9a106 100644 --- a/ableton/v2/control_surface/elements/physical_display.py +++ b/ableton/v2/control_surface/elements/physical_display.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/physical_display.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/physical_display.py +from __future__ import absolute_import, print_function from itertools import ifilter, izip, starmap, chain, imap from functools import partial from ...base import const, first, group, in_range, lazy_attribute, maybe, nop, second, slice_size, slicer, task, to_slice diff --git a/ableton/v2/control_surface/elements/slider.py b/ableton/v2/control_surface/elements/slider.py index f65e2232..965268ab 100644 --- a/ableton/v2/control_surface/elements/slider.py +++ b/ableton/v2/control_surface/elements/slider.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/slider.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/slider.py +from __future__ import absolute_import, print_function import Live from ..input_control_element import MIDI_NOTE_TYPE from .encoder import EncoderElement diff --git a/ableton/v2/control_surface/elements/sysex_element.py b/ableton/v2/control_surface/elements/sysex_element.py index 778db8c7..45310b15 100644 --- a/ableton/v2/control_surface/elements/sysex_element.py +++ b/ableton/v2/control_surface/elements/sysex_element.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/elements/sysex_element.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/elements/sysex_element.py +from __future__ import absolute_import, print_function from ..input_control_element import InputControlElement, MIDI_SYSEX_TYPE from .. import midi @@ -31,7 +31,7 @@ def __init__(self, send_message_generator = None, enquire_message = None, defaul def send_value(self, *arguments): raise self._send_message_generator is not None or AssertionError message = self._send_message_generator(*arguments) - raise midi.is_valid_sysex(message) or AssertionError, 'Trying to send sysex message %r, which is not valid.' % map(hex, message) + raise midi.is_valid_sysex(message) or AssertionError('Trying to send sysex message %r, which is not valid.' % map(hex, message)) self.send_midi(message) def enquire_value(self): diff --git a/ableton/v2/control_surface/identifiable_control_surface.py b/ableton/v2/control_surface/identifiable_control_surface.py index 9f9110b8..de8eda92 100644 --- a/ableton/v2/control_surface/identifiable_control_surface.py +++ b/ableton/v2/control_surface/identifiable_control_surface.py @@ -1,8 +1,9 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/identifiable_control_surface.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/identifiable_control_surface.py +from __future__ import absolute_import, print_function import logging from ..base import task -from .control_surface import ControlSurface, midi +from . import midi +from .control_surface import ControlSurface logger = logging.getLogger(__name__) class IdentifiableControlSurface(ControlSurface): diff --git a/ableton/v2/control_surface/input_control_element.py b/ableton/v2/control_surface/input_control_element.py index 74e330c5..ab1d86a5 100644 --- a/ableton/v2/control_surface/input_control_element.py +++ b/ableton/v2/control_surface/input_control_element.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/input_control_element.py -from __future__ import absolute_import, with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/input_control_element.py +from __future__ import absolute_import, print_function import contextlib import logging from ..base import const, depends, Disconnectable, in_range, nop, Signal, Event, task @@ -34,28 +34,28 @@ def __init__(self, parameter = None, control = None, *a, **k): self.parameter = parameter self.control = control - def _get_control(self): + @property + def control(self): return self._control - def _set_control(self, control): + @control.setter + def control(self, control): if control != self._control: self.soft_disconnect() self._control = control self.connect() - control = property(_get_control, _set_control) - - def _get_parameter(self): + @property + def parameter(self): return self._parameter - def _set_parameter(self, parameter): + @parameter.setter + def parameter(self, parameter): if parameter != self._parameter: self.soft_disconnect() self._parameter = parameter self.connect() - parameter = property(_get_parameter, _set_parameter) - def connect(self): if self._control != None and self._parameter != None: self._control.connect_to(self._parameter) @@ -181,25 +181,25 @@ def message_sysex_identifier(self): def message_map_mode(self): raise NotImplementedError - def _get_mapping_sensitivity(self): + @property + def mapping_sensitivity(self): return self._mapping_sensitivity - def _set_mapping_sensitivity(self, sensitivity): + @mapping_sensitivity.setter + def mapping_sensitivity(self, sensitivity): self._mapping_sensitivity = sensitivity self._request_rebuild() - mapping_sensitivity = property(_get_mapping_sensitivity, _set_mapping_sensitivity) - - def _get_suppress_script_forwarding(self): + @property + def suppress_script_forwarding(self): return self._suppress_script_forwarding - def _set_suppress_script_forwarding(self, value): + @suppress_script_forwarding.setter + def suppress_script_forwarding(self, value): if self._suppress_script_forwarding != value: self._suppress_script_forwarding = value self._request_rebuild() - suppress_script_forwarding = property(_get_suppress_script_forwarding, _set_suppress_script_forwarding) - def force_next_send(self): """ Enforces sending the next value regardless of wether the @@ -430,4 +430,6 @@ def _report_value(self, value, is_input): @property def _last_sent_value(self): - return self._last_sent_message[0] if self._last_sent_message else -1 \ No newline at end of file + if self._last_sent_message: + return self._last_sent_message[0] + return -1 \ No newline at end of file diff --git a/ableton/v2/control_surface/layer.py b/ableton/v2/control_surface/layer.py index 609164f9..ebd8b557 100644 --- a/ableton/v2/control_surface/layer.py +++ b/ableton/v2/control_surface/layer.py @@ -1,9 +1,9 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/layer.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/layer.py """ Module implementing a way to resource-based access to controls in an unified interface dynamic. """ -from __future__ import absolute_import +from __future__ import absolute_import, print_function from itertools import repeat, izip from .control_element import ControlElementClient, get_element from .resource import ExclusiveResource, CompoundResource @@ -46,9 +46,9 @@ def __init__(self, layer = None, layer_client = None, *a, **k): def set_control_element(self, control_element, grabbed): layer = self.layer owner = self.layer_client - raise owner or AssertionError - if not control_element in layer._element_to_names: - raise AssertionError, 'Control not in layer: %s' % (control_element,) + if not owner: + raise AssertionError + raise control_element in layer._element_to_names or AssertionError('Control not in layer: %s' % (control_element,)) names = layer._element_to_names[control_element] control_element = grabbed or None for name in names: @@ -75,16 +75,16 @@ class CompoundLayer(CompoundResource): thought. """ - def _get_priority(self): + @property + def priority(self): raise self.first.priority == self.second.priority or AssertionError return self.first.priority - def _set_priority(self, priority): + @priority.setter + def priority(self, priority): self.first.priority = priority self.second.priority = priority - priority = property(_get_priority, _set_priority) - def __getattr__(self, key): try: return getattr(self.first, key) @@ -101,17 +101,17 @@ def __init__(self, priority = None, *a, **k): def __add__(self, other): return CompoundLayer(self, other) - def _get_priority(self): + @property + def priority(self): return self._priority - def _set_priority(self, priority): + @priority.setter + def priority(self, priority): if priority != self._priority: if self.owner: raise RuntimeError("Cannot change priority of a layer while it's owned") self._priority = priority - priority = property(_get_priority, _set_priority) - def grab(self, client, *a, **k): if client == self.owner: self.on_received(client, *a, **k) diff --git a/ableton/v2/control_surface/midi.py b/ableton/v2/control_surface/midi.py index 83e49c9b..6f21f62e 100644 --- a/ableton/v2/control_surface/midi.py +++ b/ableton/v2/control_surface/midi.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/midi.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/midi.py +from __future__ import absolute_import, print_function from itertools import imap NOTE_ON_STATUS = 144 NOTE_OFF_STATUS = 128 @@ -42,7 +43,9 @@ def is_pitchbend(midi_bytes): def extract_value(midi_bytes): - return midi_bytes[1] + (midi_bytes[2] << 7) if is_pitchbend(midi_bytes) else midi_bytes[2] + if is_pitchbend(midi_bytes): + return midi_bytes[1] + (midi_bytes[2] << 7) + return midi_bytes[2] def pretty_print_bytes(midi_bytes): diff --git a/ableton/v2/control_surface/midi_map.py b/ableton/v2/control_surface/midi_map.py index 7355a49f..f3968f56 100644 --- a/ableton/v2/control_surface/midi_map.py +++ b/ableton/v2/control_surface/midi_map.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/midi_map.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/midi_map.py +from __future__ import absolute_import, print_function import Live from .elements import ButtonMatrixElement, ButtonElement, EncoderElement, SliderElement diff --git a/ableton/v2/control_surface/mode.py b/ableton/v2/control_surface/mode.py index 53280b08..af36a70a 100644 --- a/ableton/v2/control_surface/mode.py +++ b/ableton/v2/control_surface/mode.py @@ -1,8 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/mode.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/mode.py """ Mode handling components. """ -from __future__ import absolute_import +from __future__ import absolute_import, print_function from ..base import depends, infinite_context_manager, listens, is_contextmanager, is_iterable, lazy_attribute, listenable_property, NamedTuple, task from . import defaults from .layer import Layer, CompoundLayer @@ -21,7 +21,7 @@ def tomode(thing): if isinstance(thing, tuple) and len(thing) == 2: if isinstance(thing[0], Component) and isinstance(thing[1], (Layer, CompoundLayer)): return LayerMode(*thing) - elif callable(thing[0]) and callable(thing[1]): + if callable(thing[0]) and callable(thing[1]): mode = Mode() mode.enter_mode, mode.leave_mode = thing return mode @@ -126,7 +126,9 @@ def __init__(self, component = None, layer = None, *a, **k): self._layer = layer def _get_component(self): - return self._component() if callable(self._component) else self._component + if callable(self._component): + return self._component() + return self._component class LayerMode(LayerModeBase): @@ -189,7 +191,9 @@ def __init__(self, obj = None, attribute = None, value = None, *a, **k): self._value = value def _get_object(self): - return self._obj() if callable(self._obj) else self._obj + if callable(self._obj): + return self._obj() + return self._obj def enter_mode(self): self._old_value = getattr(self._get_object(), self._attribute, None) @@ -442,7 +446,9 @@ def selected_mode(self, mode): @property def selected_groups(self): entry = self._mode_map.get(self.selected_mode, None) - return entry.groups if entry else set() + if entry: + return entry.groups + return set() @property def active_modes(self): @@ -505,7 +511,9 @@ def modes(self): def get_mode_groups(self, name): entry = self._mode_map.get(name, None) - return entry.groups if entry else set() + if entry: + return entry.groups + return set() def add_mode_button_control(self, mode_name, behaviour): button_control = make_mode_button_control(self, mode_name, behaviour) @@ -514,7 +522,9 @@ def add_mode_button_control(self, mode_name, behaviour): def _get_mode_behaviour(self, name): entry = self._mode_map.get(name, None) - return entry.behaviour if entry is not None else self.default_behaviour + if entry is not None: + return entry.behaviour + return self.default_behaviour def get_mode(self, name): entry = self._mode_map.get(name, None) diff --git a/ableton/v2/control_surface/profile.py b/ableton/v2/control_surface/profile.py index e2c42803..88a0dcc7 100644 --- a/ableton/v2/control_surface/profile.py +++ b/ableton/v2/control_surface/profile.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/profile.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/profile.py +from __future__ import absolute_import, print_function from functools import wraps, partial ENABLE_PROFILING = False if ENABLE_PROFILING: @@ -17,7 +17,7 @@ def wrapper(self, *a, **k): if PROFILER: return PROFILER.runcall(partial(fn, self, *a, **k)) else: - print 'Can not profile (%s), it is probably reloaded' % fn.__name__ + print('Can not profile (%s), it is probably reloaded' % fn.__name__) return fn(*a, **k) return wrapper diff --git a/ableton/v2/control_surface/resource.py b/ableton/v2/control_surface/resource.py index 6875bedf..87202ad9 100644 --- a/ableton/v2/control_surface/resource.py +++ b/ableton/v2/control_surface/resource.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/resource.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/resource.py +from __future__ import absolute_import, print_function from functools import partial from ..base import Proxy, index_if, nop, first, NamedTuple DEFAULT_PRIORITY = 0 @@ -77,7 +77,7 @@ def __init__(self, on_received_callback = None, on_lost_callback = None, *a, **k def grab(self, client, *a, **k): if not client is not None: - raise AssertionError, 'Someone has to adquire resource' + raise AssertionError('Someone has to adquire resource') self._owner == None and self.on_received(client, *a, **k) self._owner = client return self._owner == client @@ -114,7 +114,7 @@ def __init__(self, on_received_callback = None, on_lost_callback = None, *a, **k self._clients = set() def grab(self, client, *a, **k): - raise client is not None or AssertionError, 'Someone has to adquire resource' + raise client is not None or AssertionError('Someone has to adquire resource') self.on_received(client, *a, **k) self._clients.add(client) return True @@ -131,7 +131,7 @@ def release(self, client): return False def get_owner(self): - raise False or AssertionError, 'Shared resource has no owner' + raise False or AssertionError('Shared resource has no owner') def on_received(self, client, *a, **k): raise NotImplementedError('Override or pass callback') @@ -221,11 +221,15 @@ def _remove_client(self, client): return True def _actual_owners(self): - return [self._clients[-1][0]] if self._clients else [] + if self._clients: + return [self._clients[-1][0]] + return [] @property def max_priority(self): - return self._clients[-1][1] if self._clients else DEFAULT_PRIORITY + if self._clients: + return self._clients[-1][1] + return DEFAULT_PRIORITY @property def stack_size(self): diff --git a/ableton/v2/control_surface/skin.py b/ableton/v2/control_surface/skin.py index 9e268df2..49659ec7 100644 --- a/ableton/v2/control_surface/skin.py +++ b/ableton/v2/control_surface/skin.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/ableton/v2/control_surface/skin.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/ableton/v2/control_surface/skin.py +from __future__ import absolute_import, print_function from itertools import chain from ableton.v2.base import depends, const, liveobj_valid, SlotManager from ableton.v2.control_surface.elements.color import is_dynamic_color_factory diff --git a/microKONTROL/__init__.py b/microKONTROL/__init__.py index 5f0aac1c..293146d7 100644 --- a/microKONTROL/__init__.py +++ b/microKONTROL/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/microKONTROL/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/microKONTROL/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/microKONTROL/config.py b/microKONTROL/config.py index 5880537e..b52817ba 100644 --- a/microKONTROL/config.py +++ b/microKONTROL/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/microKONTROL/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/microKONTROL/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/microKONTROL/consts.py b/microKONTROL/consts.py index 02e3227a..41d2bb64 100644 --- a/microKONTROL/consts.py +++ b/microKONTROL/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/microKONTROL/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/microKONTROL/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/padKONTROL/__init__.py b/padKONTROL/__init__.py index b8e207c8..0dee7ffb 100644 --- a/padKONTROL/__init__.py +++ b/padKONTROL/__init__.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/padKONTROL/__init__.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/padKONTROL/__init__.py from _Generic.GenericScript import GenericScript import Live from config import * diff --git a/padKONTROL/config.py b/padKONTROL/config.py index f66f723f..b04fcc14 100644 --- a/padKONTROL/config.py +++ b/padKONTROL/config.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/padKONTROL/config.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/padKONTROL/config.py from consts import * TRANSPORT_CONTROLS = {'STOP': GENERIC_STOP, 'PLAY': GENERIC_PLAY, diff --git a/padKONTROL/consts.py b/padKONTROL/consts.py index f04a13c1..9eb14578 100644 --- a/padKONTROL/consts.py +++ b/padKONTROL/consts.py @@ -1,4 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/padKONTROL/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/padKONTROL/consts.py """ The following consts should be substituted with the Sys Ex messages for requesting a controller's ID response and that response to allow for automatic lookup""" ID_REQUEST = 0 diff --git a/pushbase/__init__.py b/pushbase/__init__.py index 072fe485..e068acea 100644 --- a/pushbase/__init__.py +++ b/pushbase/__init__.py @@ -1,2 +1,2 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/__init__.py -pass \ No newline at end of file +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/__init__.py +from __future__ import absolute_import, print_function \ No newline at end of file diff --git a/pushbase/accent_component.py b/pushbase/accent_component.py index 5d44a6ab..9e5dbd72 100644 --- a/pushbase/accent_component.py +++ b/pushbase/accent_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/accent_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/accent_component.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface.mode import ModesComponent class DummyFullVelocity(object): @@ -16,9 +17,9 @@ def __init__(self, *a, **k): self.set_full_velocity(None) def set_full_velocity(self, full_velocity): - if not full_velocity: - full_velocity = DummyFullVelocity() - self._full_velocity.enabled = self._full_velocity != None and False + full_velocity = full_velocity or DummyFullVelocity() + if self._full_velocity != None: + self._full_velocity.enabled = False self._full_velocity = full_velocity self._full_velocity.enabled = self.selected_mode == 'enabled' diff --git a/pushbase/action_with_options_component.py b/pushbase/action_with_options_component.py index 2fb559ea..4736e69d 100644 --- a/pushbase/action_with_options_component.py +++ b/pushbase/action_with_options_component.py @@ -1,4 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/action_with_options_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/action_with_options_component.py +from __future__ import absolute_import, print_function +from itertools import izip_longest from ableton.v2.base import in_range, clamp, task from ableton.v2.control_surface import CompoundComponent, Component, defaults from ableton.v2.control_surface.elements import DisplayDataSource @@ -112,7 +114,7 @@ def _get_labels(self): return map(lambda segment: segment.display_string(), self._label_data_sources) def _set_labels(self, labels): - for segment, label in map(None, self._label_data_sources, labels or []): + for segment, label in izip_longest(self._label_data_sources, labels or []): segment.set_display_string(label) labels = property(_get_labels, _set_labels) @@ -141,7 +143,7 @@ def _update_select_buttons(self): button.color = self.selected_color if index == self._selected_option else self.unselected_color def _update_data_sources(self): - for index, (source, name) in enumerate(map(None, self._data_sources, self.option_names)): + for index, (source, name) in enumerate(izip_longest(self._data_sources, self.option_names)): if name: source.set_display_string((consts.CHAR_SELECT if index == self._selected_option else ' ') + name) else: diff --git a/pushbase/actions.py b/pushbase/actions.py index d0a6cdc4..da2e4eb0 100644 --- a/pushbase/actions.py +++ b/pushbase/actions.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/actions.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/actions.py +from __future__ import absolute_import, print_function from itertools import izip, count import Live from ableton.v2.base import forward_property, listens, listens_group, liveobj_valid @@ -322,7 +323,10 @@ def stop_all_clips_button(self, button): @stop_track_clips_buttons.pressed def stop_track_clips_buttons(self, button): - button.track.stop_all_clips() + self._stop_clips_in_track(button.track) + + def _stop_clips_in_track(self, track): + track.stop_all_clips() @listens('tracks') def _on_tracks_changed(self): @@ -365,9 +369,9 @@ def _color_for_button(self, track): return color def _update_stop_button(self, track, button): - if isinstance(track, Live.Track.Track): - has_clip_slots = bool(track.clip_slots) - button.color = has_clip_slots and self._color_for_button(track) + has_clip_slots = isinstance(track, Live.Track.Track) and bool(track.clip_slots) + if has_clip_slots: + button.color = self._color_for_button(track) button.enabled = bool(has_clip_slots) button.track = track diff --git a/pushbase/auto_arm_component.py b/pushbase/auto_arm_component.py index b6d8ba73..b96608d5 100644 --- a/pushbase/auto_arm_component.py +++ b/pushbase/auto_arm_component.py @@ -1,7 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/auto_arm_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/auto_arm_component.py """ Component that automatically arms the selected track. """ +from __future__ import absolute_import, print_function from functools import partial from itertools import ifilter from ableton.v2.base import mixin, nop, listens, listens_group @@ -105,14 +106,14 @@ def _hide_notification(self): def update(self): super(AutoArmComponent, self).update() song = self.song - if self.is_enabled(): - enabled = not self.needs_restore_auto_arm - selected_track = song.view.selected_track - for track in song.tracks: - if self.track_can_be_armed(track): - track.implicit_arm = enabled and selected_track == track and self.can_auto_arm_track(track) - - self._auto_arm_restore_behaviour and self._auto_arm_restore_behaviour.update() + enabled = self.is_enabled() and not self.needs_restore_auto_arm + selected_track = song.view.selected_track + for track in song.tracks: + if self.track_can_be_armed(track): + track.implicit_arm = enabled and selected_track == track and self.can_auto_arm_track(track) + + if self._auto_arm_restore_behaviour: + self._auto_arm_restore_behaviour.update() self._update_notification() def restore_auto_arm(self): diff --git a/pushbase/automation_component.py b/pushbase/automation_component.py index 7781144a..677c808c 100644 --- a/pushbase/automation_component.py +++ b/pushbase/automation_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/automation_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/automation_component.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import clamp, task, liveobj_valid from ableton.v2.control_surface.control import EncoderControl, control_list @@ -43,14 +44,14 @@ def _set_selected_time(self, value): @property def parameters(self): - return map(lambda info: info.parameter if info else None, self._parameter_infos_to_use()) + return map(lambda info: (info.parameter if info else None), self._parameter_infos_to_use()) @property def parameter_infos(self): return self._parameter_infos_to_use() def _parameter_infos_to_use(self): - return map(lambda info: info if self.parameter_is_automateable(info.parameter if info else None) else None, self._parameter_provider.parameters) + return map(lambda info: (info if self.parameter_is_automateable(info.parameter if info else None) else None), self._parameter_provider.parameters) @property def can_automate_parameters(self): @@ -72,7 +73,7 @@ def _connect_parameters(self): def parameter_to_string(self, parameter): if not parameter: return '' - elif len(self._selected_time) == 0: + if len(self._selected_time) == 0: return '-' return parameter.str_for_value(self.parameter_to_value(parameter)) diff --git a/pushbase/banking_util.py b/pushbase/banking_util.py new file mode 100644 index 00000000..713c9c44 --- /dev/null +++ b/pushbase/banking_util.py @@ -0,0 +1,109 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/banking_util.py +from __future__ import absolute_import, print_function +from math import ceil +from copy import deepcopy +from ableton.v2.base import liveobj_valid +MX_MAIN_BANK_INDEX = -1 +BANK_FORMAT = 'Bank %d' +PARAMETERS_KEY = 'Parameters' +MAIN_KEY = 'Main' + +def has_bank_count(device): + if liveobj_valid(device): + try: + num_banks = device.get_bank_count() + return num_banks > 0 + except (AttributeError, RuntimeError): + pass + + return False + + +def has_main_bank(device, definitions): + if has_bank_count(device): + try: + main_bank = device.get_bank_parameters(MX_MAIN_BANK_INDEX) + return bool(main_bank) + except (AttributeError, RuntimeError): + return False + + else: + return MAIN_KEY in definitions.get(device.class_name, {}) + + +def has_bank_names(device, definitions): + if has_bank_count(device): + try: + name = device.get_bank_name(0) + return bool(name) + except (AttributeError, RuntimeError): + return False + + else: + return bool(definitions.get(device.class_name, {}).keys()) + + +def all_parameters(device): + if liveobj_valid(device): + return list(device.parameters[1:]) + return [] + + +def device_bank_count(device, bank_size = 8, definition = None, definitions = None): + count = 0 + if liveobj_valid(device): + definition = definition or definitions.get(device.class_name, {}) + if has_bank_count(device): + count = device.get_bank_count() + int(has_main_bank(device, definitions)) + elif definition: + count = len(definition.keys()) + else: + count = int(ceil(float(len(all_parameters(device))) / bank_size)) + return count + + +def device_bank_definition(device, definitions): + original_definition = definitions.get(device.class_name, None) + definition = deepcopy(original_definition) if original_definition is not None else None + return definition + + +def device_bank_names(device, bank_size = 8, definitions = None): + names = [] + if liveobj_valid(device): + class_name = device.class_name + if class_name in definitions: + names = definitions[class_name].keys() + elif has_bank_count(device) and has_bank_names(device, definitions): + offset = int(has_main_bank(device, definitions)) + names = [ device.get_bank_name(index - offset) for index in xrange(device_bank_count(device, definitions=definitions)) ] + if has_main_bank(device, definitions) and not names[0]: + names[0] = MAIN_KEY + else: + bank_count = device_bank_count(device, bank_size=bank_size, definitions=definitions) + names = [ BANK_FORMAT % (index + 1) for index in xrange(bank_count) ] + return names + + +class BankingInfo(object): + + def __init__(self, bank_definitions): + self._bank_definitions = bank_definitions + + def has_bank_count(self, device): + return has_bank_count(device) + + def has_main_bank(self, device): + return has_main_bank(device, definitions=self._bank_definitions) + + def has_bank_names(self, device): + return has_bank_names(device, definitions=self._bank_definitions) + + def device_bank_count(self, device, **k): + return device_bank_count(device, definitions=self._bank_definitions, **k) + + def device_bank_definition(self, device): + return device_bank_definition(device, definitions=self._bank_definitions) + + def device_bank_names(self, device, **k): + return device_bank_names(device, definitions=self._bank_definitions, **k) \ No newline at end of file diff --git a/pushbase/browser_modes.py b/pushbase/browser_modes.py index 1ed07ec6..c9c3aeb9 100644 --- a/pushbase/browser_modes.py +++ b/pushbase/browser_modes.py @@ -1,7 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/browser_modes.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/browser_modes.py """ Different mode objects that turn live into different browsing modes. """ +from __future__ import absolute_import, print_function import Live from ableton.v2.base import depends, index_if, liveobj_valid from ableton.v2.control_surface.mode import Mode @@ -68,7 +69,9 @@ def leave_mode(self): self._browser.filter_type = Live.Browser.FilterType.disabled def get_insert_mode(self): - return Live.Track.DeviceInsertMode.selected_left if self.insert_left else Live.Track.DeviceInsertMode.selected_right + if self.insert_left: + return Live.Track.DeviceInsertMode.selected_left + return Live.Track.DeviceInsertMode.selected_right def get_selection_for_insert(self): """ @@ -83,9 +86,9 @@ def get_filter_type(self): index = index_if(lambda device: device == selected, chain.devices) is_drum_pad = isinstance(chain.canonical_parent, Live.DrumPad.DrumPad) midi_support = chain.has_midi_input - if not is_drum_pad: - supports_instrument = chain.has_midi_input and (chain.has_audio_output or isinstance(chain, Live.Track.Track)) - left = self.insert_left and (chain.devices[index - 1] if index > 0 else None) + supports_instrument = is_drum_pad or chain.has_midi_input and (chain.has_audio_output or isinstance(chain, Live.Track.Track)) + if self.insert_left: + left = chain.devices[index - 1] if index > 0 else None return filter_type_between(left, selected, midi_support, is_drum_pad, supports_instrument) else: right = chain.devices[index + 1] if index < chain_len - 1 else None @@ -114,7 +117,9 @@ def filter_type_between(left, right, supports_midi = False, is_drum_pad = False, return Types.audio_effect_hotswap if supports_midi: if supports_instrument: - return Types.drum_pad_hotswap if is_drum_pad else Types.instrument_hotswap + if is_drum_pad: + return Types.drum_pad_hotswap + return Types.instrument_hotswap else: return Types.midi_effect_hotswap return Types.audio_effect_hotswap \ No newline at end of file diff --git a/pushbase/browser_util.py b/pushbase/browser_util.py index 390512c8..37416078 100644 --- a/pushbase/browser_util.py +++ b/pushbase/browser_util.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/browser_util.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/browser_util.py +from __future__ import absolute_import, print_function import Live FilterType = Live.Browser.FilterType DeviceType = Live.Device.DeviceType @@ -10,16 +11,18 @@ def filter_type_for_hotswap_target(target, default = FilterType.disabled): if isinstance(target, Live.Device.Device): if target.type == DeviceType.instrument: return FilterType.instrument_hotswap - elif target.type == DeviceType.audio_effect: + if target.type == DeviceType.audio_effect: return FilterType.audio_effect_hotswap - elif target.type == DeviceType.midi_effect: + if target.type == DeviceType.midi_effect: return FilterType.midi_effect_hotswap - else: - FilterType.disabled - elif isinstance(target, Live.DrumPad.DrumPad): - return FilterType.drum_pad_hotswap - elif isinstance(target, Live.Chain.Chain): - return filter_type_for_hotswap_target(target.canonical_parent) if target else FilterType.disabled + FilterType.disabled + else: + if isinstance(target, Live.DrumPad.DrumPad): + return FilterType.drum_pad_hotswap + if isinstance(target, Live.Chain.Chain): + if target: + return filter_type_for_hotswap_target(target.canonical_parent) + return FilterType.disabled return default diff --git a/pushbase/clip_control_component.py b/pushbase/clip_control_component.py index b38cf0a4..67ba4eda 100644 --- a/pushbase/clip_control_component.py +++ b/pushbase/clip_control_component.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/clip_control_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/clip_control_component.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import clamp, listens, liveobj_valid, nop, Subject, SlotManager, forward_property from ableton.v2.control_surface import Component @@ -69,6 +69,7 @@ def _get_clip(self): def _set_clip(self, clip): self._clip = clip + self._loop_length = self._get_loop_length() self._on_looping_changed.subject = clip self._on_start_marker_changed.subject = clip self._on_loop_start_changed.subject = clip @@ -92,13 +93,13 @@ def _on_start_marker_changed(self): @listens('loop_start') def _on_loop_start_changed(self): + self._update_loop_length() self.notify_loop_start() - self.notify_loop_length() @listens('loop_end') def _on_loop_end_changed(self): + self._update_loop_length() self.notify_loop_end() - self.notify_loop_length() @listens('position') def _on_position_changed(self): @@ -106,7 +107,18 @@ def _on_position_changed(self): @property def loop_length(self): - return self.loop_end - self.loop_start + return self._loop_length + + def _get_loop_length(self): + if liveobj_valid(self._clip): + return self.loop_end - self.loop_start + return 0 + + def _update_loop_length(self): + loop_length = self._get_loop_length() + if self._loop_length != loop_length: + self._loop_length = loop_length + self.notify_loop_length() @property def can_loop(self): @@ -141,7 +153,9 @@ def _adjusted_offset(self, value, fine_grained): return value * self._encoder_factor(fine_grained) * one_measure_in_note_values(self.clip) def _encoder_factor(self, fine_grained): - return 1.0 / one_measure_in_note_values(self.clip, 16.0) if fine_grained else 1.0 + if fine_grained: + return 1.0 / one_measure_in_note_values(self.clip, 16.0) + return 1.0 class LoopSettingsControllerComponent(Component): @@ -158,6 +172,22 @@ def __init__(self, *a, **k): self._on_clip_end_value, nop, self._on_clip_looping_value] + self._touched_encoder_callbacks_looped = [self._on_clip_position_touched, + self._on_clip_end_touched, + self._on_clip_start_marker_touched, + self._on_clip_looping_touched] + self._touched_encoder_callbacks_unlooped = [self._on_clip_start_marker_touched, + self._on_clip_end_touched, + nop, + self._on_clip_looping_touched] + self._released_encoder_callbacks_looped = [self._on_clip_position_released, + self._on_clip_end_released, + self._on_clip_start_marker_released, + self._on_clip_looping_released] + self._released_encoder_callbacks_unlooped = [self._on_clip_start_marker_released, + self._on_clip_end_released, + nop, + self._on_clip_looping_released] self._loop_model = self.register_disconnectable(LoopSettingsModel(self.song)) self._update_encoder_state() @@ -180,6 +210,16 @@ def encoders(self, value, encoder): callback_set = self._encoder_callbacks_looped if self._loop_model.looping else self._encoder_callbacks_unlooped callback_set[encoder.index](value) + @encoders.touched + def encoders(self, encoder): + callback_set = self._touched_encoder_callbacks_looped if self._loop_model.looping else self._touched_encoder_callbacks_unlooped + callback_set[encoder.index]() + + @encoders.released + def encoders(self, encoder): + callback_set = self._released_encoder_callbacks_looped if self._loop_model.looping else self._released_encoder_callbacks_unlooped + callback_set[encoder.index]() + def _update_encoder_state(self): enable_encoders = liveobj_valid(self.clip) for encoder in self.encoders: @@ -200,6 +240,30 @@ def _on_clip_looping_value(self, value): if value >= 0 and not currently_looping or value < 0 and currently_looping: self._loop_model.looping = not currently_looping + def _on_clip_start_marker_touched(self): + pass + + def _on_clip_end_touched(self): + pass + + def _on_clip_position_touched(self): + pass + + def _on_clip_looping_touched(self): + pass + + def _on_clip_start_marker_released(self): + pass + + def _on_clip_end_released(self): + pass + + def _on_clip_position_released(self): + pass + + def _on_clip_looping_released(self): + pass + class LoopSettingsComponent(LoopSettingsControllerComponent): """ @@ -331,7 +395,9 @@ def set_clip_pitch_fine(self, value, fine_grained): self.clip.pitch_fine = int(self.clip.pitch_fine + value * 100.0 * self._encoder_factor(fine_grained)) def _encoder_factor(self, fine_grained): - return 0.1 if fine_grained else 1.0 + if fine_grained: + return 0.1 + return 1.0 @listens('pitch_fine') def __on_pitch_fine_changed(self): @@ -355,7 +421,9 @@ def __on_warping_changed(self): @property def available_warp_modes(self): - return list(self.clip.available_warp_modes) if liveobj_valid(self.clip) else [] + if liveobj_valid(self.clip): + return list(self.clip.available_warp_modes) + return [] class AudioClipSettingsControllerComponent(Component): @@ -529,7 +597,9 @@ def _on_name_changed(self): def _name_for_clip(self, clip): if clip: - return clip.name if clip.name else '[unnamed]' + if clip.name: + return clip.name + return '[unnamed]' else: return '[none]' diff --git a/pushbase/colors.py b/pushbase/colors.py index 7e782cc2..cef18cb9 100644 --- a/pushbase/colors.py +++ b/pushbase/colors.py @@ -1,8 +1,9 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/colors.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/colors.py """ Module for the color interfaces defining all posible ways of turning on buttons on Push. """ +from __future__ import absolute_import, print_function from itertools import izip, repeat from ableton.v2.control_surface.elements import Color, to_midi_value diff --git a/pushbase/configurable_button_element.py b/pushbase/configurable_button_element.py index 0926603b..0e1b5ae8 100644 --- a/pushbase/configurable_button_element.py +++ b/pushbase/configurable_button_element.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/configurable_button_element.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/configurable_button_element.py +from __future__ import absolute_import, print_function from ableton.v2.base import in_range from ableton.v2.control_surface import Skin, SkinColorMissingError from ableton.v2.control_surface.elements import ButtonElement, ON_VALUE, OFF_VALUE diff --git a/pushbase/consts.py b/pushbase/consts.py index 6eed2e1f..86657bb8 100644 --- a/pushbase/consts.py +++ b/pushbase/consts.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/consts.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/consts.py +from __future__ import absolute_import, print_function import sys import Live from ableton.v2.control_surface import DEFAULT_PRIORITY @@ -18,7 +19,7 @@ NOTIFICATION_PRIORITY = DEFAULT_PRIORITY + 1 BACKGROUND_PRIORITY = DEFAULT_PRIORITY - 3 ENCODER_SENSITIVITY = 0.5 -CONTINUOUS_MAPPING_SENSITIVITY = 1.0 +CONTINUOUS_MAPPING_SENSITIVITY = 2.0 FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY = 0.01 QUANTIZED_MAPPING_SENSITIVITY = 1.0 / 15.0 GLOBAL_MAP_MODE = Live.MidiMap.MapMode.relative_smooth_two_compliment diff --git a/pushbase/control_element_factory.py b/pushbase/control_element_factory.py index fbfde891..a6c52050 100644 --- a/pushbase/control_element_factory.py +++ b/pushbase/control_element_factory.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/control_element_factory.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/control_element_factory.py +from __future__ import absolute_import, print_function from ableton.v2.base import depends from ableton.v2.control_surface import MIDI_CC_TYPE, MIDI_NOTE_TYPE, PrioritizedResource, midi from ableton.v2.control_surface.elements import SysexElement diff --git a/pushbase/decoration.py b/pushbase/decoration.py new file mode 100644 index 00000000..75d5a323 --- /dev/null +++ b/pushbase/decoration.py @@ -0,0 +1,91 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/decoration.py +from __future__ import absolute_import, print_function +from itertools import ifilter +from ableton.v2.base import CompoundDisconnectable, Proxy + +class LiveObjectDict(dict): + + def __init__(self, *a, **k): + self.update(*a, **k) + + def __getitem__(self, key): + return super(LiveObjectDict, self).__getitem__(self._transform_key(key)) + + def __setitem__(self, key, value): + return super(LiveObjectDict, self).__setitem__(self._transform_key(key), value) + + def __delitem__(self, key): + return super(LiveObjectDict, self).__delitem__(self._transform_key(key)) + + def __contains__(self, key): + return super(LiveObjectDict, self).__contains__(self._transform_key(key)) + + def get(self, key, *default): + return super(LiveObjectDict, self).get(self._transform_key(key), *default) + + def _transform_key(self, key): + raise hasattr(key, '_live_ptr') or AssertionError + return key._live_ptr + + def update(self, *a, **k): + trans = self._transform_key + super(LiveObjectDict, self).update(*[ (trans(key), v) for key, v in a ], **dict(((trans(key), k[key]) for key in k))) + + def prune(self, keys): + transformed_keys = map(self._transform_key, keys) + deleted_objects = [] + for key in ifilter(lambda x: x not in transformed_keys, self.keys()): + deleted_objects.append(super(LiveObjectDict, self).__getitem__(key)) + super(LiveObjectDict, self).__delitem__(key) + + return deleted_objects + + +class LiveObjectDecorator(CompoundDisconnectable, Proxy): + + def __init__(self, live_object = None, additional_properties = {}): + raise live_object is not None or AssertionError + super(LiveObjectDecorator, self).__init__(proxied_object=live_object) + self._live_object = live_object + for name, value in additional_properties.iteritems(): + setattr(self, name, value) + + def __eq__(self, other): + return id(self) == id(other) or self._live_object == other + + def __ne__(self, other): + return not self == other + + def __nonzero__(self): + return self._live_object != None + + def __hash__(self): + return hash(self._live_object) + + +class DecoratorFactory(CompoundDisconnectable): + _decorator = LiveObjectDecorator + + def __init__(self, *a, **k): + super(DecoratorFactory, self).__init__(*a, **k) + self.decorated_objects = LiveObjectDict() + + def decorate(self, live_object, additional_properties = {}, **k): + if self._should_be_decorated(live_object): + if not self.decorated_objects.get(live_object, None): + self.decorated_objects[live_object] = self.register_disconnectable(self._get_decorated_object(live_object, additional_properties, **k)) + live_object = self.decorated_objects[live_object] + return live_object + + def _get_decorated_object(self, live_object, additional_properties, **k): + return self._decorator(live_object=live_object, additional_properties=additional_properties, **k) + + def sync_decorated_objects(self, keys): + deleted_objects = self.decorated_objects.prune(keys) + for decorated in deleted_objects: + self.unregister_disconnectable(decorated) + decorated.disconnect() + + @classmethod + def _should_be_decorated(cls, device): + return True \ No newline at end of file diff --git a/pushbase/device_chain_utils.py b/pushbase/device_chain_utils.py index 1c6bb3e6..d92bce21 100644 --- a/pushbase/device_chain_utils.py +++ b/pushbase/device_chain_utils.py @@ -1,8 +1,13 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/device_chain_utils.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/device_chain_utils.py +from __future__ import absolute_import, print_function import Live from itertools import imap, chain from functools import partial -from ableton.v2.base import find_if +from ableton.v2.base import find_if, liveobj_valid + +def is_empty_drum_pad(drum_pad): + return isinstance(drum_pad, Live.DrumPad.DrumPad) and (not drum_pad.chains or not drum_pad.chains[0].devices) + def is_first_device_on_pad(device, drum_pad): return find_if(lambda pad: pad.chains and pad.chains[0].devices and pad.chains[0].devices[0] == device, drum_pad.canonical_parent.drum_pads) @@ -13,7 +18,7 @@ def find_instrument_devices(track_or_chain): Returns a list with all instruments from a track or chain. """ instrument = find_if(lambda d: d.type == Live.Device.DeviceType.instrument, track_or_chain.devices) - if instrument: + if liveobj_valid(instrument): if not instrument.can_have_drum_pads and instrument.can_have_chains: return chain([instrument], *imap(find_instrument_devices, instrument.chains)) return [instrument] @@ -22,9 +27,13 @@ def find_instrument_devices(track_or_chain): def find_instrument_meeting_requirement(requirement, track_or_chain): instrument = find_if(lambda d: d.type == Live.Device.DeviceType.instrument, track_or_chain.devices) - if instrument: + if liveobj_valid(instrument): if requirement(instrument): return instrument - elif instrument.can_have_chains: + if instrument.can_have_chains: recursive_call = partial(find_instrument_meeting_requirement, requirement) - return find_if(bool, imap(recursive_call, instrument.chains)) \ No newline at end of file + return find_if(bool, imap(recursive_call, instrument.chains)) + + +def is_simpler(device): + return device and device.class_name == 'OriginalSimpler' \ No newline at end of file diff --git a/pushbase/device_component.py b/pushbase/device_component.py new file mode 100644 index 00000000..03414e9d --- /dev/null +++ b/pushbase/device_component.py @@ -0,0 +1,115 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/device_component.py +from __future__ import absolute_import, print_function +from ableton.v2.base import depends, listens, liveobj_valid, liveobj_changed +from ableton.v2.control_surface import CompoundComponent +from .device_parameter_bank import create_device_bank +from .parameter_provider import ParameterProvider, generate_info +from .simpler_slice_nudging import SimplerSliceNudging + +class DeviceComponent(ParameterProvider, CompoundComponent): + """ + Device component that serves as parameter provider for the + DeviceParameterComponent. + """ + __events__ = ('device',) + _provided_parameters = tuple() + + @depends(device_provider=None) + def __init__(self, device_decorator_factory = None, banking_info = None, device_bank_registry = None, device_provider = None, *a, **k): + self._bank = None + self._banking_info = banking_info + self._decorated_device = None + self._decorator_factory = device_decorator_factory + self._device_provider = device_provider + self._device_bank_registry = device_bank_registry + super(DeviceComponent, self).__init__(*a, **k) + self._initialize_subcomponents() + self.__on_bank_changed.subject = device_bank_registry + self.__on_provided_device_changed.subject = device_provider + self.__on_provided_device_changed() + + def set_device(self, device): + self._device_provider.device = device + + def device(self): + return self._decorated_device + + def _initialize_subcomponents(self): + self._slice_nudging = self.register_disconnectable(SimplerSliceNudging()) + + @property + def parameters(self): + return self._provided_parameters + + @listens('device_bank') + def __on_bank_changed(self, device, bank): + self._set_bank_index(device, bank) + + def _set_bank_index(self, device, bank): + if self._bank is not None: + self._bank.index = bank + + def _update_parameters(self): + self._provided_parameters = self._get_provided_parameters() + self.notify_parameters() + + def _setup_bank(self, device, bank_factory = create_device_bank): + if self._bank is not None: + self.disconnect_disconnectable(self._bank) + self._bank = None + if liveobj_valid(device): + self._bank = self.register_disconnectable(bank_factory(device, self._banking_info)) + + def _get_decorated_device(self, device): + if self._decorator_factory is not None: + return self._decorator_factory.decorate(device) + return device + + def _device_changed(self, device): + current_device = getattr(self.device(), '_live_object', self.device()) + return liveobj_changed(current_device, device) + + @listens('device') + def __on_provided_device_changed(self): + self._on_device_changed(self._device_provider.device) + + @listens('parameters') + def __on_parameters_changed_in_device(self): + self._update_parameters() + + def _on_device_changed(self, device): + if self._device_changed(device): + self._set_device(device) + + def _set_decorated_device(self, decorated_device): + self._setup_bank(decorated_device) + self._on_bank_parameters_changed.subject = self._bank + self._slice_nudging.set_device(decorated_device) + self._decorated_device = decorated_device + + def _set_device(self, device): + decorated_device = self._get_decorated_device(device) + self._set_decorated_device(decorated_device) + bank_index_for_device = self._device_bank_registry.get_device_bank(device) + self._set_bank_index(device, bank_index_for_device) + self.notify_device() + self._update_parameters() + self.__on_parameters_changed_in_device.subject = device + + @listens('parameters') + def _on_bank_parameters_changed(self): + self._update_parameters() + + def _current_bank_details(self): + if self._bank is not None: + return (self._bank.name, self._bank.parameters) + return ('', [None] * 8) + + def _number_of_parameter_banks(self): + if self._bank is not None: + return self._bank.bank_count() + return 0 + + def _get_provided_parameters(self): + _, parameters = self._current_bank_details() if self.device() else (None, ()) + return [ generate_info(p) for p in parameters ] \ No newline at end of file diff --git a/pushbase/device_parameter_bank.py b/pushbase/device_parameter_bank.py new file mode 100644 index 00000000..e2622ffc --- /dev/null +++ b/pushbase/device_parameter_bank.py @@ -0,0 +1,152 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/device_parameter_bank.py +from __future__ import absolute_import, print_function +from ableton.v2.base import SlotManager, Subject, find_if, listens, listens_group, listenable_property, liveobj_valid, clamp +from .banking_util import PARAMETERS_KEY, MAIN_KEY, BANK_FORMAT, all_parameters + +class DeviceParameterBank(SlotManager, Subject): + + def __init__(self, size = None, device = None, banking_info = None, *a, **k): + raise size is not None or AssertionError + super(DeviceParameterBank, self).__init__(*a, **k) + self._size = size + self._device = device + self._banking_info = banking_info + self._index = 0 + self._parameters = None + self._on_parameters_changed.subject = device + self._update_parameters() + + def bank_count(self): + return self._banking_info.device_bank_count(self._device, bank_size=self._size) + + def _adjust_index(self, index): + return clamp(index, 0, max(0, self.bank_count() - 1)) + + def _is_index_valid(self, index): + return self.bank_count() > index + + def _get_index(self): + return self._index + + def _set_index(self, index): + if self._index != index and self._is_index_valid(index): + index = self._adjust_index(index) + self._index = index + self._update_parameters() + + index = property(_get_index, _set_index) + + @listens('parameters') + def _on_parameters_changed(self): + self._index = self._adjust_index(self._index) + self._update_parameters() + + @listenable_property + def parameters(self): + return self._parameters + + def _calc_name(self): + return BANK_FORMAT % (self.index + 1) + + @property + def name(self): + if liveobj_valid(self._device): + return self._calc_name() + return '' + + @property + def device(self): + return self._device + + def _collect_parameters(self): + parameters = all_parameters(self._device) + offset = self._index * self._size + params = parameters[offset:] + params.extend([None] * (self._size - len(params))) + return params + + def _update_parameters(self): + parameters = self._collect_parameters()[:self._size] + if self._parameters != parameters: + self._parameters = parameters + self.notify_parameters() + + +class DescribedDeviceParameterBank(DeviceParameterBank): + + def __init__(self, device = None, banking_info = None, *a, **k): + self._definition = banking_info.device_bank_definition(device) + self._dynamic_slots = [] + super(DescribedDeviceParameterBank, self).__init__(device=device, banking_info=banking_info, *a, **k) + self._update_parameters() + + @listens_group('content') + def _on_slot_content_changed(self, _slot): + self._update_parameters() + + def _current_parameter_slots(self): + return self._definition.value_by_index(self.index).get(PARAMETERS_KEY) or tuple() + + def _content_slots(self): + return self._current_parameter_slots() + + def _setup_dynamic_slots(self): + for slot in self._dynamic_slots: + slot.set_parameter_host(None) + self.unregister_disconnectable(slot) + + self._dynamic_slots = filter(lambda s: hasattr(s, 'notify_content'), self._content_slots()) + for slot in self._dynamic_slots: + self.register_disconnectable(slot) + slot.set_parameter_host(self.device) + + self._on_slot_content_changed.replace_subjects(self._dynamic_slots) + + def _calc_name(self): + return self._definition.key_by_index(self.index) + + def _collect_parameters(self): + parameters = self._device.parameters + bank_slots = self._current_parameter_slots() + return [ find_if(lambda p: p.original_name == str(slot_definition), parameters) for slot_definition in bank_slots ] + + def _update_parameters(self): + self._setup_dynamic_slots() + super(DescribedDeviceParameterBank, self)._update_parameters() + + +class MaxDeviceParameterBank(DeviceParameterBank): + + def __init__(self, *a, **k): + super(MaxDeviceParameterBank, self).__init__(*a, **k) + raise hasattr(self._device, 'get_bank_count') or AssertionError + + def _calc_name(self): + if self.bank_count() == 0: + return MAIN_KEY + mx_index = self.index - int(self._banking_info.has_main_bank(self._device)) + provided_name = self.device.get_bank_name(mx_index) + if len(provided_name) > 0: + return provided_name + return super(MaxDeviceParameterBank, self)._calc_name() + + def _collect_parameters(self): + if self.bank_count() == 0: + return [None] * self._size + parameters = self._device.parameters + mx_index = self.index - int(self._banking_info.has_main_bank(self._device)) + indices = self.device.get_bank_parameters(mx_index) + return [ (parameters[index] if index >= 0 else None) for index in indices ] + + +def create_device_bank(device, banking_info): + bank = None + if liveobj_valid(device): + if banking_info.has_bank_count(device): + bank_class = MaxDeviceParameterBank + elif banking_info.device_bank_definition(device) is not None: + bank_class = DescribedDeviceParameterBank + else: + bank_class = DeviceParameterBank + bank = bank_class(device=device, size=8, banking_info=banking_info) + return bank \ No newline at end of file diff --git a/pushbase/device_parameter_component.py b/pushbase/device_parameter_component.py index e6898437..05ed7c5a 100644 --- a/pushbase/device_parameter_component.py +++ b/pushbase/device_parameter_component.py @@ -1,18 +1,20 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/device_parameter_component.py -from __future__ import absolute_import -from itertools import chain, repeat +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/device_parameter_component.py +from __future__ import absolute_import, print_function +from itertools import chain, repeat, izip_longest import Live from ableton.v2.base import listens_group, listens from ableton.v2.control_surface import Component +from ableton.v2.control_surface.control import ControlList from ableton.v2.control_surface.elements import DisplayDataSource from . import consts +from .mapped_control import MappedControl from .parameter_provider import ParameterProvider AutomationState = Live.DeviceParameter.AutomationState def graphic_bar_for_parameter(parameter): if parameter.min == -1 * parameter.max: return consts.GRAPH_PAN - elif parameter.is_quantized: + if parameter.is_quantized: return consts.GRAPH_SIN return consts.GRAPH_VOL @@ -22,7 +24,7 @@ def convert_parameter_value_to_graphic(param, param_to_value = lambda p: p.value param_range = param.max - param.min param_bar = graphic_bar_for_parameter(param) graph_range = len(param_bar) - 1 - value = int((param_to_value(param) - param.min) / param_range * graph_range) + value = int(float(param_to_value(param) - param.min) / param_range * graph_range) graphic_display_string = param_bar[value] else: graphic_display_string = ' ' @@ -37,6 +39,7 @@ def update_encoder_sensitivity(encoder, parameter_info): class DeviceParameterComponentBase(Component): + controls = ControlList(MappedControl, 8) def __init__(self, parameter_provider = None, *a, **k): super(DeviceParameterComponentBase, self).__init__(*a, **k) @@ -54,10 +57,17 @@ def _set_parameter_provider(self, provider): parameter_provider = property(_get_parameter_provider, _set_parameter_provider) def set_parameter_controls(self, encoders): - self._release_parameters() - self._parameter_controls = encoders or [] + self.controls.set_control_element(encoders) self._connect_parameters() + def _connect_parameters(self): + parameters = self._parameter_provider.parameters[:self.controls.control_count] + for control, parameter_info in map(None, self.controls, parameters): + parameter = parameter_info.parameter if parameter_info else None + control.mapped_parameter = parameter + if parameter: + control.update_sensitivities(parameter_info.default_encoder_sensitivity, parameter_info.fine_grain_encoder_sensitivity) + @property def parameters(self): return map(lambda p: p and p.parameter, self._parameter_provider.parameters) @@ -70,16 +80,6 @@ def _update_parameters(self): if self.is_enabled(): self._connect_parameters() - def _release_parameters(self): - for encoder in self._parameter_controls or []: - encoder.release_parameter() - - def _connect_parameters(self): - for info, encoder in zip(self._parameter_provider.parameters, self._parameter_controls): - if encoder: - encoder.connect_to(info.parameter) - update_encoder_sensitivity(encoder, info) - @listens('parameters') def _on_parameters_changed(self): self._update_parameters() @@ -124,11 +124,16 @@ def _update_parameters(self): super(DeviceParameterComponent, self)._update_parameters() if self.is_enabled(): parameters = self.parameters + self._on_parameter_name_changed.replace_subjects(parameters) self._on_parameter_value_changed.replace_subjects(parameters) self._on_parameter_automation_state_changed.replace_subjects(parameters) self._update_parameter_names() self._update_parameter_values() + @listens_group('name') + def _on_parameter_name_changed(self, parameter): + self._update_parameter_names() + @listens_group('value') def _on_parameter_value_changed(self, parameter): self._update_parameter_values() @@ -142,28 +147,30 @@ def _update_parameter_names(self): if self.is_enabled(): params = zip(chain(self.parameter_provider.parameters, repeat(None)), self._parameter_name_data_sources) for info, name_data_source in params: - if info: - parameter = info.parameter - name = info and info.name or '' - name = parameter and parameter.automation_state != AutomationState.none and consts.CHAR_FULL_BLOCK + name + parameter = info and info.parameter + name = info and info.name or '' + if parameter and parameter.automation_state != AutomationState.none: + name = consts.CHAR_FULL_BLOCK + name name_data_source.set_display_string(name or '') def _update_parameter_values(self): if self.is_enabled(): - for parameter, data_source in map(None, self.parameters, self._parameter_value_data_sources): + for parameter, data_source in izip_longest(self.parameters, self._parameter_value_data_sources): value_string = self.parameter_to_string(parameter) if parameter and parameter.automation_state == AutomationState.overridden: value_string = '[%s]' % value_string if data_source: data_source.set_display_string(value_string) - for param, data_source in map(None, self.parameters, self._parameter_graphic_data_sources): + for param, data_source in izip_longest(self.parameters, self._parameter_graphic_data_sources): graph = convert_parameter_value_to_graphic(param, self.parameter_to_value) if data_source: data_source.set_display_string(graph) def parameter_to_string(self, parameter): - return '' if parameter == None else unicode(parameter) + if parameter == None: + return '' + return unicode(parameter) def parameter_to_value(self, parameter): return parameter.value \ No newline at end of file diff --git a/pushbase/drum_group_component.py b/pushbase/drum_group_component.py index ba58a278..57bcae4d 100644 --- a/pushbase/drum_group_component.py +++ b/pushbase/drum_group_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/drum_group_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/drum_group_component.py +from __future__ import absolute_import, print_function from functools import partial from ableton.v2.base import nop, listens, liveobj_valid, listenable_property from ableton.v2.control_surface.control import control_matrix, ButtonControl @@ -40,7 +41,9 @@ def _finish_copying(self, drum_group_device, destination_pad): return self._show_notification(message) def duplicate_pad(self, drum_group_device, drum_pad): - return self._start_copying(drum_pad) if not self.is_copying else self._finish_copying(drum_group_device, drum_pad) + if not self.is_copying: + return self._start_copying(drum_pad) + return self._finish_copying(drum_group_device, drum_pad) def stop_copying(self): self.is_copying = False @@ -161,4 +164,6 @@ def _update_sensitivity_profile(self): @listenable_property def selected_note(self): selected_drum_pad = self._drum_group_device.view.selected_drum_pad if liveobj_valid(self._drum_group_device) else None - return selected_drum_pad.note if liveobj_valid(selected_drum_pad) else -1 \ No newline at end of file + if liveobj_valid(selected_drum_pad): + return selected_drum_pad.note + return -1 \ No newline at end of file diff --git a/pushbase/elements.py b/pushbase/elements.py index 6946589e..02bdd30c 100644 --- a/pushbase/elements.py +++ b/pushbase/elements.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/elements.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/elements.py +from __future__ import absolute_import, print_function from ableton.v2.base import depends, recursive_map from ableton.v2.control_surface import PrioritizedResource, MIDI_NOTE_TYPE from ableton.v2.control_surface.elements import ButtonMatrixElement, DoublePressElement, FineGrainWithModifierEncoderElement, MultiElement @@ -10,7 +11,7 @@ class Elements(object): - def __init__(self, deleter = None, undo_handler = None, pad_sensitivity_update = None, playhead = None, *a, **k): + def __init__(self, deleter = None, undo_handler = None, pad_sensitivity_update = None, playhead = None, continuous_mapping_sensitivity = consts.CONTINUOUS_MAPPING_SENSITIVITY, fine_grained_continuous_mapping_sensitivity = consts.FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY, *a, **k): raise deleter is not None or AssertionError raise undo_handler is not None or AssertionError raise playhead is not None or AssertionError @@ -80,12 +81,12 @@ def create_pad_button(pad_id, name, skin = None, **k): self.swing_control = TouchEncoderElement(channel=0, identifier=15, map_mode=consts.GLOBAL_MAP_MODE, name='Swing_Control', undo_step_handler=undo_handler, delete_handler=deleter, encoder_sensitivity=consts.ENCODER_SENSITIVITY, touch_element=self.swing_control_tap) self.master_volume_control_tap = create_note_button(8, 'Master_Volume_Tap') self.master_volume_control = TouchEncoderElement(channel=0, identifier=79, map_mode=consts.GLOBAL_MAP_MODE, undo_step_handler=undo_handler, delete_handler=deleter, name='Master_Volume_Control', encoder_sensitivity=consts.ENCODER_SENSITIVITY, touch_element=self.master_volume_control_tap) - self.master_volume_control.mapping_sensitivity = consts.CONTINUOUS_MAPPING_SENSITIVITY + self.master_volume_control.mapping_sensitivity = continuous_mapping_sensitivity self.global_param_touch_buttons_raw = [ create_note_button(index, 'Track_Control_Touch_' + str(index), resource_type=PrioritizedResource) for index in range(8) ] self.global_param_touch_buttons = ButtonMatrixElement(name='Track_Control_Touches', rows=[self.global_param_touch_buttons_raw]) self.parameter_controls_raw = [ TouchEncoderElement(channel=0, identifier=71 + index, map_mode=consts.GLOBAL_MAP_MODE, undo_step_handler=undo_handler, delete_handler=deleter, encoder_sensitivity=consts.ENCODER_SENSITIVITY, name='Track_Control_' + str(index), touch_element=self.global_param_touch_buttons_raw[index]) for index in xrange(8) ] self.global_param_controls = ButtonMatrixElement(name='Track_Controls', rows=[self.parameter_controls_raw]) - self.fine_grain_param_controls_raw = [ FineGrainWithModifierEncoderElement(encoder, self.shift_button, consts.FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY, consts.CONTINUOUS_MAPPING_SENSITIVITY) for encoder in self.parameter_controls_raw ] + self.fine_grain_param_controls_raw = [ FineGrainWithModifierEncoderElement(encoder, self.shift_button, fine_grained_continuous_mapping_sensitivity, continuous_mapping_sensitivity) for encoder in self.parameter_controls_raw ] self.fine_grain_param_controls = ButtonMatrixElement(rows=[self.fine_grain_param_controls_raw]) self.any_touch_button = MultiElement(*self.global_param_touch_buttons.nested_control_elements()) self.playhead_element = PlayheadElement(playhead) \ No newline at end of file diff --git a/pushbase/fixed_length.py b/pushbase/fixed_length.py index 621d3fc2..2bcb311a 100644 --- a/pushbase/fixed_length.py +++ b/pushbase/fixed_length.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/fixed_length.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/fixed_length.py +from __future__ import absolute_import, print_function from functools import partial import Live from ableton.v2.base import Subject, listens, listenable_property, task diff --git a/pushbase/grid_resolution.py b/pushbase/grid_resolution.py index 32daf2f1..c7387386 100644 --- a/pushbase/grid_resolution.py +++ b/pushbase/grid_resolution.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/grid_resolution.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/grid_resolution.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import product, listens, SlotManager, Subject GridQuantization = Live.Clip.GridQuantization diff --git a/pushbase/instrument_component.py b/pushbase/instrument_component.py index 5795313e..549cccea 100644 --- a/pushbase/instrument_component.py +++ b/pushbase/instrument_component.py @@ -1,14 +1,14 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/instrument_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/instrument_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import Subject, index_if, listenable_property, listens, liveobj_valid, find_if from ableton.v2.control_surface import CompoundComponent -from ableton.v2.control_surface.control import control_matrix, ToggleButtonControl +from ableton.v2.control_surface.control import control_matrix from ableton.v2.control_surface.components import PlayableComponent, Slideable, SlideComponent from . import consts from .melodic_pattern import SCALES, MelodicPattern, pitch_index_to_string from .message_box_component import Messenger from .pad_control import PadControl from .slideable_touch_strip_component import SlideableTouchStripComponent -from .touch_strip_element import TouchStripStates, TouchStripModes, MODWHEEL_BEHAVIOUR, DEFAULT_BEHAVIOUR DEFAULT_SCALE = SCALES[0] class NoteLayout(Subject): @@ -77,7 +77,6 @@ class InstrumentComponent(PlayableComponent, CompoundComponent, Slideable, Messe selectable layouts for the notes. """ __events__ = ('pattern',) - touch_strip_toggle = ToggleButtonControl() matrix = control_matrix(PadControl, pressed_color='Instrument.NoteAction') def __init__(self, note_layout = None, *a, **k): @@ -89,8 +88,6 @@ def __init__(self, note_layout = None, *a, **k): self._last_page_length = self.page_length self._delete_button = None self._last_page_offset = self.page_offset - self._touch_strip = None - self._touch_strip_indication = None self._detail_clip = None self._has_notes = [False] * 128 self._has_notes_pattern = self._get_pattern(0) @@ -136,12 +133,16 @@ def _on_loop_selection_changed(self): def contents(self, index): if self._detail_clip: note = self._has_notes_pattern[index].index - return self._has_notes[note] if note is not None else False + if note is not None: + return self._has_notes[note] + return False return False @property def page_length(self): - return len(self._note_layout.notes) if self._note_layout.is_in_key else 12 + if self._note_layout.is_in_key: + return len(self._note_layout.notes) + return 12 @property def position_count(self): @@ -162,7 +163,9 @@ def _first_scale_note_offset(self): @property def page_offset(self): - return 0 if self._note_layout.is_fixed else self._first_scale_note_offset() + if self._note_layout.is_fixed: + return 0 + return self._first_scale_note_offset() def _get_position(self): return self._first_note @@ -201,29 +204,6 @@ def _do_delete_pitch(self, pitch): def _on_delete_value(self, value): self._set_control_pads_from_script(bool(value)) - @touch_strip_toggle.toggled - def touch_strip_toggle(self, toggled, button): - self._update_touch_strip() - self._update_touch_strip_indication() - self.show_notification(consts.MessageBoxText.TOUCHSTRIP_MODWHEEL_MODE if toggled else consts.MessageBoxText.TOUCHSTRIP_PITCHBEND_MODE) - - def set_touch_strip(self, control): - self._touch_strip = control - self._update_touch_strip() - - def _update_touch_strip(self): - if self._touch_strip: - self._touch_strip.behaviour = MODWHEEL_BEHAVIOUR if self.touch_strip_toggle.is_toggled else DEFAULT_BEHAVIOUR - - def set_touch_strip_indication(self, control): - self._touch_strip_indication = control - self._update_touch_strip_indication() - - def _update_touch_strip_indication(self): - if self._touch_strip_indication: - self._touch_strip_indication.set_mode(TouchStripModes.CUSTOM_FREE) - self._touch_strip_indication.send_state([ (TouchStripStates.STATE_FULL if self.touch_strip_toggle.is_toggled else TouchStripStates.STATE_HALF) for _ in xrange(self._touch_strip_indication.state_count) ]) - def set_note_strip(self, strip): self._touch_slider.set_scroll_strip(strip) @@ -274,8 +254,6 @@ def update(self): if self.is_enabled(): self._update_matrix() self._update_aftertouch() - self._update_touch_strip() - self._update_touch_strip_indication() def _update_pattern(self): self._pattern = self._get_pattern() diff --git a/pushbase/internal_parameter.py b/pushbase/internal_parameter.py new file mode 100644 index 00000000..3c98e665 --- /dev/null +++ b/pushbase/internal_parameter.py @@ -0,0 +1,288 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/internal_parameter.py +from __future__ import absolute_import, print_function +from Live import DeviceParameter +from ableton.v2.base import listenable_property, liveobj_valid, nop, Slot, SlotError, SlotManager, Subject + +def identity(value, _parent): + return value + + +def to_percentage_display(value): + percentage = 100.0 * value + percentage_str = '100' + if percentage < 100.0: + precision = 2 if percentage < 10.0 else 1 + format_str = '%.' + str(precision) + 'f' + percentage_str = format_str % percentage + return unicode(percentage_str + ' %') + + +class InternalParameterBase(Subject): + is_enabled = True + is_quantized = False + + def __init__(self, name = None, *a, **k): + raise name is not None or AssertionError + super(InternalParameterBase, self).__init__(*a, **k) + self._name = name + + def _has_valid_parent(self): + return liveobj_valid(self._parent) + + @property + def canonical_parent(self): + raise NotImplementedError + + @property + def display_value(self): + raise NotImplementedError + + @property + def min(self): + raise NotImplementedError + + @property + def max(self): + raise NotImplementedError + + @property + def value(self): + raise NotImplementedError + + @listenable_property + def name(self): + return self._name + + @property + def original_name(self): + return self._name + + @property + def default_value(self): + return self.min + + @listenable_property + def automation_state(self): + return DeviceParameter.AutomationState.none + + @listenable_property + def state(self): + return DeviceParameter.ParameterState.enabled + + @property + def _live_ptr(self): + return id(self) + + def __str__(self): + return self.display_value + + +class InternalParameter(InternalParameterBase): + """ + Class implementing the DeviceParameter interface. Using instances of this class, + we can mix script-internal values with DeviceParameter instances. + """ + __events__ = ('value',) + + def __init__(self, parent = None, display_value_conversion = None, *a, **k): + super(InternalParameter, self).__init__(*a, **k) + self._value = 0.0 + self._parent = parent + self.set_display_value_conversion(display_value_conversion) + self.set_scaling_functions(None, None) + + def set_display_value_conversion(self, display_value_conversion): + self._display_value_conversion = display_value_conversion or to_percentage_display + self.notify_value() + + def set_scaling_functions(self, to_internal, from_internal): + self._to_internal = to_internal or identity + self._from_internal = from_internal or identity + + @property + def canonical_parent(self): + return self._parent + + def _get_value(self): + if self._has_valid_parent(): + return self._from_internal(self.linear_value, self._parent) + return self.min + + def _set_value(self, new_value): + raise self.min <= new_value <= self.max or AssertionError('Invalid value %f' % new_value) + self.linear_value = self._to_internal(new_value, self._parent) + + value = property(_get_value, _set_value) + + def _get_linear_value(self): + return self._value + + def _set_linear_value(self, new_value): + if new_value != self._value: + self._value = new_value + self.notify_value() + + linear_value = property(_get_linear_value, _set_linear_value) + + @property + def min(self): + return 0.0 + + @property + def max(self): + return 1.0 + + @property + def display_value(self): + return self._display_value_conversion(self.value) + + +class WrappingParameter(InternalParameter, SlotManager): + + def __init__(self, property_host = None, source_property = None, from_property_value = None, to_property_value = None, display_value_conversion = nop, value_items = [], *a, **k): + raise source_property is not None or AssertionError + super(WrappingParameter, self).__init__(display_value_conversion=display_value_conversion, *a, **k) + self._property_host = property_host + raise self._property_host == None or hasattr(self._property_host, source_property) or source_property in dir(self._property_host) or AssertionError + self._source_property = source_property + self._value_items = value_items + self.set_scaling_functions(to_property_value, from_property_value) + self._property_slot = self.register_slot(Slot(listener=self.notify_value, event=source_property, subject=self._property_host)) + + def set_property_host(self, new_host): + self._property_host = new_host + self._property_slot.subject = self._property_host + + def _get_property_value(self): + if liveobj_valid(self._property_host): + return getattr(self._property_host, self._source_property) + return self.min + + def _get_value(self): + try: + if liveobj_valid(self._property_host): + return self._from_internal(self._get_property_value(), self._property_host) + return self.min + except RuntimeError: + return self.min + + def _set_value(self, new_value): + raise self.min <= new_value <= self.max or AssertionError('Invalid value %f' % new_value) + if liveobj_valid(self._property_host): + try: + setattr(self._property_host, self._source_property, self._to_internal(new_value, self._property_host)) + except RuntimeError: + pass + + linear_value = property(_get_value, _set_value) + value = property(_get_value, _set_value) + + @property + def display_value(self): + try: + value = self._get_property_value() + return unicode(self._display_value_conversion(value) if liveobj_valid(self._property_host) else '') + except RuntimeError: + return unicode() + + @property + def is_quantized(self): + return len(self._value_items) > 0 + + @property + def value_items(self): + return self._value_items + + +class EnumWrappingParameter(InternalParameterBase, SlotManager): + is_enabled = True + is_quantized = True + + def __init__(self, parent = None, index_property_host = None, values_property_host = None, values_property = None, index_property = None, value_type = int, to_index_conversion = None, from_index_conversion = None, *a, **k): + raise parent is not None or AssertionError + raise values_property is not None or AssertionError + raise index_property is not None or AssertionError + super(EnumWrappingParameter, self).__init__(*a, **k) + self._parent = parent + self._values_property_host = values_property_host + self._index_property_host = index_property_host + self._values_property = values_property + self._index_property = index_property + self._to_index = to_index_conversion or (lambda x: x) + self._from_index = from_index_conversion or (lambda x: x) + self.value_type = value_type + self._index_property_slot = self.register_slot(index_property_host, self.notify_value, index_property) + try: + self.register_slot(self._values_property_host, self.notify_value_items, values_property) + except SlotError: + pass + + def set_index_property_host(self, new_host): + self._index_property_host = new_host + self._index_property_slot.subject = self._index_property_host + + @property + def display_value(self): + index = self._get_index() + values = self._get_values() + if index < len(values): + return unicode(values[index]) + else: + return unicode() + + @listenable_property + def value_items(self): + return self._get_values() + + @listenable_property + def value(self): + return self._get_index() + + @value.setter + def value(self, new_value): + self._set_index(new_value) + + def _get_values(self): + if liveobj_valid(self._values_property_host): + return getattr(self._values_property_host, self._values_property) + return [] + + def _get_index(self): + return self._from_index(int(getattr(self._index_property_host, self._index_property)) if liveobj_valid(self._index_property_host) else 0) + + def _set_index(self, index): + if liveobj_valid(self._index_property_host): + index = self._to_index(index) + setattr(self._index_property_host, self._index_property, self.value_type(index)) + + @property + def canonical_parent(self): + self._parent + + @property + def max(self): + return len(self.value_items) - 1 + + @property + def min(self): + return 0 + + +class RelativeInternalParameter(InternalParameter): + __events__ = ('delta',) + + @property + def default_value(self): + return 0.5 + + def _get_value(self): + return self.default_value + + def _set_value(self, new_value): + delta = new_value - self.value + if delta != 0.0: + self.notify_value() + self.notify_delta(delta) + + value = property(_get_value, _set_value) + linear_value = property(_get_value, _set_value) \ No newline at end of file diff --git a/pushbase/loop_selector_component.py b/pushbase/loop_selector_component.py index ab0c7993..0a33f393 100644 --- a/pushbase/loop_selector_component.py +++ b/pushbase/loop_selector_component.py @@ -1,9 +1,9 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/loop_selector_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/loop_selector_component.py +from __future__ import absolute_import, print_function from contextlib import contextmanager from functools import partial from itertools import izip -from ableton.v2.base import clamp, listens, liveobj_valid, Subject, task +from ableton.v2.base import clamp, listens, liveobj_changed, liveobj_valid, Subject, task from ableton.v2.control_surface import defaults, Component from ableton.v2.control_surface.control import ButtonControl @@ -132,7 +132,7 @@ def _on_detail_clip_changed(self): self.set_detail_clip(self.song.view.detail_clip) def set_detail_clip(self, clip): - if clip != self._sequencer_clip: + if liveobj_changed(clip, self._sequencer_clip): self._is_following = liveobj_valid(clip) and (self._is_following or clip_is_new_recording(clip)) self._on_playing_position_changed.subject = clip self._on_playing_status_changed.subject = clip @@ -287,7 +287,9 @@ def calculate_page_colors(): def color_for_page(absolute_page): if l_start <= absolute_page < l_start + l_length: - return 'LoopSelector.InsideLoopStartBar' if absolute_page % pages_per_measure == 0 else 'LoopSelector.InsideLoop' + if absolute_page % pages_per_measure == 0: + return 'LoopSelector.InsideLoopStartBar' + return 'LoopSelector.InsideLoop' else: return 'LoopSelector.OutsideLoop' diff --git a/pushbase/mapped_control.py b/pushbase/mapped_control.py new file mode 100644 index 00000000..d16e6dfb --- /dev/null +++ b/pushbase/mapped_control.py @@ -0,0 +1,72 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/mapped_control.py +from __future__ import absolute_import, print_function +from ableton.v2.base import clamp, listens, liveobj_valid +from ableton.v2.control_surface.control import MappedControl as MappedControlBase +from ableton.v2.control_surface.control.encoder import ValueStepper +from pushbase.internal_parameter import InternalParameterBase + +def is_internal_parameter(parameter): + return isinstance(parameter, InternalParameterBase) + + +def is_zoom_parameter(parameter): + """ Returns true for parameters, that provide a zoom method, i.e. Push 2's + waveform zooming parameter. + """ + return hasattr(parameter, 'zoom') + + +class MappedControl(MappedControlBase): + + class State(MappedControlBase.State): + default_sensitivity = 1.0 + fine_sensitivity = 0.1 + + def __init__(self, *a, **k): + super(MappedControl.State, self).__init__(*a, **k) + self._quantized_stepper = ValueStepper() + + def update_sensitivities(self, default, fine): + self.default_sensitivity = default + self.fine_sensitivity = fine + if self._control_element: + self._update_control_sensitivity() + + def _update_direct_connection(self): + if self._control_element is None or is_internal_parameter(self.mapped_parameter): + if self._control_element: + self._control_element.release_parameter() + self._control_value.subject = self._control_element + else: + self._control_value.subject = None + self._update_control_element() + self._quantized_stepper.reset() + + def _update_control_element(self): + if liveobj_valid(self.mapped_parameter): + self._control_element.connect_to(self.mapped_parameter) + else: + self._control_element.release_parameter() + self._update_control_sensitivity() + self._quantized_stepper.reset() + + def _update_control_sensitivity(self): + if hasattr(self._control_element, 'set_sensitivities'): + self._control_element.set_sensitivities(self.default_sensitivity, self.fine_sensitivity) + else: + self._control_element.mapping_sensitivity = self.default_sensitivity + + @listens('normalized_value') + def _control_value(self, value): + if is_zoom_parameter(self.mapped_parameter): + self.mapped_parameter.zoom(value) + if self.mapped_parameter.is_quantized: + steps = self._quantized_stepper.advance(value) + if steps != 0: + self.mapped_parameter.value = self._clamp_value_to_parameter_range(self.mapped_parameter.value + steps) + else: + value_offset = value * self._control_element.mapping_sensitivity + self.mapped_parameter.linear_value = self._clamp_value_to_parameter_range(self.mapped_parameter.linear_value + value_offset) + + def _clamp_value_to_parameter_range(self, value): + return clamp(value, self.mapped_parameter.min, self.mapped_parameter.max) \ No newline at end of file diff --git a/pushbase/matrix_maps.py b/pushbase/matrix_maps.py index 89477af5..1bae9006 100644 --- a/pushbase/matrix_maps.py +++ b/pushbase/matrix_maps.py @@ -1,7 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/matrix_maps.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/matrix_maps.py """ Pad Translations for Drum Rack (pad_x, pad_y, note, channel) """ +from __future__ import absolute_import, print_function PAD_TRANSLATIONS = ((0, 0, 60, 13), (1, 0, 61, 13), (2, 0, 62, 13), diff --git a/pushbase/melodic_component.py b/pushbase/melodic_component.py index 14948886..149bd3b4 100644 --- a/pushbase/melodic_component.py +++ b/pushbase/melodic_component.py @@ -1,5 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/melodic_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/melodic_component.py +from __future__ import absolute_import, print_function +from itertools import izip_longest from ableton.v2.base import forward_property, find_if, listens from ableton.v2.control_surface.elements import to_midi_value from ableton.v2.control_surface.mode import ModesComponent, LayerMode @@ -15,12 +16,12 @@ class MelodicComponent(ModesComponent, Messenger): - def __init__(self, clip_creator = None, parameter_provider = None, grid_resolution = None, note_layout = None, note_editor_settings = None, skin = None, instrument_play_layer = None, instrument_sequence_layer = None, layer = None, *a, **k): + def __init__(self, clip_creator = None, parameter_provider = None, grid_resolution = None, note_layout = None, note_editor_settings = None, note_editor_class = NoteEditorComponent, velocity_range_thresholds = None, skin = None, instrument_play_layer = None, instrument_sequence_layer = None, pitch_mod_touch_strip_mode = None, layer = None, *a, **k): super(MelodicComponent, self).__init__(*a, **k) self._matrices = None self._grid_resolution = grid_resolution self._instrument = self.register_component(InstrumentComponent(note_layout=note_layout)) - self._note_editors = self.register_components(*[ NoteEditorComponent(clip_creator=clip_creator, grid_resolution=self._grid_resolution, is_enabled=False) for _ in xrange(NUM_NOTE_EDITORS) ]) + self._note_editors = self.register_components(*[ note_editor_class(clip_creator=clip_creator, grid_resolution=self._grid_resolution, velocity_range_thresholds=velocity_range_thresholds, is_enabled=False) for _ in xrange(NUM_NOTE_EDITORS) ]) for editor in self._note_editors: note_editor_settings.add_editor(editor) @@ -28,7 +29,7 @@ def __init__(self, clip_creator = None, parameter_provider = None, grid_resoluti self._loop_selector = self.register_component(LoopSelectorComponent(clip_creator=clip_creator, paginator=self._paginator, is_enabled=False)) self._playhead = None self._playhead_component = self.register_component(PlayheadComponent(grid_resolution=grid_resolution, paginator=self._paginator, follower=self._loop_selector, feedback_channels=PLAYHEAD_FEEDBACK_CHANNELS, is_enabled=False)) - self.add_mode('play', LayerMode(self._instrument, instrument_play_layer)) + self.add_mode('play', [LayerMode(self._instrument, instrument_play_layer), pitch_mod_touch_strip_mode]) self.add_mode('sequence', [LayerMode(self._instrument, instrument_sequence_layer), self._loop_selector, note_editor_settings, @@ -63,7 +64,7 @@ def set_short_loop_selector_matrix(self, matrix): def set_note_editor_matrices(self, matrices): raise not matrices or len(matrices) <= NUM_NOTE_EDITORS or AssertionError self._matrices = matrices - for editor, matrix in map(None, self._note_editors, matrices or []): + for editor, matrix in izip_longest(self._note_editors, matrices or []): if editor: editor.set_button_matrix(matrix) diff --git a/pushbase/melodic_pattern.py b/pushbase/melodic_pattern.py index 8e8de40a..c34cdc3e 100644 --- a/pushbase/melodic_pattern.py +++ b/pushbase/melodic_pattern.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/melodic_pattern.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/melodic_pattern.py +from __future__ import absolute_import, print_function from ableton.v2.base import NamedTuple, lazy_attribute, memoize, find_if from . import consts from .matrix_maps import FEEDBACK_CHANNELS diff --git a/pushbase/message_box_component.py b/pushbase/message_box_component.py index f81621e2..8cb46f15 100644 --- a/pushbase/message_box_component.py +++ b/pushbase/message_box_component.py @@ -1,4 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/message_box_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/message_box_component.py +from __future__ import absolute_import, print_function +from itertools import izip_longest from ableton.v2.base import forward_property, const, nop, listens, listenable_property from ableton.v2.base.dependency import dependency from ableton.v2.control_surface import CompoundComponent @@ -67,7 +69,7 @@ def _update_cancel_button(self): def _update_display(self): if self._current_text != None: lines = self._current_text.split('\n') - for source_line, line in map(None, self.data_sources, lines): + for source_line, line in izip_longest(self.data_sources, lines): if source_line: source_line.set_display_string(line or '') diff --git a/pushbase/note_editor_component.py b/pushbase/note_editor_component.py index cc092dd8..75f4e19b 100644 --- a/pushbase/note_editor_component.py +++ b/pushbase/note_editor_component.py @@ -1,25 +1,24 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/note_editor_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/note_editor_component.py +from __future__ import absolute_import, print_function from contextlib import contextmanager from functools import partial from itertools import chain, imap, ifilter -from ableton.v2.base import clamp, first, in_range, listens, liveobj_valid, product, sign, Subject, task +from ableton.v2.base import clamp, first, index_if, in_range, listens, liveobj_valid, product, sign, Subject, task from ableton.v2.control_surface import CompoundComponent, defaults from .loop_selector_component import create_clip_in_selected_slot from .matrix_maps import PLAYHEAD_FEEDBACK_CHANNELS DEFAULT_VELOCITY = 100 +DEFAULT_VELOCITY_RANGE_THRESHOLDS = [127, 100, 0] +VELOCITY_RANGE_INDEX_TO_COLOR = ['Full', 'High', 'Low'] BEAT_TIME_EPSILON = 1e-05 -def color_for_note(note): +def color_for_note(note, velocity_range_thresholds = None): + thresholds = velocity_range_thresholds or DEFAULT_VELOCITY_RANGE_THRESHOLDS velocity = note[3] muted = note[4] if not muted: - if velocity == 127: - return 'Full' - elif velocity >= 100: - return 'High' - else: - return 'Low' + velocity_range_index = index_if(lambda threshold: velocity >= threshold, thresholds) + return VELOCITY_RANGE_INDEX_TO_COLOR[velocity_range_index] else: return 'Muted' @@ -112,7 +111,7 @@ def includes_time(self, time): class NoteEditorComponent(CompoundComponent, Subject): __events__ = ('page_length', 'active_steps', 'notes_changed', 'modify_all_notes') - def __init__(self, clip_creator = None, grid_resolution = None, skin_base_key = 'NoteEditor', *a, **k): + def __init__(self, clip_creator = None, grid_resolution = None, skin_base_key = 'NoteEditor', velocity_range_thresholds = None, *a, **k): raise skin_base_key is not None or AssertionError super(NoteEditorComponent, self).__init__(*a, **k) self._skin_base_key = skin_base_key @@ -144,6 +143,7 @@ def __init__(self, clip_creator = None, grid_resolution = None, skin_base_key = self._triplet_factor = 1.0 self._update_from_grid() self.background_color = self._skin_base_key + '.StepEmpty' + self._velocity_range_thresholds = velocity_range_thresholds or DEFAULT_VELOCITY_RANGE_THRESHOLDS @property def page_index(self): @@ -262,11 +262,11 @@ def _update_editor_matrix(self): if index in selected_indices: color = self._skin_base_key + '.StepSelected' elif index in editing_indices: - note_color = color_for_note(most_significant_note(notes)) + note_color = self._determine_color(notes) color = self._skin_base_key + '.StepEditing.' + note_color last_editing_notes = notes else: - note_color = color_for_note(most_significant_note(notes)) + note_color = self._determine_color(notes) color = self._skin_base_key + '.Step.' + note_color elif any(imap(time_step.overlaps_note, last_editing_notes)): color = self._skin_base_key + '.StepEditing.' + note_color @@ -281,6 +281,9 @@ def _update_editor_matrix(self): self._step_colors = step_colors self._update_editor_matrix_leds() + def _determine_color(self, notes): + return color_for_note(most_significant_note(notes), velocity_range_thresholds=self._velocity_range_thresholds) + def _visible_steps(self): first_time = self.page_length * self._page_index steps_per_page = self._get_step_count() @@ -337,6 +340,9 @@ def _on_resolution_changed(self): @listens('value') def _on_matrix_value(self, value, x, y, is_momentary): + self._on_pad_pressed(value, x, y, is_momentary) + + def _on_pad_pressed(self, value, x, y, is_momentary): if self.is_enabled(): if self._sequencer_clip == None and value or not is_momentary: clip = create_clip_in_selected_slot(self._clip_creator, self.song) @@ -586,7 +592,7 @@ def _min_max_for_notes(self, notes, start_time, min_max_values = None): def get_min_max_note_values(self): if self._modify_all_notes_enabled and len(self._clip_notes) > 0: return self._min_max_for_notes(self._clip_notes, 0.0) - elif len(self._pressed_steps) + len(self._modified_steps) > 0: + if len(self._pressed_steps) + len(self._modified_steps) > 0: min_max_values = None for x, y in chain(self._modified_steps, self._pressed_steps): start_time = self._get_step_start_time(x, y) diff --git a/pushbase/note_editor_paginator.py b/pushbase/note_editor_paginator.py index 325cbea4..d27d6f85 100644 --- a/pushbase/note_editor_paginator.py +++ b/pushbase/note_editor_paginator.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/note_editor_paginator.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/note_editor_paginator.py +from __future__ import absolute_import, print_function from ableton.v2.base import forward_property, SlotManager, listens, listens_group from .loop_selector_component import Paginator diff --git a/pushbase/note_repeat_component.py b/pushbase/note_repeat_component.py index a72f3e2c..7a7f2980 100644 --- a/pushbase/note_repeat_component.py +++ b/pushbase/note_repeat_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/note_repeat_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/note_repeat_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import listens, task from ableton.v2.control_surface import CompoundComponent from .action_with_options_component import OptionsComponent @@ -58,9 +59,9 @@ def set_select_buttons(self, buttons): self._options.select_buttons.set_control_element(buttons) def set_note_repeat(self, note_repeat): - if not note_repeat: - note_repeat = DummyNoteRepeat() - self._note_repeat.enabled = self._note_repeat != None and False + note_repeat = note_repeat or DummyNoteRepeat() + if self._note_repeat != None: + self._note_repeat.enabled = False self._note_repeat = note_repeat self._update_note_repeat(enabled=self.is_enabled()) diff --git a/pushbase/note_settings_component.py b/pushbase/note_settings_component.py index d825be70..0719d8d0 100644 --- a/pushbase/note_settings_component.py +++ b/pushbase/note_settings_component.py @@ -1,8 +1,9 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/note_settings_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/note_settings_component.py +from __future__ import absolute_import, print_function import math from functools import partial -from itertools import imap -from ableton.v2.base import chain_from_iterable, clamp, find_if, forward_property, listens, listens_group, Subject, task +from itertools import imap, chain, izip_longest +from ableton.v2.base import clamp, find_if, forward_property, listens, listens_group, Subject, task from ableton.v2.control_surface import defaults, Component from ableton.v2.control_surface.control import ButtonControl, ControlManager, EncoderControl, StepEncoderControl from ableton.v2.control_surface.elements import DisplayDataSource @@ -25,7 +26,9 @@ def encoder_value_to_attribute(self, value): @property def step_length(self): - return self._grid_resolution.step_length if self._grid_resolution else 1.0 + if self._grid_resolution: + return self._grid_resolution.step_length + return 1.0 def set_min_max(self, min_max_value): self._min_max_value = min_max_value @@ -66,7 +69,9 @@ def step_offset_percentage(step_length, value): def step_offset_min_max_to_string(step_length, min_value, max_value): min_value = step_offset_percentage(step_length, min_value) max_value = step_offset_percentage(step_length, max_value) - return '%d%%' % min_value if min_value == max_value else (RANGE_STRING_INT + '%%') % (min_value, max_value) + if min_value == max_value: + return '%d%%' % min_value + return (RANGE_STRING_INT + '%%') % (min_value, max_value) def convert_value_to_graphic(value, value_range): @@ -105,7 +110,9 @@ def format_string(value): num_non_decimal_figures = int(math.log10(value)) if value > 0 else 0 return '%%.%dg' % (num_non_decimal_figures + 2,) - return (format_string(min_value) + ' stp') % min_value if min_value == max_value else (format_string(min_value) + CHAR_ELLIPSIS + format_string(max_value)) % (min_value, max_value) + if min_value == max_value: + return (format_string(min_value) + ' stp') % min_value + return (format_string(min_value) + CHAR_ELLIPSIS + format_string(max_value)) % (min_value, max_value) def encoder_value_to_attribute(self, value): return self.step_length * value @@ -139,7 +146,9 @@ def encoder_value_to_attribute(self, value): return value * 128 def attribute_min_max_to_string(self, min_value, max_value): - return str(int(min_value)) if int(min_value) == int(max_value) else RANGE_STRING_INT % (min_value, max_value) + if int(min_value) == int(max_value): + return str(int(min_value)) + return RANGE_STRING_INT % (min_value, max_value) class NoteSettingsComponentBase(Component): @@ -159,7 +168,7 @@ def _create_settings(self, grid_resolution): self._add_setting(NoteVelocitySetting(grid_resolution=grid_resolution)) def _add_setting(self, setting): - raise len(self._settings) < 8 or AssertionError, 'Cannot show more than 8 settings' + raise len(self._settings) < 8 or AssertionError('Cannot show more than 8 settings') self._settings.append(setting) self._update_encoders() self.register_disconnectable(setting) @@ -184,7 +193,7 @@ def full_velocity_button(self, button): def _update_encoders(self): if self.is_enabled() and self._encoders: - for encoder, setting in map(None, self._encoders[-len(self._settings):], self._settings): + for encoder, setting in izip_longest(self._encoders[-len(self._settings):], self._settings): setting.encoder.set_control_element(encoder) else: @@ -306,6 +315,10 @@ def __init__(self, note_settings_component = None, automation_component = None, def step_settings(self): return self._settings_modes + @property + def editors(self): + return self._editors + def add_editor(self, editor): raise editor != None or AssertionError self._editors.append(editor) @@ -385,7 +398,7 @@ def _try_immediate_show_settings(self): @listens_group('active_steps') def _on_active_steps_changed(self, editor): if self.is_enabled(): - all_steps = list(set(chain_from_iterable(imap(lambda e: e.active_steps, self._editors)))) + all_steps = list(set(chain.from_iterable(imap(lambda e: e.active_steps, self._editors)))) self._automation.selected_time = all_steps self._update_note_infos() if len(all_steps) > 0: diff --git a/pushbase/pad_control.py b/pushbase/pad_control.py index e010a248..ef2b3eee 100644 --- a/pushbase/pad_control.py +++ b/pushbase/pad_control.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/pad_control.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/pad_control.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface.control import PlayableControl class PadControl(PlayableControl): diff --git a/pushbase/parameter_provider.py b/pushbase/parameter_provider.py index c0e38594..39fcb3a7 100644 --- a/pushbase/parameter_provider.py +++ b/pushbase/parameter_provider.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/parameter_provider.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/parameter_provider.py +from __future__ import absolute_import, print_function from ableton.v2.base import liveobj_valid, NamedTuple, Subject from . import consts DISCRETE_PARAMETERS_DICT = {'GlueCompressor': ('Ratio', 'Attack', 'Release', 'Peak Clip In')} @@ -14,24 +14,32 @@ def is_parameter_quantized(parameter, parent_device): def parameter_mapping_sensitivity(parameter): is_quantized = is_parameter_quantized(parameter, parameter and parameter.canonical_parent) - return consts.QUANTIZED_MAPPING_SENSITIVITY if is_quantized else consts.CONTINUOUS_MAPPING_SENSITIVITY + if is_quantized: + return consts.QUANTIZED_MAPPING_SENSITIVITY + return consts.CONTINUOUS_MAPPING_SENSITIVITY def fine_grain_parameter_mapping_sensitivity(parameter): is_quantized = is_parameter_quantized(parameter, parameter and parameter.canonical_parent) - return consts.QUANTIZED_MAPPING_SENSITIVITY if is_quantized else consts.FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY + if is_quantized: + return consts.QUANTIZED_MAPPING_SENSITIVITY + return consts.FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY class ParameterInfo(NamedTuple): parameter = None - name = None - default_encoder_sensitivity = consts.CONTINUOUS_MAPPING_SENSITIVITY - fine_grain_encoder_sensitivity = consts.FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY + default_encoder_sensitivity = (None,) + fine_grain_encoder_sensitivity = (None,) + + def __init__(self, name = None, *a, **k): + super(ParameterInfo, self).__init__(_overriden_name=name, *a, **k) + + @property + def name(self): + return self._overriden_name or getattr(self.parameter, 'name', '') def generate_info(parameter, name = None, default_sens_factory = parameter_mapping_sensitivity, fine_sens_factory = fine_grain_parameter_mapping_sensitivity): - if name is None: - name = parameter.name if parameter else '' return ParameterInfo(name=name, parameter=parameter, default_encoder_sensitivity=default_sens_factory(parameter), fine_grain_encoder_sensitivity=fine_sens_factory(parameter)) diff --git a/pushbase/parameter_slot_description.py b/pushbase/parameter_slot_description.py new file mode 100644 index 00000000..36df17f0 --- /dev/null +++ b/pushbase/parameter_slot_description.py @@ -0,0 +1,109 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/parameter_slot_description.py +from __future__ import absolute_import, print_function +from ableton.v2.base import find_if, listens_group, liveobj_valid, Subject, SlotManager +RESULTING_NAME_KEY = 'ResultingName' +CONDITION_NAME_KEY = 'ConditionName' +CONDITIONS_LIST_NAME_KEY = 'ConditionsListName' +PREDICATE_KEY = 'Predicate' +OPERAND_NAME_KEY = 'Operand' +AND = 'and' +OR = 'or' + +def find_parameter(name, host): + parameters = host.parameters if host != None else [] + return find_if(lambda p: p.original_name == name, parameters) + + +class ParameterSlotDescription(Subject, SlotManager): + """ + Description class that allows chosing a parameter (name) based on + the values of other parameters. To retrieve the chosen parameter name + turn the slot into a string. + + Examples: + - slot = use('A').if_parameter('B').has_value('1.0') + - slot = use('A').if_parameter('B').has_value('1.0').else_use('C') + - slot = use('A').if_parameter('B').has_value('1.0') .and_parameter('C').has_value('0.5').else_use('D') + - parameter_name = str(slot) + """ + __events__ = ('content',) + + def __init__(self, *a, **k): + super(ParameterSlotDescription, self).__init__(*a, **k) + self._parameter_host = None + self._default_parameter_name = '' + self._conditions = [] + self._cached_content = None + + def _calc_content(self): + content = self._default_parameter_name + for condition in self._conditions: + result = True + for subcond in condition[CONDITIONS_LIST_NAME_KEY]: + result = eval('%s %s %s' % (result, subcond[OPERAND_NAME_KEY], subcond[PREDICATE_KEY](find_parameter(subcond[CONDITION_NAME_KEY], self._parameter_host)))) + if not result: + continue + + if result: + content = condition[RESULTING_NAME_KEY] + break + + return content + + @listens_group('value') + def __on_condition_value_changed(self, _parameter): + new_content = self._calc_content() + if new_content != self._cached_content: + self._cached_content = new_content + self.notify_content() + + def set_parameter_host(self, host): + self._parameter_host = host + self._cached_content = self._calc_content() + params_names = set() + for c in self._conditions: + params_names.update([ cond[CONDITION_NAME_KEY] for cond in c[CONDITIONS_LIST_NAME_KEY] ]) + + self.__on_condition_value_changed.replace_subjects([ find_parameter(name, self._parameter_host) for name in params_names ]) + + def if_parameter(self, parameter_name): + self._conditions.append({RESULTING_NAME_KEY: self._default_parameter_name, + CONDITIONS_LIST_NAME_KEY: [{CONDITION_NAME_KEY: parameter_name, + OPERAND_NAME_KEY: AND}]}) + self._default_parameter_name = '' + return self + + def chain_condition(self, operand, parameter_name): + raise len(self._conditions) > 0 and len(self._conditions[-1][CONDITIONS_LIST_NAME_KEY]) > 0 and not self._default_parameter_name or AssertionError + self._conditions[-1][CONDITIONS_LIST_NAME_KEY].append({CONDITION_NAME_KEY: parameter_name, + OPERAND_NAME_KEY: operand}) + return self + + def and_parameter(self, parameter_name): + return self.chain_condition(AND, parameter_name) + + def or_parameter(self, parameter_name): + return self.chain_condition(OR, parameter_name) + + def _add_condition_predicate(self, predicate): + raise len(self._conditions) > 0 and PREDICATE_KEY not in self._conditions[-1][CONDITIONS_LIST_NAME_KEY][-1] or AssertionError + self._conditions[-1][CONDITIONS_LIST_NAME_KEY][-1][PREDICATE_KEY] = predicate + + def has_value(self, value): + self._add_condition_predicate(lambda p: str(p) == value) + return self + + def is_available(self, value): + self._add_condition_predicate(lambda p: liveobj_valid(p) == value) + return self + + def else_use(self, parameter_name): + self._default_parameter_name = parameter_name + return self + + def __str__(self): + return self._cached_content + + +def use(parameter_name): + return ParameterSlotDescription().else_use(parameter_name) \ No newline at end of file diff --git a/pushbase/percussion_instrument_finder_component.py b/pushbase/percussion_instrument_finder_component.py index 4c3c977d..16abcb34 100644 --- a/pushbase/percussion_instrument_finder_component.py +++ b/pushbase/percussion_instrument_finder_component.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/percussion_instrument_finder_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/percussion_instrument_finder_component.py +from __future__ import absolute_import, print_function import Live from itertools import chain from ableton.v2.base import Subject, listens_group, liveobj_changed, liveobj_valid @@ -80,11 +80,11 @@ def _update_listeners(self): def _update_instruments(self): drum_group = find_drum_group_device(self.device_parent) simpler = find_sliced_simpler(self.device_parent) - if not liveobj_changed(drum_group, self._drum_group): - do_notify = liveobj_changed(simpler, self._simpler) - self._drum_group = drum_group - self._simpler = simpler - do_notify and self.notify_instrument() + do_notify = liveobj_changed(drum_group, self._drum_group) or liveobj_changed(simpler, self._simpler) + self._drum_group = drum_group + self._simpler = simpler + if do_notify: + self.notify_instrument() def find_drum_group_device(track_or_chain): diff --git a/pushbase/playhead_component.py b/pushbase/playhead_component.py index 47312aef..e2aed205 100644 --- a/pushbase/playhead_component.py +++ b/pushbase/playhead_component.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/playhead_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/playhead_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import listens from ableton.v2.control_surface import Component diff --git a/pushbase/playhead_element.py b/pushbase/playhead_element.py index f12bb2c3..50136fe8 100644 --- a/pushbase/playhead_element.py +++ b/pushbase/playhead_element.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/playhead_element.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/playhead_element.py +from __future__ import absolute_import, print_function from ableton.v2.base import Proxy, nop from ableton.v2.control_surface import ControlElement diff --git a/pushbase/push_base.py b/pushbase/push_base.py index 045810d3..b10d174d 100644 --- a/pushbase/push_base.py +++ b/pushbase/push_base.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/push_base.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/push_base.py +from __future__ import absolute_import, print_function from contextlib import contextmanager from functools import partial from itertools import imap @@ -7,11 +7,12 @@ from ableton.v2.control_surface import BackgroundLayer, ClipCreator, ControlSurface, DeviceBankRegistry, Layer, midi from ableton.v2.control_surface.components import BackgroundComponent, M4LInterfaceComponent, ModifierBackgroundComponent, SessionNavigationComponent, SessionRingComponent, SessionOverviewComponent, ViewControlComponent from ableton.v2.control_surface.elements import adjust_string, ButtonElement, ButtonMatrixElement, ChoosingElement, ComboElement, DoublePressContext, MultiElement, OptionalElement, to_midi_value -from ableton.v2.control_surface.mode import AddLayerMode, LazyComponentMode, ReenterBehaviour, ModesComponent, EnablingModesComponent +from ableton.v2.control_surface.mode import AddLayerMode, LayerMode, LazyComponentMode, ReenterBehaviour, ModesComponent, EnablingModesComponent from .accent_component import AccentComponent from .actions import CaptureAndInsertSceneComponent, DeleteAndReturnToDefaultComponent, DeleteComponent, DeleteSelectedClipComponent, DeleteSelectedSceneComponent, DuplicateDetailClipComponent, DuplicateLoopComponent, UndoRedoComponent from .auto_arm_component import AutoArmComponent from .automation_component import AutomationComponent +from .banking_util import BankingInfo from .clip_control_component import ClipControlComponent from .device_parameter_component import DeviceParameterComponent from .grid_resolution import GridResolution @@ -21,20 +22,18 @@ from .matrix_maps import FEEDBACK_CHANNELS from .melodic_component import MelodicComponent from .message_box_component import DialogComponent, InfoComponent -from .note_editor_component import NoteEditorComponent +from .note_editor_component import DEFAULT_VELOCITY_RANGE_THRESHOLDS from .note_repeat_component import NoteRepeatComponent from .note_settings_component import NoteEditorSettingsComponent -from .provider_device_component import ProviderDeviceComponent from .selected_track_parameter_provider import SelectedTrackParameterProvider from .selection import PushSelection from .select_playing_clip_component import SelectPlayingClipComponent from .skin_default import make_default_skin from .sliced_simpler_component import SlicedSimplerComponent -from .special_mixer_component import SpecialMixerComponent from .special_session_component import SpecialSessionComponent from .step_seq_component import StepSeqComponent from .percussion_instrument_finder_component import PercussionInstrumentFinderComponent -from .touch_strip_controller import TouchStripControllerComponent, TouchStripEncoderConnection +from .touch_strip_controller import TouchStripControllerComponent, TouchStripEncoderConnection, TouchStripPitchModComponent from .track_frozen_mode import TrackFrozenModesComponent from .transport_component import TransportComponent from .value_component import ValueComponent, ParameterValueComponent @@ -42,6 +41,7 @@ from . import sysex NUM_TRACKS = 8 NUM_SCENES = 8 +TEMPO_SWING_TOUCH_DELAY = 0.4 def tracks_to_use_from_song(song): return tuple(song.visible_tracks) + tuple(song.return_tracks) @@ -51,10 +51,16 @@ class PushBase(ControlSurface): preferences_key = 'Push' session_component_type = SpecialSessionComponent drum_group_note_editor_skin = 'NoteEditor' + note_editor_velocity_range_thresholds = DEFAULT_VELOCITY_RANGE_THRESHOLDS + device_component_class = None + bank_definitions = None + note_editor_class = None def __init__(self, *a, **k): super(PushBase, self).__init__(*a, **k) self.register_slot(self.song.view, self._on_selected_track_changed, 'selected_track') + self._device_decorator_factory = self._create_device_decorator_factory() + self.register_disconnectable(self._device_decorator_factory) self._double_press_context = DoublePressContext() injecting = self._create_injector() self._push_injector = injecting.everywhere() @@ -97,6 +103,9 @@ def _component_guard(self): if song_view.selected_track != old_selected_track: self._track_selection_changed_by_action() + def _create_device_decorator_factory(self): + raise NotImplementedError + def _create_components(self): self._init_settings() self._init_notification() @@ -115,10 +124,10 @@ def _create_components(self): self._init_transport_and_recording() self._init_stop_clips_action() self._init_value_components() + self._init_track_list() self._init_mixer() self._init_track_mixer() self._init_session() - self._init_track_list() self._init_grid_resolution() self._init_drum_component() self._init_slicing_component() @@ -207,13 +216,16 @@ def _init_touch_strip_controller(self): for encoder in self.elements.global_param_controls.nested_control_elements(): encoder.set_observer(self._strip_connection) + self._pitch_mod_touch_strip = TouchStripPitchModComponent() + self._pitch_mod_touch_strip_layer = Layer(touch_strip='touch_strip_control', touch_strip_indication=self._with_firmware_version(1, 16, ComboElement('touch_strip_control', modifier='select_button')), touch_strip_toggle=self._with_firmware_version(1, 16, ComboElement('touch_strip_tap', modifier='select_button'))) + def _create_session_mode(self): raise NotImplementedError def _create_slicing_modes(self): slicing_modes = ModesComponent(name='Slicing_Modes', is_enabled=False) - slicing_modes.add_mode('64pads', [AddLayerMode(self._slicing_component, Layer(matrix='matrix'))]) - slicing_modes.add_mode('sequencer', [self._slice_step_sequencer, self._note_editor_settings_component, AddLayerMode(self._slicing_component, Layer(matrix=self.elements.matrix.submatrix[:4, 4:8]))]) + slicing_modes.add_mode('64pads', [AddLayerMode(self._slicing_component, Layer(matrix='matrix')), LayerMode(self._pitch_mod_touch_strip, self._pitch_mod_touch_strip_layer)]) + slicing_modes.add_mode('sequencer', [self._slice_step_sequencer, self._note_editor_settings_component, AddLayerMode(self._slicing_component, Layer(matrix=self.elements.matrix.submatrix[:4, 4:8], page_strip='touch_strip_control', scroll_strip=self._with_shift('touch_strip_control')))]) slicing_modes.selected_mode = '64pads' return slicing_modes @@ -395,50 +407,8 @@ def _init_track_frozen(self): def _create_track_frozen_layer(self): return Layer() - def _create_mixer(self): - return SpecialMixerComponent(tracks_provider=self._session_ring, is_root=True) - - def _create_mixer_layer(self): - return Layer(track_select_buttons='select_buttons') - - def _create_mixer_pan_send_layer(self): - return Layer(track_select_buttons='select_buttons', pan_send_toggle='pan_send_mix_mode_button', pan_send_controls='fine_grain_param_controls') - - def _create_mixer_volume_layer(self): - return Layer(track_select_buttons='select_buttons', volume_controls='fine_grain_param_controls') - - def _create_mixer_track_layer(self): - return Layer(track_select_buttons='select_buttons') - - def _create_mixer_solo_layer(self): - return Layer(solo_buttons='track_state_buttons') - - def _create_mixer_mute_layer(self): - return Layer(mute_buttons='track_state_buttons') - def _init_mixer(self): - self._mixer = self._create_mixer() - self._mixer.set_enabled(False) - self._mixer.name = 'Mixer' - self._mixer_layer = self._create_mixer_layer() - self._mixer_pan_send_layer = self._create_mixer_pan_send_layer() - self._mixer_volume_layer = self._create_mixer_volume_layer() - self._mixer_track_layer = self._create_mixer_track_layer() - self._mixer_solo_layer = self._create_mixer_solo_layer() - self._mixer_mute_layer = self._create_mixer_mute_layer() - for track in xrange(self.elements.matrix.width()): - strip = self._mixer.channel_strip(track) - strip.name = 'Channel_Strip_' + str(track) - strip.set_invert_mute_feedback(True) - strip.set_delete_handler(self._delete_component) - strip._do_select_track = self.on_select_track - strip.layer = Layer(shift_button='shift_button', duplicate_button='duplicate_button', selector_button='select_button') - - self._mixer.selected_strip().name = 'Selected_Channel_strip' - self._mixer.master_strip().name = 'Master_Channel_strip' - self._mixer.master_strip()._do_select_track = self.on_select_track - self._mixer.master_strip().layer = Layer(select_button='master_select_button', selector_button='select_button') - self._mixer.set_enabled(True) + pass def _init_track_mixer(self): self._track_parameter_provider = self.register_disconnectable(SelectedTrackParameterProvider()) @@ -448,7 +418,7 @@ def _create_track_mixer_layer(self): return Layer(parameter_controls='fine_grain_param_controls') def _create_device_component(self): - return ProviderDeviceComponent(device_bank_registry=self._device_bank_registry, name='DeviceComponent', is_enabled=True, is_root=True) + return self.device_component_class(device_decorator_factory=self._device_decorator_factory, device_bank_registry=self._device_bank_registry, banking_info=self._banking_info, name='DeviceComponent', is_enabled=True, is_root=True) def _create_device_parameter_component(self): return DeviceParameterComponent(parameter_provider=self._device_component, is_enabled=False, layer=self._create_device_parameter_layer()) @@ -461,9 +431,8 @@ def _create_device_navigation(self): def _init_device(self): self._device_bank_registry = DeviceBankRegistry() + self._banking_info = BankingInfo(self.bank_definitions) self._device_component = self._create_device_component() - self._device_component.device_selection_follows_track_selection = True - self.set_device_component(self._device_component) self._device_parameter_component = self._create_device_parameter_component() self._device_navigation = self._create_device_navigation() @@ -489,7 +458,7 @@ def _init_transport_and_recording(self): self._view_control.layer = Layer(prev_track_button='nav_left_button', next_track_button='nav_right_button', prev_scene_button=OptionalElement('nav_up_button', self._settings['workflow'], False), next_scene_button=OptionalElement('nav_down_button', self._settings['workflow'], False), prev_scene_list_button=OptionalElement('nav_up_button', self._settings['workflow'], True), next_scene_list_button=OptionalElement('nav_down_button', self._settings['workflow'], True)) self._session_recording = self._create_session_recording() new_button = MultiElement(self.elements.new_button, self.elements.foot_pedal_button.double_press) - self._session_recording.layer = Layer(new_button=OptionalElement(new_button, self._settings['workflow'], False), scene_list_new_button=OptionalElement(new_button, self._settings['workflow'], True), record_button='record_button', automation_button='automation_button', new_scene_button=self._with_shift('new_button'), re_enable_automation_button=self._with_shift('automation_button'), delete_automation_button=ComboElement('automation_button', 'delete_button'), foot_switch_button=self.elements.foot_pedal_button.single_press, _uses_foot_pedal='foot_pedal_button') + self._session_recording.layer = Layer(new_button=OptionalElement(new_button, self._settings['workflow'], False), scene_list_new_button=OptionalElement(new_button, self._settings['workflow'], True), record_button='record_button', arrangement_record_button=self._with_shift('record_button'), automation_button='automation_button', new_scene_button=self._with_shift('new_button'), re_enable_automation_button=self._with_shift('automation_button'), delete_automation_button=ComboElement('automation_button', 'delete_button'), foot_switch_button=self.elements.foot_pedal_button.single_press, _uses_foot_pedal='foot_pedal_button') self._transport = TransportComponent(name='Transport', is_root=True) self._transport.layer = Layer(play_button='play_button', stop_button=self._with_shift('play_button'), tap_tempo_button='tap_tempo_button', metronome_button='metronome_button') @@ -534,7 +503,7 @@ def _create_instrument_layer(self): def _init_instrument(self): self._note_layout = NoteLayout(song=self.song, preferences=self.preferences) instrument_basic_layer = Layer(octave_strip=self._with_shift('touch_strip_control'), octave_up_button='octave_up_button', octave_down_button='octave_down_button', scale_up_button=self._with_shift('octave_up_button'), scale_down_button=self._with_shift('octave_down_button')) - self._instrument = MelodicComponent(skin=self._skin, is_enabled=False, clip_creator=self._clip_creator, name='Melodic_Component', grid_resolution=self._grid_resolution, note_layout=self._note_layout, note_editor_settings=self._note_editor_settings_component, layer=self._create_instrument_layer(), instrument_play_layer=instrument_basic_layer + Layer(matrix='matrix', touch_strip='touch_strip_control', touch_strip_indication=self._with_firmware_version(1, 16, ComboElement('touch_strip_control', modifier='select_button')), touch_strip_toggle=self._with_firmware_version(1, 16, ComboElement('touch_strip_tap', modifier='select_button')), aftertouch_control='aftertouch_control', delete_button='delete_button'), instrument_sequence_layer=instrument_basic_layer + Layer(note_strip='touch_strip_control')) + self._instrument = MelodicComponent(skin=self._skin, is_enabled=False, clip_creator=self._clip_creator, name='Melodic_Component', grid_resolution=self._grid_resolution, note_layout=self._note_layout, note_editor_settings=self._note_editor_settings_component, note_editor_class=self.note_editor_class, velocity_range_thresholds=self.note_editor_velocity_range_thresholds, layer=self._create_instrument_layer(), instrument_play_layer=instrument_basic_layer + Layer(matrix='matrix', aftertouch_control='aftertouch_control', delete_button='delete_button'), instrument_sequence_layer=instrument_basic_layer + Layer(note_strip='touch_strip_control'), pitch_mod_touch_strip_mode=LayerMode(self._pitch_mod_touch_strip, self._pitch_mod_touch_strip_layer)) self.__on_note_editor_layout_changed.subject = self._instrument def _create_scales_enabler(self): @@ -547,7 +516,7 @@ def _create_step_sequencer_layer(self): return Layer(playhead='playhead_element', button_matrix=self.elements.matrix.submatrix[:8, :4], loop_selector_matrix=self.elements.double_press_matrix.submatrix[4:8, 4:8], short_loop_selector_matrix=self.elements.double_press_event_matrix.submatrix[4:8, 4:8], quantization_buttons='side_buttons', solo_button='global_solo_button', select_button='select_button', delete_button='delete_button', shift_button='shift_button', mute_button='global_mute_button') def _init_step_sequencer(self): - drum_note_editor = NoteEditorComponent(clip_creator=self._clip_creator, grid_resolution=self._grid_resolution, skin_base_key=self.drum_group_note_editor_skin) + drum_note_editor = self.note_editor_class(clip_creator=self._clip_creator, grid_resolution=self._grid_resolution, skin_base_key=self.drum_group_note_editor_skin, velocity_range_thresholds=self.note_editor_velocity_range_thresholds) self._note_editor_settings_component.add_editor(drum_note_editor) self._drum_step_sequencer = StepSeqComponent(self._clip_creator, self._skin, name='Drum_Step_Sequencer', grid_resolution=self._grid_resolution, note_editor_component=drum_note_editor, instrument_component=self._drum_component) self._drum_step_sequencer.set_enabled(False) @@ -555,7 +524,7 @@ def _init_step_sequencer(self): self._audio_loop = LoopSelectorComponent(follow_detail_clip=True, measure_length=1.0, name='Loop_Selector') self._audio_loop.set_enabled(False) self._audio_loop.layer = Layer(loop_selector_matrix='matrix') - slice_note_editor = NoteEditorComponent(clip_creator=self._clip_creator, grid_resolution=self._grid_resolution, skin_base_key=self.drum_group_note_editor_skin) + slice_note_editor = self.note_editor_class(clip_creator=self._clip_creator, grid_resolution=self._grid_resolution, skin_base_key=self.drum_group_note_editor_skin, velocity_range_thresholds=self.note_editor_velocity_range_thresholds) self._note_editor_settings_component.add_editor(slice_note_editor) self._slice_step_sequencer = StepSeqComponent(self._clip_creator, self._skin, name='Slice_Step_Sequencer', grid_resolution=self._grid_resolution, note_editor_component=slice_note_editor, instrument_component=self._slicing_component, is_enabled=False) self._slice_step_sequencer.layer = Layer(playhead='playhead_element', button_matrix=self.elements.matrix.submatrix[:8, :4], loop_selector_matrix=self.elements.double_press_matrix.submatrix[4:8, 4:8], short_loop_selector_matrix=self.elements.double_press_event_matrix.submatrix[4:8, 4:8], quantization_buttons='side_buttons', select_button='select_button') @@ -572,7 +541,7 @@ def _init_drum_component(self): def _init_slicing_component(self): self._slicing_component = SlicedSimplerComponent(is_enabled=False) - self._slicing_component.layer = Layer(page_strip='touch_strip_control', scroll_strip=self._with_shift('touch_strip_control'), scroll_page_up_button='octave_up_button', scroll_page_down_button='octave_down_button', scroll_up_button=self._with_shift('octave_up_button'), scroll_down_button=self._with_shift('octave_down_button'), delete_button='delete_button', select_button='select_button') + self._slicing_component.layer = Layer(scroll_page_up_button='octave_up_button', scroll_page_down_button='octave_down_button', scroll_up_button=self._with_shift('octave_up_button'), scroll_down_button=self._with_shift('octave_down_button'), delete_button='delete_button', select_button='select_button') def _init_note_repeat(self): self._note_repeat = NoteRepeatComponent(name='Note_Repeat') @@ -613,7 +582,7 @@ def _init_undo_redo_actions(self): self._undo_redo.layer = Layer(undo_button='undo_button', redo_button=self._with_shift('undo_button')) def _init_stop_clips_action(self): - raise NotImplementedError + pass def _create_capture_and_insert_scene_component(self): return CaptureAndInsertSceneComponent(name='Capture_And_Insert_Scene', is_root=True) @@ -643,9 +612,9 @@ def _init_quantize_actions(self): raise NotImplementedError def _init_value_components(self): - self._swing_amount = ValueComponent('swing_amount', self.song, display_label='Swing Amount:', display_format='%d%%', model_transform=lambda x: clamp(x / 200.0, 0.0, 0.5), view_transform=lambda x: x * 200.0, encoder_factor=100.0, is_root=True) + self._swing_amount = ValueComponent('swing_amount', self.song, display_label='Swing Amount:', display_format='%d%%', model_transform=lambda x: clamp(x / 200.0, 0.0, 0.5), view_transform=lambda x: x * 200.0, encoder_factor=100.0, encoder_touch_delay=TEMPO_SWING_TOUCH_DELAY, is_root=True) self._swing_amount.layer = Layer(encoder='swing_control') - self._tempo = ValueComponent('tempo', self.song, display_label='Tempo:', display_format='%0.2f BPM', encoder_factor=128.0, is_root=True) + self._tempo = ValueComponent('tempo', self.song, display_label='Tempo:', display_format='%0.2f BPM', encoder_factor=128.0, encoder_touch_delay=TEMPO_SWING_TOUCH_DELAY, is_root=True) self._tempo.layer = Layer(encoder='tempo_control', shift_button='shift_button') self._master_vol = ParameterValueComponent(self.song.master_track.mixer_device.volume, display_label='Master Volume:', display_seg_start=3, name='Master_Volume_Display', is_root=True) self._master_vol.layer = Layer(encoder='master_volume_control') @@ -732,7 +701,7 @@ def __on_matrix_mode_changed(self, mode): self._update_auto_arm(selected_mode=mode) def _update_auto_arm(self, selected_mode = None): - self._auto_arm.set_enabled(self._user.mode == sysex.LIVE_MODE and (selected_mode or self._matrix_modes.selected_mode == 'note')) + self._auto_arm.set_enabled(self._user.mode == sysex.LIVE_MODE and (selected_mode or self._matrix_modes.selected_mode) == 'note') @listens('instrument') def __on_percussion_instrument_changed(self): diff --git a/pushbase/quantization_component.py b/pushbase/quantization_component.py index 5a1f8cf3..ca1f37ee 100644 --- a/pushbase/quantization_component.py +++ b/pushbase/quantization_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/quantization_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/quantization_component.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import clamp, listenable_property, listens from ableton.v2.control_surface import Component, CompoundComponent @@ -16,6 +17,7 @@ RecordingQuantization.rec_q_thirtysecond] DEFAULT_QUANTIZATION_INDEX = QUANTIZATION_OPTIONS.index(RecordingQuantization.rec_q_sixtenth) QUANTIZATION_NAMES = ('1/4', '1/8', '1/8t', '1/8+t', '1/16', '1/16t', '1/16+t', '1/32') +QUANTIZATION_NAMES_UNICODE = (u'\xbc', u'\u215b', u'\u215bt', u'\u215b+t', u'\ue001', u'\ue001t', u'\ue001+t', u'\ue002') def quantize_amount_to_string(amount): """ @@ -34,8 +36,9 @@ class QuantizationSettingsComponent(Component): quantize_to_index = listenable_property.managed(DEFAULT_QUANTIZATION_INDEX) record_quantization_index = listenable_property.managed(DEFAULT_QUANTIZATION_INDEX) - def __init__(self, *a, **k): + def __init__(self, quantization_names = QUANTIZATION_NAMES, *a, **k): super(QuantizationSettingsComponent, self).__init__(*a, **k) + self._quantization_names = quantization_names self.__on_swing_amount_changed.subject = self.song self.__on_record_quantization_changed.subject = self.song self.__on_record_quantization_changed() @@ -54,7 +57,11 @@ def record_quantization_enabled(self): @property def quantization_option_names(self): - return QUANTIZATION_NAMES + return self._quantization_names + + @property + def selected_quantization_name(self): + return self.quantization_option_names[self.quantize_to_index] @swing_amount_encoder.value def swing_amount_encoder(self, value, encoder): @@ -113,7 +120,7 @@ def quantize_pitch(self, note): clip = self.song.view.detail_clip if clip: clip.quantize_pitch(note, self._settings.quantize_to, self._settings.quantize_amount) - self.show_notification(MessageBoxText.QUANTIZE_CLIP_PITCH % dict(amount=quantize_amount_to_string(self._settings.quantize_amount), to=QUANTIZATION_NAMES[self._settings.quantize_to_index])) + self.show_notification(MessageBoxText.QUANTIZE_CLIP_PITCH % dict(amount=quantize_amount_to_string(self._settings.quantize_amount), to=self._settings.selected_quantization_name)) self._cancel_quantize = True @action_button.pressed_delayed @@ -130,5 +137,5 @@ def action_button(self, button): clip = self.song.view.detail_clip if clip and not self._cancel_quantize: clip.quantize(self._settings.quantize_to, self._settings.quantize_amount) - self.show_notification(MessageBoxText.QUANTIZE_CLIP % dict(amount=quantize_amount_to_string(self._settings.quantize_amount), to=QUANTIZATION_NAMES[self._settings.quantize_to_index])) + self.show_notification(MessageBoxText.QUANTIZE_CLIP % dict(amount=quantize_amount_to_string(self._settings.quantize_amount), to=self._settings.selected_quantization_name)) self._cancel_quantize = False \ No newline at end of file diff --git a/pushbase/scrollable_list.py b/pushbase/scrollable_list.py index af0041db..16f9b9b3 100644 --- a/pushbase/scrollable_list.py +++ b/pushbase/scrollable_list.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/scrollable_list.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/scrollable_list.py +from __future__ import absolute_import, print_function from functools import partial from ableton.v2.base import BooleanContext, clamp, forward_property, in_range, index_if, Subject, listens, task from ableton.v2.control_surface import CompoundComponent, defaults @@ -167,7 +167,8 @@ def _normalize_offset(self, index): @property def selected_item(self): - return self._items[self.selected_item_index] if in_range(self._selected_item_index, 0, len(self._items)) else None + if in_range(self._selected_item_index, 0, len(self._items)): + return self._items[self.selected_item_index] @property def items(self): @@ -382,7 +383,8 @@ def _execute_action(self): @property def selected_item(self): - return self._scrollable_list.selected_item if self._scrollable_list != None else None + if self._scrollable_list != None: + return self._scrollable_list.selected_item @property def next_item(self): diff --git a/pushbase/scrollable_list_component.py b/pushbase/scrollable_list_component.py index 5f81c7de..e08e1db1 100644 --- a/pushbase/scrollable_list_component.py +++ b/pushbase/scrollable_list_component.py @@ -1,7 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/scrollable_list_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/scrollable_list_component.py """ Scrollable list component. """ +from __future__ import absolute_import, print_function from functools import partial from ableton.v2.base import in_range, Event from ableton.v2.base.signal import short_circuit_signal diff --git a/pushbase/select_playing_clip_component.py b/pushbase/select_playing_clip_component.py index e80bf4f6..71b8be71 100644 --- a/pushbase/select_playing_clip_component.py +++ b/pushbase/select_playing_clip_component.py @@ -1,7 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/select_playing_clip_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/select_playing_clip_component.py """ Component that automatically selects the playing clip in the selected track. """ +from __future__ import absolute_import, print_function from ableton.v2.base import index_if, partial, nop, listens, task from ableton.v2.control_surface.control import ButtonControl from ableton.v2.control_surface.mode import ModesComponent, AddLayerMode @@ -52,7 +53,7 @@ def _show_notification(self, display_text): def _selected_track_clip_is_playing(self): playing_clip_slot = self._playing_clip_slot() - return playing_clip_slot and not playing_clip_slot.clip != self.song.view.detail_clip + return not (playing_clip_slot and playing_clip_slot.clip != self.song.view.detail_clip) def _playing_clip_slot(self): track = self.song.view.selected_track diff --git a/pushbase/selected_track_parameter_provider.py b/pushbase/selected_track_parameter_provider.py index 20dd2030..4c8de9f7 100644 --- a/pushbase/selected_track_parameter_provider.py +++ b/pushbase/selected_track_parameter_provider.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/selected_track_parameter_provider.py -from __future__ import absolute_import +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/selected_track_parameter_provider.py +from __future__ import absolute_import, print_function from ableton.v2.base import depends, listens, SlotManager from .special_chan_strip_component import TRACK_PARAMETER_NAMES from .parameter_provider import ParameterProvider, generate_info diff --git a/pushbase/selection.py b/pushbase/selection.py index aea7bfed..1715625c 100644 --- a/pushbase/selection.py +++ b/pushbase/selection.py @@ -1,7 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/selection.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/selection.py """ Object that encapsulates selection in the Push controller. """ +from __future__ import absolute_import, print_function import Live class Selection(object): @@ -79,7 +80,7 @@ def _set_selected_object(self, lom_object): if isinstance(lom_object, Live.Chain.Chain): lom_object.canonical_parent.view.selected_chain = lom_object else: - self._application.get_document().view.select_device(lom_object) + self._application.get_document().view.select_device(lom_object, False) selected_object = property(_get_selected_object, _set_selected_object) diff --git a/pushbase/session_recording_component.py b/pushbase/session_recording_component.py index e613f14f..9487c025 100644 --- a/pushbase/session_recording_component.py +++ b/pushbase/session_recording_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/session_recording_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/session_recording_component.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import listens from ableton.v2.control_surface.control import ButtonControl @@ -13,17 +14,43 @@ def track_can_overdub(track): class FixedLengthSessionRecordingComponent(SessionRecordingComponent, Messenger): foot_switch_button = ButtonControl() + arrangement_record_button = ButtonControl() def __init__(self, fixed_length_setting = None, *a, **k): raise fixed_length_setting is not None or AssertionError super(FixedLengthSessionRecordingComponent, self).__init__(*a, **k) self._fixed_length_setting = fixed_length_setting self.__on_setting_selected_index_changes.subject = self._fixed_length_setting + self.__on_record_mode_changed.subject = self.song + self.__on_record_mode_changed() @foot_switch_button.pressed def foot_switch_button(self, button): self._trigger_recording() + @arrangement_record_button.pressed + def arrangement_record_button(self, button): + self.song.record_mode = not self.song.record_mode + + def _trigger_recording(self): + if self.is_enabled(): + if self.song.record_mode: + self.song.record_mode = False + else: + super(FixedLengthSessionRecordingComponent, self)._trigger_recording() + + def _update_record_button(self): + if self.is_enabled(): + if self.song.record_mode: + self._record_button.color = 'Recording.ArrangementRecordingOn' + else: + super(FixedLengthSessionRecordingComponent, self)._update_record_button() + self.arrangement_record_button.color = self._record_button.color + + @listens('record_mode') + def __on_record_mode_changed(self): + self._update_record_button() + def _start_recording(self): song = self.song song.overdub = True diff --git a/pushbase/setting.py b/pushbase/setting.py index 791097fb..8f643160 100644 --- a/pushbase/setting.py +++ b/pushbase/setting.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/setting.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/setting.py +from __future__ import absolute_import, print_function from math import fabs from ableton.v2.base import sign, clamp, Subject, Event @@ -12,10 +13,10 @@ class Setting(Subject): def __init__(self, name = '', values = None, default_value = None, preferences = None, *a, **k): super(Setting, self).__init__(*a, **k) self.name = name - if not values: - self.values = [] - self._preferences = preferences if preferences != None else {} - default_value = name in self._preferences and self._preferences[name] in values and self._preferences[name] + self.values = values or [] + self._preferences = preferences if preferences != None else {} + if name in self._preferences and self._preferences[name] in values: + default_value = self._preferences[name] self._preferences[name] = None self.value = default_value @@ -84,7 +85,8 @@ def _jump_relative(self, relative_position): current_position = self.values.index(self.value) new_position = clamp(current_position + relative_position, 0, len(self.values) - 1) self.value = self.values[new_position] - return new_position if current_position != new_position else None + if current_position != new_position: + return new_position def on_value_changed(self, value): self._relative_value = 0.0 diff --git a/pushbase/simpler_decoration.py b/pushbase/simpler_decoration.py new file mode 100644 index 00000000..c17f6f9f --- /dev/null +++ b/pushbase/simpler_decoration.py @@ -0,0 +1,160 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/simpler_decoration.py +from __future__ import absolute_import, print_function +from functools import partial +import Live +from ableton.v2.base import clamp, liveobj_valid, listenable_property, listens, SlotManager, Subject +from ableton.v2.base.collection import IndexedDict +from .decoration import DecoratorFactory, LiveObjectDecorator +from .internal_parameter import EnumWrappingParameter, RelativeInternalParameter, to_percentage_display, WrappingParameter +BoolWrappingParameter = partial(WrappingParameter, to_property_value=lambda integer, _simpler: bool(integer), from_property_value=lambda boolean, _simpler: int(boolean), value_items=['off', 'on'], display_value_conversion=lambda val: ('on' if val else 'off')) + +def from_user_range(minv, maxv): + return lambda v, s: (v - minv) / float(maxv - minv) + + +def to_user_range(minv, maxv): + return lambda v, s: clamp(v * (maxv - minv) + minv, minv, maxv) + + +def from_sample_count(value, sample): + return float(value) / sample.length + + +def to_sample_count(value, sample): + return clamp(int(value * sample.length), 0, sample.length - 1) + + +SimplerWarpModes = IndexedDict(((Live.Clip.WarpMode.beats, 'Beats'), + (Live.Clip.WarpMode.tones, 'Tones'), + (Live.Clip.WarpMode.texture, 'Texture'), + (Live.Clip.WarpMode.repitch, 'Re-Pitch'), + (Live.Clip.WarpMode.complex, 'Complex'), + (Live.Clip.WarpMode.complex_pro, 'Pro'))) + +class SimplerDeviceDecorator(Subject, SlotManager, LiveObjectDecorator): + + def __init__(self, *a, **k): + super(SimplerDeviceDecorator, self).__init__(*a, **k) + self._sample_based_parameters = [] + self._additional_parameters = [] + self.setup_parameters() + self.register_disconnectables(self._decorated_parameters()) + self.__on_playback_mode_changed.subject = self._live_object + self.__on_sample_changed.subject = self._live_object + self.__on_slices_changed.subject = self._live_object.sample + + def setup_parameters(self): + self.start = WrappingParameter(name='Start', parent=self, property_host=self._live_object.sample, source_property='start_marker', from_property_value=from_sample_count, to_property_value=to_sample_count) + self.end = WrappingParameter(name='End', parent=self, property_host=self._live_object.sample, source_property='end_marker', from_property_value=from_sample_count, to_property_value=to_sample_count) + self.sensitivity = WrappingParameter(name='Sensitivity', parent=self, property_host=self._live_object.sample, source_property='slicing_sensitivity', display_value_conversion=to_percentage_display) + self.mode = EnumWrappingParameter(name='Mode', parent=self, values_property_host=self, index_property_host=self, values_property='available_playback_modes', index_property='playback_mode') + self.slicing_playback_mode_param = EnumWrappingParameter(name='Playback', parent=self, values_property_host=self, index_property_host=self, values_property='available_slicing_playback_modes', index_property='slicing_playback_mode') + self.pad_slicing_param = BoolWrappingParameter(name='Pad Slicing', parent=self, property_host=self._live_object, source_property='pad_slicing') + self.nudge = RelativeInternalParameter(name='Nudge', parent=self) + self.multi_sample_mode_param = BoolWrappingParameter(name='Multi Sample', parent=self, property_host=self._live_object, source_property='multi_sample_mode') + self.warp = BoolWrappingParameter(name='Warp', parent=self, property_host=self._live_object.sample, source_property='warping') + self.warp_mode_param = EnumWrappingParameter(name='Warp Mode', parent=self, values_property_host=self, index_property_host=self._live_object.sample, values_property='available_warp_modes', index_property='warp_mode', to_index_conversion=lambda i: Live.Clip.WarpMode(SimplerWarpModes.key_by_index(i)), from_index_conversion=lambda i: SimplerWarpModes.index_by_key(i)) + self.voices_param = EnumWrappingParameter(name='Voices', parent=self, values_property_host=self, index_property_host=self, values_property='available_voice_numbers', index_property='voices', to_index_conversion=lambda i: self.available_voice_numbers[i], from_index_conversion=lambda i: self.available_voice_numbers.index(i)) + self.granulation_resolution = EnumWrappingParameter(name='Preserve', parent=self, values_property_host=self, index_property_host=self._live_object.sample, values_property='available_resolutions', index_property='beats_granulation_resolution') + self.transient_loop_mode = EnumWrappingParameter(name='Loop Mode', parent=self, values_property_host=self, index_property_host=self._live_object.sample, values_property='available_transient_loop_modes', index_property='beats_transient_loop_mode') + self.transient_envelope = WrappingParameter(name='Envelope', parent=self, property_host=self._live_object.sample, source_property='beats_transient_envelope', from_property_value=from_user_range(0.0, 100.0), to_property_value=to_user_range(0.0, 100.0)) + self.tones_grain_size_param = WrappingParameter(name='Grain Size Tones', parent=self, property_host=self._live_object.sample, source_property='tones_grain_size', from_property_value=from_user_range(12.0, 100.0), to_property_value=to_user_range(12.0, 100.0)) + self.texture_grain_size_param = WrappingParameter(name='Grain Size Texture', parent=self, property_host=self._live_object.sample, source_property='texture_grain_size', from_property_value=from_user_range(2.0, 263.0), to_property_value=to_user_range(2.0, 263.0)) + self.flux = WrappingParameter(name='Flux', parent=self, property_host=self._live_object.sample, source_property='texture_flux', from_property_value=from_user_range(0.0, 100.0), to_property_value=to_user_range(0.0, 100.0)) + self.formants = WrappingParameter(name='Formants', parent=self, property_host=self._live_object.sample, source_property='complex_pro_formants', from_property_value=from_user_range(0.0, 100.0), to_property_value=to_user_range(0.0, 100.0)) + self.complex_pro_envelope_param = WrappingParameter(name='Envelope Complex Pro', parent=self, property_host=self._live_object.sample, source_property='complex_pro_envelope', from_property_value=from_user_range(8.0, 256.0), to_property_value=to_user_range(8.0, 256.0)) + self.gain_param = WrappingParameter(name='Gain', parent=self, property_host=self._live_object.sample, source_property='gain', display_value_conversion=lambda _: (self._live_object.sample.gain_display_string() if liveobj_valid(self._live_object) and liveobj_valid(self._live_object.sample) else '')) + self._sample_based_parameters.extend([self.start, + self.end, + self.sensitivity, + self.warp, + self.transient_envelope, + self.tones_grain_size_param, + self.texture_grain_size_param, + self.flux, + self.formants, + self.complex_pro_envelope_param, + self.gain_param]) + self._additional_parameters.extend([self.mode, + self.slicing_playback_mode_param, + self.pad_slicing_param, + self.nudge, + self.multi_sample_mode_param, + self.warp_mode_param, + self.voices_param, + self.granulation_resolution, + self.transient_loop_mode]) + + def _decorated_parameters(self): + return tuple(self._sample_based_parameters) + tuple(self._additional_parameters) + + @property + def parameters(self): + return tuple(self._live_object.parameters) + self._decorated_parameters() + + @property + def available_playback_modes(self): + return ['Classic', 'One-Shot', 'Slicing'] + + @property + def available_slicing_playback_modes(self): + return ['Mono', 'Poly', 'Thru'] + + @property + def available_voice_numbers(self): + return list(Live.SimplerDevice.get_available_voice_numbers()) + + @property + def available_warp_modes(self): + return SimplerWarpModes.values() + + @property + def available_resolutions(self): + return (u'1 Bar', u'1/2', u'1/4', u'1/8', u'1/16', u'1/32', u'Transients') + + @property + def available_transient_loop_modes(self): + return ('Off', 'Forward', 'Alternate') + + @listenable_property + def current_playback_mode(self): + return self._live_object.playback_mode + + @listenable_property + def slices(self): + if liveobj_valid(self._live_object) and liveobj_valid(self._live_object.sample): + return self._live_object.sample.slices + return [] + + @listens('sample') + def __on_sample_changed(self): + self._reconnect_sample_listeners() + + def _reconnect_sample_listeners(self): + for param in self._sample_based_parameters: + param.set_property_host(self._live_object.sample) + + for param in (self.warp_mode_param, self.granulation_resolution, self.transient_loop_mode): + param.set_index_property_host(self._live_object.sample) + + self._reconnect_to_slices() + + def _reconnect_to_slices(self): + self.__on_slices_changed.subject = self._live_object.sample + self.notify_slices() + + @listens('slices') + def __on_slices_changed(self): + self.notify_slices() + + @listens('playback_mode') + def __on_playback_mode_changed(self): + self.notify_current_playback_mode() + + +class SimplerDecoratorFactory(DecoratorFactory): + _decorator = SimplerDeviceDecorator + + @classmethod + def _should_be_decorated(cls, device): + return liveobj_valid(device) and device.class_name == 'OriginalSimpler' \ No newline at end of file diff --git a/pushbase/simpler_slice_nudging.py b/pushbase/simpler_slice_nudging.py new file mode 100644 index 00000000..233ba721 --- /dev/null +++ b/pushbase/simpler_slice_nudging.py @@ -0,0 +1,73 @@ +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/simpler_slice_nudging.py +from __future__ import absolute_import, print_function +from contextlib import contextmanager +import Live +from ableton.v2.base import SlotManager, find_if, liveobj_valid, clamp, listens +from .device_chain_utils import is_simpler +CENTERED_NUDGE_VALUE = 0.5 +MINIMUM_SLICE_DISTANCE = 2 + +class SimplerSliceNudging(SlotManager): + _simpler = None + _nudge_parameter = None + + def set_device(self, device): + self._simpler = device if is_simpler(device) else None + self.__on_selected_slice_changed.subject = self._simpler + with self._updating_nudge_parameter(): + self._nudge_parameter = find_if(lambda p: p.name == 'Nudge', self._simpler.parameters if liveobj_valid(self._simpler) else []) + + @contextmanager + def _updating_nudge_parameter(self): + if self._nudge_parameter: + self._nudge_parameter.set_display_value_conversion(None) + yield + if self._nudge_parameter: + self._nudge_parameter.set_display_value_conversion(self._display_value_conversion) + self.__on_nudge_delta.subject = self._nudge_parameter + + def _can_access_slicing_properties(self): + return liveobj_valid(self._simpler) and liveobj_valid(self._simpler.sample) and self._simpler.current_playback_mode == Live.SimplerDevice.PlaybackMode.slicing + + @listens('view.selected_slice') + def __on_selected_slice_changed(self): + if self._nudge_parameter: + self._nudge_parameter.notify_value() + + @listens('delta') + def __on_nudge_delta(self, delta): + if self._can_access_slicing_properties(): + old_slice_time = self._simpler.view.selected_slice + if old_slice_time >= 0: + if self._is_first_slice_at_time(old_slice_time): + new_start = self._new_start_marker_time(old_slice_time, delta) + self._simpler.sample.start_marker = new_start + return + new_slice_time = old_slice_time + self._sample_change_from_delta(delta) + if old_slice_time != new_slice_time: + original_slices = self._simpler.sample.slices + returned_time = self._simpler.sample.move_slice(old_slice_time, new_slice_time) + try: + self._simpler.view.selected_slice = returned_time + except RuntimeError: + self._simpler.view.selected_slice = self._simpler.slices[list(original_slices).index(old_slice_time)] + + def _is_first_slice_at_time(self, slice_time): + start_sample = self._simpler.sample.start_marker + return abs(slice_time - start_sample) < MINIMUM_SLICE_DISTANCE + + def _new_start_marker_time(self, old_slice_time, delta): + change_in_samples = self._sample_change_from_delta(delta) + new_start_marker_time = old_slice_time + change_in_samples + return clamp(new_start_marker_time, 0, self._simpler.sample.length - MINIMUM_SLICE_DISTANCE) + + def _sample_change_from_delta(self, delta): + sample_length = self._simpler.sample.length + change_in_samples = round(delta * sample_length / 10) + return int(change_in_samples) + + def _display_value_conversion(self, _value): + selected_slice = self._simpler.view.selected_slice if self._can_access_slicing_properties() else -1 + if selected_slice >= 0: + return str(selected_slice) + return '-' \ No newline at end of file diff --git a/pushbase/skin_default.py b/pushbase/skin_default.py index 0fbb24a7..317a32b1 100644 --- a/pushbase/skin_default.py +++ b/pushbase/skin_default.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/skin_default.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/skin_default.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface import Skin from .colors import Basic, Rgb, Pulse, Blink, BiLed @@ -46,6 +47,7 @@ class Recording: On = Basic.FULL Off = Basic.HALF Transition = Basic.FULL_BLINK_FAST + ArrangementRecordingOn = Basic.FULL_BLINK_SLOW FixedLengthRecordingOn = BiLed.YELLOW FixedLengthRecordingOff = BiLed.OFF diff --git a/pushbase/sliced_simpler_component.py b/pushbase/sliced_simpler_component.py index d7b4b1e7..6c338c4d 100644 --- a/pushbase/sliced_simpler_component.py +++ b/pushbase/sliced_simpler_component.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/sliced_simpler_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/sliced_simpler_component.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface.components import PlayableComponent from ableton.v2.control_surface.components import Slideable, SlideComponent from ableton.v2.control_surface.control import ButtonControl @@ -33,9 +33,9 @@ def _set_position(self, index): def set_simpler(self, simpler): self._simpler = simpler - self.__on_slices_changed.subject = simpler self.__on_selected_slice_changed.subject = simpler self.__on_file_changed.subject = simpler + self.__on_slices_changed.subject = simpler.sample if liveobj_valid(simpler) else None self._update_led_feedback() self.update() @@ -49,7 +49,9 @@ def __on_selected_slice_changed(self): self.notify_selected_note() def _slices(self): - return self._simpler.slices if liveobj_valid(self._simpler) and self._simpler.sample_file_path else [] + if liveobj_valid(self._simpler) and liveobj_valid(self._simpler.sample): + return self._simpler.sample.slices + return [] @listenable_property def selected_note(self): @@ -59,12 +61,13 @@ def selected_note(self): return BASE_SLICING_NOTE + index def _selected_slice(self): - return self._simpler.view.selected_slice if liveobj_valid(self._simpler) else -1 + if liveobj_valid(self._simpler): + return self._simpler.view.selected_slice + return -1 - @listens('sample_file_path') + @listens('sample') def __on_file_changed(self): - self.__on_slices_changed.subject = None - self.__on_slices_changed.subject = self._simpler + self.__on_slices_changed.subject = self._simpler.sample if liveobj_valid(self._simpler) else None self._update_led_feedback() def _button_coordinate_to_slice_index(self, button): @@ -91,19 +94,18 @@ def delete_button(self, value, button): self._set_control_pads_from_script(bool(value)) def _try_delete_slice_at_index(self, index): - if liveobj_valid(self._simpler): + if liveobj_valid(self._simpler) and liveobj_valid(self._simpler.sample): slices = self._slices() if len(slices) > index: - self._simpler.remove_slice(slices[index]) + self._simpler.sample.remove_slice(slices[index]) def set_select_button(self, button): self.select_button.set_control_element(button) def _try_select_slice_at_index(self, index): - if liveobj_valid(self._simpler): - slices = self._simpler.slices - if len(slices) > index: - self._simpler.view.selected_slice = slices[index] + slices = self._slices() + if len(slices) > index: + self._simpler.view.selected_slice = slices[index] def _on_matrix_pressed(self, button): slice_index = self._button_coordinate_to_slice_index(button) diff --git a/pushbase/slideable_touch_strip_component.py b/pushbase/slideable_touch_strip_component.py index 6257aec4..a3bbfad0 100644 --- a/pushbase/slideable_touch_strip_component.py +++ b/pushbase/slideable_touch_strip_component.py @@ -1,7 +1,8 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/slideable_touch_strip_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/slideable_touch_strip_component.py """ Component that navigates a series of pages. """ +from __future__ import absolute_import, print_function from math import ceil from itertools import imap from ableton.v2.base import clamp, listens diff --git a/pushbase/special_chan_strip_component.py b/pushbase/special_chan_strip_component.py index 03c34ee4..1650e9ec 100644 --- a/pushbase/special_chan_strip_component.py +++ b/pushbase/special_chan_strip_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/special_chan_strip_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/special_chan_strip_component.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import flatten, listens, listens_group, liveobj_valid, task from ableton.v2.control_surface import components, ParameterSlot @@ -53,27 +54,30 @@ def __init__(self, *a, **k): def set_delete_handler(self, delete_handler): self._delete_handler = delete_handler - def set_volume_control(self, control): + def _update_control_sensitivities(self, control): if control: - control.mapping_sensitivity = consts.CONTINUOUS_MAPPING_SENSITIVITY + if hasattr(control, 'set_sensitivities'): + control.set_sensitivities(consts.CONTINUOUS_MAPPING_SENSITIVITY, consts.FINE_GRAINED_CONTINUOUS_MAPPING_SENSITIVITY) + else: + control.mapping_sensitivity = consts.CONTINUOUS_MAPPING_SENSITIVITY + + def set_volume_control(self, control): + self._update_control_sensitivities(control) super(SpecialChanStripComponent, self).set_volume_control(control) def set_pan_control(self, control): - if control: - control.mapping_sensitivity = consts.CONTINUOUS_MAPPING_SENSITIVITY + self._update_control_sensitivities(control) super(SpecialChanStripComponent, self).set_pan_control(control) def set_send_controls(self, controls): if controls != None: for control in controls: - if control: - control.mapping_sensitivity = consts.CONTINUOUS_MAPPING_SENSITIVITY + self._update_control_sensitivities(control) super(SpecialChanStripComponent, self).set_send_controls(controls) def set_cue_volume_control(self, control): - if control: - control.mapping_sensitivity = consts.CONTINUOUS_MAPPING_SENSITIVITY + self._update_control_sensitivities(control) self._cue_volume_slot.control = control def set_duplicate_button(self, duplicate_button): diff --git a/pushbase/special_mixer_component.py b/pushbase/special_mixer_component.py index 4a2acdbb..29fcdfd9 100644 --- a/pushbase/special_mixer_component.py +++ b/pushbase/special_mixer_component.py @@ -1,4 +1,6 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/special_mixer_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/special_mixer_component.py +from __future__ import absolute_import, print_function +from itertools import izip_longest from ableton.v2.base import listens from ableton.v2.control_surface import components from ableton.v2.control_surface.elements import DisplayDataSource @@ -45,19 +47,19 @@ def set_selected_track_name_display(self, display): display.set_data_sources(self._selected_track_data_sources) def set_track_select_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.set_on_off_values('Option.Selected', 'Option.Unselected') strip.set_select_button(button) def set_solo_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.set_on_off_values('Mixer.SoloOn', 'Mixer.SoloOff') strip.set_solo_button(button) def set_mute_buttons(self, buttons): - for strip, button in map(None, self._channel_strips, buttons or []): + for strip, button in izip_longest(self._channel_strips, buttons or []): if button: button.set_on_off_values('Mixer.MuteOff', 'Mixer.MuteOn') strip.set_mute_button(button) @@ -77,7 +79,7 @@ def set_volume_graphics_display(self, display): self._set_parameter_graphics_display(display, 0) def set_volume_controls(self, controls): - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): strip.set_volume_control(control) def set_pan_send_names_display(self, display): @@ -111,11 +113,11 @@ def _on_track_list_changed(self): self._update_pan_sends() def set_pan_controls(self, controls): - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): strip.set_pan_control(control) def set_send_controls(self, controls): - for strip, control in map(None, self._channel_strips, controls or []): + for strip, control in izip_longest(self._channel_strips, controls or []): strip.set_send_controls(control) def _set_parameter_names_display(self, display, parameter): diff --git a/pushbase/special_session_component.py b/pushbase/special_session_component.py index fc28820c..1f568f98 100644 --- a/pushbase/special_session_component.py +++ b/pushbase/special_session_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/special_session_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/special_session_component.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import forward_property, listens, liveobj_valid from ableton.v2.control_surface import Component diff --git a/pushbase/step_seq_component.py b/pushbase/step_seq_component.py index a797a599..f1948b64 100644 --- a/pushbase/step_seq_component.py +++ b/pushbase/step_seq_component.py @@ -1,5 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/step_seq_component.py -from __future__ import with_statement +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/step_seq_component.py +from __future__ import absolute_import, print_function from itertools import chain, starmap from ableton.v2.base import forward_property, listens from ableton.v2.control_surface import CompoundComponent diff --git a/pushbase/sysex.py b/pushbase/sysex.py index 6493dc68..64d99145 100644 --- a/pushbase/sysex.py +++ b/pushbase/sysex.py @@ -1,3 +1,4 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/sysex.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/sysex.py +from __future__ import absolute_import, print_function USER_MODE = 1 LIVE_MODE = 0 \ No newline at end of file diff --git a/pushbase/touch_encoder_element.py b/pushbase/touch_encoder_element.py index 275176a9..c87d526a 100644 --- a/pushbase/touch_encoder_element.py +++ b/pushbase/touch_encoder_element.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/touch_encoder_element.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/touch_encoder_element.py +from __future__ import absolute_import, print_function from ableton.v2.base import SlotManager from ableton.v2.control_surface.elements import TouchEncoderElement as TouchEncoderElementBase diff --git a/pushbase/touch_strip_controller.py b/pushbase/touch_strip_controller.py index d7620e9c..025c9f56 100644 --- a/pushbase/touch_strip_controller.py +++ b/pushbase/touch_strip_controller.py @@ -1,8 +1,11 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/touch_strip_controller.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/touch_strip_controller.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface import Component +from ableton.v2.control_surface.control import ToggleButtonControl from . import consts +from .message_box_component import Messenger from .touch_encoder_element import TouchEncoderObserver -from .touch_strip_element import TouchStripModes, SimpleBehaviour +from .touch_strip_element import DEFAULT_BEHAVIOUR, MODWHEEL_BEHAVIOUR, SimpleBehaviour, TouchStripModes, TouchStripStates class TouchStripControllerComponent(Component): @@ -67,4 +70,42 @@ def _set_touched_encoder(self, encoder): self._encoder = encoder parameter = encoder.mapped_parameter() if encoder != None else None self._strip_controller.set_parameter(parameter) - self._strip_controller.set_enabled(parameter != None) \ No newline at end of file + self._strip_controller.set_enabled(parameter != None) + + +class TouchStripPitchModComponent(Component, Messenger): + touch_strip_toggle = ToggleButtonControl() + + def __init__(self, *a, **k): + super(TouchStripPitchModComponent, self).__init__(*a, **k) + self._touch_strip = None + self._touch_strip_indication = None + + def set_touch_strip(self, control): + self._touch_strip = control + self._update_touch_strip() + + def _update_touch_strip(self): + if self._touch_strip: + self._touch_strip.behaviour = MODWHEEL_BEHAVIOUR if self.touch_strip_toggle.is_toggled else DEFAULT_BEHAVIOUR + + @touch_strip_toggle.toggled + def touch_strip_toggle(self, toggled, button): + self._update_touch_strip() + self._update_touch_strip_indication() + self.show_notification(consts.MessageBoxText.TOUCHSTRIP_MODWHEEL_MODE if toggled else consts.MessageBoxText.TOUCHSTRIP_PITCHBEND_MODE) + + def set_touch_strip_indication(self, control): + self._touch_strip_indication = control + self._update_touch_strip_indication() + + def _update_touch_strip_indication(self): + if self._touch_strip_indication: + self._touch_strip_indication.set_mode(TouchStripModes.CUSTOM_FREE) + self._touch_strip_indication.send_state([ (TouchStripStates.STATE_FULL if self.touch_strip_toggle.is_toggled else TouchStripStates.STATE_HALF) for _ in xrange(self._touch_strip_indication.state_count) ]) + + def update(self): + super(TouchStripPitchModComponent, self).update() + if self.is_enabled(): + self._update_touch_strip() + self._update_touch_strip_indication() \ No newline at end of file diff --git a/pushbase/touch_strip_element.py b/pushbase/touch_strip_element.py index 4f9f5c5c..b9592c21 100644 --- a/pushbase/touch_strip_element.py +++ b/pushbase/touch_strip_element.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/touch_strip_element.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/touch_strip_element.py +from __future__ import absolute_import, print_function import Live from ableton.v2.base import SlotManager, in_range, nop, NamedTuple, clamp from ableton.v2.control_surface import InputControlElement, MIDI_PB_TYPE @@ -119,7 +120,8 @@ def touch_button(self): return self._touch_button def _get_mode(self): - return self._behaviour.mode if self._behaviour != None else None + if self._behaviour != None: + return self._behaviour.mode def set_mode(self, mode): if not in_range(mode, 0, TouchStripModes.COUNT): @@ -129,9 +131,9 @@ def set_mode(self, mode): mode = property(_get_mode, set_mode) def _set_behaviour(self, behaviour): - if not behaviour: - behaviour = DEFAULT_BEHAVIOUR - self._behaviour = behaviour != self._behaviour and behaviour + behaviour = behaviour or DEFAULT_BEHAVIOUR + if behaviour != self._behaviour: + self._behaviour = behaviour self._touch_slot.listener = behaviour.handle_touch self._mode_element.send_value(behaviour.mode) diff --git a/pushbase/track_frozen_mode.py b/pushbase/track_frozen_mode.py index cdc7d3f0..ae04e0c1 100644 --- a/pushbase/track_frozen_mode.py +++ b/pushbase/track_frozen_mode.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/track_frozen_mode.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/track_frozen_mode.py +from __future__ import absolute_import, print_function from ableton.v2.base import listens from ableton.v2.control_surface.mode import ModesComponent diff --git a/pushbase/transport_component.py b/pushbase/transport_component.py index 92813254..d060ea5f 100644 --- a/pushbase/transport_component.py +++ b/pushbase/transport_component.py @@ -1,8 +1,9 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/transport_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/transport_component.py +from __future__ import absolute_import, print_function from ableton.v2.control_surface import components class TransportComponent(components.TransportComponent): def __init__(self, *a, **k): super(TransportComponent, self).__init__(*a, **k) - self._metronome_toggle.view_transform = lambda v: 'Metronome.On' if v else 'Metronome.Off' \ No newline at end of file + self._metronome_toggle.view_transform = lambda v: ('Metronome.On' if v else 'Metronome.Off') \ No newline at end of file diff --git a/pushbase/user_component.py b/pushbase/user_component.py index 4668b10b..9e7a0f23 100644 --- a/pushbase/user_component.py +++ b/pushbase/user_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/user_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/user_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import listens, task from ableton.v2.control_surface import Component from . import sysex @@ -22,13 +23,16 @@ def _get_mode(self): return self._selected_mode def _set_mode(self, mode): + self._do_set_mode(mode) + + mode = property(_get_mode, _set_mode) + + def _do_set_mode(self, mode): if self.is_enabled(): self._apply_mode(mode) else: self._pending_mode_to_select = mode - mode = property(_get_mode, _set_mode) - def update(self): super(UserComponentBase, self).update() if self.is_enabled() and self._pending_mode_to_select: diff --git a/pushbase/value_component.py b/pushbase/value_component.py index d26d1084..f4b4042e 100644 --- a/pushbase/value_component.py +++ b/pushbase/value_component.py @@ -1,4 +1,5 @@ -#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/midi-remote-scripts/pushbase/value_component.py +#Embedded file name: /Users/versonator/Jenkins/live/output/mac_64_static/Release/python-bundle/MIDI Remote Scripts/pushbase/value_component.py +from __future__ import absolute_import, print_function from ableton.v2.base import listenable_property, listens from ableton.v2.control_surface import CompoundComponent, Component, ParameterSlot from ableton.v2.control_surface.control import EncoderControl, ButtonControl @@ -67,10 +68,13 @@ class ValueComponentBase(CompoundComponent): def create_display_component(self, *a, **k): raise NotImplementedError - encoder = EncoderControl() - - def __init__(self, display_label = ' ', display_seg_start = 0, *a, **k): + def __init__(self, display_label = ' ', display_seg_start = 0, encoder_touch_delay = 0, *a, **k): super(ValueComponentBase, self).__init__(*a, **k) + encoder = EncoderControl(touch_event_delay=encoder_touch_delay) + encoder.touched = ValueComponentBase.__on_encoder_touched + encoder.released = ValueComponentBase.__on_encoder_released + encoder.value = ValueComponentBase.__on_encoder_value + self.add_control('encoder', encoder) self._display = self.register_component(self.create_display_component(display_label=display_label, display_seg_start=display_seg_start)) self._display.set_enabled(False) @@ -78,16 +82,13 @@ def __init__(self, display_label = ' ', display_seg_start = 0, *a, **k): def display(self): return self._display - @encoder.touched - def encoder(self, encoder): + def __on_encoder_touched(self, encoder): self._update_display_state() - @encoder.released - def encoder(self, encoder): + def __on_encoder_released(self, encoder): self._update_display_state() - @encoder.value - def encoder(self, value, encoder): + def __on_encoder_value(self, value, encoder): self._on_value(value) def _on_value(self, value):