Ejemplo n.º 1
0
gboolean
gst_lv2_check_required_features (const LilvPlugin * lv2plugin)
{
  LilvNodes *required_features = lilv_plugin_get_required_features (lv2plugin);
  if (required_features) {
    LilvIter *i;
    gint j;
    gboolean missing = FALSE;

    for (i = lilv_nodes_begin (required_features);
        !lilv_nodes_is_end (required_features, i);
        i = lilv_nodes_next (required_features, i)) {
      const LilvNode *required_feature = lilv_nodes_get (required_features, i);
      const char *required_feature_uri = lilv_node_as_uri (required_feature);
      missing = TRUE;

      for (j = 0; lv2_features[j]; j++) {
        if (!strcmp (lv2_features[j]->URI, required_feature_uri)) {
          missing = FALSE;
          break;
        }
      }
      if (missing) {
        GST_FIXME ("lv2 plugin %s needs host feature: %s",
            lilv_node_as_uri (lilv_plugin_get_uri (lv2plugin)),
            required_feature_uri);
        break;
      }
    }
    lilv_nodes_free (required_features);
    return (!missing);
  }
  return TRUE;
}
Ejemplo n.º 2
0
bool
LV2World::isPluginSupported (const LilvPlugin* plugin)
{
    // Required features support
    LilvNodes* nodes = lilv_plugin_get_required_features (plugin);
    LILV_FOREACH (nodes, iter, nodes)
    {
        const LilvNode* node (lilv_nodes_get (nodes, iter));
        if (! isFeatureSupported (CharPointer_UTF8 (lilv_node_as_uri (node)))) {
            return false; // Feature not supported
        }
    }
    lilv_nodes_free (nodes); nodes = nullptr;
    
    
    // Check this plugin's port types are supported
    const uint32 numPorts = lilv_plugin_get_num_ports (plugin);
    for (uint32 i = 0; i < numPorts; ++i)
    {
        // const LilvPort* port (lilv_plugin_get_port_by_index (plugin, i));
        // nothing here yet (or ever)
    }
    
    return true;
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
Lv2Plugin *Lv2PluginCache::getPlugin(const char *uri, const char *preset, Lv2State *state) {
    // create a unique key for uri/preset/state
    std::string keyString(uri);
    if(preset) {
        keyString.append(":");
        keyString.append(preset);
    }
    std::size_t hash = std::hash<std::string>()(keyString);
    if(state) {
        hash = hash ^ (state->getHash() << 1);
    }

    // count tells how many instances of this type of plugin
    int count = ++instanceCount[hash];

    // return cached plugin instance if available
    int key = hash + count;
    Lv2Plugin *cachedPlugin = findObject(key);
    if(cachedPlugin) {
        cachedPlugin->restore();
        return cachedPlugin;
    }

    // look in cache for plugin type by uri
    std::string uriString(uri);
    const LilvPlugin *lilvPlugin = pluginMap[uriString];
    if(!lilvPlugin) {
        // find lv2 plugin in lilv
        LilvNode *lilvUri = lilv_new_uri(world, uri);
        lilvPlugin = lilv_plugins_get_by_uri(plugins, lilvUri);
        lilv_node_free(lilvUri);

        if(!lilvPlugin) {
            throw std::logic_error(std::string("Plugin is not installed on this system: ") + uriString);
        }

        // check that required features are supported
        LilvNodes* features = lilv_plugin_get_required_features(lilvPlugin);
        for (LilvIter* f = lilv_nodes_begin(features); !lilv_nodes_is_end(features, f); f = lilv_nodes_next(features, f)) {
            const char* featureUri = lilv_node_as_uri(lilv_nodes_get(features, f));
            if(!supported[featureUri]) {
                throw std::logic_error(std::string("Plugin ") + uriString + " requires unsupported feature: " + featureUri);
            }
        }
        lilv_nodes_free(features);
        pluginMap[uriString] = lilvPlugin;
    }

    // create worker if required
    Lv2Worker *worker = 0;
    if (lilv_plugin_has_feature(lilvPlugin, lv2Constants.lv2WorkerSchedule)
        && lilv_plugin_has_extension_data(lilvPlugin, lv2Constants.lv2WorkerInterface)) {
        worker = new Lv2Worker();
        ((LV2_Worker_Schedule*)lv2Features[5]->data)->handle = worker;
    }

    // instantiate
    LilvInstance *instance = lilv_plugin_instantiate(lilvPlugin, sampleRate, lv2Features);

    // connect worker with plugin instance
    if(worker) {
        worker->setInstance(instance);
    }

    // create plugin object
    Lv2Plugin *plugin = new Lv2Plugin(lilvPlugin, instance, lv2Constants, worker);

    // restore baseline default state
    LilvState *defaultState =  lilv_state_new_from_world(world, &map, lilv_plugin_get_uri(lilvPlugin));
    lilv_state_restore(defaultState, instance, setPortValue, plugin, 0, lv2Features);

    // find and restore preset
    if(preset) {
        LilvNodes* presets = lilv_plugin_get_related(lilvPlugin, lv2Constants.lv2Presets);
        LilvNode *myPreset = 0;
        LILV_FOREACH(nodes, i, presets) {
            const LilvNode* presetNode = lilv_nodes_get(presets, i);
            lilv_world_load_resource(world, presetNode);
            LilvNodes* labels = lilv_world_find_nodes(world, presetNode, lv2Constants.lv2RdfsLabel, NULL);
            if (labels) {
                const LilvNode* label = lilv_nodes_get_first(labels);
                const char *labelString = lilv_node_as_string(label); // TODO: free?
                if(!strcmp(labelString, preset)) {
                    myPreset = lilv_node_duplicate(presetNode);
                }
                lilv_nodes_free(labels);
            }
        }
        lilv_nodes_free(presets);
        if(myPreset) {
            LilvState* presetState = lilv_state_new_from_world(world, &map, myPreset);
            lilv_state_restore(presetState, instance, setPortValue, plugin, 0, NULL);
            // lilv_state_free(state); // TODO
        }
        else {
            throw std::logic_error(std::string("Plugin ") + uriString + " has no such preset: " + preset);
        }
    }
    // restore state
    else if(state) {    // TODO: what if state is requested on a plugin that doesn't support?
Ejemplo n.º 5
0
static double
bench(const LilvPlugin* p, uint32_t sample_count, uint32_t block_size)
{
	URITable uri_table;
	uri_table_init(&uri_table);

	LV2_URID_Map       map           = { &uri_table, uri_table_map };
	LV2_Feature        map_feature   = { LV2_URID_MAP_URI, &map };
	LV2_URID_Unmap     unmap         = { &uri_table, uri_table_unmap };
	LV2_Feature        unmap_feature = { LV2_URID_UNMAP_URI, &unmap };
	const LV2_Feature* features[]    = { &map_feature, &unmap_feature, NULL };

	float* const buf = (float*)calloc(block_size * 2, sizeof(float));
	float* const in  = buf;
	float* const out = buf + block_size;
	if (!buf) {
		fprintf(stderr, "Out of memory\n");
		return 0.0;
	}

	LV2_Atom_Sequence seq = {
		{ sizeof(LV2_Atom_Sequence_Body),
		  uri_table_map(&uri_table, LV2_ATOM__Sequence) },
		{ 0, 0 } };

	const char* uri      = lilv_node_as_string(lilv_plugin_get_uri(p));
	LilvNodes*  required = lilv_plugin_get_required_features(p);
	LILV_FOREACH(nodes, i, required) {
		const LilvNode* feature = lilv_nodes_get(required, i);
		if (!lilv_node_equals(feature, urid_map)) {
			fprintf(stderr, "<%s> requires feature <%s>, skipping\n",
			        uri, lilv_node_as_uri(feature));
			free(buf);
			uri_table_destroy(&uri_table);
			return 0.0;
		}
	}

	LilvInstance* instance = lilv_plugin_instantiate(p, 48000.0, features);
	if (!instance) {
		fprintf(stderr, "Failed to instantiate <%s>\n",
		        lilv_node_as_uri(lilv_plugin_get_uri(p)));
		free(buf);
		uri_table_destroy(&uri_table);
		return 0.0;
	}

	float* controls = (float*)calloc(
		lilv_plugin_get_num_ports(p), sizeof(float));
	lilv_plugin_get_port_ranges_float(p, NULL, NULL, controls);

	const uint32_t n_ports = lilv_plugin_get_num_ports(p);
	for (uint32_t index = 0; index < n_ports; ++index) {
		const LilvPort* port = lilv_plugin_get_port_by_index(p, index);
		if (lilv_port_is_a(p, port, lv2_ControlPort)) {
			lilv_instance_connect_port(instance, index, &controls[index]);
		} else if (lilv_port_is_a(p, port, lv2_AudioPort) ||
		           lilv_port_is_a(p, port, lv2_CVPort)) {
			if (lilv_port_is_a(p, port, lv2_InputPort)) {
				lilv_instance_connect_port(instance, index, in);
			} else if (lilv_port_is_a(p, port, lv2_OutputPort)) {
				lilv_instance_connect_port(instance, index, out);
			} else {
				fprintf(stderr, "<%s> port %d neither input nor output, skipping\n",
				        uri, index);
				lilv_instance_free(instance);
				free(buf);
				free(controls);
				uri_table_destroy(&uri_table);
				return 0.0;
			}
		} else if (lilv_port_is_a(p, port, atom_AtomPort)) {
			lilv_instance_connect_port(instance, index, &seq);
		} else {
			fprintf(stderr, "<%s> port %d has unknown type, skipping\n",
			        uri, index);
			lilv_instance_free(instance);
			free(buf);
			free(controls);
			uri_table_destroy(&uri_table);
			return 0.0;
		}
	}

	lilv_instance_activate(instance);

	struct timespec ts = bench_start();
	for (uint32_t i = 0; i < (sample_count / block_size); ++i) {
		lilv_instance_run(instance, block_size);
	}
	const double elapsed = bench_end(&ts);

	lilv_instance_deactivate(instance);
	lilv_instance_free(instance);

	uri_table_destroy(&uri_table);

	if (full_output) {
		printf("%d %d ", block_size, sample_count);
	}
	printf("%lf %s\n", elapsed, uri);

	free(buf);
	free(controls);
	return elapsed;
}