Exemplo n.º 1
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);
}
Exemplo n.º 2
0
const LV2PortGroup& LV2Effect::GetPortGroups() {

   if (!mPortGroupsRetrieved) {
      
      // Find all port groups with ports in them.
      char portGroupQuery[] = 
         "PREFIX : <http://lv2plug.in/ns/lv2core#>\n"
         "PREFIX pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>\n"
         "SELECT ?index, ?uri, ?label WHERE {\n"
         "<> :port ?port.\n"
         "?port :index ?index.\n"
         "?port pg:membership ?ms.\n"
         "?ms pg:group ?uri.\n"
         "?uri rdfs:label ?label.\n"
         "}";
      
      SLV2Values portIndices = slv2_plugin_query_variable(mData, 
                                                          portGroupQuery, 0);
      SLV2Values groupUris = slv2_plugin_query_variable(mData, 
                                                          portGroupQuery, 1);
      SLV2Values groupLabels = slv2_plugin_query_variable(mData, 
                                                          portGroupQuery, 2);
      
      std::map<wxString, LV2PortGroup> portGroups;
      std::vector<bool> inGroup(mControlInputs.size(), false);
      size_t nMemberships = slv2_values_size(portIndices);
      for (size_t i = 0; i < nMemberships; ++i) {
         uint32_t idx = slv2_value_as_int(slv2_values_get_at(portIndices, i));
         uint32_t p;
         for (p = 0; p < mControlInputs.size(); ++p) {
            if (mControlInputs[p].mIndex == idx)
               break;
         }
         if (p == mControlInputs.size())
            continue;
         wxString uri = wxString::FromUTF8(slv2_value_as_string(slv2_values_get_at(groupUris, i)));
         wxString label = wxString::FromUTF8(slv2_value_as_string(slv2_values_get_at(groupLabels, i)));
         std::map<wxString, LV2PortGroup>::iterator iter = 
            portGroups.find(uri);
         if (iter == portGroups.end())
            portGroups[uri] = LV2PortGroup(label);
         portGroups[uri].AddParameter(p);
         inGroup[p] = true;
      }
      slv2_values_free(portIndices);
      slv2_values_free(groupUris);
      slv2_values_free(groupLabels);
      
      // Add all ports that aren't in any port groups to the root group.
      for (uint32_t p = 0; p < mControlInputs.size(); ++p) {
         if (!inGroup[p])
            mRootGroup.AddParameter(p);
      }
      
      // Find all subgroup relationships.
      char subGroupQuery[] = 
         "PREFIX : <http://lv2plug.in/ns/lv2core#>\n"
         "PREFIX pg: <http://ll-plugins.nongnu.org/lv2/ext/portgroups#>\n"
         "SELECT ?sub, ?parent WHERE {\n"
         "?sub pg:subgroupOf ?parent.\n"
         "}";
      
      SLV2Values subs = slv2_plugin_query_variable(mData, subGroupQuery, 0);
      SLV2Values parents = slv2_plugin_query_variable(mData, subGroupQuery, 1);
      size_t nSubgroups = slv2_values_size(subs);
      for (size_t i = 0; i < nSubgroups; ++i) {
         wxString parent = 
            wxString::FromUTF8(slv2_value_as_uri(slv2_values_get_at(parents, i)));
         wxString sub = 
            wxString::FromUTF8(slv2_value_as_uri(slv2_values_get_at(subs, i)));
         std::map<wxString, LV2PortGroup>::iterator iter = 
            portGroups.find(parent);
         std::map<wxString, LV2PortGroup>::iterator iter2 = 
            portGroups.find(sub);
         if (iter != portGroups.end() && iter2 != portGroups.end()) {
            iter->second.AddSubGroup(iter2->second);
         }
      }
      slv2_values_free(subs);
      slv2_values_free(parents);

      // Make all groups subgroups of the root group.
      std::map<wxString, LV2PortGroup>::iterator iter;
      for (iter = portGroups.begin(); iter != portGroups.end(); ++iter)
         mRootGroup.AddSubGroup(iter->second);
      
      mPortGroupsRetrieved = true;
   }
   
   std::queue<const LV2PortGroup*> groups;
   groups.push(&mRootGroup);
   while (!groups.empty()) {
      const LV2PortGroup* g = groups.front();
      groups.pop();
      const std::vector<LV2PortGroup>& subs = g->GetSubGroups();
      for (std::vector<LV2PortGroup>::const_iterator iter = subs.begin();
           iter != subs.end(); ++iter)
         groups.push(&*iter);
   }
   
   return mRootGroup;
}