Several people (more than I imagined) have discovered my LOM.Navigator and it seems most of you have one thing in common: you’re curious to know how to get the most out it. Sure I wrote a readme file and included it with the full archive but… (note: you can grab the patch on both MaxForLive.com and my M4L download page which gives you the full archive).
So I figured I’d might as well try to combine the effort and give you guys both a dose of the navigator as well as an attempt to explain the (what I tend to call) basics behind the whole Live Object Model.
Now, this is probably unnecessary but I would like to clearly state that the overview picture of the LOM below is copyrighted (so I assume) and owned by Cycling ‘74, I sort of used it without asking for their permission. I’m pretty sure its alright, but just so you know: this isn’t mine nor mine to ‘give away’. Also keep in mind that this picture is dated, you’ll find the latest information on the Live Object Model webpage. The reason I used it is so that you (the reader) won’t have to flip back and forth but can direct your attention to this page only. Also: should someone from C’74 for whatever reason not agree with its use I’ll obviously remove it if so requested.
The Live Object Model – how to use and read.
Here you can see the diagram which is basically the roadmap to everything that Max for Live can access inside the Live application. The only problem, like so many other things; once you grasped the basics its easy yet it can take up some time before you actually reach that point. And those of you who know this chart by heart now: yes, I cut out the bottom section (control_surfaces); that is for a later time.
You read the map from left to right and as you can see there are 2 starting points here: live_app and live_set. These 2 are so called root objects. Just consider these 2 separate starting points. One gives you access to specific details of the Live application (“live_app”) itself whereas the other gives access to everything which involves the Live set you’re working on (conveniently called ‘live_set’). There are more root objects, but I will get to those later.
Classes and their relations.
All boxed items you see in the chart represent so called classes. Think of a class as a portal which provides you with direct access to some of the things which are directly related to that section. For example; the first class you’ll see after “live_set” is “song”. Here our journey starts.. “live_set” is basically a path name, or in technical terms a so called relation, which points us to a class called ‘song’.
As the path “live_set” implies; this section is all about our live set (‘song’) in general. When we look at the song reference section (see the link) you’ll notice that it provides children, properties and functions. Think of ‘children’ are routes to other sections in the model. Properties on the other hand represent specific values whereas functions provide direct means to control.
How does this work?
Lets stick with the Song class for now (path being “live_set”). When you look at the reference page you’ll notice 7 children: “tracks”, “return_tracks”, “master_track”, “visible_tracks”, “scenes”, “cue_points” and “appointed_device”. Now look at the picture above; you will see each and every one of these children appear in the diagram as names appearing on the lines between the classes. These lines represent the relations between the several classes. When one class has access to another it is because that other class is a child of the first class.
For example.. A live set contains tracks. You have your midi and audio tracks, return tracks (2 by default) and your master track. Look at the diagram again..
The arrow called “master_track” is a straight arrow from “Song” to “Track”. That should be obvious since every live set can only have 1 master track. When looking at the arrow (‘relation’) called “return_tracks” however we see a line which doesn’t have an arrow point but 3 separations at the end. Why is that ?
A live set can have none or several return tracks. Sure; you have 2 by default. There’s nothing stopping you to delete ‘m all (try it!) nor to actually add even more than the 2 you already have. So; when you want to access a return track you will need to clearly specify which one out of the list of several you want to use.
And that is what the so called “list relation” is telling us; when we access this path we should expect a list of possibilities to use. Then out of that list we can make a selection of what we actually want. In even more technical terms: we are dealing with a “one to many” relationship. One song can have many return tracks.
And this logic is used throughout the entire model. Look at the relation called “tracks”. The exact same logic applies here, to a certain degree. A live set can have 1 (not 0) or many tracks. So here we see yet another list relation. After we try to access a certain track we need to clearly specify which track we actually want to address.
Look between “Device” and “DeviceParameter”. A device represents either an instrument, midi effect or audio effect. And there is no telling up front how many parameters such a device provides. So here we see the same logic at work again: one device can have many parameters.
Next to the solid lines you will also notice lots of “dotted” lines. Note that I’m only talking about the lines which aren’t printed in bold. The ‘bold dotted lines’ are so called optional relationships, but I’ll get to those in a moment.
A reference behaves in many ways the same as a relation. It represents the child of a class, it can have one direct link or provide several options to chose from (like the “list relation”) and as such basically seems totally equal to a normal relation.
However, as the name suggests, because they merely refer to something this usually gives a small part or section of something else.
For example; take the reference called “visible_tracks”. The main difference between “visible_tracks” and “tracks” is that the latter will always return the full list of tracks available in your live set whereas the first only lists the tracks which are currently visible (so not folded up into a group for example).
But in general it is safe to simply treat a reference as if it was some kind of relation.
And those optional relationships? Simple; their usage is fully optional and determined by other influences. For example; in the diagram you’ll notice a bold dotted arrow between “Device” and “Chain” as well as between “ClipSlot” and “Clip”. Its simple: a track or scene consists of many clip slots, but not every clip slot contains an actual clip; so this is an optional relationship. A Device can be an instrument, VST or a rack device (Instrument Rack, Audio Effect rack, etc.). If we’re dealing with a Rack we’ll also be able to access its chains. A regular instrument on the other hand d
oesn’t provide chain access like a rack does; so once again this relation is strictly optional.
Properties and functions
Besides children each class also has a list of properties and functions. These control values (properties) or specific means of access (functions) to the section which the class represents.
Take for example the Track class. It has properties like “arm” which represent the arm state of the track; you can retrieve its value (“get”) or actually change it yourself (“set”). The same applies to stuff like “solo” (is the track solo’d or not), “name”, “mute”, “is_visible” and so on.
The main thing to keep in mind with properties is their access level. Not all properties can be set to a specific value for example…
Finally functions; the moment we need to perform a specific task we resort to functions. For example; when you’re using a track you can use the “stop all clips” option which will stop all the clips in the track (the ones playing, cued, etc.). This is specific behavior of the track class, as such not represented by a property but controlled by a function. By calling the function called “stop_all_clips” we mimic the behavior as if someone has clicked on the stop all clips button.
The LOM Navigator is a patch that I wrote to make it easier to navigate through the whole object model and thus allows you to check the right path towards certain objects without the hassle of looking at the diagram of the Live Object Model all the time.
My main idea was to have a native Ableton device which could be used right from within Live. I’m going to look into adding support for a floating window, but that’s for later.
Also note: the navigator can not be accessed by a control surface. This was a deliberate choice because it also provides access to control surfaces, so in order to avoid any risk of clashes I decided to leave this out entirely.
Navigating begins at the top by selecting one of the so called root devices. In my explanation above I already mentioned 2 of these, there are actually two more: “control_surfaces” which I’ll be addressing in my next post as well as “this_device” which basically points you to the M4L device itself. As can be seen above by default the Navigator starts with the live_set root device.
Once you selected a root object you basically selected your starting class. In the case of “live_set” you basically selected the “Song” class, so now you can access its children, properties and functions.
Say we want to access track 2 on which I set some devices. As explained above; navigating to a track is basically using a “list relationship”. So we need to first select the child we want (“tracks”) after which we’ll need to specify which one it is we want to use:
As you can see; the moment you select ‘tracks’ the sub menu behind ‘Children’ will fill up. When you click on it you’ll see a list similar to that shown in the right picture: a list of all the tracks with their name behind it (if any) between brackets.
All that’s left to do is simply select one of the tracks you want after which the current path will be changed (as can be seen at the bottom of the patch).
Note that the moment you select a child representing a ‘list relation’ while it has only 1 member then this member will be selected automatically. For example: suppose you’re working in a live set which contains only 1 track then you won’t see the submenu being filled up like I demonstrated above. Instead the track will be instantly selected the very moment you clicked on the ‘tracks’ child.
Another thing which is good to know, though I assume most of you have spotted this by now: the Children menu shows you both the name of the relation (path name) as well as the name of the Class which it points to. As you can see here; “tracks Track”. ‘tracks’ is the name of the relation (the actual path) which points to the Track class. Thus we end up with the path “live_set tracks 1” (see below).
Properties and functions
If you want to check up on a certain property then all you need to do is select it from the ‘Properties’ menu. Click on the menu to see a full list of properties appear; select one of those and its value should appear in the “Prop. value” field at the bottom. Note: I am aware of a bug which sometimes causes the value not to display at the first attempt. Just select the property again and then it should display the value.
You can also change the value of a property. Do note that the navigator cannot check the access level of a property so even if a property cannot be set it will still try. Just see the Max window (or runtime window) for any error messages if nothing seems to happen.
Once you selected a property and see its value being displayed (like in this screenshot) then simply click on the field which contains the value (the message box). Now a dialog will appear which will ask you for a new value. Enter it, click ok or press enter and the new value will be immediately set.
Functions work in almost the same manner, however because there are some ‘dangerous’ functions available I build in a fail save that you cannot start a function by simply selecting it. This is to avoid any accidents where you select a function and then suddenly realize that you need something else. If functions start right away then I’m sure it can eventually cause unwanted behavior.
So; select the function from the list, then click the round “call function” button shown below the Prop. value field. If the function produces any output then this will be shown in the field behind the ‘call function’ button.
When dealing with functions which actually need to set a value then you can do so by first selecting the function, then click on the “output” field after which a dialog appears. Enter the desired value, hit enter (or click ok) and then this value will appear in the “output” field. Now click “call function” and if applicable the value will be set:
Note that the input dialog can appear anywhere on your screen. Just for screenshot convenience I’ve dragged it behind the patch before taking a picture, but with regular use this will probably appear somewhere in the middle of your screen.
Navigating back up
The final topic I will address in this post.. When you’re at a certain location, how to move back “up the ladder” so to speak ? When dealing with, say, device parameters then it can be extremely bothersome if you’d have to start navigating all the way from the root device again.
Fortunately this isn’t necessary.
Once you’re at a certain location and wish to go back to the previous section (class) in the path you simply expand the Children menu and look for the child called “canonical_parent”.
As with all children the class to which this child points is mentioned behind it. And when you’re using the Navigator on different locations you will eventually notice that the canonical_parent child will actually point to several different classes.
In short: this child points to the class “above”. When you selected a device on a track (“path live_set tracks 0 devices 0”) and then click the children menu you’ll notice a “canonical_parent” which points right back to the Track class.
Once you’ve reached the Track class again (the situation shown in the screenshot) you’ll see that this time ‘canonical_parent’ points back to the Song class. And so on…
Note that “canonical_parent” isn’t merely handy in the Navigator; your own devices can benefit from this as well. Say you want to know on which track your device resides… As explained above there is a root device called “this_device” which points to your M4L device.
The ‘canonical_parent’ of a device is the Track class which in this case represents the track the device is on.
SO… By using “path this_device canonical_parent” we can easily access the track on which the device has been put.
In the next part I will go into more detail on how to access control surfaces as well as explain how I use the Navigator for it. This is still somewhat unfamiliar territory for me as well but we’ll see how far I can take it.
Oh; needless to say but if you have any comments or questions I’d love to hear ‘m.