void Lv2Plugin::init () { m_activated = false; m_features = m_world.features.array(); m_instance = slv2_plugin_instantiate( m_plugin, m_sampleRate, m_features->get(Feature::PLUGIN_FEATURE) ); Q_ASSERT(m_instance); m_name = slv2_plugin_get_name( m_plugin ); Q_ASSERT(m_name); int count = slv2_plugin_get_num_ports(m_plugin); m_ports.resize( count ); for (int i = 0; i < count; ++i) { m_ports[i] = new Lv2Port( m_world, this, i ); } m_authorName = slv2_plugin_get_author_name( m_plugin ); m_authorEmail = slv2_plugin_get_author_email( m_plugin ); m_authorHomepage = slv2_plugin_get_author_homepage( m_plugin ); m_features->initialize( *this ); }
static void gst_lv2_base_init (gpointer g_class) { GstLV2Class *klass = (GstLV2Class *) g_class; GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); GstSignalProcessorClass *gsp_class = GST_SIGNAL_PROCESSOR_CLASS (g_class); GstElementDetails *details; SLV2Plugin lv2plugin; SLV2Value val; guint j, audio_in_count, audio_out_count, control_in_count, control_out_count; gchar *klass_tags; GST_DEBUG ("base_init %p", g_class); lv2plugin = (SLV2Plugin) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), GST_SLV2_PLUGIN_QDATA); g_assert (lv2plugin); /* pad templates */ gsp_class->num_audio_in = 0; gsp_class->num_audio_out = 0; /* properties */ gsp_class->num_control_in = 0; gsp_class->num_control_out = 0; for (j = 0; j < slv2_plugin_get_num_ports (lv2plugin); j++) { SLV2Port port = slv2_plugin_get_port_by_index (lv2plugin, j); if (slv2_port_is_a (lv2plugin, port, audio_class)) { gchar *name = g_strdup (slv2_value_as_string (slv2_port_get_symbol (lv2plugin, port))); GST_DEBUG ("LV2 port name: \"%s\"", name); if (slv2_port_is_a (lv2plugin, port, input_class)) gst_signal_processor_class_add_pad_template (gsp_class, name, GST_PAD_SINK, gsp_class->num_audio_in++); else if (slv2_port_is_a (lv2plugin, port, output_class)) gst_signal_processor_class_add_pad_template (gsp_class, name, GST_PAD_SRC, gsp_class->num_audio_out++); /* TODO: else ignore plugin */ g_free (name); } else if (slv2_port_is_a (lv2plugin, port, control_class)) { if (slv2_port_is_a (lv2plugin, port, input_class)) gsp_class->num_control_in++; else if (slv2_port_is_a (lv2plugin, port, output_class)) gsp_class->num_control_out++; /* TODO: else ignore plugin */ } /* TODO: else ignore plugin */ } /* construct the element details struct */ details = g_new0 (GstElementDetails, 1); val = slv2_plugin_get_name (lv2plugin); if (val) { details->longname = g_strdup (slv2_value_as_string (val)); slv2_value_free (val); } else { details->longname = g_strdup ("no description available"); } details->description = details->longname; val = slv2_plugin_get_author_name (lv2plugin); if (val) { details->author = g_strdup (slv2_value_as_string (val)); slv2_value_free (val); } else { details->author = g_strdup ("no author available"); } if (gsp_class->num_audio_in == 0) klass_tags = "Source/Audio/LV2"; else if (gsp_class->num_audio_out == 0) { if (gsp_class->num_control_out == 0) klass_tags = "Sink/Audio/LV2"; else klass_tags = "Sink/Analyzer/Audio/LV2"; } else klass_tags = "Filter/Effect/Audio/LV2"; details->klass = klass_tags; GST_INFO ("tags : %s", details->klass); gst_element_class_set_details (element_class, details); g_free (details->longname); g_free (details->author); g_free (details); klass->audio_in_portnums = g_new0 (gint, gsp_class->num_audio_in); klass->audio_out_portnums = g_new0 (gint, gsp_class->num_audio_out); klass->control_in_portnums = g_new0 (gint, gsp_class->num_control_in); klass->control_out_portnums = g_new0 (gint, gsp_class->num_control_out); audio_in_count = audio_out_count = control_in_count = control_out_count = 0; for (j = 0; j < slv2_plugin_get_num_ports (lv2plugin); j++) { SLV2Port port = slv2_plugin_get_port_by_index (lv2plugin, j); gboolean is_input = slv2_port_is_a (lv2plugin, port, input_class); if (slv2_port_is_a (lv2plugin, port, audio_class)) { if (is_input) klass->audio_in_portnums[audio_in_count++] = j; else klass->audio_out_portnums[audio_out_count++] = j; } else if (slv2_port_is_a (lv2plugin, port, control_class)) { if (is_input) klass->control_in_portnums[control_in_count++] = j; else klass->control_out_portnums[control_out_count++] = j; } } g_assert (audio_in_count == gsp_class->num_audio_in); g_assert (audio_out_count == gsp_class->num_audio_out); g_assert (control_in_count == gsp_class->num_control_in); g_assert (control_out_count == gsp_class->num_control_out); /*if (!LV2_IS_INPLACE_BROKEN (desc->Properties)) GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE (klass); */ klass->plugin = lv2plugin; }
LV2Effect::LV2Effect(SLV2Plugin data, const std::set<wxString>& categories) : mValid(true), mCategories(categories), mMidiInput(0), mScalePointsRetrieved(false), mPortGroupsRetrieved(false) { // We don't support any features at all, so if the plugin requires // any we skip it. SLV2Values req = slv2_plugin_get_required_features(data); size_t nFeatures = slv2_values_size(req); slv2_values_free(req); if (nFeatures > 0) { mValid = false; return; } mData = data; pluginName = wxString::FromUTF8(slv2_value_as_string(slv2_plugin_get_name(mData))); fInBuffer = NULL; fOutBuffer = NULL; mLength = 0; uint32_t p; // Allocate buffers for the port indices and the default control values uint32_t numPorts = slv2_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) slv2_plugin_get_port_ranges_float(mData, minimumValues, maximumValues, defaultValues); // Get info about all ports for(p = 0; p < numPorts; p++) { SLV2Port port = slv2_plugin_get_port_by_index(mData, p); LV2Port internalPort; internalPort.mIndex = p; // Get the port name SLV2Value tmpName = slv2_port_get_name(data, port); internalPort.mName = LAT1CTOWX(slv2_value_as_string(tmpName)); slv2_value_free(tmpName); // Get the port type if (slv2_port_is_a(mData, port, gAudioPortClass)) { if (slv2_port_is_a(mData, port, gInputPortClass)) mAudioInputs.push_back(internalPort); else if (slv2_port_is_a(mData, port, gOutputPortClass)) mAudioOutputs.push_back(internalPort); } else if (slv2_port_is_a(mData, port, gControlPortClass) && slv2_port_is_a(mData, port, gInputPortClass)) { internalPort.mControlBuffer = float(1.0); internalPort.mMin = minimumValues[p]; internalPort.mMax = maximumValues[p]; internalPort.mDefault = defaultValues[p]; if (std::isfinite(defaultValues[p])) internalPort.mControlBuffer = defaultValues[p]; else if (std::isfinite(minimumValues[p])) internalPort.mControlBuffer = minimumValues[p]; else if (std::isfinite(maximumValues[p])) internalPort.mControlBuffer = maximumValues[p]; if (slv2_port_has_property(data, port, gPortToggled)) internalPort.mToggle = true; if (slv2_port_has_property(data, port, gPortIsInteger)) internalPort.mInteger = true; if (slv2_port_has_property(data, port, gPortIsSampleRate)) internalPort.mSampleRate = true; mControlInputs.push_back(internalPort); } else if (slv2_port_is_a(mData, port, gMidiPortClass) && slv2_port_is_a(mData, port, gInputPortClass)) { // If there are more than one MIDI input ports, 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.size() > 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) flags = PLUGIN_EFFECT; if (mAudioInputs.size() == 0) flags |= INSERT_EFFECT; else if (mAudioOutputs.size() == 0) flags |= ANALYZE_EFFECT; else flags |= PROCESS_EFFECT; }
SLV2Instance slv2_plugin_instantiate(SLV2Plugin plugin, double sample_rate, const LV2_Feature*const* features) { struct _Instance* result = NULL; const LV2_Feature** local_features = NULL; if (features == NULL) { local_features = malloc(sizeof(LV2_Feature)); local_features[0] = NULL; } const char* const lib_uri = slv2_value_as_uri(slv2_plugin_get_library_uri(plugin)); const char* const lib_path = slv2_uri_to_path(lib_uri); if (!lib_path) return NULL; dlerror(); void* lib = dlopen(lib_path, RTLD_NOW); if (!lib) { fprintf(stderr, "Unable to open library %s (%s)\n", lib_path, dlerror()); return NULL; } LV2_Descriptor_Function df = dlsym(lib, "lv2_descriptor"); if (!df) { fprintf(stderr, "Could not find symbol 'lv2_descriptor', " "%s is not a LV2 plugin.\n", lib_path); dlclose(lib); return NULL; } else { // Search for plugin by URI // FIXME: Kludge to get bundle path (containing directory of binary) const char* bundle_path = slv2_uri_to_path(slv2_value_as_uri( slv2_plugin_get_bundle_uri(plugin))); //printf("Bundle path: %s\n", bundle_path); for (uint32_t i=0; 1; ++i) { const LV2_Descriptor* ld = df(i); if (!ld) { fprintf(stderr, "Did not find plugin %s in %s\n", slv2_value_as_uri(slv2_plugin_get_uri(plugin)), lib_path); dlclose(lib); break; // return NULL } else if (!strcmp(ld->URI, slv2_value_as_uri(slv2_plugin_get_uri(plugin)))) { assert(plugin->plugin_uri); //printf("Found %s at index %u in:\n\t%s\n\n", // librdf_uri_as_string(plugin->plugin_uri), i, lib_path); assert(ld->instantiate); // Create SLV2Instance to return result = malloc(sizeof(struct _Instance)); result->lv2_descriptor = ld; result->lv2_handle = ld->instantiate(ld, sample_rate, (char*)bundle_path, (features) ? features : local_features); struct _InstanceImpl* impl = malloc(sizeof(struct _InstanceImpl)); impl->lib_handle = lib; result->pimpl = impl; break; } } } if (result) { assert(slv2_plugin_get_num_ports(plugin) > 0); // Failed to instantiate if (result->lv2_handle == NULL) { //printf("Failed to instantiate %s\n", plugin->plugin_uri); free(result); return NULL; } // "Connect" all ports to NULL (catches bugs) for (uint32_t i=0; i < slv2_plugin_get_num_ports(plugin); ++i) result->lv2_descriptor->connect_port(result->lv2_handle, i, NULL); } free(local_features); return result; }