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; }
int main(int argc, char** argv) { if (argc != 2) { fprintf(stderr, "USAGE: %s BUNDLE\n", argv[0]); return 1; } const char* bundle_path = argv[1]; LilvWorld* world = lilv_world_new(); // Load test plugin bundle uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(bundle_path); SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); lilv_world_load_bundle(world, bundle_uri); free(abs_bundle); serd_node_free(&bundle); lilv_node_free(bundle_uri); LilvNode* plugin_uri = lilv_new_uri(world, PLUGIN_URI); const LilvPlugins* plugins = lilv_world_get_all_plugins(world); const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri); TEST_ASSERT(plugin); LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL); TEST_ASSERT(!instance); lilv_node_free(plugin_uri); lilv_world_free(world); return 0; }
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(); }
void lilv_scale_point_free(LilvScalePoint* point) { if (point) { lilv_node_free(point->value); lilv_node_free(point->label); free(point); } }
URISet properties(World* world, SPtr<const Client::ObjectModel> model) { URISet properties; URISet types = RDFS::types(world, model); LilvNode* rdf_type = lilv_new_uri(world->lilv_world(), LILV_NS_RDF "type"); LilvNode* rdf_Property = lilv_new_uri(world->lilv_world(), LILV_NS_RDF "Property"); LilvNode* rdfs_domain = lilv_new_uri(world->lilv_world(), LILV_NS_RDFS "domain"); LilvNodes* props = lilv_world_find_nodes( world->lilv_world(), NULL, rdf_type, rdf_Property); LILV_FOREACH(nodes, p, props) { const LilvNode* prop = lilv_nodes_get(props, p); if (lilv_node_is_uri(prop)) { LilvNodes* domains = lilv_world_find_nodes( world->lilv_world(), prop, rdfs_domain, NULL); unsigned n_matching_domains = 0; LILV_FOREACH(nodes, d, domains) { const LilvNode* domain_node = lilv_nodes_get(domains, d); if (!lilv_node_is_uri(domain_node)) { // TODO: Blank node domains (e.g. unions) continue; } const Raul::URI domain(lilv_node_as_uri(domain_node)); if (types.count(domain)) { ++n_matching_domains; } } if (lilv_nodes_size(domains) == 0 || ( n_matching_domains > 0 && n_matching_domains == lilv_nodes_size(domains))) { properties.insert(Raul::URI(lilv_node_as_uri(prop))); } lilv_nodes_free(domains); } } lilv_node_free(rdfs_domain); lilv_node_free(rdf_Property); lilv_node_free(rdf_type); return properties; }
void lilv_ui_free(LilvUI* ui) { lilv_node_free(ui->uri); ui->uri = NULL; lilv_node_free(ui->bundle_uri); ui->bundle_uri = NULL; lilv_node_free(ui->binary_uri); ui->binary_uri = NULL; lilv_nodes_free(ui->classes); free(ui); }
LILV_API void lilv_state_free(LilvState* state) { if (state) { for (uint32_t i = 0; i < state->num_props; ++i) { free(state->props[i].value); } for (uint32_t i = 0; i < state->num_values; ++i) { free(state->values[i].value); free(state->values[i].symbol); } lilv_node_free(state->plugin_uri); zix_tree_free(state->abs2rel); zix_tree_free(state->rel2abs); free(state->props); free(state->values); free(state->label); free(state->dir); free(state->file_dir); free(state->copy_dir); free(state->link_dir); free(state); } }
bool LV2EffectsModule::IsPluginValid(const wxString & path) { LilvNode *uri = lilv_new_uri(gWorld, path.ToUTF8()); const LilvPlugin *plugin = lilv_plugins_get_by_uri(lilv_world_get_all_plugins(gWorld), uri); lilv_node_free(uri); return plugin != NULL; }
const LilvPlugin* LV2World::getPlugin (const String& uri) const { LilvNode* p (lilv_new_uri (world, uri.toUTF8())); const LilvPlugin* plugin = lilv_plugins_get_by_uri (getAllPlugins(), p); lilv_node_free (p); return plugin; }
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))); } }
void classes(World* world, URISet& types, bool super) { LilvNode* rdfs_subClassOf = lilv_new_uri( world->lilv_world(), LILV_NS_RDFS "subClassOf"); closure(world, rdfs_subClassOf, types, super); lilv_node_free(rdfs_subClassOf); }
void datatypes(World* world, URISet& types, bool super) { LilvNode* owl_onDatatype = lilv_new_uri( world->lilv_world(), LILV_NS_OWL "onDatatype"); closure(world, owl_onDatatype, types, super); lilv_node_free(owl_onDatatype); }
void lilv_port_free(const LilvPlugin* plugin, LilvPort* port) { if (port) { sord_node_free(plugin->world->world, port->node); lilv_nodes_free(port->classes); lilv_node_free(port->symbol); free(port); } }
wxString LV2Effect::GetString(LilvNode *node, bool free) { wxString str = GetString(node); if (free) { lilv_node_free(node); } return str; }
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; }
const LilvPlugin *LV2EffectsModule::GetPlugin(const wxString & path) { LilvNode *uri = lilv_new_uri(gWorld, path.ToUTF8()); if (!uri) { return NULL; } const LilvPlugin *plug = lilv_plugins_get_by_uri(lilv_world_get_all_plugins(gWorld), uri); lilv_node_free(uri); return plug; }
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; }
URIs::Quark::~Quark() { lilv_node_free(lnode); }
void LV2EffectsModule::Terminate() { lilv_node_free(gAudioPortClass); gAudioPortClass = NULL; lilv_node_free(gControlPortClass); gControlPortClass = NULL; lilv_node_free(gMidiPortClass); gMidiPortClass = NULL; lilv_node_free(gInputPortClass); gInputPortClass = NULL; lilv_node_free(gOutputPortClass); gOutputPortClass = NULL; lilv_node_free(gPortToggled); gPortToggled = NULL; lilv_node_free(gPortIsInteger); gPortIsInteger = NULL; lilv_node_free(gPortIsSampleRate); gPortIsSampleRate = NULL; lilv_node_free(gPortIsEnumeration); gPortIsEnumeration = NULL; lilv_node_free(gPortIsLatency); gPortIsLatency = NULL; lilv_node_free(gPortIsOptional); gPortIsOptional = NULL; lilv_node_free(gName); gName = NULL; lilv_node_free(gPortGroup); gPortGroup = NULL; lilv_node_free(gSubGroupOf); gSubGroupOf = NULL; lilv_world_free(gWorld); gWorld = NULL; return; }
LV2EffectDialog::LV2EffectDialog(LV2Effect *effect, wxWindow *parent, const LilvPlugin *data, int sampleRate, double length, double WXUNUSED(noteLength), unsigned char WXUNUSED(noteVelocity), unsigned char WXUNUSED(noteKey)) : wxDialog(parent, wxID_ANY, mEffect->GetString(lilv_plugin_get_name(data)), wxDefaultPosition, wxSize(500, -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), mEffect(effect), mData(data), mControls(effect->GetControls()), mSampleRate(sampleRate), mLength(length) { #if defined(__WXMSW__) // On Windows, for some reason, wxWindows calls OnTextCtrl during creation // of the text control, and LV2EffectDialog::OnTextCtrl calls HandleText, // which assumes all the mFields have been initialized. // This can give us a bad pointer crash, so manipulate inSlider to // no-op HandleText during creation. inSlider = true; #else inSlider = false; #endif inText = false; inText = true; // Allocate memory for the user parameter controls int ctrlcnt = (int) mControls.GetCount(); mToggles = new wxCheckBox*[ctrlcnt]; mSliders = new wxSlider*[ctrlcnt]; mFields = new wxTextCtrl*[ctrlcnt]; mLabels = new wxStaticText*[ctrlcnt]; mEnums = new wxChoice*[ctrlcnt]; wxControl *item; wxBoxSizer *vSizer = new wxBoxSizer(wxVERTICAL); // Add information about the plugin LilvNode *tmpValue = lilv_plugin_get_author_name(data); if (tmpValue) { wxString author(_("Author: ") + mEffect->GetString(tmpValue)); item = new wxStaticText(this, wxID_ANY, author); vSizer->Add(item, 0, wxALL, 5); lilv_node_free(tmpValue); } wxScrolledWindow *w = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL | wxTAB_TRAVERSAL); // Try to give the window a sensible default/minimum size w->SetMinSize(wxSize( wxMax(600, parent->GetSize().GetWidth() * 2/3), parent->GetSize().GetHeight() / 2)); w->SetScrollRate(0, 20); vSizer->Add(w, 1, wxEXPAND|wxALL, 5); // Preview, OK, & Cancel buttons vSizer->Add(CreateStdButtonSizer(this, ePreviewButton|eCancelButton|eOkButton), 0, wxEXPAND); SetSizer(vSizer); wxSizer *paramSizer = new wxStaticBoxSizer(wxVERTICAL, w, _("Effect Settings")); wxFlexGridSizer *gridSizer = new wxFlexGridSizer(5, 0, 0); gridSizer->AddGrowableCol(3); // Now add the length control if (mEffect->GetEffectFlags() & INSERT_EFFECT) { item = new wxStaticText(w, 0, _("Length (seconds)")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); mSeconds = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(length)); mSeconds->SetName(_("Length (seconds)")); gridSizer->Add(mSeconds, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); ConnectFocus(mSeconds); } // The note controls if the plugin is a synth if (mEffect->IsSynth()) { // Note length control item = new wxStaticText(w, wxID_ANY, _("Note length (seconds)")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); mNoteSeconds = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(length / 2)); mNoteSeconds->SetName(_("Note length (seconds)")); gridSizer->Add(mNoteSeconds, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); ConnectFocus(mNoteSeconds); // Note velocity control item = new wxStaticText(w, wxID_ANY, _("Note velocity")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); mNoteVelocity = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(64)); mNoteVelocity->SetName(_("Note velocity")); gridSizer->Add(mNoteVelocity, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); ConnectFocus(mNoteVelocity); // Note key control item = new wxStaticText(w, wxID_ANY, _("Note key")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); mNoteKey = new wxTextCtrl(w, LADSPA_SECONDS_ID, Internat::ToDisplayString(64)); mNoteKey->SetName(_("Note key")); gridSizer->Add(mNoteKey, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); ConnectFocus(mNoteKey); } paramSizer->Add(gridSizer, 1, wxEXPAND | wxALL, 5); // Create user parameter controls std::queue<const LV2PortGroup *> groups; groups.push(&mEffect->GetRootGroup()); while (!groups.empty()) { const LV2PortGroup* pg = groups.front(); groups.pop(); if (pg->GetName() != wxEmptyString) { wxSizer *groupSizer = new wxStaticBoxSizer(wxVERTICAL, w, pg->GetName()); paramSizer->Add(groupSizer, 0, wxEXPAND | wxALL, 5); gridSizer = new wxFlexGridSizer(5, 0, 0); gridSizer->AddGrowableCol(3); groupSizer->Add(gridSizer, 1, wxEXPAND | wxALL, 5); } const LV2PortGroupArray & subgroups = pg->GetSubGroups(); LV2PortGroupArray::const_iterator si; for (si = subgroups.begin(); si != subgroups.end(); si++) { if ((*si)->GetParameters().GetCount() != 0) { groups.push(*si); } } const wxArrayInt & params = pg->GetParameters(); for (size_t pi = 0; pi < params.GetCount(); pi++) { int p = params[pi]; if (p >= ctrlcnt) { continue; } LV2Port & port = mControls[p]; wxString labelText = port.mName; item = new wxStaticText(w, 0, labelText + wxT(":")); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); wxString fieldText; if (port.mToggle) { mToggles[p] = new wxCheckBox(w, p, wxT("")); mToggles[p]->SetName(labelText); mToggles[p]->SetValue(port.mControlBuffer > 0); gridSizer->Add(mToggles[p], 0, wxALL, 5); ConnectFocus(mToggles[p]); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); } else if (port.mEnumeration) { mEnums[p] = new wxChoice(w, p); mEnums[p]->SetName(labelText); mEnums[p]->Append(port.mScaleLabels); int s; for (s = (int) port.mScaleValues.GetCount() - 1; s >= 0; s--) { if (port.mControlBuffer >= port.mScaleValues[s]) { break; } } if (s < 0) { s = 0; } mEnums[p]->SetSelection(s); gridSizer->Add(mEnums[p], 0, wxALL | wxEXPAND, 5); ConnectFocus(mEnums[p]); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); gridSizer->Add(1, 1, 0); } else { if (port.mInteger) { fieldText.Printf(wxT("%d"), (int)(port.mControlBuffer + 0.5)); } else { fieldText = Internat::ToDisplayString(port.mControlBuffer); } mFields[p] = new wxTextCtrl(w, p, fieldText); mFields[p]->SetName(labelText); gridSizer->Add(mFields[p], 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); ConnectFocus(mFields[p]); wxString bound; double lower = 0.0; double upper = 0.0; bool haslo = false; bool hashi = false; bool forceint = false; wxString loLabel; wxString hiLabel; #if 0 ScalePointMap::const_iterator iter = scalePoints.find(port.mIndex); if (!wxNaN(port.mMin)) { lower = port.mMin; haslo = true; if (iter != scalePoints.end()) { std::map<float, wxString>::const_iterator iter2 = iter->second.find(lower); if (iter2 != iter->second.end()) { loLabel = iter2->second; } } } if (!isnan(port.mMax)) { upper = port.mMax; hashi = true; if (iter != scalePoints.end()) { std::map<float, wxString>::const_iterator iter2 = iter->second.find(upper); if (iter2 != iter->second.end()) { hiLabel = iter2->second; } } } #endif if (port.mSampleRate) { lower *= mSampleRate * 1000; upper *= mSampleRate; forceint = true; } wxString str; if (haslo) { str = loLabel; if (str.IsEmpty()) { if (port.mInteger || forceint) { str.Printf(wxT("%d"), (int)(lower + 0.5)); } else { str = Internat::ToDisplayString(lower); } } item = new wxStaticText(w, wxID_ANY, str); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); } else { gridSizer->Add(1, 1, 0); } mSliders[p] = new wxSlider(w, p, 0, 0, 1000, wxDefaultPosition, wxSize(200, -1)); mSliders[p]->SetName(labelText); gridSizer->Add(mSliders[p], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxALL, 5); ConnectFocus(mSliders[p]); if (hashi) { str = hiLabel; if (str.IsEmpty()) { if (port.mInteger || forceint) { str.Printf(wxT("%d"), (int)(upper + 0.5)); } else { str = Internat::ToDisplayString(upper); } } item = new wxStaticText(w, wxID_ANY, str); gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 5); } else { gridSizer->Add(1, 1, 0); } } } } // Set all of the mSliders based on the value in the // text mFields inSlider = false; // Now we're ready for HandleText to actually do something. HandleText(); w->SetSizer(paramSizer); Layout(); Fit(); SetSizeHints(GetSize()); }
LV2Effect::LV2Effect(const LilvPlugin *data, const std::set<wxString> & categories) : mValid(true), mCategories(categories), mMidiInput(0), mLatencyPortIndex(-1) { // We don't support any features at all, so if the plugin requires // any we skip it. LilvNodes *req = lilv_plugin_get_required_features(data); size_t nFeatures = lilv_nodes_size(req); lilv_nodes_free(req); if (nFeatures > 0) { mValid = false; return; } mData = data; pluginName = GetString(lilv_plugin_get_name(mData), true); fInBuffer = NULL; fOutBuffer = NULL; mLength = 0; // Allocate buffers for the port indices and the default control values int numPorts = lilv_plugin_get_num_ports(mData); float *minimumValues = new float [numPorts]; float *maximumValues = new float [numPorts]; float *defaultValues = new float [numPorts]; // Retrieve the port ranges for all ports (some values may be NaN) lilv_plugin_get_port_ranges_float(mData, minimumValues, maximumValues, defaultValues); // Get info about all ports for (int i = 0; i < numPorts; i++) { const LilvPort *port = lilv_plugin_get_port_by_index(mData, i); LV2Port internalPort; internalPort.mIndex = lilv_port_get_index(mData, port); // Get the port name LilvNode *tmpName = lilv_port_get_name(mData, port); internalPort.mName = GetString(tmpName); lilv_node_free(tmpName); // Get the scale points LilvScalePoints* points = lilv_port_get_scale_points(mData, port); LILV_FOREACH(scale_points, j, points) { const LilvScalePoint *point = lilv_scale_points_get(points, j); internalPort.mScaleValues.Add(lilv_node_as_float(lilv_scale_point_get_value(point))); internalPort.mScaleLabels.Add(GetString(lilv_scale_point_get_label(point))); } lilv_scale_points_free(points); // Get the groups LilvNodes *groups = lilv_port_get_value(mData, port, gPortGroup); if (groups) { LilvNode *group = lilv_nodes_get_first(groups); wxString uri = GetString(group); wxString label; const LilvNode *name = lilv_world_get(gWorld, group, gName, NULL); if (name) { label = GetString(name); } else { // Shouldn't happen, but provide something label = uri; } lilv_nodes_free(groups); // Check for new group if (mPortGroups.find(uri) == mPortGroups.end()) { mPortGroups[uri] = LV2PortGroup(label); } #if 0 // Get subgroup // // LLL: This isn't right...must find or construct a plugin with // subgroups. LilvNodes *subgroup = lilv_node_get_value(mData, port, gSubGroupOf); if (subgroups) { LilvNode *subgroup = lilv_nodes_get_first(subgroups); wxString uri = GetString(subgroup); const LilvNode *subgroup = lilv_world_get(gWorld, group, gSubGroupOf, NULL); wxString label = GetString(name); lilv_nodes_free(subgroup); } else #endif { mRootGroup.AddSubGroup(mPortGroups[uri]); } mPortGroups[uri].AddParameter(i); } else { mRootGroup.AddParameter(i); } // Get the port type if (lilv_port_is_a(mData, port, gAudioPortClass)) { if (lilv_port_is_a(mData, port, gInputPortClass)) { mAudioInputs.Add(internalPort); } else if (lilv_port_is_a(mData, port, gOutputPortClass)) { mAudioOutputs.Add(internalPort); } } else if (lilv_port_is_a(mData, port, gControlPortClass) && lilv_port_is_a(mData, port, gInputPortClass)) { internalPort.mControlBuffer = float(1.0); internalPort.mMin = minimumValues[i]; internalPort.mMax = maximumValues[i]; internalPort.mDefault = defaultValues[i]; if (isfinite(defaultValues[i])) { internalPort.mControlBuffer = defaultValues[i]; } else if (isfinite(minimumValues[i])) { internalPort.mControlBuffer = minimumValues[i]; } else if (isfinite(maximumValues[i])) { internalPort.mControlBuffer = maximumValues[i]; } if (lilv_port_has_property(mData, port, gPortToggled)) { internalPort.mToggle = true; } else if (lilv_port_has_property(mData, port, gPortIsInteger)) { internalPort.mInteger = true; } else if (lilv_port_has_property(mData, port, gPortIsSampleRate)) { internalPort.mSampleRate = true; } else if (lilv_port_has_property(mData, port, gPortIsEnumeration)) { internalPort.mEnumeration = true; } mControlInputs.Add(internalPort); } else if (lilv_port_is_a(mData, port, gControlPortClass) && lilv_port_is_a(mData, port, gOutputPortClass)) { // If there is more than one latency port, the plugin is invalid if (lilv_port_has_property(mData, port, gPortIsLatency)) { if (mLatencyPortIndex >= 0) { mValid = false; continue; } mLatencyPortIndex = i; } else if (!lilv_port_has_property(mData, port, gPortIsOptional)) { mControlOutputs.Add(internalPort); } } else if (lilv_port_is_a(mData, port, gMidiPortClass) && lilv_port_is_a(mData, port, gInputPortClass)) { // If there is more than one MIDI input port, the plugin is invalid if (mMidiInput) { mValid = false; continue; } mMidiInput = new LV2Port(internalPort); } else { // Unknown port type, we set the invalid flag // mValid = false; } } delete [] minimumValues; delete [] maximumValues; delete [] defaultValues; // MIDI synths may not have any audio inputs. if (mMidiInput && mAudioInputs.GetCount() > 0) { mValid = false; } // Determine whether the plugin is a generator, effect or analyser // depending on the number of ports of each type (not completely accurate, // but works most of the time) int flags = PLUGIN_EFFECT; if (mAudioInputs.GetCount() == 0) { flags |= INSERT_EFFECT; } else if (mAudioOutputs.GetCount() == 0) { flags |= ANALYZE_EFFECT; } else { flags |= PROCESS_EFFECT; } SetEffectFlags(flags); }
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; }
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; }
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?
/** * Get livl plugin by uri */ const LilvPlugin * get_livl_plugin(const char *uri, Lv2Lib * lv2Lib) { LilvNode *plugin_uri = lilv_new_uri(lv2Lib->world, uri); const LilvPlugin *plugin = lilv_plugins_get_by_uri(lv2Lib->plugins, plugin_uri); lilv_node_free(plugin_uri); return plugin; }