Vangelis doesn't honor LV2 ttl controller order

When I added my plugin to Vangelis, each time I restart zynthian the parameters appear in a different random order. They’re nicely ordered in the MyPlugin.lv2/dsp.ttl:

plug:_1_Bypassed
        a lv2:Parameter ;
        rdfs:label "Bypassed" ;
        rdfs:range atom:Float ;
        lv2:default 0 ;
        lv2:minimum 0 ;
        lv2:maximum 1    ;
        lv2:portProperty lv2:enumeration , lv2:toggled ;
        lv2:scalePoint [
                rdfs:label "Off" ;
                rdf:value 0 ;
        ], [
                rdfs:label "On" ;
                rdf:value 1 ;
        ] .

plug:_2_InputGain
        a lv2:Parameter ;
        rdfs:label "Input Gain" ;
        rdfs:range atom:Float ;
        lv2:default 1.07288e-06 ;
        lv2:minimum -72 ;
        lv2:maximum 36 .

Do I have to write a separate ttl file for Zynthian? Is there a better way in the plugin code to provide ordering hints? (Or could Zynthian sort them?)

Note that I’m using JUCE with Projucer, so I’m not writing the dsp.ttl by hand, but the parameters are correctly ordered and the IDs are sortable.

I tried to write down some things here. Look out for the term displayPriority:

1 Like

Thanks. Just above, it says "If not edited further, LV2 parameters will be presented in a manner being sorted by their parameter ID "

Is this no longer true?

You must use DisplayPriority .

Regards

OK, I changed “in a manner being sorted by their parameter ID” to “in a random order.”

Really not possible to sort them? Won’t this affect existing plugins that don’t have z-specific ttl’s?

Hannesmenzel’s notes apply to groups. How do we order the parameters themselves, and assign them to groups?

Use this, please.
DisplayPriority is the way. All LV2 hosts, including zynthian, would honor DisplayPriority.

2 Likes

It applies to both. Groups are ordered first, then parameters with the same group. Assigning parameters to groups is described in the wiki, ch. 3.2.2 / 3.2.3

I can imagine it would be possible to sort by param ID, I would even like to say it used to default to that. DisplayPrioruty anyhow isn’t zynthian specific, its part of lv2 port properties:

1 Like

Right, I added the priorities. But some existing plugins might now get re-ordered randomly.

By the way, I think in your ttl your control parameters don’t even have an index. In fact, only your audio ports have the ID. So that might be the reason they’re not ordered. I’m pretty sure my own plugin compiled with the DPF framework automatically introduced the index and it ordered it accordingly. Could you please review this in order to review your wiki changes?

plug:_2_InputGain
	lv2:displayPriority 190 ;
	a lv2:Parameter ;
	rdfs:label "Input Gain" ;
	rdfs:range atom:Float ;
	lv2:default 1.07288e-06 ;
	lv2:minimum -72 ;
	lv2:maximum 36 .
a lv2:OutputPort , lv2:AudioPort ;
		lv2:index 2 ; // output port ID
		lv2:symbol "audio_out_1" ;
		lv2:name "Audio Out 1" ;
		pg:group plug:output_group_1 ;
		lv2:designation <http://lv2plug.in/ns/ext/port-groups#left> ;
1 Like

OK, I’ll look into it. My ttl file was created by JUCE, so I’d have to do a feature request to JUCE to add these indexes. But thanks for pointing them out. If it turns out as we both expect, I’d change the text to “sorted by index if present, or random order” or something like that.

(I’m currently postprocessing what Projucer creates to add the priorities.)

What does your lv2:Parameter entry look like?

You can have a look right here:

Or you can have a look as some best practice examples here:

2 Likes

I’ve been going thru the rabit hole and this is how LV2 parameters are sorted in zynthian:

  • First, “Control Ports” are parsed and ordered by index.
  • Then “Property Parameters” are appended after “Control Ports”. Parsed like this:
for control in world.find_nodes(plugin.get_uri(), world.ns.patch.writable, None):
    # some code
LV2 docs say:

The LilvNodes* collection returned by lilv_world_find_nodes is undefined and completely unordered

  • Then, the full list is sorted using the “DisplayPriority” property. Like this:

zctrl_dict = dict(sorted(zctrl_dict.items(), key=lambda item: item[1].display_priority, reverse=True))

“DisplayPriority” is set to 0 by default, so ordering by it should not alter the “initial order” if “DisplayPriority” is not explicitly set.

So, if your plugin uses Control Ports, they would be sorted by “index”, then by “DisplayPriority”
If your plugin uses “Property Parameters” (JUCE), they would be sorted by “DisplayPriority” only.

Please, tell me if this is not the observed behaviour and i would investigate.

Regards,

That’s not the observable behavior. At least, not quite.

Without the priority lines, every time I restart zynthian I get a different order. There may be things that are consistent, but I haven’t noticed them. (That is, they might be always grouped together into the same pages, but pages shown in random order.)

Sorry, i just modified my last post. Please, read again :wink:

OK, that makes sense. It’d be hard to summarize, though!

Perhaps:

Controls organized by Control Port are ordered by index and then sorted by DisplayPriority.
Controls listed under Property Parameters are randomly ordered and then sorted by DisplayPriority.

I think that gives anyone adding a plugin enough information to know where to look and what to do. But it omits any mention of the groups, which might complicate things, and I don’t want to guess how that factors in.