new version avaliable : V1.5 Important update
sources are avaliable here Sources
changelog here
Edit january 2014 : link to the Video: Enjoy
https://vidd.me/HiH
Sources are avaliable on the 9th post
Hi everybody,
Lately I have bought a sparkle ( step sequencer from Arturia ), and i have decided to write a midi remote script for this hardware.I knew nothing about Python programming, Poo programming and else.
I am glad poeple like Hanz Petrovand Julien Baylehad put lots of tips to describe how Midi remote scripts worked.
Thank to them, i have been able to write an alpha version of my step sequencer.
Now that I understand more precisely how midi remote script works, I have decided to start a new midi remote
script from scratch in a more flexible way.
I) How do I create a midi remote script?
All the files of your script have to be in a folder that have the name of your script, situated in the Ableton\ Live \Resources\MIDI Remote Scriptsfolder.
To initialise your script you have to create a __init__.py file, you can use Notepad++, Ulipad, or any other software
This file is mandatory, because it tells to Live that you want to initialise a script. For the sparkle i have made this __init.__py file:
Code: Select all
from sparkLE2 import sparkLE2 # you import your main program during the initialisation of your script
def create_instance(c_instance): # this function tells live that you create a new midi remote script
return sparkLE2(c_instance) # the initialisation result is the calling of the main function of your script.
below, their is a script that does NOTHING but contain all the requirement to be a working script
Code: Select all
from __future__ import with_statement #compatibility for Live 9, need to be written at the first line of the script
import Live #you import Live, in order to be able to use its components
from _Framework.ControlSurface import ControlSurface # importthe Controle surface module
class sparkLE2(ControlSurface): # create a class element
__module__=__name__ #name of the class
__doc__="Sparkle function" #documentation
def __init__(self, c_instance): #initialize the sparkLE2 class as a ControleSurface
ControlSurface.__init__(self,c_instance) #import the components of a ControlSurface
with self.component_guard(): #don't know the us of this, but it is recquiered in live 9 scripts
self.__c_instance = c_instance
This is it! you have created your first useless script
II) How do I debug my script ?
To actualise your script you have to close and reopen live (you can keep notepad++ open).
To debug your script you have to check the logfile made by Live. You can find this logfile (on window) here
C:\Users\Raztua\AppData\Roaming\Ableton\Live 9.1\Preferences\Log.txt
Errors are logged in this file.
To follow the execution of your script you can use two different functions:
self.show_message('your message here') writes on the status bar of Live
self.log_message('your message here') writes on the log file your message
III) Helloworld
To make this helloworld we will create a function that write on the log_message and the status bar Hello world
This function will be called during the nitialisation of the surface
Code: Select all
from __future__ import with_statement #compatibility for Live 9, need to be written at the first line of the script
import Live #you import Live, in order to be able to use its components
from _Framework.ControlSurface import ControlSurface
class sparkLE2(ControlSurface):
__module__=__name__
__doc__="Sparkle function"
def __init__(self, c_instance):
ControlSurface.__init__(self,c_instance)
with self.component_guard():
self.__c_instance = c_instance
self.helloworld() #call the helloworld function during the initialisation of your script
def helloworld(self): #create the helloworld fuction (with the self argument, live uderstand that this function belong to the SparkLE object)
self.log_message('helloworld')
self.show_message('helloworld')
a) send midi :
You can find more precise information about midi messages here :http://www.midi.org/techspecs/midimessages.php
My sparkle surface uses only midi note message to "talk" with the computer, ( it uses sysex too but i will not talk about this).
Midi notes messages hare a tuple of 3 integer.
for exemple (144,60,100) the key C3 ( value 60 ) is pressed (value 144 ) on the channel 0 vith a velocity of 100
the first integer have two information : a key is pressed (note on message is 144) on the channel 1 (channels are labelled from 0 to 15)
144+0=144
if I want to send a note off message for the C3 on the channel 2 key ill send the tuple ( 128+1=129, 60, 0 )
Ill only use note on and note of message to light the leds of my surfaces
The command used to send mii message is self._send_midi( 'tuple' )
b) receive midi :
there is two way to receive a midi message :
Implicitly : if you dont program anything on your surface concerning a midi button, it will automatically be mapped to live.
The following part of the script allow to use autom mapping from live
Code: Select all
def build_midi_map(self, midi_map_handle):
ControlSurface.build_midi_map(self, midi_map_handle)
and is used this way :
Code: Select all
[ButtonElement].add_value_listener('the order to launch',identify_sender= True)
c) Create a button element:
To be able to use a button element on a ControlSurface you have to import the ButtonElement class.
To import constants associated with midi note and command cc, we import the package InputControlElement
At the start of the script we add : from _Framework.ButtonElement import ButtonElement
from _Framework.InputControlElement import *
Then we create a button element associated to one of the pad of the surface (here the pad 50)
the command is:
self.pad=ButtonElement(not IS_MOMENTARY, MIDI_NOTE_TYPE, 0, 18
d)Practical example:
The aim of this example is to create a script that will light the pad 61 and write on the log file "HelloWorld" when the pad 60 is pressed
Code: Select all
from __future__ import with_statement #compatibility for Live 9, need to be written at the first line of the script
import Live #you import Live, in order to be able to use its components
from _Framework.ControlSurface import ControlSurface
from _Framework.ButtonElement import ButtonElement
from _Framework.InputControlElement import *
IS_MOMENTARY=True
class sparkLE2(ControlSurface):
__module__=__name__
__doc__="Sparkle function"
def __init__(self, c_instance):
ControlSurface.__init__(self,c_instance)
with self.component_guard():
self.__c_instance = c_instance
self.show_message('Script initiated')
self.Pad1=ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 0,60) # identifies P&d1 as a ButtonElement. IS_MOMENTARY is true if the button send a message on being released
self.Pad1.add_value_listener(self.helloworld,identify_sender= False) #adda value listener that will lauch the method self.helloworld when Pad1 is pressed
def disconnect(self): #this function is automatically called by live when the program is closed
self.turn_off_led(60)
self.turn_lef_off(61)
def helloworld(self,value):
if value>0: #value>0 when the pad is pressed
self.log_message(self,'hello world')
self.turn_led_on(61)
else:
self.turn_led_off(61)
def turn_led_on(self,value):
self._send_midi((144,value,64))
def turn_led_off(self,value):
self._send_midi((128,value,64))
V) clipslots, clips and note:
the current sont is accessed via the command :
self.actual_song=Live.Application.get_application().get_document()
this command gives access to the tracks, clips... of the song.
a)creating a clip
to select the first clipshot on the first track:
Code: Select all
self.first_clipslot=self.actual_song.tracks[0].clip_slots[0]
Code: Select all
self.first_clipslot.create_clip(length)
to add a note on a clip, for example a C3 at the second beat 0.5beat long, with a velocity of 64:
Code: Select all
self.first_clip=self.first_clipslot.clip
self.first_clip.set_notes(((60,1.0,0.5,64,False),)) #the attribute is a tuple of tuple with the argument ((note,start,length,velocity,muted),)
c)get and remove notes
to gets notes:
Code: Select all
self.first_clip.get_notes(1.0,60,0.5,2) #to get all the notes from C3 to C4, between 1 and 1.5 beat , arguments: (starting beat,base note,length of the selection,rand of notes)
Code: Select all
self.first_clip.remove_notes(1.0,60,0.5,2) #to get all the notes from C3 to C4, between 1 and 1.5 beat , arguments: (starting beat,base note,length of the selection,rand of notes)
VI) Session mode:
Sessions are groups of clips. they are showed on live with colored boxes(sometime called ring).
the aim on this script is to use my pads 50 and 51 to move my session to the right and to the left
Code: Select all
from __future__ import with_statement #compatibility for Live 9, need to be written at the first line of the script
import Live #you import Live, in order to be able to use its components
from _Framework.ControlSurface import ControlSurface
from _Framework.ButtonElement import ButtonElement
from _Framework.InputControlElement import *
from _Framework.SessionComponent import SessionComponent #this is the component used to create Sessions
IS_MOMENTARY=True
class sparkLE2(ControlSurface):
__module__=__name__
__doc__="Sparkle function"
def __init__(self, c_instance):
ControlSurface.__init__(self,c_instance)
with self.component_guard():
self.__c_instance = c_instance
#initialisation and setup of the pad
self.Pad_left=ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 0,60)
self.Pad_right=ButtonElement(IS_MOMENTARY, MIDI_NOTE_TYPE, 0,61)
#initialisation of the session
self.create_session_control()
self.set_highlighting_session_component(self.Session) #link the session model to the Live object-> shows your ring
def create_session_control(self):
width=1 #width of the Session
height=8 #height of the Session
self.Session=SessionComponent(width,height) #here we create a session called Session
self.Session.set_offsets(0,0) #offset start a the up-left corner (track1,row1)
self.Session._do_show_highlight() #to ensure that this session will be highlighted
self.Session.set_track_bank_buttons(self.Pad_right,self.Pad_left) #associate buttons
As I said i am new to scripting, but ill be glad to help you if needed, and i ll be even more happy if poeple correct my mistakes, or scripting errors
PS: if you want to see my former script in action --------> Video