Saturday, October 3, 2009

Controlling Ardour and Jackd through OSC and Python


OSC, or Open Sound Control, is a flexible network messaging system intented to allow the control of various music and sound oriented software. There are several mature applications that currently support external control via OSC. These apps include Jamin, Ardour, and Jack. In this post, I'd like to concentrate on controlling Ardour and Jack through Python using OSC.

Ardour has a little known set of OSC messages that it can understand. Oddly enough, this set is vaugly documented in the Supercolider wiki. The messages currently implemented (As of this writing the latest stable version of ardour is 2.8.2) controll basic channel routing functions and simple transport operations (Mute/Solo/Rec Arm, Stop/Play/Punch In). So without the use of any external software we have a basic control of Ardour which can be extended to external interfaces (think midi controllers for Ardour!).

Thanks to a small python module called Simple OSC, it is possible to send, recieve and manipulate OSC messages within Python. We will use python to glue all this stuff together and actually do something interesting.

Unfortunately, Ardour only offers rudimentary control of its transport mechanism over OSC. Which means we mush use some other means to locate the playhead to specific locations and get current time line/meter/tempo information. This is where a little app called jack.clock (or jack.osc) which is a member of the jack-tools package.

The bellow python code is about as simple as it gets, this module will allow a user to play and stop ardour through osc, as well as enter timecode locations (in seconds)
import osc

osc.init() #Initialize the OSC module

def play():
#Send a play message to ardour, there is no additional information required for this
#Hence the empty list!
try:osc.sendMsg('/ardour/transport_play',[],'localhost',3819)
except: raise

def stop():
#Send a stop message to ardour, there is also no additional info for this message
#Hence the empty list!
try:osc.sendMsg('/ardour/transport_stop',[],'localhost',3819)
except: raise

def locate(loc):
#This message requires that there is a jack.clock instance running at port 9001
#jack.clock is a member of the jack-tools package and controls the jackd timeline
try:osc.sendMsg('/jck_rl',[loc],'localhost',9001)
except: raise