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_instance_free(instance); LilvNode* eg_blob = lilv_new_uri(world, "http://example.org/blob"); LilvNode* blob = lilv_world_get(world, plugin_uri, eg_blob, NULL); TEST_ASSERT(lilv_node_is_literal(blob)); lilv_node_free(blob); lilv_node_free(eg_blob); LilvNode* eg_junk = lilv_new_uri(world, "http://example.org/junk"); LilvNode* junk = lilv_world_get(world, plugin_uri, eg_junk, NULL); TEST_ASSERT(lilv_node_is_literal(junk)); lilv_node_free(junk); lilv_node_free(eg_junk); lilv_node_free(plugin_uri); lilv_world_free(world); return 0; }
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); }