Saving plugin internal state

Hi all,

I have a plugin that has an internal gain state. It isn’t exposed as a control as it is internally calculated/modified as part of the plugin audio processing logic. However when someone saves a snapshot on the MOD I would love for the internal gain state to also be saved/loaded as part of the snapshot to provide an initial value to start on.

I saw somewhere that LV2 State (LV2 State) is supported by the mod and seems like it might be the correct way to do this. Does anyone have a pointer to a simple example project of using the state interface to save/load internal plugin state?

1 Like

you need to have it as readable or writable parameter in order to have that saved in snapshots.

1 Like

Thanks. Your support for MOD is amazing I appreciate the help.

I am not completely familiar with the terminology of LV2. When you say a readable/writable parameter is that a LV2 Patch with Set/Get of a named parameter?

If so would this project be a good sample to use as a basis to “copy” from:

2 Likes

More or less yes.
eg-sampler from LV2 also has a working example of this, robin/x42 example plugins were missing a few tiny bits last time I checked.

the steps are typically:

  1. define a lv2:Parameter of a known type (bool, int, long, float, double, string, path or vector)
  2. mark such parameter as readable (host can see it and let it pass through UI<->DSP but not change it) or writable (will be shown as editable widget under plugin settings on MOD)
  3. have an atom input and output port, where you listen to changes made to the parameter (via input) and also report them back to the host (via output)
  4. save and reload such parameter info during the state save&restore calls (note: when restoring state, make sure to notify host later, via worker or some internal flag, that this state has changed)
2 Likes

I have some some code in test now that is logging when I get save/restore calls and can see them being called on save/load of the pedalboard and they seem to be working correctly.

However it seems they are not being saved/restored on changing snapshots.

Is there some way I can make params saves/restored when changing snapshots?

Its quite likely I have a bug as from what you said above it sounds like I should see an editable widget for my parameter (which I dont I only see the existing control widgets). I have created a “gain” parameter that is both readable/writable. Is this permitted?

1 Like

yes, that is what the readable/writable param status is for. you can see it with the notes plugin which uses a string parameter. the contents are saved and change on each snapshot.
this requires the plugin to report any internal changes to the host though, because what ends up in the snapshot is the local cached value instead of plugin-side status.

yes, but not needed. writable assumes readable too.

2 Likes

Thanks. I will keep debugging then and focus on checking the message from the plugin to the host and checking the ttl file.

Should I expect to see an editable knob for the gain in dB next to the other controls when this is working (if so then there is probably something wrong with my ttl file I assume)?

1 Like

yes. eg-sampler (called “Exampler”) has the gain as patch parameter, and notes uses a string parameter, both available to install from the store

1 Like

Fantastic!! Thanks for the pointers. Its working now.

I was creating my own “gain” parameter and I think something was wrong with it. I switched to just using param:gain now and it is working.

I cant see any requirements of what is required for Parameters but I am guessing my gain which looked like below need a default/min/max and possibly a units:

plug:gain
   a lv2:Parameter ;
   rdfs:label "gain" ;
   rdfs:range atom:Float .
2 Likes

best to give it a range and default yes, unit is optional.

2 Likes

I have made a lot of progress and now am trying to create presets for my plugin. However I am not sure how to set the state of the above gain param as part of a preset.

I see other examples of presets for patch parameters, but all I greped are files or strings (not a float) and the eg-sampler doesn’t define a preset.

When I try setting the state in a preset I see errors logged from my code indicating that the data passed in is a non-float. I debugged and found it is a String with content “0.0”

I can work-around this by parsing the string in my restore code and thus allow two different supported formats of the gain param (string and float), but I assume there is a “proper” way to do this I cant see to have the preset code auto provide me a float instead of a string to behave like the snapshots.

I have tried a few different formats for the preset:

        plug:gain "0.0"^^xsd:float
        plug:gain 0.0
        plug:gain "0.0"
        plug:gain <0.0>

The preset data currently looks like:

@prefix plug: <https://github.com/bjcosta/baudio-plugins/@LV2NAME@#> .
@prefix lv2:    <http://lv2plug.in/ns/lv2core#> .
@prefix modgui: <http://moddevices.com/ns/modgui#> .
@prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
@prefix pset:  <http://lv2plug.in/ns/ext/presets#> .
@prefix state: <http://lv2plug.in/ns/ext/state#> .

<default-preset>
    a pset:Preset ;
    lv2:appliesTo <https://github.com/bjcosta/baudio-plugins/@LV2NAME@> ;
    rdfs:label "Default" ;
    lv2:port [
        lv2:symbol "mode" ;
        pset:value 0
    ] , [
        lv2:symbol "adjust_rate" ;
        pset:value 1.0 ;
    ] , [
        lv2:symbol "target" ;
        pset:value 0.0 ;
    ] , [
        lv2:symbol "gui_update_period" ;
        pset:value 0.0 ;
    ] ;
    state:state [
        plug:gain "0.0"^^xsd:float
    ] 
    .

The other issue with using this (“0.0”^^xsd:float) is the validator reports:

Verifying https://github.com/bjcosta/baudio-plugins/blevel-match-dev... error: failed to expand CURIE `xsd:float'
3 Likes

Adding
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
will solve that.

3 Likes

I should have seen that :frowning: Thanks. Looks like it is working now.

4 Likes