Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to access state:state values in presets? #57

Open
rerdavies opened this issue Jun 5, 2023 · 3 comments
Open

How to access state:state values in presets? #57

rerdavies opened this issue Jun 5, 2023 · 3 comments

Comments

@rerdavies
Copy link

rerdavies commented Jun 5, 2023

I'm writing an LV2 host that leverages lilv for parsing lv2 ttl files... but not currently using the lilv methods for preset management and state. That may have been a mistake, but I'm too far along to easily correct that problem.

The specific problem: I'm trying to copy factory presets (presets included in plugin manifest.ttl files) into my own json-based preset management system. Copying of factory presets is done once when a plugin is first detected. But I'm having a trouble extracting the state:state part of the presets in the manifest.ttl/preset.ttl files.

I've tried both lilv_state_ functions; and lilv_world / lilv_node approaches, without success so far.

A sample preset looks like this:

tpset:toob-convolution-reverb-preset-2
    a pset:Preset ; 
    lv2:appliesTo <http://two-play.com/plugins/toob-convolution-reverb> ;
    rdfs:label "Hall" ;

    lv2:port [
 
        ...
    ] ;

    # Note the atom__Path for the selected impulse file, stored in state here
    state:state [
        <http://two-play.com/plugins/toob-impulse#impulseFile> <ReverbImpulseFiles/St.%20Margaret\u0027s%20Church.wav> ;
    ] .
}

It's straightforward to read port values using lilv_state_emit_port_values; but I can't find a way to access values in the state::state array (which I assume contain the state values). I found lilv_state_num_properties. But I can't find a _get_property method.

So I tried to read the state values using lilv_world_find_nodes queries. But I get stuck when receiving blank nodes after calling lilv_world_find_nodes with

` <preset_iri> state:state nullptr

which succeeds, returning a single blank node.

But I can't find a way to enumerate the predicates in the resulting blank-node triples. lilv_world_find_nodes does not allow a null predicate node; and, generally, I can't predict what other plugins are going to use as predicates. I can't figure what to do next. If there's a way to get a list of triples, given only a blank nodes returned by LILV_FOREACH, I can't find it.

I can think of desperate ways to get this to work (creating a temporary instance of the plugin so that I can load via lilv, and then extract the state through lv2 host APIs. But I'm hoping I've missing something simple and obvious..

So far, I have:


  AutoLilvNode t = lilv_world_get(pWorld,presetUri, ,this->lilvUris.state__state,nullptr);
  
  AutoLilvNodes stateProperties = lilv_world_find_nodes(pWorld,preset,lilvUris.state__state,nullptr);
  LILV_FOREACH(nodes,j,stateProperties)
  {
      AutoLilvNode propertyNode = lilv_nodes_get(stateProperties,j);

     /*  WHAT NOW? propertyNode contains a blank URI, and I need to get the predicate for each blank node. **
  }

I rummaged through liv's state.c file to see how lilv does it. lilv uses

 SordIter* props = sord_search(model, state_node, 0, 0, 0);

But lilv_world_find_nodes doesn't allow a null predicate, and if lilv has a method for enumerating matching triples, I can't find it.

I feel like I'm missing something embarassingly obvious. :-/

@rerdavies
Copy link
Author

If it's worth asking about, it's worth making a pull request. I have just made a pull request to expose the information I need.

The pull request adds a new method, lilv_state_emit_properties that enumerates properties in the state. I've tried to model it as much as possible, stylistically, on lilv_state_emit_port_values. All told, about a dozen new lines of code (not including docs, declarations and test cases).

If there are any code-review issues, let me know. I'm more than happy to modify the pull request.

@drobilla
Copy link
Collaborator

but not currently using the lilv methods for preset management and state. That may have been a mistake, but I'm too far along to easily correct that problem.

I don't think it was, if you aren't loading and restoring state from instances, the lilv state API probably isn't the tool for the job.

So I tried to read the state values using lilv_world_find_nodes queries.

This seems like the right thing here to me, but...

But I can't find a way to enumerate the predicates in the resulting blank-node triples.

It seems like the API isn't up to the task. In a future version I think the world model should just be exposed directly so the lilv API can't get in the way, but that doesn't help now. You're right that the thing you want to do here is iterate over triples, but unfortunately that's missing from the API. You're not missing anything, the API just wasn't designed to be an all-purpose preset investigator, it was designed to save and restore state.

I suppose an easy stop-gap way to make this possible without adding a whole statement API would be to add something like lilv_world_get_predicates(world, subject).

It would be possible to just parse the files and do all of this yourself, although that's not very convenient. For this specific case, I'm tempted to write it off as "don't do that" (i.e., either use the lilv state API or don't, it's not designed to support half-implementing it yourself for some reason), but since it's generally important for the host to be able to read data from the world, I think it would be a good idea to add some way to do this regardless.

@drobilla
Copy link
Collaborator

Your solution in the PR might be fine, though. It seems elegant to expose state properties just like port values, but I need to think a bit about the potential problems of exposing details about the in-memory LilvState representation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants