/* ladspa2lv2 * Copyright (C) 2007 Dave Robillard * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #define U(x) ((const unsigned char*)(x)) #define NS_RDF(x) "http://www.w3.org/1999/02/22-rdf-syntax-ns#" x #define NS_LV2(x) "http://lv2plug.in/ontology#" x #define NS_DOAP(x) "http://usefulinc.com/ns/doap#" x librdf_world* world = NULL; LADSPA_Descriptor* load_ladspa_plugin(const char* lib_path, unsigned long index) { void* const handle = dlopen(lib_path, RTLD_LAZY); if (handle == NULL) return NULL; LADSPA_Descriptor_Function df = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor"); if (df == NULL) { dlclose(handle); return NULL; } LADSPA_Descriptor* const descriptor = (LADSPA_Descriptor*)df(index); return descriptor; } void add_resource(librdf_model* model, librdf_node* subject, const char* predicate_uri, const char* object_uri) { librdf_node* predicate = librdf_new_node_from_uri_string(world, U(predicate_uri)); librdf_node* object = librdf_new_node_from_uri_string(world, U(object_uri)); librdf_statement* triple = librdf_new_statement_from_nodes(world, subject, predicate, object); librdf_model_add_statement(model, triple); //librdf_free_statement(triple); } void add_node(librdf_model* model, librdf_node* subject, const char* predicate_uri, librdf_node* object) { librdf_node* predicate = librdf_new_node_from_uri_string(world, U(predicate_uri)); librdf_statement* triple = librdf_new_statement_from_nodes(world, subject, predicate, object); librdf_model_add_statement(model, triple); //librdf_free_statement(triple); } void add_string(librdf_model* model, librdf_node* subject, const char* predicate_uri, const char* object_string) { librdf_node* predicate = librdf_new_node_from_uri_string(world, U(predicate_uri)); librdf_node* object = librdf_new_node_from_literal(world, U(object_string), NULL, 0); librdf_statement* triple = librdf_new_statement_from_nodes(world, subject, predicate, object); librdf_model_add_statement(model, triple); //librdf_free_statement(triple); } void add_int(librdf_model* model, librdf_node* subject, const char* predicate_uri, int object_int) { static const size_t MAX_LEN = 21; // strlen(2^64) + 1 char object_str[MAX_LEN]; snprintf(object_str, MAX_LEN, "%d", object_int); librdf_uri* type = librdf_new_uri(world, U("http://www.w3.org/2001/XMLSchema#integer")); librdf_node* predicate = librdf_new_node_from_uri_string(world, U(predicate_uri)); librdf_node* object = librdf_new_node_from_typed_literal(world, U(object_str), NULL, type); librdf_statement* triple = librdf_new_statement_from_nodes(world, subject, predicate, object); librdf_model_add_statement(model, triple); //librdf_free_statement(triple); librdf_free_uri(type); } void add_float(librdf_model* model, librdf_node* subject, const char* predicate_uri, float object_float) { static const size_t MAX_LEN = 64; // ? char object_str[MAX_LEN]; snprintf(object_str, MAX_LEN, "%f", object_float); librdf_uri* type = librdf_new_uri(world, U("http://www.w3.org/2001/XMLSchema#decimal")); librdf_node* predicate = librdf_new_node_from_uri_string(world, U(predicate_uri)); librdf_node* object = librdf_new_node_from_typed_literal(world, U(object_str), NULL, type); librdf_statement* triple = librdf_new_statement_from_nodes(world, subject, predicate, object); librdf_model_add_statement(model, triple); //librdf_free_statement(triple); librdf_free_uri(type); } void write_lv2_turtle(LADSPA_Descriptor* descriptor, const char* plugin_uri, const char* filename) { librdf_storage* storage = librdf_new_storage(world, "hashes", NULL, "hash-type='memory'"); librdf_model* model = librdf_new_model(world, storage, NULL); librdf_serializer* serializer = librdf_new_serializer(world, "turtle", NULL, NULL); librdf_node* plugin = librdf_new_node_from_uri_string(world, U(plugin_uri)); // Set up namespaces librdf_serializer_set_namespace(serializer, librdf_new_uri(world, U("http://www.w3.org/1999/02/22-rdf-syntax-ns#")), "rdf"); librdf_serializer_set_namespace(serializer, librdf_new_uri(world, U("http://www.w3.org/2000/01/rdf-schema#")), "rdfs"); librdf_serializer_set_namespace(serializer, librdf_new_uri(world, U("http://www.w3.org/2001/XMLSchema")), "xsd"); librdf_serializer_set_namespace(serializer, librdf_new_uri(world, U("http://usefulinc.com/ns/doap#")), "doap"); librdf_serializer_set_namespace(serializer, librdf_new_uri(world, U("http://xmlns.com/foaf/0.1/")), "foaf"); librdf_serializer_set_namespace(serializer, librdf_new_uri(world, U("http://lv2plug.in/ontology#")), "lv2"); add_resource(model, plugin, NS_RDF("type"), NS_LV2("Plugin")); add_string(model, plugin, NS_DOAP("name"), descriptor->Name); if (LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties)) add_resource(model, plugin, NS_LV2("property"), NS_LV2("hardRTCapable")); for (uint32_t i=0; i < descriptor->PortCount; ++i) { char index_str[32]; snprintf(index_str, (size_t)32, "%u", i); const LADSPA_PortDescriptor port_descriptor = descriptor->PortDescriptors[i]; librdf_node* port_node = librdf_new_node(world); add_node(model, plugin, NS_LV2("port"), port_node); add_int(model, port_node, NS_LV2("index"), (int)i); add_resource(model, port_node, NS_RDF("type"), NS_LV2("Port")); if (LADSPA_IS_PORT_INPUT(port_descriptor)) add_resource(model, port_node, NS_RDF("type"), NS_LV2("InputPort")); else add_resource(model, port_node, NS_RDF("type"), NS_LV2("OutputPort")); if (LADSPA_IS_PORT_AUDIO(port_descriptor)) add_resource(model, port_node, NS_RDF("type"), NS_LV2("ControlPort")); else add_resource(model, port_node, NS_RDF("type"), NS_LV2("AudioPort")); add_string(model, port_node, NS_LV2("name"), descriptor->PortNames[i]); } librdf_serializer_serialize_model_to_file(serializer, filename, NULL, model); } void print_usage() { printf("Usage: ladspa2slv2 /path/to/laddspalib.so ladspa_index lv2_uri\n"); printf("Partially convert a LADSPA plugin to an LV2 plugin.\n"); printf("This utility is for developers, it will not generate a usable\n"); printf("LV2 plugin directly.\n\n"); } int main(int argc, char** argv) { if (argc != 4) { print_usage(); return 1; } const char* const lib_path = argv[1]; const unsigned long index = atol(argv[2]); const char* const uri = argv[3]; world = librdf_new_world(); librdf_world_open(world); LADSPA_Descriptor* descriptor = load_ladspa_plugin(lib_path, index); if (descriptor) { printf("Loaded %s : %lu\n", lib_path, index); write_lv2_turtle(descriptor, uri, "ladspaplugin.ttl"); } else { printf("Failed to load %s : %lu\n", lib_path, index); } librdf_free_world(world); return 0; }