How to observe a changing string with [live.observer]?

Marc Assenmacher's icon

I need to use a [live.observer] to observe a changing string. So far I could only find strings on hidden parameters, which can be observed but won't update.

Is there any way to observe a changing string with [live.observer]?

Source Audio's icon

why do you make your life so difficult with live.observer ?

you can use anything to report that something changed when it does.

what is a changing string ?

list with numbers ?

or ascii chars ?

Marc Assenmacher's icon

I am building a remote control for a [live.step]. I want to use the dump function in one device and prepend the dump in X other devices and vice versa.

My [live.step] has 64x4 + 22 = 278 values that need to be observed. Performance wise that is a nightmare. So I though I could [pack] the values into several string (e.g. 5 strings in groups of 64, 64, 64 ,64, 22 values) and just use 5 observers instead of 278.


The requirement is to use [live.observer]'s for the data connection instead of [save]/[forward] and [receive], because there are timing issues that (I think) cannot be solved with the current state of how Live renders tracks in random order.

Source Audio's icon

you will anyway have to dump all values of live-step,

not only steps , but also number of steps and loop points

if you want to clone one of them to another one (in different track or device ??? )

Let's say you collect that infos into coll or pattr, whatever,

one long list.

live.observer can not cope with that.

but other objects could grab stored values and apply them into live.step which is set as destination.

I am not using live, so sorry, can't help you with whatever problems live has to do that

simple task.

tyler mazaika's icon

The requirement is to use [live.observer]'s for the data connection instead of [save]/[forward] and [receive], because there are timing issues that (I think) cannot be solved with the current state of how Live renders tracks in random order.

First, I don't think using live.observer is going to solve that problem or significantly change timing performance vs. send/receive.

Second, I think I've only seen live.observer output three types of messages:

1) numbers when DeviceParameter API objects change values

2) id nn (or lists of id nn) messages

3) bang

I don't think getting a string out of [live.observer] is ever going to happen.

Marc Assenmacher's icon

My main goal is to have several devices that can be controlled by one device.

I have one sequencer on every track in Live. I also have one main track with one control sequencer that controls all other sequencers.

When selecting a track, the dump from that tracks sequencer needs to be sent to the control sequencer once. Then, when changing parameters on the control sequencer, its dump gets pushed to the sequencer of the selected track.


I already have a solution that works with [forward] & [receive]:

Example.maxpat
Max Patch

But it does not always work. Live seems to render tracks in random order. Sometimes the id change in the control device is not done before the sequencer device has pushed its last values. I tried with different delay times but that does not seem to change the output. Also on selecting a new track I get CPU spikes of 200% in Live.

When working with observers this does not happen. For all my other devices I switched to work with [live.observer] for that reason but they have 20 parameters at max, not 278. I am afraid 278 observers would also cause bis CPU spikes when selecting a new track.


Do you have any different ideas on how to solve this problem?

tyler mazaika's icon

Rather than pushing sequencer settings from one device to another when track selection changes, why don't you just have each device store it's sequencer settings in a data structure that can be read by all the other devices (e.g. a dict). This way each instance can get the sequencer values as soon as it's own "selected_track" observer changed without any delays.

{
  "id 3" : [0,1,2,3],
  "id 8" : [1,3,2,5],
…
}
Source Audio's icon

"My main goal is to have several devices that can be controlled by one device.

I have one sequencer on every track in Live. I also have one main track with one control sequencer that controls all other sequencers.

When selecting a track, the dump from that tracks sequencer needs to be sent to the control sequencer once. Then, when changing parameters on the control sequencer, its dump gets pushed to the sequencer of the selected track."

If I understand correctly, that control sequencer only serves as GUI or remote editor

for sequencer of selected track.

Can you not just float GUI of selected track's sequencer and work on it ?

At same time any remote control could be routed to that selected track.

for that "master" track/controller would make sense.

Marc Assenmacher's icon

Yes, your assumption is correct. I want to use the control sequencer as GUI to control every other sequencer in my set, always the one on my selected track.

I could just use a floating GUI with [pcontrol] on every of my sequencers but there are some problems:

  1. The window position depends on the screen used.

  2. I'm on a mac and you can not enter fullscreen mode from max – which I want to use and do so once on startup at the moment. Not in fullscreen mode I loose space of my screen for the title bar of the window.

  3. When closing one and opening another window every time I switch a track the window loses focus and needs one more mouse click (touch press in my case).

These are the reasons why I need to build a separate control device.

Also, I am not only controlling the sequencer on a track from my control device but several other Live devices and racks, presets, etc.

Here is a screen for the full scope of my project:

I have never worked with [dict] before, but it looks promising.

Still this seems quite complicated. I need to store an external file with my set that gets updated everytime I...

  • add a new sequencer device to my set. (new id & values)

  • delete a sequencer from my set. (delete id & values)

  • change values in any of my sequencers. (new values on its id)

  • change values in my control device. (new values to selected id)

Is this what you mean?

Marc Assenmacher's icon

This is what I cam up with now. It seems to work well. I just haven't figured out, how to delete entries of deleted devices yet.

Test_Dict.amxd
amxd

Do you have any suggestions on how to improve this?

tyler mazaika's icon
Max Patch
Copy patch and select New From Clipboard in Max.

1) You had a bunch of redundant "set <key> <values>" messages to [dict] objects due to how you used [pak]. I showed a way to use [join] object to optimize that a bit by dynamically switching its @triggers attribute.

2) re: deleted devices, you can use the [freebang] object to fire from within a device when it's been deleted and trigger a "remove <key>" to the dict.

3) I don't fundamentally understand the "Pattr Device" groups here, or why they have a [pattr] called "sequencer" that just duplicates the data that would be present inside the [dict MySeqDict].

4) For "Control GUI", have you considered binding its objects directly to your "Sequencer Device" knobs using [pattr]? If you have the current thing working okay it may not be worth it, but with a little plumbing and some [pattrmarker] objects in your "Sequencer Device" objects you can do it. Basically in "Sequencer Device" put a [pattrmarker] and when your device loads, set the "name" attribute to the device's id (which is unique), like "id 45". Then when you want "Control GUI" to show those controls you send "id 45" to "Control GUI", and construct messages to [pattr] objects there like:

bindto "::id 45::live.dial[1]"

Connect that [pattr] to the corresponding dial in "Control GUI". That'll get you ui-object-to-object mirroring of values.

Then you could actually remove the [dict] value getting/setting code from Control GUI, since, by virtue of being bound via pattr, the changes initiated in Control GUI will cause the dict data to be written in "Sequencer Device", so that it can be read from "Pattr Device". This removes the need for the "I just changed the values!" notification bangs being sent around.

FWIW I'd recommended the [dict] approach as a way to avoid one device (which I thought was a sequencer with very time-critical need to get data, rather than a UI patch) needing to ask another device for data and then wait for a response back.

5) Just in case you hadn't considered it, using the "this_device canonical_parent" assumes your device isn't in a DeviceRack.

6) Text comments about sends/receives would've been more helpful than color schemes.