void print_group(const LilvPlugin* p, const LilvNode* group, LilvNode* type, LilvNode* symbol) { printf("\n\tGroup %s:\n", lilv_node_as_string(group)); printf("\t\tType: %s\n", lilv_node_as_string(type)); printf("\t\tSymbol: %s\n", lilv_node_as_string(symbol)); }
/** * List all ports by uri */ void Lv2Lib_ports_of(const char *uri, Lv2Lib * lv2Lib) { const LilvPlugin *plugin = get_livl_plugin(uri, lv2Lib); if (plugin == NULL) { printf("Plugin não informado: %s", uri); return; } uint32_t ports_count = lilv_plugin_get_num_ports(plugin); float * min_values = calloc(ports_count, sizeof(float *)); float * max_values = calloc(ports_count, sizeof(float *)); float * def_values = calloc(ports_count, sizeof(float *)); lilv_plugin_get_port_ranges_float(plugin, min_values, max_values, def_values); for (unsigned int i=0; i<ports_count; i++) { const LilvPort* port = lilv_plugin_get_port_by_index(plugin, i); const LilvNode* port_name_node = lilv_port_get_name(plugin, port); const char* port_name = lilv_node_as_string(port_name_node); printf("%u - Port \"%s\" : %f %f %f\n", i, port_name, min_values[i], max_values[i], def_values[i]); } free(min_values); free(max_values); free(def_values); min_values = NULL; max_values = NULL; def_values = NULL; }
LilvUI* lilv_ui_new(LilvWorld* world, LilvNode* uri, LilvNode* type_uri, LilvNode* binary_uri) { assert(uri); assert(type_uri); assert(binary_uri); LilvUI* ui = (LilvUI*)malloc(sizeof(LilvUI)); ui->world = world; ui->uri = uri; ui->binary_uri = binary_uri; // FIXME: kludge char* bundle = lilv_strdup(lilv_node_as_string(ui->binary_uri)); char* last_slash = strrchr(bundle, '/') + 1; *last_slash = '\0'; ui->bundle_uri = lilv_new_uri(world, bundle); free(bundle); ui->classes = lilv_nodes_new(); zix_tree_insert((ZixTree*)ui->classes, type_uri, NULL); return ui; }
std::string NodeModel::port_label(SharedPtr<const PortModel> port) const { const Raul::Atom& name = port->get_property("http://lv2plug.in/ns/lv2core#name"); if (name.is_valid()) { return name.get_string(); } if (_plugin && _plugin->type() == PluginModel::LV2) { LilvWorld* c_world = _plugin->lilv_world(); const LilvPlugin* c_plugin = _plugin->lilv_plugin(); LilvNode* c_sym = lilv_new_string(c_world, port->symbol().c_str()); const LilvPort* c_port = lilv_plugin_get_port_by_symbol(c_plugin, c_sym); if (c_port) { LilvNode* c_name = lilv_port_get_name(c_plugin, c_port); if (c_name && lilv_node_is_string(c_name)) { std::string ret(lilv_node_as_string(c_name)); lilv_node_free(c_name); return ret; } lilv_node_free(c_name); } } return port->symbol().c_str(); }
Objects instances(World* world, const URISet& types) { LilvNode* rdf_type = lilv_new_uri( world->lilv_world(), LILV_NS_RDF "type"); Objects result; for (const auto& t : types) { LilvNode* type = lilv_new_uri(world->lilv_world(), t.c_str()); LilvNodes* objects = lilv_world_find_nodes( world->lilv_world(), NULL, rdf_type, type); LILV_FOREACH(nodes, o, objects) { const LilvNode* object = lilv_nodes_get(objects, o); if (!lilv_node_is_uri(object)) { continue; } const std::string label = RDFS::label(world, object); result.insert( std::make_pair(label, Raul::URI(lilv_node_as_string(object)))); } lilv_node_free(type); } lilv_node_free(rdf_type); return result; }
String LV2Module::getClassLabel() const { if (const LilvPluginClass* klass = lilv_plugin_get_class (plugin)) if (const LilvNode* node = lilv_plugin_class_get_label (klass)) return CharPointer_UTF8 (lilv_node_as_string (node)); return String::empty; }
static gchar * gst_lv2_filter_class_get_param_nick (GstLV2FilterClass * klass, const LilvPort * port) { LilvPlugin *lv2plugin = klass->plugin; return g_strdup (lilv_node_as_string (lilv_port_get_name (lv2plugin, port))); }
LILV_FOREACH(plugins, i, list) { const LilvPlugin* p = lilv_plugins_get(list, i); if (show_names) { LilvNode* n = lilv_plugin_get_name(p); printf("%s\n", lilv_node_as_string(n)); lilv_node_free(n); } else { printf("%s\n", lilv_node_as_uri(lilv_plugin_get_uri(p))); } }
String LV2Module::getAuthorName() const { if (LilvNode* node = lilv_plugin_get_author_name (plugin)) { String name (CharPointer_UTF8 (lilv_node_as_string (node))); lilv_node_free (node); return name; } return String::empty; }
const String LV2Module::getPortName (uint32 index) const { if (const LilvPort* port = getPort (index)) { LilvNode* node = lilv_port_get_name (plugin, port); const String name = CharPointer_UTF8 (lilv_node_as_string (node)); lilv_node_free (node); return name; } return String::empty; }
URISet range(World* world, const LilvNode* prop, bool recursive) { LilvNode* rdfs_range = lilv_new_uri( world->lilv_world(), LILV_NS_RDFS "range"); LilvNodes* nodes = lilv_world_find_nodes( world->lilv_world(), prop, rdfs_range, NULL); URISet ranges; LILV_FOREACH(nodes, n, nodes) { ranges.insert(Raul::URI(lilv_node_as_string(lilv_nodes_get(nodes, n)))); }
static int add_state_to_manifest(const LilvNode* plugin_uri, const char* manifest_path, const char* state_uri, const char* state_path) { FILE* fd = fopen((char*)manifest_path, "a"); if (!fd) { LILV_ERRORF("Failed to open %s (%s)\n", manifest_path, strerror(errno)); return 4; } lilv_flock(fd, true); SerdNode file = serd_node_new_file_uri(USTR(state_path), 0, 0, 0); SerdNode manifest = serd_node_new_file_uri(USTR(manifest_path), 0, 0, 0); SerdEnv* env = NULL; SerdWriter* writer = ttl_file_writer(fd, &manifest, &env); if (!state_uri) { state_uri = (const char*)file.buf; } // <state> a pset:Preset SerdNode s = serd_node_from_string(SERD_URI, USTR(state_uri)); 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, &s, &p, &o, NULL, NULL); // <state> rdfs:seeAlso <file> p = serd_node_from_string(SERD_URI, USTR(LILV_NS_RDFS "seeAlso")); serd_writer_write_statement(writer, 0, NULL, &s, &p, &file, NULL, NULL); // <state> lv2:appliesTo <plugin> p = serd_node_from_string(SERD_URI, USTR(LV2_CORE__appliesTo)); o = serd_node_from_string( SERD_URI, USTR(lilv_node_as_string(plugin_uri))); serd_writer_write_statement(writer, 0, NULL, &s, &p, &o, NULL, NULL); serd_node_free(&file); serd_node_free(&manifest); serd_writer_free(writer); serd_env_free(env); lilv_flock(fd, false); fclose(fd); return 0; }
static gchar * gst_lv2_filter_class_get_param_name (GstLV2FilterClass * klass, const LilvPort * port) { LilvPlugin *lv2plugin = klass->plugin; gchar *ret; ret = g_strdup (lilv_node_as_string (lilv_port_get_symbol (lv2plugin, port))); /* this is the same thing that param_spec_* will do */ g_strcanon (ret, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-'); /* satisfy glib2 (argname[0] must be [A-Za-z]) */ if (!((ret[0] >= 'a' && ret[0] <= 'z') || (ret[0] >= 'A' && ret[0] <= 'Z'))) { gchar *tempstr = ret; ret = g_strconcat ("param-", ret, NULL); g_free (tempstr); } /* check for duplicate property names */ if (g_object_class_find_property (G_OBJECT_CLASS (klass), ret)) { gint n = 1; gchar *nret = g_strdup_printf ("%s-%d", ret, n++); while (g_object_class_find_property (G_OBJECT_CLASS (klass), nret)) { g_free (nret); nret = g_strdup_printf ("%s-%d", ret, n++); } g_free (ret); ret = nret; } GST_DEBUG ("built property name '%s' from port name '%s'", ret, lilv_node_as_string (lilv_port_get_symbol (lv2plugin, port))); return ret; }
bool LV2EffectsModule::AutoRegisterPlugins(PluginManagerInterface & pm) { EffectManager& em = EffectManager::Get(); #ifdef EFFECT_CATEGORIES // Add all LV2 categories and their relationships LilvPluginClasses classes = Lilv_world_get_plugin_classes(gWorld); for (unsigned index = 0; index < Lilv_plugin_classes_size(classes);++index){ LilvPluginClass c = Lilv_plugin_classes_get_at(classes, index); em.AddCategory(wxString::FromUTF8(lilv_node_as_uri(Lilv_plugin_class_get_uri(c))), wxString::FromUTF8(lilv_node_as_string(Lilv_plugin_class_get_label(c)))); } for (unsigned index = 0; index < Lilv_plugin_classes_size(classes);++index){ LilvPluginClass c = Lilv_plugin_classes_get_at(classes, index); LilvPluginClasses ch = Lilv_plugin_class_get_children(c); EffectCategory* pCat = em.LookupCategory(wxString::FromUTF8(lilv_node_as_uri(Lilv_plugin_class_get_uri(c)))); for (unsigned j = 0; j < Lilv_plugin_classes_size(ch); ++j) { EffectCategory* chCat = em.LookupCategory(wxString::FromUTF8(lilv_node_as_uri(Lilv_plugin_class_get_uri(Lilv_plugin_classes_get_at(ch, j))))); if (chCat && pCat) { em.AddCategoryParent(chCat, pCat); } } } #endif // Retrieve data about all plugins const LilvPlugins *plugs = lilv_world_get_all_plugins(gWorld); // Iterate over all plugins and register them with the EffectManager LILV_FOREACH(plugins, i, plugs) { const LilvPlugin *plug = lilv_plugins_get(plugs, i); std::set<wxString> cats; cats.insert(wxString::FromUTF8(lilv_node_as_uri(lilv_plugin_class_get_uri(lilv_plugin_get_class(plug))))); LV2Effect *effect = new LV2Effect(plug, cats); if (effect->IsValid()) { em.RegisterEffect(this, effect); } else { delete effect; } } return true; }
LILV_API LilvState* lilv_state_new_from_world(LilvWorld* world, const LV2_URID_Map* map, const LilvNode* node) { if (!lilv_node_is_uri(node) && !lilv_node_is_blank(node)) { LILV_ERRORF("Subject `%s' is not a URI or blank node.\n", lilv_node_as_string(node)); return NULL; } LilvState* state = new_state_from_model( world, map, world->model, node->node, NULL); return state; }
LILV_API LilvState* lilv_state_new_from_file(LilvWorld* world, const LV2_URID_Map* map, const LilvNode* subject, const char* path) { if (subject && !lilv_node_is_uri(subject) && !lilv_node_is_blank(subject)) { LILV_ERRORF("Subject `%s' is not a URI or blank node.\n", lilv_node_as_string(subject)); return NULL; } uint8_t* abs_path = (uint8_t*)lilv_path_absolute(path); SerdNode node = serd_node_new_file_uri(abs_path, NULL, NULL, 0); SerdEnv* env = serd_env_new(&node); SordModel* model = sord_new(world->world, SORD_SPO, false); SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); serd_reader_read_file(reader, node.buf); SordNode* subject_node = (subject) ? subject->node : sord_node_from_serd_node(world->world, env, &node, NULL, NULL); char* dirname = lilv_dirname(path); char* real_path = lilv_realpath(dirname); LilvState* state = new_state_from_model( world, map, model, subject_node, real_path); free(dirname); free(real_path); serd_node_free(&node); free(abs_path); serd_reader_free(reader); sord_free(model); serd_env_free(env); return state; }
static double bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size) { URITable uri_table; uri_table_init(&uri_table); LV2_URID_Map map = { &uri_table, uri_table_map }; LV2_Feature map_feature = { LV2_URID_MAP_URI, &map }; LV2_URID_Unmap unmap = { &uri_table, uri_table_unmap }; LV2_Feature unmap_feature = { LV2_URID_UNMAP_URI, &unmap }; const LV2_Feature* features[] = { &map_feature, &unmap_feature, NULL }; float* const buf = (float*)calloc(block_size * 2, sizeof(float)); float* const in = buf; float* const out = buf + block_size; if (!buf) { fprintf(stderr, "Out of memory\n"); return 0.0; } LV2_Atom_Sequence seq = { { sizeof(LV2_Atom_Sequence_Body), uri_table_map(&uri_table, LV2_ATOM__Sequence) }, { 0, 0 } }; const char* uri = lilv_node_as_string(lilv_plugin_get_uri(p)); LilvNodes* required = lilv_plugin_get_required_features(p); LILV_FOREACH(nodes, i, required) { const LilvNode* feature = lilv_nodes_get(required, i); if (!lilv_node_equals(feature, urid_map)) { fprintf(stderr, "<%s> requires feature <%s>, skipping\n", uri, lilv_node_as_uri(feature)); free(buf); uri_table_destroy(&uri_table); return 0.0; } } LilvInstance* instance = lilv_plugin_instantiate(p, 48000.0, features); if (!instance) { fprintf(stderr, "Failed to instantiate <%s>\n", lilv_node_as_uri(lilv_plugin_get_uri(p))); free(buf); uri_table_destroy(&uri_table); return 0.0; } float* controls = (float*)calloc( lilv_plugin_get_num_ports(p), sizeof(float)); lilv_plugin_get_port_ranges_float(p, NULL, NULL, controls); const uint32_t n_ports = lilv_plugin_get_num_ports(p); for (uint32_t index = 0; index < n_ports; ++index) { const LilvPort* port = lilv_plugin_get_port_by_index(p, index); if (lilv_port_is_a(p, port, lv2_ControlPort)) { lilv_instance_connect_port(instance, index, &controls[index]); } else if (lilv_port_is_a(p, port, lv2_AudioPort) || lilv_port_is_a(p, port, lv2_CVPort)) { if (lilv_port_is_a(p, port, lv2_InputPort)) { lilv_instance_connect_port(instance, index, in); } else if (lilv_port_is_a(p, port, lv2_OutputPort)) { lilv_instance_connect_port(instance, index, out); } else { fprintf(stderr, "<%s> port %d neither input nor output, skipping\n", uri, index); lilv_instance_free(instance); free(buf); free(controls); uri_table_destroy(&uri_table); return 0.0; } } else if (lilv_port_is_a(p, port, atom_AtomPort)) { lilv_instance_connect_port(instance, index, &seq); } else { fprintf(stderr, "<%s> port %d has unknown type, skipping\n", uri, index); lilv_instance_free(instance); free(buf); free(controls); uri_table_destroy(&uri_table); return 0.0; } } lilv_instance_activate(instance); struct timespec ts = bench_start(); for (uint32_t i = 0; i < (sample_count / block_size); ++i) { lilv_instance_run(instance, block_size); } const double elapsed = bench_end(&ts); lilv_instance_deactivate(instance); lilv_instance_free(instance); uri_table_destroy(&uri_table); if (full_output) { printf("%d %d ", block_size, sample_count); } printf("%lf %s\n", elapsed, uri); free(buf); free(controls); return elapsed; }
Lv2Plugin *Lv2PluginCache::getPlugin(const char *uri, const char *preset, Lv2State *state) { // create a unique key for uri/preset/state std::string keyString(uri); if(preset) { keyString.append(":"); keyString.append(preset); } std::size_t hash = std::hash<std::string>()(keyString); if(state) { hash = hash ^ (state->getHash() << 1); } // count tells how many instances of this type of plugin int count = ++instanceCount[hash]; // return cached plugin instance if available int key = hash + count; Lv2Plugin *cachedPlugin = findObject(key); if(cachedPlugin) { cachedPlugin->restore(); return cachedPlugin; } // look in cache for plugin type by uri std::string uriString(uri); const LilvPlugin *lilvPlugin = pluginMap[uriString]; if(!lilvPlugin) { // find lv2 plugin in lilv LilvNode *lilvUri = lilv_new_uri(world, uri); lilvPlugin = lilv_plugins_get_by_uri(plugins, lilvUri); lilv_node_free(lilvUri); if(!lilvPlugin) { throw std::logic_error(std::string("Plugin is not installed on this system: ") + uriString); } // check that required features are supported LilvNodes* features = lilv_plugin_get_required_features(lilvPlugin); for (LilvIter* f = lilv_nodes_begin(features); !lilv_nodes_is_end(features, f); f = lilv_nodes_next(features, f)) { const char* featureUri = lilv_node_as_uri(lilv_nodes_get(features, f)); if(!supported[featureUri]) { throw std::logic_error(std::string("Plugin ") + uriString + " requires unsupported feature: " + featureUri); } } lilv_nodes_free(features); pluginMap[uriString] = lilvPlugin; } // create worker if required Lv2Worker *worker = 0; if (lilv_plugin_has_feature(lilvPlugin, lv2Constants.lv2WorkerSchedule) && lilv_plugin_has_extension_data(lilvPlugin, lv2Constants.lv2WorkerInterface)) { worker = new Lv2Worker(); ((LV2_Worker_Schedule*)lv2Features[5]->data)->handle = worker; } // instantiate LilvInstance *instance = lilv_plugin_instantiate(lilvPlugin, sampleRate, lv2Features); // connect worker with plugin instance if(worker) { worker->setInstance(instance); } // create plugin object Lv2Plugin *plugin = new Lv2Plugin(lilvPlugin, instance, lv2Constants, worker); // restore baseline default state LilvState *defaultState = lilv_state_new_from_world(world, &map, lilv_plugin_get_uri(lilvPlugin)); lilv_state_restore(defaultState, instance, setPortValue, plugin, 0, lv2Features); // find and restore preset if(preset) { LilvNodes* presets = lilv_plugin_get_related(lilvPlugin, lv2Constants.lv2Presets); LilvNode *myPreset = 0; LILV_FOREACH(nodes, i, presets) { const LilvNode* presetNode = lilv_nodes_get(presets, i); lilv_world_load_resource(world, presetNode); LilvNodes* labels = lilv_world_find_nodes(world, presetNode, lv2Constants.lv2RdfsLabel, NULL); if (labels) { const LilvNode* label = lilv_nodes_get_first(labels); const char *labelString = lilv_node_as_string(label); // TODO: free? if(!strcmp(labelString, preset)) { myPreset = lilv_node_duplicate(presetNode); } lilv_nodes_free(labels); } } lilv_nodes_free(presets); if(myPreset) { LilvState* presetState = lilv_state_new_from_world(world, &map, myPreset); lilv_state_restore(presetState, instance, setPortValue, plugin, 0, NULL); // lilv_state_free(state); // TODO } else { throw std::logic_error(std::string("Plugin ") + uriString + " has no such preset: " + preset); } } // restore state else if(state) { // TODO: what if state is requested on a plugin that doesn't support?
wxString LV2Effect::GetString(const LilvNode *node) { return wxString::FromUTF8(lilv_node_as_string(node)); }
static GParamSpec * gst_lv2_filter_class_get_param_spec (GstLV2FilterClass * klass, gint portnum) { LilvPlugin *lv2plugin = klass->plugin; const LilvPort *port = lilv_plugin_get_port_by_index (lv2plugin, portnum); LilvNode *lv2def, *lv2min, *lv2max; GParamSpec *ret; gchar *name, *nick; gint perms; gfloat lower = 0.0f, upper = 1.0f, def = 0.0f; nick = gst_lv2_filter_class_get_param_nick (klass, port); name = gst_lv2_filter_class_get_param_name (klass, port); GST_DEBUG ("%s trying port %s : %s", lilv_node_as_string (lilv_plugin_get_uri (lv2plugin)), name, nick); perms = G_PARAM_READABLE; if (lilv_port_is_a (lv2plugin, port, input_class)) perms |= G_PARAM_WRITABLE | G_PARAM_CONSTRUCT; if (lilv_port_is_a (lv2plugin, port, control_class)) perms |= GST_PARAM_CONTROLLABLE; if (lilv_port_has_property (lv2plugin, port, toggled_prop)) { ret = g_param_spec_boolean (name, nick, nick, FALSE, perms); goto done; } lilv_port_get_range (lv2plugin, port, &lv2def, &lv2min, &lv2max); if (lv2def) def = lilv_node_as_float (lv2def); if (lv2min) lower = lilv_node_as_float (lv2min); if (lv2max) upper = lilv_node_as_float (lv2max); lilv_node_free (lv2def); lilv_node_free (lv2min); lilv_node_free (lv2max); if (def < lower) { GST_WARNING ("%s has lower bound %f > default %f", lilv_node_as_string (lilv_plugin_get_uri (lv2plugin)), lower, def); lower = def; } if (def > upper) { GST_WARNING ("%s has upper bound %f < default %f", lilv_node_as_string (lilv_plugin_get_uri (lv2plugin)), upper, def); upper = def; } if (lilv_port_has_property (lv2plugin, port, integer_prop)) ret = g_param_spec_int (name, nick, nick, lower, upper, def, perms); else ret = g_param_spec_float (name, nick, nick, lower, upper, def, perms); done: g_free (name); g_free (nick); return ret; }
LILV_API LilvState* lilv_state_new_from_instance(const LilvPlugin* plugin, LilvInstance* instance, LV2_URID_Map* map, const char* file_dir, const char* copy_dir, const char* link_dir, const char* save_dir, LilvGetPortValueFunc get_value, void* user_data, uint32_t flags, const LV2_Feature *const * features) { const LV2_Feature** sfeatures = NULL; LilvWorld* const world = plugin->world; LilvState* const state = (LilvState*)malloc(sizeof(LilvState)); memset(state, '\0', sizeof(LilvState)); state->plugin_uri = lilv_node_duplicate(lilv_plugin_get_uri(plugin)); state->abs2rel = zix_tree_new(false, abs_cmp, NULL, path_rel_free); state->rel2abs = zix_tree_new(false, rel_cmp, NULL, NULL); state->file_dir = file_dir ? absolute_dir(file_dir) : NULL; state->copy_dir = copy_dir ? absolute_dir(copy_dir) : NULL; state->link_dir = link_dir ? absolute_dir(link_dir) : NULL; state->dir = save_dir ? absolute_dir(save_dir) : NULL; state->atom_Path = map->map(map->handle, LV2_ATOM__Path); LV2_State_Map_Path pmap = { state, abstract_path, absolute_path }; LV2_Feature pmap_feature = { LV2_STATE__mapPath, &pmap }; LV2_State_Make_Path pmake = { state, make_path }; LV2_Feature pmake_feature = { LV2_STATE__makePath, &pmake }; features = sfeatures = add_features(features, &pmap_feature, save_dir ? &pmake_feature : NULL); // Store port values if (get_value) { LilvNode* lv2_ControlPort = lilv_new_uri(world, LILV_URI_CONTROL_PORT); LilvNode* lv2_InputPort = lilv_new_uri(world, LILV_URI_INPUT_PORT); for (uint32_t i = 0; i < plugin->num_ports; ++i) { const LilvPort* const port = plugin->ports[i]; if (lilv_port_is_a(plugin, port, lv2_ControlPort) && lilv_port_is_a(plugin, port, lv2_InputPort)) { uint32_t size, type; const char* sym = lilv_node_as_string(port->symbol); const void* value = get_value(sym, user_data, &size, &type); append_port_value(state, sym, value, size, type); } } lilv_node_free(lv2_ControlPort); lilv_node_free(lv2_InputPort); } // Store properties const LV2_Descriptor* desc = instance->lv2_descriptor; const LV2_State_Interface* iface = (desc->extension_data) ? (LV2_State_Interface*)desc->extension_data(LV2_STATE__interface) : NULL; if (iface) { LV2_State_Status st = iface->save( instance->lv2_handle, store_callback, state, flags, features); if (st) { LILV_ERRORF("Error saving plugin state: %s\n", state_strerror(st)); free(state->props); state->props = NULL; state->num_props = 0; } else { qsort(state->props, state->num_props, sizeof(Property), property_cmp); } } qsort(state->values, state->num_values, sizeof(PortValue), value_cmp); free(sfeatures); return state; }
static void gst_lv2_filter_base_init (gpointer g_class) { GstLV2FilterClass *klass = (GstLV2FilterClass *) g_class; GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); LilvPlugin *lv2plugin; LilvNode *val; /* FIXME Handle channels positionning * GstAudioChannelPosition position = GST_AUDIO_CHANNEL_POSITION_INVALID; */ guint j, in_pad_index = 0, out_pad_index = 0; gchar *longname, *author; lv2plugin = (LilvPlugin *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), descriptor_quark); g_assert (lv2plugin); GST_INFO ("base_init %p, plugin %s", g_class, lilv_node_get_turtle_token (lilv_plugin_get_uri (lv2plugin))); klass->in_group.ports = g_array_new (FALSE, TRUE, sizeof (GstLV2FilterPort)); klass->out_group.ports = g_array_new (FALSE, TRUE, sizeof (GstLV2FilterPort)); klass->control_in_ports = g_array_new (FALSE, TRUE, sizeof (GstLV2FilterPort)); klass->control_out_ports = g_array_new (FALSE, TRUE, sizeof (GstLV2FilterPort)); /* find ports and groups */ for (j = 0; j < lilv_plugin_get_num_ports (lv2plugin); j++) { const LilvPort *port = lilv_plugin_get_port_by_index (lv2plugin, j); const gboolean is_input = lilv_port_is_a (lv2plugin, port, input_class); struct _GstLV2FilterPort desc = { j, 0, }; LilvNodes *lv2group = lilv_port_get (lv2plugin, port, group_pred); if (lv2group) { /* port is part of a group */ const gchar *group_uri = lilv_node_as_uri (lv2group); GstLV2FilterGroup *group = is_input ? &klass->in_group : &klass->out_group; if (group->uri == NULL) { group->uri = g_strdup (group_uri); group->pad = is_input ? in_pad_index++ : out_pad_index++; group->ports = g_array_new (FALSE, TRUE, sizeof (GstLV2FilterPort)); } /* FIXME Handle channels positionning position = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; sub_values = lilv_port_get_value (lv2plugin, port, has_role_pred); if (lilv_nodes_size (sub_values) > 0) { LilvNode *role = lilv_nodes_get_at (sub_values, 0); position = gst_lv2_filter_role_to_position (role); } lilv_nodes_free (sub_values); if (position != GST_AUDIO_CHANNEL_POSITION_INVALID) { desc.position = position; } */ g_array_append_val (group->ports, desc); } else { /* port is not part of a group, or it is part of a group but that group * is illegal so we just ignore it */ if (lilv_port_is_a (lv2plugin, port, audio_class)) { desc.pad = is_input ? in_pad_index++ : out_pad_index++; if (is_input) g_array_append_val (klass->in_group.ports, desc); else g_array_append_val (klass->out_group.ports, desc); } else if (lilv_port_is_a (lv2plugin, port, control_class)) { if (is_input) g_array_append_val (klass->control_in_ports, desc); else g_array_append_val (klass->control_out_ports, desc); } else { /* unknown port type */ GST_INFO ("unhandled port %d", j); continue; } } } gst_lv2_filter_type_class_add_pad_templates (klass); val = lilv_plugin_get_name (lv2plugin); if (val) { longname = g_strdup (lilv_node_as_string (val)); lilv_node_free (val); } else { longname = g_strdup ("no description available"); } val = lilv_plugin_get_author_name (lv2plugin); if (val) { author = g_strdup (lilv_node_as_string (val)); lilv_node_free (val); } else { author = g_strdup ("no author available"); } gst_element_class_set_metadata (element_class, longname, "Filter/Effect/Audio/LV2", longname, author); g_free (longname); g_free (author); klass->plugin = lv2plugin; }
static gboolean gst_lv2_filter_setup (GstAudioFilter * gsp, const GstAudioInfo * info) { GstLV2Filter *self; GstLV2FilterClass *oclass; GstAudioFilterClass *audiofilter_class; gint i; audiofilter_class = GST_AUDIO_FILTER_GET_CLASS (gsp); self = (GstLV2Filter *) gsp; oclass = (GstLV2FilterClass *) audiofilter_class; g_return_val_if_fail (self->activated == FALSE, FALSE); GST_DEBUG_OBJECT (self, "instantiating the plugin at %d Hz", GST_AUDIO_INFO_RATE (info)); if (self->instance) lilv_instance_free (self->instance); if (!(self->instance = lilv_plugin_instantiate (oclass->plugin, GST_AUDIO_INFO_RATE (info), NULL))) goto no_instance; /* connect the control ports */ for (i = 0; i < oclass->control_in_ports->len; i++) lilv_instance_connect_port (self->instance, g_array_index (oclass->control_in_ports, GstLV2FilterPort, i).index, &(self->ports.control.in[i])); for (i = 0; i < oclass->control_out_ports->len; i++) lilv_instance_connect_port (self->instance, g_array_index (oclass->control_out_ports, GstLV2FilterPort, i).index, &(self->ports.control.out[i])); /* FIXME Handle audio channel positionning while negotiating CAPS */ #if 0 /* set input group pad audio channel position */ for (i = 0; i < oclass->in_groups->len; ++i) { group = &g_array_index (oclass->in_groups, GstLV2FilterGroup, i); if (group->has_roles) { if ((positions = gst_lv2_filter_build_positions (group))) { if ((pad = gst_element_get_static_pad (GST_ELEMENT (gsp), lilv_node_as_string (group->symbol)))) { GST_INFO_OBJECT (self, "set audio channel positions on sink pad %s", lilv_node_as_string (group->symbol)); s = gst_caps_get_structure (caps, 0); gst_audio_set_channel_positions (s, positions); gst_object_unref (pad); } g_free (positions); positions = NULL; } } } /* set output group pad audio channel position */ for (i = 0; i < oclass->out_groups->len; ++i) { group = &g_array_index (oclass->out_groups, GstLV2FilterGroup, i); if (group->has_roles) { if ((positions = gst_lv2_filter_build_positions (group))) { if ((pad = gst_element_get_static_pad (GST_ELEMENT (gsp), lilv_node_as_string (group->symbol)))) { GST_INFO_OBJECT (self, "set audio channel positions on src pad %s", lilv_node_as_string (group->symbol)); s = gst_caps_get_structure (caps, 0); gst_audio_set_channel_positions (s, positions); gst_object_unref (pad); } g_free (positions); positions = NULL; } } } #endif lilv_instance_activate (self->instance); self->activated = TRUE; return TRUE; no_instance: { GST_ERROR_OBJECT (gsp, "could not create instance"); return FALSE; } }
Lv2Plugin::Lv2Plugin(const LilvPlugin *plugin, LilvInstance *instance, const Lv2Constants &uris, Lv2Worker *worker) : plugin(plugin), instance(instance), midiOutputCount(0), controlConnections(4), newControlMappingsQueue(16), worker(worker) { // audio inputs audioInputCount = lilv_plugin_get_num_ports_of_class(plugin, uris.lv2AudioPort, uris.lv2InputPort, 0); audioInputIndex = new uint32_t[audioInputCount]; audioInput = new AudioConnector[audioInputCount]; // audio outputs audioOutputCount = lilv_plugin_get_num_ports_of_class(plugin, uris.lv2AudioPort, uris.lv2OutputPort, 0); audioOutputIndex = new uint32_t[audioOutputCount]; audioOutput = new AudioConnection*[audioOutputCount]; for(uint32_t i = 0; i < audioOutputCount; i++) { audioOutput[i] = new AudioConnection(this); audioOutput[i]->clear(); } // initialize port structures uint32_t numPorts = lilv_plugin_get_num_ports(plugin); uint32_t audioInputCounter = 0; uint32_t audioOutputCounter = 0; for(uint32_t i = 0; i < numPorts; i++) { const LilvPort *port = lilv_plugin_get_port_by_index(plugin, i); if(lilv_port_is_a(plugin, port, uris.lv2AudioPort)) { if(lilv_port_is_a(plugin, port, uris.lv2InputPort)) { audioInputIndex[audioInputCounter++] = i; } else if(lilv_port_is_a(plugin, port, uris.lv2OutputPort)) { audioOutputIndex[audioOutputCounter++] = i; } } else if(lilv_port_is_a(plugin, port, uris.lv2ControlPort) && lilv_port_is_a(plugin, port, uris.lv2InputPort)) { // get control name const LilvNode* symbol = lilv_port_get_symbol(plugin, port); std::string portName(lilv_node_as_string(symbol)); // create, connect and hash new control port object Lv2ControlPort *newPort = new Lv2ControlPort(); LilvNode *dfault, *minimum, *maximum; lilv_port_get_range(plugin, port, &dfault, &minimum, &maximum); newPort->dfault = dfault ? lilv_node_as_float(dfault) : 0; newPort->minimum = lilv_node_as_float(minimum); newPort->maximum = lilv_node_as_float(maximum); lilv_instance_connect_port(instance, i, &(newPort->value)); controlMap[portName] = newPort; } else if(lilv_port_is_a(plugin, port, uris.lv2AtomPort)) { // is it a MIDI/atom input? LilvNodes *atomBufferType = lilv_port_get_value(plugin, port, uris.lv2AtomBufferType); LilvNodes* atomSupports = lilv_port_get_value(plugin, port, uris.lv2AtomSupports); if (lilv_port_is_a(plugin, port, uris.lv2InputPort) && lilv_nodes_contains(atomBufferType, uris.lv2AtomSequence) && lilv_nodes_contains(atomSupports, uris.lv2MidiEvent)) { // create new inputs and connect to atom sequence location Lv2MidiInput *newAtomPort = new Lv2MidiInput(); lilv_instance_connect_port(instance, i, newAtomPort->getAtomSequence()); midiInputList.add(newAtomPort); } else if (lilv_port_is_a(plugin, port, uris.lv2OutputPort)) { //atomSequence->atom.type = Lv2PluginFactory::instance()->uridMapper.uriToId(LV2_ATOM__Sequence); Lv2MidiOutput *midiOutput = new Lv2MidiOutput(this); lilv_instance_connect_port(instance, i, midiOutput->getAtomSequence()); midiOutputList.add(midiOutput); midiOutputCount++; } else { // warn std::cout << "!!! unknown atom port at index " << i << ": " << lilv_node_as_string(lilv_port_get_name(plugin, port)) << std::endl; } lilv_nodes_free(atomSupports); lilv_nodes_free(atomBufferType); } else { lilv_instance_connect_port(instance, i, NULL); std::cout << "!!! unknown port at index " << i << ": " << lilv_node_as_string(lilv_port_get_name(plugin, port)) << std::endl; } } }
String LV2Module::getURI() const { return lilv_node_as_string (lilv_plugin_get_uri (plugin)); }