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; }
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()); }
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; }