No control over group and control id assignment in preset

The editor automatically assigns ids to a group or a control, without the possibility for the user to assign one explicitly. The assigned identifier appears to depend on the location (ie page and position) of the group or control.

This is problematic if you later want to refer to a particular group or control (eg to chan ge value, name or visibility) from a script independent of the layout of the preset. I.e. you want to be able to move controls and groups around without their ids changing.

1 Like

I’m with you. Especially when using lua code for for instance hiding or showing controls, this logic gets broken if someone uses such preset and decides to change the layout. The lua may even become inunderstandable afterwards. A better option may be that once an ID is assigned to a control, this ID remains with the control even after moving it. Although this will have copy / paste consequences: I haven’t found a way yet to move a control to another page, apart from copying at pasting it. But the logic above would give that copied control a different ID (since the original still exists on the moment of paste), so the maintenance of these ID’s would not yet be that simple and lua might still be difficult to keep in pace with the ID’s

2 Likes

Exactly. This is one of the reasons why my Ableton Live script is not hiding unused controls at the moment.

1 Like

I sincerely think that being able to change ids would introduce a lot of headaches . What you can do is to assemble a repository by yourself, filled at boot. Just loop through all the possible controls available and set them on a table, so the index might be the name, parameter number, etc, so you can request them later with getControlerByName(“FADER 1”)

1 Like

To be clear: I’m NOT asking for the ability to change ids on the fly once a preset is uploaded. What I am asking for is the ability to assign a specific id to a control when editing a preset, just as the editor now allows you to assign a MIDI CC (or NOTE or…) to a control (and to also allow this for groups). Not sure how that could lead to any headaches, but perhaps I am overlooking something.

2 Likes

yup, currently, the Ids are assigned to the controls according to their position in the preset. It comes from the early JSON versions where bounding boxes (position and size of the control) were not supported. The web based editor relied on the Ids a lot - in terms of both layout and referencing the controls. I need to check much much dependency is still left there (in the editor I mean).

I am basically with @jhh and @NewIgnis. There should be a way to assign an “identifier” for referencing the control (or any other object). I am considering adding a special “referenceId” field. Especially if using current ids would represent a bigger problem with backward compatibility.

3 Likes

@martin @jhh The problem would be that you will still be using unique ids! And the issue of maintaining ids will prevail. What about you delete an control? is the ID repeated? Do you have a list to keep the order of used numbers?..

A Solution: using a Repository call. Sample Code:

cRep = {}

-- Returns control or nil, without errors
cRep.getById = function(id)
    local control
    if pcall(function () control = controls.get(id) end) then
        return control
    else
        return nil
    end
end

-- Returns first control found with name
cRep.getFirstWithName = function(self, name)
    local control
    local nameToFind = string.upper(name)
    for i=1,432 do 
        control = cRep.getById(i)
        if (control ~= nil and control:getName() == nameToFind) then 
            return control
        end
    end
    return nil
end

-- Returns first control found using the parameter number
cRep.getFirstWithParameterNumber = function(self, number)
    local control
    for i=1,432 do 
        control = cRep.getById(i)
        if (control ~= nil and control:getValue(0):getMessage():getParameterNumber() == number) then 
                  print("found "..i)
            return control
        end
    end
    return nil
end

-- Sample Usage
local superFader = cRep:getFirstWithName("Super Fader 1")   
local panning = cRep:getFirstWithParameterNumber(3)

It should work, but will not be really optimized (however, I would prefer to use processor than memory for this things.)

the first day I played with the E1 I thought the same: I need to move the Ids! And even tried ways to figure it out. However, E1 Strength is that every control can be moved, and have code tied to those controls, by its action or its parameter. this other way of working turned out way cleaner, easier and organized.

I usually have calls like pan = cRep:getControlFromTopOfControl(fader) because I know they will always be next to each other. Or maybe I never repeat parameter number for ANY control, so I can call them that way and move them all around! You can build your repository with cache on a table (controlId, CCNumber, name, other field, etc), and search for them no matter where they are. I think parameterNumber is pretty much never repeated, so its a good match for most calls.
This decoupling of code from interface is ideal, and coupling it will only give you more problems on the long run.

Of course, this is just MY opinion. An extra ID in the controls could be used, sure. But I wouldn’t recommend using it unless there is no other way.

------- EDIT -------

Thinking it over, if the identifier is a STRING, then it would be welcome! Event oriented programming will take you only so far in such a limited environment.

In my opinion such reference should be non-mandatory, unique if not empty, and be divided in two string-fields. The first field could then be used to identify a control target (vco1, filter, amp env…), the second to identify a controller within that target (tune, fine tune, sync… or 1,2,3…).
If I look at the use cases, like hiding controls, renaming effects parameters of colour changes, I’d be using user friendly descriptions in my lua for the target, and then numbers for the subID, so I could address them easily in for-statements or in arrays with only one dimension. But some one else could choose to keep the target empty and use non numerical strings in the subID.

By the way, I have the same parameter in multiple places in a single preset, for various practical reasons, but that is a bit off-topic.

1 Like

@NewIgnis I got you. Now I understand. The first post called about being able to manipulate the current ids, and went into my head into INT type! the idea as I see it now is to request an ID like a Variable Name, so you can name the controls VCO_1, VCO_2, FILTER_ENV, AMP_ENV…

We could type that now in the name field, and then search them by name (as per my previous post), however, the name value cannot be fixed with a Formatter function to remove the “_”.

Yes, a variable name like Field would be nice! And current name should be the display one. I fully understand the request now and like it! Thanks for clarifying it to me.

Actually, I was thinking of it as an int type reference, for efficiency. But @NewIgnis suggestion is actually quite elegant, especially if there would be a possibility to address a set of controls by the first (type) field, and then e.g. hide or recolour them all with a single LUA command…

Oh @jhh , couldn’t you just pretend that was your original idea? :wink:

INT keys suck for what you are looking for! So yes to Variable-Name like additional field.
and I already see someone requesting 2 more fields to group controls inside controls… and soon a database is being built! We just need one! We can easily create a little function that reads all the identifiers in the E1 preset and fills a table with n categories (example identifier: “MIXER1-FADERS-FADER1”) and then search for them like allFaders = controlCategories:getControlsInSection(2, "FADERS") And voila! ready to be looped. Just one field is needed to have multiple categories.

I disagree int keys suck, but that’s perhaps because I’m old school and efficiency matters to me: if I need to address something specific, I prefer to do so with an integer address/idx :wink:

But LUA stores both numbers and variables to table addresses, so no efficiency gained!