Loop recursively (racks inside racks etc) through a Live set

Rivanni's icon

I made a patch that loops through all Live tracks, racks, and chains to find all devices. This process gives me several properties of each level, such as the names. So, I need not only the device properties but also some of the tracks, racks, and chains.

I encounter a problem with racks. 

Take, for example, an audio rack with three racks. The first rack contains another audio rack with two chains. Each chain contains an audio effect device, and the other two chains in the main rack do the same.

When the rack in a rack is found, it correctly lists all two chains and devices in those chains. However, instead of going to the second chain in the main rack next, it outputs the data of the second chain in the sub rack.

it’s as if Max 'knows' it still has to process the second chain in the main rack, but, the id of it is overwritten by the one of the sub rack.

After outputting the wrong second chain, it correctly continues with the third chain in the main rack.

When I add a third chain to the sub rack, it also ignores the third chain in the main rack.

This is only a small example. With multiple racks inside racks, this won’t work at all.

What adjustments must I make to go recursively through the Live set, no matter how many nested racks there are?

I made a small demo project that contains the rack and Max device (made in Live 11.3.25 so most of you can open it).

The patch is also below.

Max Patch
Copy patch and select New From Clipboard in Max.

schlam's icon

Hello Rivanni

Away from keyboard so I cannot see your patch..

Did you look in the new "Variation" device of L12 how the recursive loop part of the patch is made ?

It seems to work perfectly to list all devices in racks in racks in racks etc...

Rivanni's icon

Thanks for the suggestion.

Unfortunately, the device suffers from similar issues. Values a returned randomly, if at all. And that's only with my simple demo rack. So this means another bug report...

Rivanni's icon

Despite the bug, the Variation device was a useful example. I could use some of its ideas to adjust my patch.

All (sub) racks chains and devices are now listed correctly.

I want to improve only the order because now all sub racks are listed at the end. I will figure this out later.

Below is the patch for anyone who wants to use or improve it.

Max Patch
Copy patch and select New From Clipboard in Max.

Rivanni's icon

Follow-up question:

I’m grappling with the execution order due to defer low and I need some guidance. 

The left part of the patch below traverses all devices in a Live set and stores the id numbers in a bag.

There are two recursive loops: one for devices in rack chains and one for devices in drum rack return chains.

Next, it starts dumping the bag’s contents into a collection (orange cord) and doing other things during this process (yellow cords).

Here is the problem. The dumping process occurs before the two recursive loops (with a deferlow) are finished. Because of this, the data from the recursive part is not added bag and hence not to the the collection.

When I manually start the dump process (orange bang), all data is added to the collection since fetching all ids has finished.

So I tried to automatically delay the dumping using [delay], [pipe], [deferlow] etc in all kinds of places, and changed trigger orders etc. Nothing worked, and sometimes, the fetching process was even terminated at an earlier stage. But most of the time it just executed as described above.

In essence, how do I send a bang when the whole id fetching process is finished, so I can continue with other processes?

recursive deferlow problem [rvn].amxd
amxd

Roman Thilenius's icon

delay and deferlow are contradictions; delay will always output to the high priority if available.

deferlow moves to the end of the queue, which to my understanding should only help the stuff at the beginning of the queue, i.e. without safely having a certain own "property".
i dont think you can track when something has finished in defer or deferlow, at least not with the usual [t b b]-at-the-beginning approach.
if in amxd you really need to do that because it doesnt execute otherwise, a generous delay would be my preference.

to experiment with this it might be useful to isolate the loop mechanics completely from the actual process which is performed in it. (and maybe you want to have an emergency brake? something which does not allow, say, more than 50 loops.)

Rivanni's icon

Adding a delay (in the orange cord) has the weird effect of processing only 1 item from the bag, even though it's executed after all id's, including the recursive ones, were added to the bag (according to a watchpoint going to the bag).

The recursive loop was isolated in earlier stages. I moved the 'yellow' part inside to see if it would change things. Even when it was outside, I still needed a bang to know the loop had been completed to continue with the further steps in the process.

The start of the loop is a button press, by the way.

An emergency break is not an option, as I want to traverse the whole Live set. The purpose of the Max device is to list all plugins, Max, and Live devices in a set, and it does this part well. The loop is not the problem, but not knowing when it's finished is. It surprises me there is no simple way to do this.

In a version of the patch where I remove the first bang to clear the bag, I get the result I want by clicking the button twice in a row. The loop executes again, but the bag does not accept duplicates. The loop is going very fast when executed inside Live. For some reason, the loop takes longer to execute in Max. But even though it can be very quick, a user might click too fast in case of very large Live sets.

When asking users to click twice, I can expect question why I don't program it this way.

I tried to replicate this double-click in Max, but it didn't solve the issue.

I attach the full device so you and others can see what it is supposed to do.

If you use it in a large Live set, you'll see that the generated list is larger after the second click on the button.

Changing the three toggles on the left results in the [bag] being emptied. This can't be done upon a button-click because otherwise a second-click would start all over and delete the deferred id's.

Device Lister [rvn].amxd
amxd

Source Audio's icon

why do you use bag ?

coll can work better, not only because you can check it's contents for debugging,

but also can dump instead of running uzi

try this a bit rearanged patch

Device Lister.amxd
amxd


if that is not reliable, as alternative you could insert delay at id collection to

get end of list.


Rivanni's icon

Thanks for your adjustments. The collection instead of the bag is indeed a cleaner solution, and I added it to my device.

However, it does not fix the problem.

The deferred dump message is sent before the loop has been completed. This is the same result I got with my device.

Delaying the dump acts in the same strange way I saw when I delayed sending the bag's contents.

A watchpoint tells me that all ids from the collection are sent to [p StoreIdNumber+Path].

But the collection inside this sub-patch only contains the last id that was dumped.

Also when I manually bang before the delay to start the dump, only the last id is stored.

When I click on the dump message after the delay, everything is stored.

I'm puzzled.

Source Audio's icon

I am not using Live at all and can't say much about that weird behaviour.

But problem is in first place not knowing when

collecting of all ID's is done.

I have inserted couple of drum racks and have no problems getting all dumps all right,

but maybe live set is not loaded as much to cause problems.

One could pass id's from first coll directly to coll id_path

and insert that delay thing here :

but at the end I don't think that dump or fast output from coll id_path

can work because it is too fast for that last subpatch where you again query

all infos

maybe you need to insert one by one grabbing of previous coll.

something like this :

Device Lister.amxd
amxd


Rivanni's icon

Thanks for taking another look.

For some reason, when I load your device, a [text] list opens. This list does not contain everything. Only a second click on the button does so (like with my own patch), but very slowly.

Also, the collection is not sorted. When I add a sort after the delay (where it only says dump in your image), the collection is sorted but not dumped.

And when I manually dump, I get all sorts of errors from the receiving sub-patch.

I noticed you adjusted this next sub-patch (added a counter, delay, coll, etc.). I'm not sure why you added this since no delays are necessary at this stage.

I'll look at all of it later with some fresh eyes.

Source Audio's icon

That was because of initial values set for switches + loadbang 1.

I don't know why you can't get this to work,

I loaded today several tracks full of effects, racks etc, and it simply works.

I changed few little things, and removed that init values.

Device_Lister.amxd
amxd


Rivanni's icon

Like your previous device, everything is returned in the list, but this time very quickly. However, the order of devices is still not correct.

I don't understand why, since the collection is sorted correctly.

Also, what's coming from your 'counter go next' loop* and is going into [route symbol] is correct (according to a watchpoint).

*) Could you explain why you chose to loop through the collection using a counter and small delays?

Source Audio's icon

It must be order of execution,

you used sort 0, what do you want to sort exactly ?

I used next messages to step through ID's only when

previous one produced result.

Rivanni's icon

Sort 0 sorts by the path.

I saw you used the id in your loop. But as I wrote, the message coming out of the collection are strangely enough in the correct order. Can't explain.

I'm not at the computer now, so I can't test it, but I can send a renumber message to the collection after the sort. The actual Ids don't matter. This way your loop should work. I will test this later this evening.

Rivanni's icon

I added 'renumber 1' and this renumbered the collection properly. But it didn't help to get a correctly ordered list.

Your version of the device also executes things in different order even though the same data is fed. I noticed this when I replaced one rack with another, and it listed names from the previous rack.

Take, for example, the order in the sub-path [IsChain]. In your version, GetName (watchpoint 11) is executed after the [combine] is sent (7) instead of before (8), whereas, in my patch, it is executed in the correct order.

I don't know why it behaves wrongly in your patch. Could it still be the deferlows in the main sub-patch?

I tried in several Live 11/12 and Max versions, but this made no difference.

Source Audio's icon

My version only executes items from coll id_list one by one,

means when 1st item passes through all the "if this than that, add cr cr etc)

subpatches and outputs all it has, next item gets recalled.

Maybe your version puts a strain on the subpatches, so that they

output in different order.

You could try to simplify it and enforce order of execution.

just by triggering something in wanted order does NOT mean

that it will also execute in that order.

possibly this delay plays a role here.

but it can't work without it.