Example #1
0
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;
}
Example #2
0
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;
}