[LV2] Writing to control input ports w/o UI (DSP -> host; via atom output port) - RFC

Rui Nuno Capela rncbc at rncbc.org
Sat Apr 18 02:47:00 PDT 2020


Many thanks for the quick reply and comments.

It's really appreciated and exactly to the point I was expecting for...

On 4/17/20 8:43 PM, David Robillard wrote:
>> [...] _urid_map(LV2_ATOM__portEvent));
> Types (classes) are capitalized, PortEvent in this case.

No sweat, class `PortEvent` it is!
#define LV2_ATOM__PortEvent LV2_ATOM_PREFIX "PortEvent" ///<

>> [...] lv2_atom_forge_key(forge, forge->Tuple);
> Similarly, atom:Tuple is not a property (key), it is a type.  You
> will need to invent a property for this.

Easy as this, maybe a new property `portTuple`?

#define LV2_ATOM__portTuple LV2_ATOM_PREFIX "portTuple" ///<

>> [...]
> Most importantly however, thanks for prototyping this, but PLEASE DO 
> NOT EXIST IN LV2 MASTER!  Use URIs in some other namespace at first
> for things like this, people can't invent whatever URIs in the LV2 
> namespaces they want, that has caused real problems in the past.

Don't worry. Although already implemented and working as proposed, in
qtractor and the vee-ones upstream, it's all still experimental code and
not yet "officially" released (simply as that, the new proposed URIs are
currently declared as above with `#ifndef`/`#define`s).

Besides, the new couple of URIs are here still proposed to the
`LV2:Atom` namespace, for which I believe is the right one, as this is
NOT a brand new  extension or vocabulary on its own: it's just about one
and simple possibility that's been missed here since a long time ago :)

Anyway, here below follows the now corrected code snippets...

Host: ** read_port_event **
#include "lv2/lv2plug.in/ns/ext/atom/util.h"

//  LV2_Atom *atom;
//  `atom` is a `LV2_ATOM__Object`, read from the plugin's atom output
//  port buffer, while on the real-time processing thread and then
//  transferred to the main host (non-DSP) thread, possibly via a
//  ring-buffer, wrapped in a `LV2_ATOM__eventTransfer` container.
    const LV2_Atom_Object *obj = (const LV2_Atom_Object *) atom;

    if (obj->body.otype == _urid_map(LV2_ATOM__PortEvent)) {
        const LV2_Atom_Tuple *tup = nullptr;
            _urid_map(LV2_ATOM__portTuple), (const LV2_Atom *) &tup, 0);
        uint32_t port_index = 0;
        if (tup) {
            uint32_t port_index = 0;
            LV2_ATOM_TUPLE_FOREACH(tup, iter) {
                if (iter->type == _urid_map(LV2_ATOM__Int))
                    port_index = *(uint32_t *) (iter + 1);
                if (iter->type == _urid_map(LV2_ATOM__Float)) {
                    const uint32_t buffer_size = iter->size;
                    const void *buffer = iter + 1;
                    _control_port_write(port_index, buffer_size, 0, buffer);
//  ...

Plugin: ** write_port_event(s) **
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"

//  LV2_Atom_Forge *forge;
//  `forge` should be bound to the plugin's atom output port buffer;
//  nb. remember to declare an minimum adequate port buffer size (via
//  `LV2_RESIZE_PORT__minimumSize` property) if you intend to notify in
//  bulk ie. more than one tuple or pairs (`port_index`, `port_value`)
//  in contiguous sequence.
//  uint32_t port_index;
//  float port_value;
//  `port_index` (int) is the control input port index that is desired
//  to get updated on the host-side with `port_value` (float), forming
//  one or more tuples wrapped in a LV2_ATOM__PortEvent object and sent
//  out to host.
    lv2_atom_forge_frame_time(forge, 0);

    LV2_Atom_Forge_Frame obj_frame;
    lv2_atom_forge_object(forge, &obj_frame, 0,
    lv2_atom_forge_key(forge, _urid_map(LV2_ATOM__portTuple));

    LV2_Atom_Forge_Frame tup_frame;
    lv2_atom_forge_tuple(forge, &tup_frame);

    // for each (port_index, port_value) tuple ...
    lv2_atom_forge_int(forge, port_index);
    lv2_atom_forge_float(forge, port_value);
    // ...

    lv2_atom_forge_pop(forge, &tup_frame);
    lv2_atom_forge_pop(forge, &obj_frame);

//  ...

Hope it all looks a tad better now ;)

Cheers && Thanks again
rncbc aka. Rui Nuno Capela

More information about the Devel mailing list