The real differences are in the interface itself.
It's really incredible how the same Object Model can be accessed in so many different ways.
If you put side by side:
Max Patch, JS LiveAPI code, Python LiveAPI code
they are all different and deal with things in different ways.
The bad thing is that Python LiveAPI seems to be the best one for performance
and has an understandable programming interface (properties, methods, objects
often require very little explanation), but (1) there's no real debugging (apart from logging) (2) even if is somehow supported there's no official documentation and similia (3) the facts that there's no real debugging and no real support/documentation are confirmed by the fact that Live Crashing is 'part of the development workflow' (if I'm missing some wonderful ways of managing python liveapi coding let me know, please.... in my humble opinion and experience even with simple mistakes Live simply crashes)
The JS LiveAPI is different from Python liveAPI. It seems that it'll be the supported/official way of doing a certain kind of things. The programming style is a bit different...
Let's make an example:
In JS LiveAPI every track has a solo property, that you can get, set and observe. Most of the interactions with the track object pass through one or more 'instances' of the one and only LiveAPI() object. You have one single callback per LiveAPI instance... etc, etc
In Python LiveAPI every track has the same solo property but there are a bunch of explicit functions: add_solo_listener, solo_has_listener, remove_solo_listener (and this are only for adding/removing/checking the callback function for solo property)
Sure the general programming interface of some objects is cluttered but in the end the code it's more readable. (at least it seems more readable to me, but I'd love to hear comments on this). In python there is the possibility to set a callback function (listener) for specific properties...
In MAX Patches everything it's different again, MAX programming interface it's another one... there isn't the generic LiveAPI object but the trio of Live.path, Live.object, Live.observer.
Sure this objects are designed to work inside the flow of messages of Max patches but sometimes I have the feeling that in some places a simple object coming from the Live Object Model would have been more readable in the patch, and more usable from people that is already using these concepts every day to make music.
In js you'll write something like this:
Code: Select all
var track_0 = new LiveAPI(this.patcher, track_0_callback, ["live_set tracks 0"]);
track_0.property = "mute";
track_0.property = "solo";
track_0.property = "arm";
function track_0_callback(args)
{
switch(args[0])
{
case "mute":
...
break;
case "solo":
...
break;
case "arm":
...
break;
}
}
or like this:
Code: Select all
var track_0_mute = new LiveAPI(this.patcher, track_0_mute_callback, ["live_set tracks 0"]);
track_0_mute.property = "mute";
var track_0_solo = new LiveAPI(this.patcher, track_0_solo_callback, ["live_set tracks 0"]);
track_0_solo.property = "solo";
var track_0_arm = new LiveAPI(this.patcher, track_0_arm_callback, ["live_set tracks 0"]);
track_0_arm.property = "arm";
function track_0_mute_callback(args)
{
...
}
function track_0_solo_callback(args)
{
...
}
function track_0_arm_callback(args)
{
...
}
In Python you'll write something like:
Code: Select all
tracks = self.song().visible_tracks
track_0 = tracks[0]
if ( track_0 != self.song().master_track)
track_0.add_solo_listener(self._on_solo_changed)
track_0.add_mute_listener(self._on_mute_changed)
if track_0.can_be_armed == 1:
track.add_arm_listener(self._on_arm_changed)
def _on_solo_changed(self):
...
def _on_mute_changed(self):
...
def _on_arm_changed(self):
...
Ina Max Patch you'll connect a message to a Live.Path, then connect the output to a Live.object and a Live.observer, then connect the output of the Live.observer to the rest of the patch that acts as a callback function.
Am I the only one thinking that python interface is more readable?
Sure python interface has too much functions, but...
between something like:
Code: Select all
var track_0 = new LiveAPI(this.patcher, track_0_solo_callback, ["live_set tracks 0 solo"]);
track_0.property = "solo";
where the fact of assigning the 'solo' string to the 'property' property of a track...
means that the solo property is now observed and that the changes are notified to the function given during the creation of a generic LiveAPI object.... that in reality is a track object, but could change whenever you assign a different path to this same object... and what happens to the observed property/object... etc, etc.

in other words, not straightforward...
and something like:
Code: Select all
track_0.add_solo_listener(self._on_solo_changed)
where you have at least two functions named after every observable property. so if you have an object with 20 properties you already have 40 functions, and this is only if you have two functions per property...
isn't there something like:
Code: Select all
track.1.add_observer(solo, solo_callback)
where you:
- navigate directly to an object. the object it's already there inside the song tree so there's no need (at least conceptually IMHO), to create a new one (see the totally misleading "new LiveAPI" instruction)
- add directly an observer with a function. the function is the same for every observable property, for every object that has observable properties. there's no need to have objects with a huge number of functions. there's no need to eventually learn the names of these functions if they appear to be named inconsistently
- the intentions of the code are readable. add an observer/subscriber to the solo property, notify changes of this property to the solo_callback function.
@amounra93
Python works very well because, even if the liveapi stuff that 'has been around for a while' is a hack, controller scripts are originally written in python.
I really don't understand what is that Ableton started supporting about this hack, it seems to me that they simply acknowledged it. If they started supporting we should have a bit of documentation and maybe a simple console window to do some simple debugging and maybe avoid some of Live Crashes.
I personally think that m4l and it's access to the API do not make things more elegant, maybe more supported but surely not more elegant (IMHO of course).