Forums > Max For Live

observe devices inside rack chain

March 8, 2013 | 6:43 pm

Hi,

Im trying to observe the devices inside a rack, when theyre deleted or added. I have the following code, which works most of the time, but it seems to get stuck listening to the last added chain for some reason. If there is a device inside one of the other chains, this is not observed.

Would be grateful if anyone has any pointers.

– Pasted Max Patch, click to expand. –

Cheers

N


March 11, 2013 | 9:19 am

ive just tested this in ableton live 9 and found that this works as expected. Something must have changed between live 8 and 9 that has resulted in this functionality now working. Is there anyone that can confirm this?

The code basically bangs when something is added or deleted in a rack chain, or track.

Also, would be really grateful to find out if there is a way of doing this in js. ie to observe all levels of chains, rather than the 1st level.


March 11, 2013 | 9:25 am

newtfish, I posted a JS in answer to your last post about iterating devices in chains which demonstrates how to find all of the devices. You should be able to install observers along the way and get what you want.

Best, Jeremy


March 11, 2013 | 9:32 am

cool thx for this jeremy, your js solution is amazing! :)


March 11, 2013 | 11:50 am

Im not that great with js, so i try the following code, with callbacks, but I dont get any output when observed (device is deleted or added). Is there something im doing drastically wrong? grateful for any help.

autowatch = 1;
outlets = 4;
function bang()
{
	var api = getTrackPath();
	if (!api) return;

	iterateDevices(api);
}

function iterateDevices(api)
{
	var count = api.getcount("devices");
	var apiPath = dequotePath(api);
	for (var i = 0; i < count; i++) {
		var deviceApi = new LiveAPI(callback,apiPath + " devices " + i);
		if (deviceApi) {
			var deviceName = deviceApi.get("name");
			var deviceId = deviceApi.id;
			var deviceApiPath = dequotePath(deviceApi);
			var chainsCount;
			var chainApi;
			var j;

//			post("found device " + deviceName + " at path '" + deviceApiPath + "'n");
			outlet(0, "append", deviceName);
			outlet(1, "append", deviceId);
			if (deviceApi.get("can_have_chains") == 1) {
				chainsCount = deviceApi.getcount("chains"); // only racks have chains
				for (j = 0; j < chainsCount; j++) {
					chainApi = new LiveAPI(callback,deviceApiPath + " chains " + j);
					iterateDevices(chainApi);
				}
				chainsCount = deviceApi.getcount("return_chains"); // only racks have chains
				for (j = 0; j < chainsCount; j++) {
					chainApi = new LiveAPI(callback,deviceApiPath + " return_chains " + j);
					iterateDevices(chainApi);
				}
			}
		}
	}
}
iterateDevices.local = 1;

function getTrackPath()
{
	var api = new LiveAPI("this_device");
	if (api) {
		trackPath = dequotePath(api);
		trackPath = trackPath.replace(/s+devices.*?$/g, ""); // remove 'devices N' at the end
		return new LiveAPI(trackPath);
	}
	return null;
}
getTrackPath.local = 1;

function dequotePath(api)
{
	return api.path.replace(/"/g, ""); // remove quotes
}
dequotePath.local = 1;
function callback(args)
{
  outlet(0,args[1]);
  outlet(1,this.id);
post(args);
}

March 11, 2013 | 4:37 pm

Try this. I might have mangled your additions a little, but I think it’s right. There may be a couple of things going wrong in your version:

- in addition to the callback function, you need to assign the LiveAPI object’s "property" attribute to the property you want to observe. In the case of the track, this is "devices", in the case of a rack device, this is "chains", in the case of a chain, this is "devices" and so on.
- once a JavaScript object goes out of scope it can be garbage collected if it’s not in use elsewhere. So I’m stuffing the objects that we’re observing into a global array to be certain that they can’t disappear.

Note that to observe both chains and return chains, you actually need 2 LiveAPI objects (each object can only observe 1 property). I left this as an exercise to the reader.

Best, Jeremy


March 11, 2013 | 4:38 pm

Sorry, forgot the JS.

Attachments:
  1. alltrackdevices.js

March 11, 2013 | 8:10 pm

thanks Jeremy,

There seems to be a bit of a problem with the unquotedpath in this script? Im wondering what unquotedpath is? Is this something built into the object? The first error I get is when using unquotedpath, which results in trackPath throwing an undefined error.


March 11, 2013 | 9:09 pm

Oh sorry, I was testing something here and forgot to change it back. Remove that line and uncomment the one below it.

Best, Jeremy


March 11, 2013 | 10:21 pm

This is really amazing, didnt realise js was so useful. Thanks so much Jeremy.

The one thing I have noticed is that when a device is added in an existing chain, the device id is output. However, if I drag a device to create a new chain (automatically creating a new chain by dragging), then it only outputs the chains and not the new device id. I also noticed this behaviour when using the max objects, it doesnt seem to notice the new device id. Maybe this is a feature that im missing. Ideally, I would really like to just refresh the individual id that is added/deleted, but this works great for now, so I can just check if something has changed within a rack and refresh all device ids on the track.

Cheers Jeremy :)


March 12, 2013 | 5:19 pm

yes, as Im looking deeper into this, im finding that when a new chain is added, the array needs refreshing, but live cant seem to tell me when this happens. I thought that maybe changing:

for (j = 0; j < chainsCount; j++) {

to

for (j = 0; j < = chainsCount; j++) {

might work, so the array refreshes on the first chain. However, this doesnt seem to be the case. Im afraid this "chain 0" thing is becoming a bit elusive for me, it seems to work the same in max objects as it does in js and the liveapi cannot seem to see the past the first chain.


September 28, 2014 | 2:58 am

Hi,

Ive been using the following code to output a bang when any device is added or deleted whether it is inside a rack chain, or not. This works ok most of the time. However, when you add a new chain, the devices inside the "new chain" are not observed. Its strange, because it is observing the chain and therefore must be calling the function "iterateDevices()". However, it seems not to be triggering this function inside a chain. Would be grateful for some pointers as to why new devices are not being observed inside a new chain.

autowatch = 1;
outlets = 1;

var apiArray = new Array();

function iterate(x){
	var a = "id " + x;
	//delete api.cb_private;	
	var api = new LiveAPI( a);
	iterateDevices(api);

}

function iterateDevices(api)

	api.property = "devices"; // we want to observe the devices tuple
	apiArray.push(api); // push it onto our array so it doesn't get GC'd

	var count = api.getcount("devices");
	var apiPath = dequotePath(api);

	for (var i = 0; i < count; i++) {
		var deviceApi = new LiveAPI(callback, apiPath + " devices " + i);
		if (deviceApi) {
			var deviceName = deviceApi.get("name");
			var deviceId = deviceApi.id;
			var deviceApiPath = dequotePath(deviceApi);
			var chainsCount;
			var chainApi;
			var j;

			if (deviceApi.get("can_have_chains") == 1) {

				deviceApi.property = "chains"; // we want to observe the chains tuple
				apiArray.push(deviceApi); // push it onto our array so it doesn't get GC'd

				chainsCount = deviceApi.getcount("chains"); // only racks have chains
				for (j = 0; j < chainsCount; j++) {
					chainApi = new LiveAPI(callback, deviceApiPath + " chains " + j);
					if (chainApi) {
						iterateDevices(chainApi);
					}
				}
				chainsCount = deviceApi.getcount("return_chains"); // only racks have chains
				for (j = 0; j < chainsCount; j++) {
					chainApi = new LiveAPI(callback, deviceApiPath + " return_chains " + j);
					if (chainApi) {
						iterateDevices(chainApi);
					}
				}
			}
		}
	}
}
iterateDevices.local = 1;

function dequotePath(api)
{
	//return api.unquotedpath;
	return api.path.replace(/\"/g, ""); // remove quotes
}
dequotePath.local = 1;

function callback(args)
{
	//outlet(0,args[1]);
	//outlet(1,this.id);
	//post(args[1]);
	if(args){
	//outlet(0,'bang');
	}
	//post();
outlet(0,'bang');
}

Viewing 12 posts - 1 through 12 (of 12 total)