I wrote a script to have a Red Box, or Session Box, and to control it up, down, left and right.
I'm using M Audio Oxygen 49 so I also managed to assign the 8 pads to launch the scenes inside the red box.
I have absolutely no knowledge or skills about coding, python, and I've only recently began using Ableton. This was only possible thanks to few pieces of information shared by users of this forum, and very few other sites, so I think it's only fair for me to share this.
I know anyone who uses an M Audio Oxygen may find this useful, but this should work with any other midi device.
This is it:
1. __init__
Code: Select all
from sim_ses import sim_ses
def create_instance(c_instance):
return sim_ses(c_instance)
2. sim_ses
Code: Select all
from __future__ import with_statement
import Live
from _Framework.ControlSurface import ControlSurface
from _Framework.ControlSurfaceComponent import ControlSurfaceComponent
from _Framework.InputControlElement import *
from _Framework.ButtonElement import ButtonElement
from _Framework.ButtonMatrixElement import ButtonMatrixElement
from _Framework.SessionComponent import SessionComponent
from _Framework.TransportComponent import TransportComponent
from _Framework.EncoderElement import EncoderElement
from SpecialTransportComponent import SpecialTransportComponent
numTRA = 4 #number of tracks
numSCE = 2 #number of scenes
sesBUT = [27, 22, 28, 26, 13, 15, 19, 23] #1st top/left button of your matrix
upBUT = 53
dowBUT = 54
lefBUT = 55
rigBUT = 52
CHANNEL = 0 #main channel (0 - 15)
BUTTYP = MIDI_CC_TYPE
BUTTNP = MIDI_NOTE_TYPE
is_momentary = True
undoBUT = 113
CHANNELPADS = 9
class sim_ses(ControlSurface):
def __init__(self, c_instance):
super(sim_ses, self).__init__(c_instance)
with self.component_guard():
self._setup_controls()
self._setup_session()
def _setup_controls(self):
self._pads = [ButtonElement(is_momentary, BUTTNP, CHANNELPADS, sesBUT[index]) for index in range(numTRA*numSCE)]
self._grid = ButtonMatrixElement(rows=[self._pads[(index*numTRA):(index*numTRA)+numTRA] for index in range(numSCE)])
self._up_but = ButtonElement(is_momentary, BUTTYP, CHANNEL, upBUT)
self._dow_but = ButtonElement(is_momentary, BUTTYP, CHANNEL, dowBUT)
self._lef_but = ButtonElement(is_momentary, BUTTYP, CHANNEL, lefBUT)
self._rig_but = ButtonElement(is_momentary, BUTTYP, CHANNEL, rigBUT)
def _setup_session(self):
self._session = SessionComponent(numTRA, numSCE, enable_skinning = True)
self._session.set_clip_launch_buttons(self._grid)
self.set_highlighting_session_component(self._session)
self._session.set_scene_bank_up_button(self._up_but)
self._session.set_scene_bank_down_button(self._dow_but)
self._session.set_track_bank_left_button(self._lef_but)
self._session.set_track_bank_right_button(self._rig_but)
self._session._link()
def _setup_device_and_transport_control(self):
is_momentary = True
device_param_controls = []
for index in range(8):
device_param_controls.append(EncoderElement(MIDI_CC_TYPE, 15, 62 - index, Live.MidiMap.MapMode.absolute))
device = SpecialDeviceComponent()
device.set_bank_nav_buttons(ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 107), ButtonElement(is_momentary, MIDI_CC_TYPE, 15, 106))
device.set_parameter_controls(tuple(device_param_controls))
self.set_device_component(device)
transport = SpecialTransportComponent()
transport.set_undo_button(ButtonElement(is_momentary, MIDI_CC_TYPE, 0, undoBUT))
def disconnect(self):
super(sim_ses, self).disconnect()
Code: Select all
import Live
from _Framework.TransportComponent import TransportComponent
from _Framework.InputControlElement import *
from _Framework.ButtonElement import ButtonElement
from _Framework.EncoderElement import EncoderElement
class SpecialTransportComponent(TransportComponent):
""" Transport component that takes buttons for Undo and Redo """
def __init__(self):
TransportComponent.__init__(self)
self._undo_button = None
def disconnect(self):
TransportComponent.disconnect(self)
if self._undo_button != None:
self._undo_button.remove_value_listener(self._undo_value)
self._undo_button = None
def set_undo_button(self, undo_button):
if not isinstance(undo_button, (ButtonElement, type(None))):
raise AssertionError
if undo_button != self._undo_button:
if self._undo_button != None:
self._undo_button.remove_value_listener(self._undo_value)
self._undo_button = undo_button
self._undo_button != None and self._undo_button.add_value_listener(self._undo_value)
self.update()
def _undo_value(self, value):
if not self._undo_button != None:
raise AssertionError
if not value in range(128):
raise AssertionError
if self.is_enabled():
(value != 0 or not self._undo_button.is_momentary()) and self.song().can_undo and self.song().undo()
I'm also trying to have the up, down, left, right assigned to only 2 knobs, instead of 4, but this one is making my head spin.
Would appreciate any hints!