### Parameter Mapping Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md A complete example demonstrating how to map MIDI controls (encoders) to Live parameters, such as master track volume and device parameters. ```APIDOC ## Parameter Mapping Example A complete example demonstrating how to map MIDI controls (encoders) to Live parameters, such as master track volume and device parameters. ### Class `ParameterMapper(ControlSurface)` ### Initialization Initializes the mapper and sets up encoder mappings. ### Mappings - **Master Volume Encoder**: Maps MIDI CC 7 to the master track's volume parameter using `Live.MidiMap.MapMode.absolute`. - **Device Parameter Encoder**: Maps MIDI CC 8 to the first parameter of the appointed device, if available, using `Live.MidiMap.MapMode.absolute`. ``` -------------------------------- ### Complete Component Usage Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/02-framework-components.md A comprehensive example showing the integration of various components like SessionComponent, MixerComponent, DeviceComponent, and TransportComponent within a custom ControlSurface. ```python from _Framework.ControlSurface import ControlSurface from _Framework.SessionComponent import SessionComponent from _Framework.MixerComponent import MixerComponent from _Framework.DeviceComponent import DeviceComponent from _Framework.TransportComponent import TransportComponent from _Framework.ButtonMatrixElement import ButtonMatrixElement from _Framework.ButtonElement import ButtonElement from _Framework.EncoderElement import EncoderElement from _Framework.Layer import Layer from _Framework.InputControlElement import MIDI_NOTE_TYPE, MIDI_CC_TYPE import Live class MyController(ControlSurface): def __init__(self, c_instance): super(MyController, self).__init__(c_instance) with self.component_guard(): # Create session grid (8x8 clips) clip_buttons = ButtonMatrixElement(rows=[ [ButtonElement(True, MIDI_NOTE_TYPE, 0, 36+i+j*8) for i in range(8)] for j in range(8) ], name="Clip_Buttons") # Create mixer controls volume_encoders = [ EncoderElement(MIDI_CC_TYPE, 0, 7+i, Live.MidiMap.MapMode.absolute) for i in range(8) ] # Instantiate components session = SessionComponent(num_tracks=8, num_scenes=8) session.set_clip_launch_buttons(clip_buttons) session.set_enabled(True) mixer = MixerComponent(num_tracks=8, include_master=True) mixer.set_volume_controls(volume_encoders) mixer.set_enabled(True) device = DeviceComponent() device.set_enabled(True) transport = TransportComponent() transport.set_play_button(ButtonElement(True, MIDI_NOTE_TYPE, 0, 60)) transport.set_stop_button(ButtonElement(True, MIDI_NOTE_TYPE, 0, 61)) transport.set_record_button(ButtonElement(True, MIDI_NOTE_TYPE, 0, 62)) transport.set_enabled(True) self.log_message("MyController ready") ``` -------------------------------- ### API Lookup and Learning Paths Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/README.md This section outlines how to use the documentation for different purposes. For direct API lookup, refer to the framework modules. For learning the basics, follow the structured paths. For implementation examples and best practices, consult the examples and device implementation documents. ```APIDOC ## API Lookup and Learning ### For API Lookup: Use [08-framework-modules.md](08-framework-modules.md) for complete class/method reference. ### For Learning: Start with [00-index.md](00-index.md) and follow the appropriate learning path. ### For Implementation: Reference [05-examples-and-patterns.md](05-examples-and-patterns.md) for patterns. ### For Device Control: Check [06-midi-reference.md](06-midi-reference.md) for MIDI/Live object model. ### For Production: Study [07-device-implementations.md](07-device-implementations.md) for best practices. ``` -------------------------------- ### Custom ControlSurface Implementation Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/04-ableton-v3-api.md This example demonstrates how to create a custom control surface by extending ControlSurface and defining a specification. Override setup() and drum_group_changed() for custom behavior. ```python from ableton.v3.control_surface import ControlSurface, ControlSurfaceSpecification from ableton.v3.control_surface.elements import ElementsBase class MyElements(ElementsBase): # Define your elements here pass class MyControllerSpecification(ControlSurfaceSpecification): elements_type = MyElements # Custom elements class num_tracks = 8 num_scenes = 8 include_master = True class MyController(ControlSurface): def __init__(self, c_instance): super().__init__(MyControllerSpecification, c_instance) def setup(self): super().setup() self.log_message("Setup complete") def drum_group_changed(self, drum_group): if drum_group: self.show_message(f"Drum group: {drum_group.name}") ``` -------------------------------- ### MyElements Class Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/04-ableton-v3-api.md An example of a custom ElementsBase class demonstrating the creation of button matrices, parameter encoders, and navigation buttons. ```python class MyElements(ElementsBase): def __init__(self): super().__init__() # Button matrices for pads self.pads = create_matrix_identifiers( name='Pads', rows=8, columns=8, start_note=36 ) # Encoders for parameters self.parameter_encoders = [ create_encoder( name=f'Param_{i}', channel=0, cc=20+i, map_mode=MapMode.absolute ) for i in range(8) ] # Navigation buttons self.scene_up_button = create_button( name='Scene_Up', channel=0, note=104 ) self.scene_down_button = create_button( name='Scene_Down', channel=0, note=105 ) ``` -------------------------------- ### Capabilities Declaration Function Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/01-framework-core.md Provides an example of the get_capabilities function, which must be defined at the module level. It returns a dictionary specifying controller identification and port properties for Live. ```python import _Framework.Capabilities as caps def get_capabilities(): return { caps.CONTROLLER_ID_KEY: caps.controller_id( vendor_id=2536, # USB vendor ID product_ids=[46, 47, 48], # USB product IDs model_name=["Model1", "Model2", "Model3"] ), caps.PORTS_KEY: [ caps.inport(props=[caps.NOTES_CC, caps.SCRIPT, caps.REMOTE]), caps.outport(props=[caps.NOTES_CC, caps.SCRIPT]) ] } def create_instance(c_instance): return MyControlSurface(c_instance) ``` -------------------------------- ### Component Guard for Setup Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/07-device-implementations.md Defers MIDI map rebuilding during the initial setup phase. Use this pattern when making multiple control assignments to ensure the MIDI map is rebuilt only once after all assignments are complete. ```python with self.component_guard(): # Multiple control assignments component1.set_control(control1) component2.set_control(control2) # MIDI map rebuilt once after exiting context ``` -------------------------------- ### Skin Initialization and Usage Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/01-framework-core.md Demonstrates how to initialize a Skin object and assign Color values to different states, including ON_VALUE, OFF_VALUE, and a custom 'Muted' state. Shows how a button uses the skin to set its light. ```python from _Framework.Skin import Skin from _Framework.ButtonElement import Color, ON_VALUE, OFF_VALUE skin = Skin() skin[ON_VALUE] = Color(127) # Bright when on skin[OFF_VALUE] = Color(0) # Dark when off skin["Muted"] = Color(64) # Dim when muted button.set_light(ON_VALUE) # Uses skin to send appropriate color ``` -------------------------------- ### Parameter Mapping Example in Python Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md Map MIDI CC controls to Live parameters like master track volume and device parameters using ControlSurface. ```python from _Framework.ControlSurface import ControlSurface from _Framework.EncoderElement import EncoderElement from _Framework.InputControlElement import MIDI_CC_TYPE import Live class ParameterMapper(ControlSurface): def __init__(self, c_instance): super(ParameterMapper, self).__init__(c_instance) with self.component_guard(): song = self.song() # Create encoder on CC 7 (Volume) volume_encoder = EncoderElement( MIDI_CC_TYPE, 0, 7, Live.MidiMap.MapMode.absolute, name="Master_Volume" ) # Connect to master track volume volume_encoder.connect_to(song.master_track.mixer_device.volume) # Create encoder for first device parameter device = song.appointed_device if device and len(device.parameters) > 0: param_encoder = EncoderElement( MIDI_CC_TYPE, 0, 8, Live.MidiMap.MapMode.absolute, name="Device_Param_0" ) # Connect to first parameter param_encoder.connect_to(device.parameters[0]) self.log_message("Parameter mapper initialized") ``` -------------------------------- ### CompoundComponent Example Usage Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/02-framework-components.md Demonstrates how to create and manage a CompoundComponent, which groups other components. Child components are enabled and disabled together. ```python from _Framework.CompoundComponent import CompoundComponent from _Framework.SessionComponent import SessionComponent from _Framework.MixerComponent import MixerComponent main = CompoundComponent( session_component, mixer_component, device_component, is_enabled=True ) # All child components are enabled/disabled together main.set_enabled(False) # Disables all children ``` -------------------------------- ### Schedule Message Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/01-framework-core.md Shows how to schedule a callback function to be executed after a specified delay in milliseconds using the schedule_message method. ```python def do_something(): self.show_message("Deferred action!") self.schedule_message(100, do_something) # Execute after 100ms ``` -------------------------------- ### ControlSurface Component Guard Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/01-framework-core.md Use the component_guard context manager to defer MIDI map rebuilds during bulk operations when setting up controls. ```python from _Framework.ControlSurface import ControlSurface from _Framework.ButtonElement import ButtonElement from _Framework.EncoderElement import EncoderElement from _Framework.InputControlElement import MIDI_NOTE_TYPE, MIDI_CC_TYPE class MyController(ControlSurface): def __init__(self, c_instance): super(MyController, self).__init__(c_instance) with self.component_guard(): # Create controls play_button = ButtonElement( True, # is_momentary MIDI_NOTE_TYPE, 0, # channel 60, # note name="Play" ) volume_encoder = EncoderElement( MIDI_CC_TYPE, 0, # channel 7, # CC number Live.MidiMap.MapMode.absolute, name="Volume" ) # Store for later use self._play_button = play_button self._volume_encoder = volume_encoder # Log startup self.log_message("MyController initialized") ``` -------------------------------- ### Full Controller Implementation Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/08-framework-modules.md This snippet demonstrates a complete ControlSurface implementation, integrating session, mixer, device, and transport components with custom button and encoder mappings. It includes setup for pads, encoders, and transport buttons, along with defining controller capabilities. ```python from _Framework.ControlSurface import ControlSurface from _Framework.ButtonElement import ButtonElement from _Framework.EncoderElement import EncoderElement from _Framework.ButtonMatrixElement import ButtonMatrixElement from _Framework.SessionComponent import SessionComponent from _Framework.MixerComponent import MixerComponent from _Framework.DeviceComponent import DeviceComponent from _Framework.TransportComponent import TransportComponent from _Framework.ModesComponent import ModesComponent from _Framework.Layer import Layer from _Framework.InputControlElement import MIDI_NOTE_TYPE, MIDI_CC_TYPE import _Framework.Capabilities as caps import Live class FullController(ControlSurface): def __init__(self, c_instance): super(FullController, self).__init__(c_instance) with self.component_guard(): # Elements pads = ButtonMatrixElement(rows=[ [ButtonElement(True, MIDI_NOTE_TYPE, 0, 36+i+j*8) for i in range(8)] for j in range(8) ]) encoders = [ EncoderElement(MIDI_CC_TYPE, 0, 20+i, Live.MidiMap.MapMode.absolute) for i in range(8) ] buttons = [ ButtonElement(True, MIDI_NOTE_TYPE, 0, 48+i) for i in range(8) ] # Components session = SessionComponent(num_tracks=8, num_scenes=8) session.set_clip_launch_buttons(pads) mixer = MixerComponent(num_tracks=8, include_master=True) mixer.set_volume_controls(encoders) device = DeviceComponent() transport = TransportComponent() transport.set_play_button(buttons[0]) transport.set_stop_button(buttons[1]) transport.set_record_button(buttons[2]) def get_capabilities(): return { caps.CONTROLLER_ID_KEY: caps.controller_id( vendor_id=9999, product_ids=[1], model_name="Full Controller" ), caps.PORTS_KEY: [ caps.inport(props=[caps.NOTES_CC, caps.SCRIPT]), caps.outport(props=[caps.NOTES_CC, caps.SCRIPT]) ] } def create_instance(c_instance): return FullController(c_instance) ``` -------------------------------- ### APC64 Specification Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/07-device-implementations.md Defines the specification for the Akai APC64 control surface using the v3 architecture. Includes component mapping, display configuration, and recording settings. ```python class Specification(ControlSurfaceSpecification): elements_type = Elements control_surface_skin = create_skin(skin=Skin, colors=Rgb) num_tracks = 8 num_scenes = 8 include_returns = True include_master = True include_auto_arming = True right_align_non_player_tracks = True # Custom components component_map = { 'Device': DeviceComponent, 'Global_Quantization': GlobalQuantizationComponent, 'Mixer': MixerComponent, 'Render_To_Clip': RenderToClipComponent, 'Session': SessionComponent, 'Transport': TransportComponent, 'Settings': SettingsComponent } # Display configuration display_specification = display_specification # Recording settings recording_method_type = FixedLengthRecordingMethod # Device identification identity_response_id_bytes = (71, 83, 0, 25) # Macro mappings for different drum rack sizes create_mappings_function = create_mappings ``` -------------------------------- ### Create an 8x8 Pad Matrix Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/03-control-elements.md Instantiates a ButtonMatrixElement for an 8x8 grid of pads, mapping them to MIDI notes starting from 36. Requires ButtonElement and MIDI_NOTE_TYPE. ```python from _Framework.ButtonMatrixElement import ButtonMatrixElement from _Framework.ButtonElement import ButtonElement from _Framework.InputControlElement import MIDI_NOTE_TYPE # Create 8x8 pad matrix starting at MIDI note 36 pad_matrix = ButtonMatrixElement( rows=[ [ButtonElement(True, MIDI_NOTE_TYPE, 0, 36+i+j*8, name=f"Pad_{j}_{i}") for i in range(8)] for j in range(8) ], name="Pad_Matrix" ) ``` -------------------------------- ### BackgroundComponent Purpose Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/02-framework-components.md Illustrates how to use BackgroundComponent to prevent unassigned MIDI controls from being forwarded to Live. Disabled components do not forward MIDI. ```python background = BackgroundComponent(is_enabled=True, layer=Layer( unused_buttons=all_buttons, unused_encoders=all_encoders )) background.set_enabled(False) # Disabled components don't forward MIDI ``` -------------------------------- ### Minimal Ableton V3 Controller Configuration Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/04-ableton-v3-api.md A complete, minimal example of an Ableton V3 control surface. It defines elements, a specification, the control surface class, and module-level capabilities for hardware integration. ```python from ableton.v3.control_surface import ( ControlSurface, ControlSurfaceSpecification, ElementsBase, create_button, create_encoder, create_matrix_identifiers, MapMode, create_skin, Skin ) from ableton.v3.control_surface.capabilities import ( CONTROLLER_ID_KEY, PORTS_KEY, controller_id, inport, outport, NOTES_CC, SCRIPT ) # 1. Define elements (hardware) class MinimalElements(ElementsBase): def __init__(self): super().__init__() self.pads = create_matrix_identifiers( 'Pads', rows=4, columns=8, start_note=36 ) self.encoders = [ create_encoder(f'Encoder_{i}', 0, 20+i, MapMode.ABSOLUTE) for i in range(8) ] # 2. Define specification class MinimalSpecification(ControlSurfaceSpecification): elements_type = MinimalElements num_tracks = 8 num_scenes = 4 include_master = True # 3. Define control surface class MinimalController(ControlSurface): def __init__(self, c_instance): super().__init__(MinimalSpecification, c_instance) # 4. Module-level capabilities def get_capabilities(): return { CONTROLLER_ID_KEY: controller_id( vendor_id=9999, product_ids=[1], model_name="Minimal Controller" ), PORTS_KEY: [ inport(props=[NOTES_CC, SCRIPT]), outport(props=[NOTES_CC, SCRIPT]) ] } def create_instance(c_instance): return MinimalController(c_instance) ``` -------------------------------- ### Mock Live Object for Testing Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/07-device-implementations.md Tests components by using mock objects that simulate Ableton Live's internal objects, such as tracks and mixer devices. This allows for unit testing without requiring a full Live installation. ```python class MockTrack: def __init__(self): self.name = "Test Track" self.devices = [] self.mixer_device = MockMixerDevice() class TestMyComponent(unittest.TestCase): def test_track_selection(self): track = MockTrack() component = MyComponent() component.set_track(track) self.assertEqual(component.track(), track) ``` -------------------------------- ### Accessing View Properties Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md Demonstrates how to access the View object to get information about the current selection state within Ableton Live, such as the selected track, device, or scene. It also includes methods for programmatic selection. ```python view = song.view # Selection selected_track: Track # Currently selected track selected_scene: Scene # Currently selected scene selected_return_track: Track # Selected return selected_device: Device # Selected device selected_device_chain: Chain # Selected chain canonical_parent: object # View parent object # Methods select_device(device, exclusive_focus=False) select_track(track, force_exclusive_arm=False) select_scene(scene) ``` -------------------------------- ### Accessing Device Properties Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md Illustrates how to get a Device object from a track and access its properties such as name, class name, type, and its parameters. It also covers properties related to rack devices like chains and macros. ```python device = track.devices[0] # Identity name: str # Device name class_name: str # Device type type: str # 'instrument' or 'audio_effect' is_active: bool # Device enabled/disabled # Parameters parameters: list[Parameter] # Device parameters parameter_names: list[str] # Parameter names chains: list[Chain] # Chains in rack devices visible_chains: list[Chain] # Visible chains view: DeviceView # Device view # Methods can_have_chains: bool # Is a rack device can_have_drum_pads: bool # Is a drum rack has_macro_mappings: bool # Has macro controls (racks) visible_macro_count: int # Number of visible macros ``` -------------------------------- ### ButtonElement Initialization and Usage Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/01-framework-core.md Demonstrates how to create and use a ButtonElement. This includes initializing a button with specific MIDI parameters, turning it on, and adding a listener for press events. ```python from _Framework.ButtonElement import ButtonElement from _Framework.InputControlElement import MIDI_NOTE_TYPE # Create a momentary button on channel 0, note 60 play_button = ButtonElement( is_momentary=True, msg_type=MIDI_NOTE_TYPE, channel=0, identifier=60, name="Play Button" ) # Light it up play_button.turn_on() # Listen for presses def on_play_pressed(value): if value > 0: print("Play pressed!") play_button.add_value_listener(on_play_pressed) ``` -------------------------------- ### Initialize Simple MIDI Keyboard Controller Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/05-examples-and-patterns.md Defines the capabilities for a simple MIDI keyboard controller, including vendor and product IDs, and supported input/output ports. This is the entry point for the script. ```python # keyboard_controller/__init__.py import _Framework.Capabilities as caps from .KeyboardController import KeyboardController def get_capabilities(): return { caps.CONTROLLER_ID_KEY: caps.controller_id( vendor_id=2536, product_ids=[9001, 9002], model_name=["Simple Keyboard 49", "Simple Keyboard 61"] ), caps.PORTS_KEY: [ caps.inport(props=[caps.NOTES_CC, caps.SCRIPT]), caps.outport(props=[caps.NOTES_CC, caps.SCRIPT]) ] } def create_instance(c_instance): return KeyboardController(c_instance) ``` -------------------------------- ### ControlSurface (v3) Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/04-ableton-v3-api.md The main base class for creating control surfaces. It handles component mapping and setup based on a provided specification. ```APIDOC ## ControlSurface (v3) ### Description Modern control surface base class with integrated component mapping and specification-driven setup. It serves as the foundation for custom remote scripts. ### Signature ```python class ControlSurface: def __init__(self, specification: ControlSurfaceSpecification, c_instance) ``` ### Parameters #### Path Parameters - **specification** (ControlSurfaceSpecification) - Required - Configuration object defining the surface layout - **c_instance** (Live.ControlSurfaceInitArgs) - Required - Live's control surface instance ### Key Properties - **elements** (ElementsBase) - All physical controls and hardware elements - **component_map** (dict) - Named components indexed by role (Session, Device, Mixer, etc.) - **specification** (ControlSurfaceSpecification) - Configuration specification - **skin** (Skin) - Color/light mapping for buttons ### Key Methods #### `setup()` Called after initialization. Override to perform custom setup after components are created. #### `disconnect()` Cleanup when the script is disabled. #### `refresh_state()` Requests that all component states be refreshed (lights, displays, etc.). #### `set_can_update_controlled_track(can_update: bool)` Enables/disables automatic track selection updates. #### `set_can_arm(can_arm: bool)` Enables/disables automatic track arm on selection. #### `drum_group_changed(drum_group: Live.Device | None)` Called when the selected drum group changes. Override to handle pad mode changes. ### Example Usage ```python from ableton.v3.control_surface import ControlSurface, ControlSurfaceSpecification from ableton.v3.control_surface.elements import ElementsBase class MyControllerSpecification(ControlSurfaceSpecification): elements_type = MyElements # Custom elements class num_tracks = 8 num_scenes = 8 include_master = True class MyController(ControlSurface): def __init__(self, c_instance): super().__init__(MyControllerSpecification, c_instance) def setup(self): super().setup() self.log_message("Setup complete") def drum_group_changed(self, drum_group): if drum_group: self.show_message(f"Drum group: {drum_group.name}") ``` ``` -------------------------------- ### Implement Simple MIDI Keyboard Controller Logic Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/05-examples-and-patterns.md Sets up transport controls (play, stop, record, loop) using note inputs for a simple keyboard controller. Initializes the control surface and logs a message upon completion. ```python # keyboard_controller/KeyboardController.py from __future__ import absolute_import, unicode_literals from _Framework.ControlSurface import ControlSurface from _Framework.ButtonElement import ButtonElement from _Framework.TransportComponent import TransportComponent from _Framework.Layer import Layer from _Framework.InputControlElement import MIDI_NOTE_TYPE, MIDI_CC_TYPE import Live class KeyboardController(ControlSurface): def __init__(self, c_instance): super(KeyboardController, self).__init__(c_instance) with self.component_guard(): # Transport controls in the top octave (notes 96-103) play_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 96, name="Play") stop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 97, name="Stop") record_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 98, name="Record") loop_button = ButtonElement(True, MIDI_NOTE_TYPE, 0, 99, name="Loop") # Create transport component transport = TransportComponent( is_enabled=False, layer=Layer( play_button=play_button, stop_button=stop_button, record_button=record_button, loop_button=loop_button ) ) transport.set_enabled(True) self.log_message("Simple Keyboard Controller initialized") ``` -------------------------------- ### Legacy Framework Entry Point Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/00-index.md Defines the entry point for the legacy framework, returning controller capabilities and creating a ControlSurface instance. ```python def get_capabilities(): return {caps.CONTROLLER_ID_KEY: ..., caps.PORTS_KEY: [...]} def create_instance(c_instance): return MyControlSurface(c_instance) ``` -------------------------------- ### Add Value Listener Example Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/01-framework-core.md Registers a callback function to be executed when a control's value changes. The listener function receives the new value as an argument. ```python def on_button_pressed(value): print(f"Button value: {value}") button.add_value_listener(on_button_pressed) ``` -------------------------------- ### Initialize SessionComponent with Clip Launch Buttons Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/02-framework-components.md Assigns a button matrix for clip launching within the SessionComponent. Ensure the ButtonMatrixElement is correctly configured with ButtonElements. ```python clip_buttons = ButtonMatrixElement(rows=[ [ButtonElement(...) for _ in range(8)] for _ in range(8) ]) session.set_clip_launch_buttons(clip_buttons) ``` -------------------------------- ### Modern Ableton.v3 API Entry Point Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/00-index.md Defines the entry point for the modern v3 API, returning controller capabilities and creating a ControlSurface instance. ```python def get_capabilities(): return {CONTROLLER_ID_KEY: ..., PORTS_KEY: [...]} def create_instance(c_instance): return MyControlSurface(c_instance) ``` -------------------------------- ### Relative Smooth Binary Offset Encoder Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md Example of creating an EncoderElement using the relative_smooth_binary_offset mapping mode. This mode is useful for controlling parameters that have a center point and change smoothly in both directions. ```python encoder = EncoderElement( MIDI_CC_TYPE, 0, 20, Live.MidiMap.MapMode.relative_smooth_binary_offset ) ``` -------------------------------- ### SceneComponent Key Methods Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/08-framework-modules.md Manages the launching of a single scene. Methods allow setting the scene, assigning launch and stop buttons, and retrieving the controlled scene. ```python set_scene(scene) ``` ```python scene() ``` ```python set_launch_button(button) ``` ```python set_stop_button(button) ``` -------------------------------- ### ADVANCE Device Control and Drum Pads Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/07-device-implementations.md Initializes the Advance control surface, setting up encoders for device control and a 4x4 pad grid for drum racks. Uses legacy _Framework module. ```python class Advance(ControlSurface): def __init__(self, *a, **k): super(Advance, self).__init__(*a, **k) with self.component_guard(): # Create encoders (CC 22-29) encoders = ButtonMatrixElement(rows=[ [make_encoder(index + 22, f"Encoder_{index}") for index in range(8)] ]) # Create 4x4 pads pads = ButtonMatrixElement(rows=[ [make_button(identifier, f"Pad_{col}_{row}") for col, identifier in enumerate(row_ids)] for row, row_ids in enumerate(PAD_IDS) ]) # Wire components device = DeviceComponent(layer=Layer(parameter_controls=encoders)) drums = DrumRackComponent(layer=Layer(pads=pads)) transport = TransportComponent(layer=Layer(...)) ``` -------------------------------- ### DeviceComponent Constructor and Methods Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/08-framework-modules.md Manages device parameter control. Constructor can take a device bank registry and track selection preference. Key methods set the device, assign parameter controls, and manage bank selection/navigation. ```python DeviceComponent(device_bank_registry=None, device_selection_follows_track_selection=False, **kwargs) ``` ```python set_device(device) ``` ```python device() ``` ```python set_parameter_controls(controls) ``` ```python set_bank_buttons(buttons) ``` ```python set_bank_nav_buttons(up, down) ``` ```python set_on_off_button(button) ``` ```python set_lock_button(button) ``` -------------------------------- ### Switch Control Modes Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/00-index.md Initializes a ModesComponent, adds 'Session' and 'Device' modes, and sets the initial mode to 'Session'. ```python modes = ModesComponent() modes.add_mode("Session", session_component) modes.add_mode("Device", device_component) modes.set_mode("Session") ``` -------------------------------- ### Live.MidiMap Mapping Modes Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md Import and use standard and 14-bit mapping modes for MIDI controls. ```python import Live modes = Live.MidiMap.MapMode # Standard modes mode = modes.absolute # 0-127 linear mode = modes.relative_smooth_two_compliment # Relative (two's comp) mode = modes.relative_smooth_signed_bit # Relative (signed bit) mode = modes.relative_smooth_binary_offset # Relative (binary offset) # 14-bit modes mode = modes.absolute_14_bit # 14-bit absolute (0-16383) mode = modes.relative_smooth_14_bit_two_compliment mode = modes.relative_smooth_14_bit_signed_bit mode = modes.relative_smooth_14_bit_binary_offset ``` -------------------------------- ### Live Integration Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/README.md Information on how to integrate remote scripts with Ableton Live, covering parameter mapping, device control, session and mixer navigation, and display feedback mechanisms. ```APIDOC ## Live Integration - Parameter mapping and synchronization - Device parameter banking - Track and scene navigation - Session grid control - Mixer control - Display feedback ``` -------------------------------- ### DeviceComponent Initialization Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/04-ableton-v3-api.md Initializes a modern DeviceComponent for controlling device parameters, with options for automatic device selection and macro handling. ```python from ableton.v3.control_surface.components import DeviceComponent device = DeviceComponent( name='Device', device_selection_follows_track_selection=True, allow_macro_on_non_macro_devices=False ) ``` -------------------------------- ### Accessing Song Properties Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md Demonstrates how to access the Song object and its key properties like tracks, tempo, and playback state. This is fundamental for any script interacting with the Live session. ```python song = c_instance.song() # Tracks and content tracks: list[Track] # All tracks return_tracks: list[Track] # Return/auxiliary tracks master_track: Track # Master track cue_point: float # Cue point time tempo: float # BPM (60-300) time_signature: (int, int) # Beats per measure, note value # Transport is_playing: bool # Playback active record_mode: bool # Recording enabled metronome: bool # Metronome enabled # Selection view: View # Current view visible_tracks: list[Track] # Visible (non-deleted) tracks appointed_device: Device # Current controlled device ``` -------------------------------- ### Create a Session Grid Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/00-index.md Creates a ButtonMatrixElement for session clip launching and assigns it to a SessionComponent. ```python pads = ButtonMatrixElement(rows=[ [ButtonElement(True, MIDI_NOTE_TYPE, 0, 36+i+j*8) for i in range(8)] for j in range(8) ]) session = SessionComponent(8, 8) session.set_clip_launch_buttons(pads) ``` -------------------------------- ### Control Matrix Construction Helper Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/03-control-elements.md A factory class to create organized control matrices including pad grids, encoder strips, and button strips. It requires importing necessary classes from the _Framework. ```python from _Framework.ButtonMatrixElement import ButtonMatrixElement from _Framework.ButtonElement import ButtonElement from _Framework.EncoderElement import EncoderElement from _Framework.InputControlElement import MIDI_NOTE_TYPE, MIDI_CC_TYPE import Live class ControlMatrix: """Factory for creating organized control matrices.""" def __init__(self, start_note=36, start_cc=20, num_cols=8, num_rows=8): self.start_note = start_note self.start_cc = start_cc self.num_cols = num_cols self.num_rows = num_rows def create_pad_matrix(self, channel=0): """Create an 8x8 pad grid for clip launching.""" rows = [] for row in range(self.num_rows): row_buttons = [] for col in range(self.num_cols): note = self.start_note + col + row * self.num_cols button = ButtonElement( is_momentary=True, msg_type=MIDI_NOTE_TYPE, channel=channel, identifier=note, name=f"Pad_{row}_{col}" ) row_buttons.append(button) rows.append(row_buttons) return ButtonMatrixElement(rows=rows, name="Pads") def create_encoder_strips(self, channel=0, count=8): """Create a row of continuous encoders.""" encoders = [] for i in range(count): cc = self.start_cc + i encoder = EncoderElement( msg_type=MIDI_CC_TYPE, channel=channel, identifier=cc, map_mode=Live.MidiMap.MapMode.absolute, name=f"Encoder_{i}" ) encoders.append(encoder) return encoders def create_button_strips(self, channel=0, count=8, start_note=None): """Create a row of button controls.""" start_note = start_note or (self.start_note + 64) buttons = [] for i in range(count): note = start_note + i button = ButtonElement( is_momentary=True, msg_type=MIDI_NOTE_TYPE, channel=channel, identifier=note, name=f"Button_{i}" ) buttons.append(button) return buttons # Usage matrix = ControlMatrix(start_note=36, start_cc=20) pads = matrix.create_pad_matrix(channel=0) encoders = matrix.create_encoder_strips(channel=0) buttons = matrix.create_button_strips(channel=0) ``` -------------------------------- ### Create and Listen to a Relative Encoder Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/01-framework-core.md Demonstrates how to instantiate an EncoderElement for relative control, set up a listener for value changes, and map it to a Live parameter. This is typically used for continuous controls like volume or pan. ```python from _Framework.EncoderElement import EncoderElement from _Framework.InputControlElement import MIDI_CC_TYPE import Live # Create a relative encoder on channel 0, CC 7 (coarse) # For a two-knob relative encoder setup volume = EncoderElement( MIDI_CC_TYPE, 0, # channel 7, # CC number Live.MidiMap.MapMode.relative_smooth_binary_offset, encoder_sensitivity=1.0, name="Volume" ) # Listen for changes def on_volume_changed(value): print(f"Volume delta: {value}") volume.add_normalized_value_listener(on_volume_changed) # Map to a parameter volume.connect_to(song.master_track.mixer_device.volume) ``` -------------------------------- ### SessionComponent Constructor and Methods Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/08-framework-modules.md Manages session view, including clip launching and navigation. Methods allow assignment of clip launch buttons, track/scene bank navigation, and scene selection. ```python SessionComponent(num_tracks=None, num_scenes=None, is_enabled=True, **kwargs) ``` ```python set_clip_launch_buttons(buttons) ``` ```python set_track_bank_buttons(left, right) ``` ```python set_scene_bank_buttons(up, down) ``` ```python set_selected_scene(index) ``` ```python selected_scene() ``` -------------------------------- ### Configure Display Specification Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/04-ableton-v3-api.md Sets up the display specification for LCD/OLED screens. This includes dimensions, segment count, message type, channel, and sysex ID. ```python from ableton.v3.control_surface.display import DisplaySpecification display_spec = DisplaySpecification( width=128, height=32, num_segments=1, message_type=0, channel=0, sysex_id=b'\x47\x00\x20\x29\x01' ) ``` -------------------------------- ### Live.MidiMap Mapping Modes Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md Provides an overview of the different mapping modes available in Live.MidiMap, including standard and 14-bit modes. ```APIDOC ## Live.MidiMap Mapping Modes Provides an overview of the different mapping modes available in Live.MidiMap, including standard and 14-bit modes. ### Modes - **Standard modes**: - `absolute`: 0-127 linear mapping. - `relative_smooth_two_compliment`: Relative mapping using two's compliment. - `relative_smooth_signed_bit`: Relative mapping using a signed bit. - `relative_smooth_binary_offset`: Relative mapping using a binary offset. - **14-bit modes**: - `absolute_14_bit`: 14-bit absolute mapping (0-16383). - `relative_smooth_14_bit_two_compliment`: 14-bit relative mapping using two's compliment. - `relative_smooth_14_bit_signed_bit`: 14-bit relative mapping using a signed bit. - `relative_smooth_14_bit_binary_offset`: 14-bit relative mapping using a binary offset. ``` -------------------------------- ### TransportComponent Initialization Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/04-ableton-v3-api.md Initializes a modern TransportComponent for handling playback controls. ```python from ableton.v3.control_surface.components import TransportComponent transport = TransportComponent( name='Transport' ) ``` -------------------------------- ### MixerComponent Initialization Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/04-ableton-v3-api.md Initializes a modern MixerComponent for managing tracks and returns, with options for master track inclusion and track scrolling. ```python from ableton.v3.control_surface.components import MixerComponent mixer = MixerComponent( name='Mixer', num_tracks=8, num_returns=2, include_master=True, can_scroll_tracks=True ) ``` -------------------------------- ### Create a 4x4 Button Matrix Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/03-control-elements.md Demonstrates creating a smaller 4x4 ButtonMatrixElement. The ButtonElement constructor is shown with ellipsis, indicating it's a placeholder. ```python small_matrix = ButtonMatrixElement( rows=[ [ButtonElement(...) for _ in range(4)] for _ in range(4) ] ) ``` -------------------------------- ### Device Controller Implementation Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/05-examples-and-patterns.md This script defines a custom Device Controller for Ableton Live 12, managing device parameters, bank navigation, and on/off states. It utilizes the v3 Control Surface API. ```python from ableton.v3.control_surface import ( ControlSurface, ControlSurfaceSpecification, ElementsBase, create_button, create_encoder, MapMode, create_skin ) from ableton.v3.control_surface.components import DeviceComponent from ableton.v3.control_surface.capabilities import * from ableton.v3.control_surface.colors import Rgb class DeviceColors: ACTIVE = Rgb(0, 255, 128) INACTIVE = Rgb(50, 50, 50) PARAMETER = Rgb(255, 165, 0) class DeviceElements(ElementsBase): def __init__(self): super().__init__() # Parameter controls (8 encoders) self.param_controls = [ create_encoder(f'Param_{i}', 0, 20+i, MapMode.ABSOLUTE) for i in range(8) ] # Bank navigation self.bank_up = create_button('Bank_Up', 0, 104) self.bank_down = create_button('Bank_Down', 0, 105) # Device selection self.device_left = create_button('Device_Left', 0, 106) self.device_right = create_button('Device_Right', 0, 107) # Device control self.on_off = create_button('Device_On_Off', 0, 108) self.lock = create_button('Device_Lock', 0, 109) # Display (optional) self.param_names = [ create_button(f'Param_Label_{i}', 0, 48+i) for i in range(8) ] class DeviceSpec(ControlSurfaceSpecification): elements_type = DeviceElements control_surface_skin = create_skin( skin=DeviceColors, colors=DeviceColors ) class DeviceController(ControlSurface): def __init__(self, c_instance): super().__init__(DeviceSpec, c_instance) def setup(self): super().setup() device = self.component_map['Device'] device.set_parameter_controls(self.elements.param_controls) device.set_bank_nav_buttons( self.elements.bank_up, self.elements.bank_down ) device.set_on_off_button(self.elements.on_off) device.set_lock_button(self.elements.lock) self.log_message("Device Controller ready") def get_capabilities(): return { CONTROLLER_ID_KEY: controller_id( vendor_id=9999, product_ids=[2001], model_name="Device Controller" ), PORTS_KEY: [ inport(props=[NOTES_CC, SCRIPT]), outport(props=[NOTES_CC, SCRIPT]) ] } def create_instance(c_instance): return DeviceController(c_instance) ``` -------------------------------- ### Parameter Value Display Component in Python Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/05-examples-and-patterns.md Create a component to display parameter names and their normalized values on a physical display. Requires a display object and parameter controls to be assigned. ```python from _Framework.DisplayDataSource import DisplayDataSource class ParameterDisplayComponent(ControlSurfaceComponent): """Shows parameter names and values on a display.""" def __init__(self, display, num_params=8, *a, **k): super(ParameterDisplayComponent, self).__init__(*a, **k) self._display = display self._num_params = num_params self._param_controls = [] self._param_sources = [] for i in range(num_params): source = DisplayDataSource(num_segments=2, default="") self._param_sources.append(source) def set_parameter_controls(self, controls): """Assign controls and create display sources.""" self._param_controls = controls for i, control in enumerate(controls): self.register_slot(control, self._on_param_value, "value") def _on_param_value(self, value, control): index = self._param_controls.index(control) # Display parameter name and normalized value param_name = control.name or f"Param {index}" # Format value as 0-127 value_str = f"{int(value * 127 / 100):3d}" # Update display display_text = f"{param_name[:6]:6s} {value_str}" self._param_sources[index].text = display_text ``` -------------------------------- ### Built-in Components Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/04-ableton-v3-api.md Provides pre-built components for common Ableton Live functionalities like Session, Mixer, Device, and Transport control. ```APIDOC ## Built-in Components (v3) ### SessionComponent Modern session component with integrated navigation and clip launching. ```python from ableton.v3.control_surface.components import SessionComponent session = SessionComponent( name='Session', num_tracks=8, num_scenes=8, can_scroll_tracks=True, can_scroll_scenes=True ) ``` ### MixerComponent Modern mixer with track selection and send control. ```python from ableton.v3.control_surface.components import MixerComponent mixer = MixerComponent( name='Mixer', num_tracks=8, num_returns=2, include_master=True, can_scroll_tracks=True ) ``` ### DeviceComponent Modern device control with macro handling. ```python from ableton.v3.control_surface.components import DeviceComponent device = DeviceComponent( name='Device', device_selection_follows_track_selection=True, allow_macro_on_non_macro_devices=False ) ``` ### TransportComponent Modern playback control. ```python from ableton.v3.control_surface.components import TransportComponent transport = TransportComponent( name='Transport' ) ``` ``` -------------------------------- ### ChannelStripComponent Key Methods Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/08-framework-modules.md Controls a single track's mixer parameters. Methods allow setting the track, assigning volume, pan, send controls, and mute/solo/arm buttons. ```python set_track(track) ``` ```python track() ``` ```python set_volume_control(encoder) ``` ```python set_pan_control(encoder) ``` ```python set_send_controls(encoders) ``` ```python set_mute_button(button) ``` ```python set_solo_button(button) ``` ```python set_arm_button(button) ``` -------------------------------- ### Initialize DeviceComponent with Parameter Controls Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/02-framework-components.md Assigns a list of encoder elements to control device parameters within the DeviceComponent. The number of encoders should match the number of parameters to be controlled. ```python param_controls = [EncoderElement(...) for _ in range(8)] device.set_parameter_controls(param_controls) ``` -------------------------------- ### Accessing Parameter Properties Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md Details how to access a Parameter object from a device and retrieve its name, value, range (min/max), and quantization status. It also shows how to format values as strings. ```python param = device.parameters[0] # Identity name: str # Parameter name original_name: str # Original (unmodified) name # Value value: float # Current value default_value: float # Default value min: float # Minimum value max: float # Maximum value value_items: list[str] # Enum choices (if applicable) # Behavior is_quantized: bool # Quantized to steps is_enabled: bool # Parameter is functional # Methods str_for_value(value): str # Format value as string ``` -------------------------------- ### Create a Note Button Element Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/06-midi-reference.md Instantiate a ButtonElement for MIDI Note On/Off messages. Specify message type, channel, and note identifier. ```python from _Framework.ButtonElement import ButtonElement from _Framework.InputControlElement import MIDI_NOTE_TYPE button = ButtonElement( is_momentary=True, msg_type=MIDI_NOTE_TYPE, channel=0, # Channel 1 (0-15 = 1-16) identifier=60, # Middle C name="My_Button" ) ``` -------------------------------- ### Core Framework Components Source: https://github.com/gluon/abletonlive12_midiremotescripts/blob/main/_autodocs/README.md Details on the fundamental building blocks of the MIDI remote script framework, including ControlSurface lifecycle, MIDI routing, input elements, components, and the color/skin mapping system. ```APIDOC ## Core Framework - ControlSurface lifecycle and MIDI routing - InputControlElement and subclasses (Button, Encoder, Slider) - 30+ component types (Session, Mixer, Device, Transport, etc.) - Control assignment system (Layer) - Color/skin mapping system - Task scheduling and callbacks ```