bool SocketWriter::write(const LV2_Atom* msg) { sratom_write(_sratom, &_map.urid_unmap_feature()->urid_unmap, 0, NULL, NULL, msg->type, msg->size, LV2_ATOM_BODY_CONST(msg)); serd_writer_finish(_writer); return true; }
SRATOM_API int sratom_write(Sratom* sratom, LV2_URID_Unmap* unmap, uint32_t flags, const SerdNode* subject, const SerdNode* predicate, uint32_t type_urid, uint32_t size, const void* body) { const char* const type = unmap->unmap(unmap->handle, type_urid); uint8_t idbuf[12] = "b0000000000"; SerdNode id = serd_node_from_string(SERD_BLANK, idbuf); uint8_t nodebuf[12] = "b0000000000"; SerdNode node = serd_node_from_string(SERD_BLANK, nodebuf); SerdNode object = SERD_NODE_NULL; SerdNode datatype = SERD_NODE_NULL; SerdNode language = SERD_NODE_NULL; bool new_node = false; if (type_urid == 0 && size == 0) { object = serd_node_from_string(SERD_URI, USTR(NS_RDF "nil")); } else if (type_urid == sratom->forge.String) { object = serd_node_from_string(SERD_LITERAL, (const uint8_t*)body); } else if (type_urid == sratom->forge.Chunk) { datatype = serd_node_from_string(SERD_URI, NS_XSD "base64Binary"); object = serd_node_new_blob(body, size, true); new_node = true; } else if (type_urid == sratom->forge.Literal) { const LV2_Atom_Literal_Body* lit = (const LV2_Atom_Literal_Body*)body; const uint8_t* str = USTR(lit + 1); object = serd_node_from_string(SERD_LITERAL, str); if (lit->datatype) { datatype = serd_node_from_string( SERD_URI, USTR(unmap->unmap(unmap->handle, lit->datatype))); } else if (lit->lang) { const char* lang = unmap->unmap(unmap->handle, lit->lang); const char* prefix = "http://lexvo.org/id/iso639-3/"; const size_t prefix_len = strlen(prefix); if (lang && !strncmp(lang, prefix, prefix_len)) { language = serd_node_from_string( SERD_LITERAL, USTR(lang + prefix_len)); } else { fprintf(stderr, "Unknown language URID %d\n", lit->lang); } } } else if (type_urid == sratom->forge.URID) { const uint32_t urid = *(const uint32_t*)body; const uint8_t* str = USTR(unmap->unmap(unmap->handle, urid)); object = serd_node_from_string(SERD_URI, str); } else if (type_urid == sratom->forge.Path) { const uint8_t* str = USTR(body); if (path_is_absolute((const char*)str)) { new_node = true; object = serd_node_new_file_uri(str, NULL, NULL, false); } else { SerdURI base_uri = SERD_URI_NULL; if (!sratom->base_uri.buf || strncmp((const char*)sratom->base_uri.buf, "file://", 7)) { fprintf(stderr, "warning: Relative path but base is not a file URI.\n"); fprintf(stderr, "warning: Writing ambiguous atom:Path literal.\n"); object = serd_node_from_string(SERD_LITERAL, str); datatype = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__Path)); } else { if (sratom->base_uri.buf) { serd_uri_parse(sratom->base_uri.buf, &base_uri); } new_node = true; SerdNode rel = serd_node_new_file_uri(str, NULL, NULL, false); object = serd_node_new_uri_from_node(&rel, &base_uri, NULL); serd_node_free(&rel); } } } else if (type_urid == sratom->forge.URI) { const uint8_t* str = USTR(body); object = serd_node_from_string(SERD_URI, str); } else if (type_urid == sratom->forge.Int) { new_node = true; object = serd_node_new_integer(*(const int32_t*)body); datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers) ? NS_XSD "integer" : NS_XSD "int"); } else if (type_urid == sratom->forge.Long) { new_node = true; object = serd_node_new_integer(*(const int64_t*)body); datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers) ? NS_XSD "integer" : NS_XSD "long"); } else if (type_urid == sratom->forge.Float) { new_node = true; object = serd_node_new_decimal(*(const float*)body, 8); datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers) ? NS_XSD "decimal" : NS_XSD "float"); } else if (type_urid == sratom->forge.Double) { new_node = true; object = serd_node_new_decimal(*(const double*)body, 16); datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers) ? NS_XSD "decimal" : NS_XSD "double"); } else if (type_urid == sratom->forge.Bool) { const int32_t val = *(const int32_t*)body; datatype = serd_node_from_string(SERD_URI, NS_XSD "boolean"); object = serd_node_from_string(SERD_LITERAL, USTR(val ? "true" : "false")); } else if (type_urid == sratom->midi_MidiEvent) { new_node = true; datatype = serd_node_from_string(SERD_URI, USTR(LV2_MIDI__MidiEvent)); uint8_t* str = (uint8_t*)calloc(size * 2 + 1, 1); for (uint32_t i = 0; i < size; ++i) { snprintf((char*)str + (2 * i), size * 2 + 1, "%02X", (unsigned)(uint8_t)*((const uint8_t*)body + i)); } object = serd_node_from_string(SERD_LITERAL, USTR(str)); } else if (type_urid == sratom->atom_Event) { const LV2_Atom_Event* ev = (const LV2_Atom_Event*)body; gensym(&id, 'e', sratom->next_id++); start_object(sratom, &flags, subject, predicate, &id, NULL); // TODO: beat time SerdNode time = serd_node_new_integer(ev->time.frames); SerdNode p = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__frameTime)); datatype = serd_node_from_string(SERD_URI, NS_XSD "decimal"); sratom->write_statement(sratom->handle, SERD_ANON_CONT, NULL, &id, &p, &time, &datatype, &language); serd_node_free(&time); p = serd_node_from_string(SERD_URI, NS_RDF "value"); sratom_write(sratom, unmap, SERD_ANON_CONT, &id, &p, ev->body.type, ev->body.size, LV2_ATOM_BODY(&ev->body)); if (sratom->end_anon) { sratom->end_anon(sratom->handle, &id); } } else if (type_urid == sratom->forge.Tuple) { gensym(&id, 't', sratom->next_id++); start_object(sratom, &flags, subject, predicate, &id, type); SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); flags |= SERD_LIST_O_BEGIN; LV2_ATOM_TUPLE_BODY_FOREACH(body, size, i) { list_append(sratom, unmap, &flags, &id, &p, &node, i->size, i->type, LV2_ATOM_BODY(i)); }
static int lilv_state_write(LilvWorld* world, LV2_URID_Map* map, LV2_URID_Unmap* unmap, const LilvState* state, SerdWriter* writer, const char* uri, const char* dir) { SerdNode lv2_appliesTo = serd_node_from_string( SERD_CURIE, USTR("lv2:appliesTo")); const SerdNode* plugin_uri = sord_node_to_serd_node( state->plugin_uri->node); SerdNode subject = serd_node_from_string(SERD_URI, USTR(uri ? uri : "")); // <subject> a pset:Preset SerdNode p = serd_node_from_string(SERD_URI, USTR(LILV_NS_RDF "type")); SerdNode o = serd_node_from_string(SERD_URI, USTR(LV2_PRESETS__Preset)); serd_writer_write_statement(writer, 0, NULL, &subject, &p, &o, NULL, NULL); // <subject> lv2:appliesTo <http://example.org/plugin> serd_writer_write_statement(writer, 0, NULL, &subject, &lv2_appliesTo, plugin_uri, NULL, NULL); // <subject> rdfs:label label if (state->label) { p = serd_node_from_string(SERD_URI, USTR(LILV_NS_RDFS "label")); o = serd_node_from_string(SERD_LITERAL, USTR(state->label)); serd_writer_write_statement(writer, 0, NULL, &subject, &p, &o, NULL, NULL); } SerdEnv* env = serd_writer_get_env(writer); const SerdNode* base = serd_env_get_base_uri(env, NULL); Sratom* sratom = sratom_new(map); sratom_set_sink(sratom, (const char*)base->buf, (SerdStatementSink)serd_writer_write_statement, (SerdEndSink)serd_writer_end_anon, writer); // Write port values as pretty numbers sratom_set_pretty_numbers(sratom, true); // Write port values for (uint32_t i = 0; i < state->num_values; ++i) { PortValue* const value = &state->values[i]; const SerdNode port = serd_node_from_string( SERD_BLANK, USTR(value->symbol)); // <> lv2:port _:symbol p = serd_node_from_string(SERD_URI, USTR(LV2_CORE__port)); serd_writer_write_statement(writer, SERD_ANON_O_BEGIN, NULL, &subject, &p, &port, NULL, NULL); // _:symbol lv2:symbol "symbol" p = serd_node_from_string(SERD_URI, USTR(LV2_CORE__symbol)); o = serd_node_from_string(SERD_LITERAL, USTR(value->symbol)); serd_writer_write_statement(writer, SERD_ANON_CONT, NULL, &port, &p, &o, NULL, NULL); // _:symbol pset:value value p = serd_node_from_string(SERD_URI, USTR(LV2_PRESETS__value)); sratom_write(sratom, unmap, SERD_ANON_CONT, &port, &p, value->type, value->size, value->value); serd_writer_end_anon(writer, &port); } // Write property values with precise types sratom_set_pretty_numbers(sratom, false); // Write properties const SerdNode state_node = serd_node_from_string(SERD_BLANK, USTR("2state")); if (state->num_props > 0) { p = serd_node_from_string(SERD_URI, USTR(LV2_STATE__state)); serd_writer_write_statement(writer, SERD_ANON_O_BEGIN, NULL, &subject, &p, &state_node, NULL, NULL); } for (uint32_t i = 0; i < state->num_props; ++i) { Property* prop = &state->props[i]; const char* key = unmap->unmap(unmap->handle, prop->key); p = serd_node_from_string(SERD_URI, USTR(key)); if (prop->type == state->atom_Path && !dir) { const char* path = (const char*)prop->value; const char* abs_path = lilv_state_rel2abs(state, path); sratom_write(sratom, unmap, SERD_ANON_CONT, &state_node, &p, prop->type, strlen(abs_path) + 1, abs_path); } else { sratom_write(sratom, unmap, SERD_ANON_CONT, &state_node, &p, prop->type, prop->size, prop->value); } } if (state->num_props > 0) { serd_writer_end_anon(writer, &state_node); } sratom_free(sratom); return 0; }