LILV_API LilvState* lilv_state_new_from_string(LilvWorld* world, const LV2_URID_Map* map, const char* str) { if (!str) { return NULL; } SerdNode base = SERD_NODE_NULL; SerdEnv* env = serd_env_new(&base); SordModel* model = sord_new(world->world, SORD_SPO|SORD_OPS, false); SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); set_prefixes(env); serd_reader_read_string(reader, USTR(str)); SordNode* o = sord_new_uri(world->world, USTR(LV2_PRESETS__Preset)); SordNode* s = sord_get(model, NULL, world->uris.rdf_a, o, NULL); LilvState* state = new_state_from_model(world, map, model, s, NULL); sord_node_free(world->world, s); sord_node_free(world->world, o); serd_reader_free(reader); sord_free(model); serd_env_free(env); return state; }
SordNode* sord_new_relative_uri(SordWorld* world, const uint8_t* str, const uint8_t* base_str) { if (serd_uri_string_has_scheme(str)) { return sord_new_uri(world, str); } SerdURI buri = SERD_URI_NULL; SerdNode base = serd_node_new_uri_from_string(base_str, NULL, &buri); SerdNode node = serd_node_new_uri_from_string(str, &buri, NULL); SordNode* ret = sord_new_uri_counted( world, node.buf, node.n_bytes, node.n_chars, false); serd_node_free(&base); return ret; }
/** Note that if `type` is numeric or boolean, the returned value is corrupt * until lilv_node_set_numerics_from_string is called. It is not * automatically called from here to avoid overhead and imprecision when the * exact string value is known. */ LilvNode* lilv_node_new(LilvWorld* world, LilvNodeType type, const char* str) { LilvNode* val = (LilvNode*)malloc(sizeof(LilvNode)); val->world = world; val->type = type; const uint8_t* ustr = (const uint8_t*)str; switch (type) { case LILV_VALUE_URI: val->node = sord_new_uri(world->world, ustr); break; case LILV_VALUE_BLANK: val->node = sord_new_blank(world->world, ustr); break; case LILV_VALUE_STRING: val->node = sord_new_literal(world->world, NULL, ustr, NULL); break; case LILV_VALUE_INT: val->node = sord_new_literal( world->world, world->uris.xsd_integer, ustr, NULL); break; case LILV_VALUE_FLOAT: val->node = sord_new_literal( world->world, world->uris.xsd_decimal, ustr, NULL); break; case LILV_VALUE_BOOL: val->node = sord_new_literal( world->world, world->uris.xsd_boolean, ustr, NULL); break; case LILV_VALUE_BLOB: val->node = sord_new_literal( world->world, world->uris.xsd_base64Binary, ustr, NULL); break; } if (!val->node) { free(val); return NULL; } return val; }
static LilvState* new_state_from_model(LilvWorld* world, LV2_URID_Map* map, SordModel* model, const SordNode* node, const char* dir) { LilvState* const state = (LilvState*)malloc(sizeof(LilvState)); memset(state, '\0', sizeof(LilvState)); state->dir = lilv_strdup(dir); state->atom_Path = map->map(map->handle, LV2_ATOM__Path); // Get the plugin URI this state applies to SordIter* i = sord_search(model, node, world->uris.lv2_appliesTo, 0, 0); if (i) { const SordNode* object = sord_iter_get_node(i, SORD_OBJECT); const SordNode* graph = sord_iter_get_node(i, SORD_GRAPH); state->plugin_uri = lilv_node_new_from_node(world, object); if (!state->dir && graph) { state->dir = lilv_strdup((const char*)sord_node_get_string(graph)); } sord_iter_free(i); } else if (sord_ask(model, node, world->uris.rdf_a, world->uris.lv2_Plugin, 0)) { // Loading plugin description as state (default state) state->plugin_uri = lilv_node_new_from_node(world, node); } else { LILV_ERRORF("State %s missing lv2:appliesTo property\n", sord_node_get_string(node)); } // Get the state label i = sord_search(model, node, world->uris.rdfs_label, NULL, NULL); if (i) { const SordNode* object = sord_iter_get_node(i, SORD_OBJECT); const SordNode* graph = sord_iter_get_node(i, SORD_GRAPH); state->label = lilv_strdup((const char*)sord_node_get_string(object)); if (!state->dir) { state->dir = lilv_strdup((const char*)sord_node_get_string(graph)); } sord_iter_free(i); } Sratom* sratom = sratom_new(map); SerdChunk chunk = { NULL, 0 }; LV2_Atom_Forge forge; lv2_atom_forge_init(&forge, map); lv2_atom_forge_set_sink( &forge, sratom_forge_sink, sratom_forge_deref, &chunk); // Get port values SordIter* ports = sord_search(model, node, world->uris.lv2_port, 0, 0); FOREACH_MATCH(ports) { const SordNode* port = sord_iter_get_node(ports, SORD_OBJECT); SordNode* label = sord_get(model, port, world->uris.rdfs_label, 0, 0); SordNode* symbol = sord_get(model, port, world->uris.lv2_symbol, 0, 0); SordNode* value = sord_get(model, port, world->uris.pset_value, 0, 0); if (!value) { value = sord_get(model, port, world->uris.lv2_default, 0, 0); } if (!symbol) { LILV_ERRORF("State `%s' port missing symbol.\n", sord_node_get_string(node)); } else if (value) { chunk.len = 0; sratom_read(sratom, &forge, world->world, model, value); LV2_Atom* atom = (LV2_Atom*)chunk.buf; append_port_value(state, (const char*)sord_node_get_string(symbol), LV2_ATOM_BODY(atom), atom->size, atom->type); if (label) { lilv_state_set_label(state, (const char*)sord_node_get_string(label)); } } sord_node_free(world->world, value); sord_node_free(world->world, symbol); sord_node_free(world->world, label); } sord_iter_free(ports); // Get properties SordNode* statep = sord_new_uri(world->world, USTR(LV2_STATE__state)); SordNode* state_node = sord_get(model, node, statep, NULL, NULL); if (state_node) { SordIter* props = sord_search(model, state_node, 0, 0, 0); FOREACH_MATCH(props) { const SordNode* p = sord_iter_get_node(props, SORD_PREDICATE); const SordNode* o = sord_iter_get_node(props, SORD_OBJECT); chunk.len = 0; lv2_atom_forge_set_sink( &forge, sratom_forge_sink, sratom_forge_deref, &chunk); sratom_read(sratom, &forge, world->world, model, o); LV2_Atom* atom = (LV2_Atom*)chunk.buf; uint32_t flags = LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE; Property prop = { NULL, 0, 0, 0, flags }; prop.key = map->map(map->handle, (const char*)sord_node_get_string(p)); prop.type = atom->type; prop.size = atom->size; prop.value = malloc(atom->size); memcpy(prop.value, LV2_ATOM_BODY(atom), atom->size); if (atom->type == forge.Path) { prop.flags = LV2_STATE_IS_PORTABLE; } if (prop.value) { state->props = (Property*)realloc( state->props, (++state->num_props) * sizeof(Property)); state->props[state->num_props - 1] = prop; } } sord_iter_free(props); } sord_node_free(world->world, state_node); sord_node_free(world->world, statep); free((void*)chunk.buf); sratom_free(sratom); qsort(state->props, state->num_props, sizeof(Property), property_cmp); qsort(state->values, state->num_values, sizeof(PortValue), value_cmp); return state; }