Exemple #1
0
static int plugin_tilde_ladspa_alloc_outofplace_memory (Pd_Plugin_Tilde* x, unsigned long buflen)
{
  plugin_tilde_ladspa_free_outofplace_memory (x);

  if (LADSPA_IS_INPLACE_BROKEN (x->plugin.ladspa.type->Properties))
    {
      unsigned i = 0;

      x->plugin.ladspa.outofplace_audio_outputs = (t_float**)
        calloc (x->num_audio_outputs, sizeof (t_float*));
      if (x->plugin.ladspa.outofplace_audio_outputs == NULL) {
        return 1; /* error */
      }

      for (i = 0; i < x->num_audio_outputs; i++)
        {
          x->plugin.ladspa.outofplace_audio_outputs[i] = (t_float*)
            calloc (buflen, sizeof (t_float));
          if (x->plugin.ladspa.outofplace_audio_outputs[i] == NULL) {
            /* FIXME free got buffers? */
            return 1; /* error */
          }
        }
    }
  return 0; /* success */
}
Exemple #2
0
static void
gst_ladspa_init (GstLADSPA * ladspa, GstLADSPAClass * klass)
{
  ladspa->descriptor = klass->descriptor;
  ladspa->activated = FALSE;
  ladspa->inplace_broken =
      LADSPA_IS_INPLACE_BROKEN (ladspa->descriptor->Properties);
}
Exemple #3
0
bool LadspaManager::isInplaceBroken( const ladspa_key_t &  _plugin )
{
	if( m_ladspaManagerMap.contains( _plugin ) )
	{
		LADSPA_Descriptor_Function descriptorFunction =
			m_ladspaManagerMap[_plugin]->descriptorFunction;
		const LADSPA_Descriptor * descriptor =
				descriptorFunction(
					m_ladspaManagerMap[_plugin]->index );
		return( LADSPA_IS_INPLACE_BROKEN( descriptor->Properties ) );
	}
	else
	{
		return( false );
	}
}
void	 				WiredLADSPAInstance::Process(float **input, float **output, long sample_length)
{
	if (IsLoaded() == false || _InputAudioPluginsPorts.empty() || _OutputAudioPluginsPorts.empty() || 
		(LADSPA_IS_INPLACE_BROKEN(_Properties) && *input == *output) || _IsPlaying == false || _Bypass == true)
	{
		memcpy(output[0], input[0], sample_length * sizeof(float));
		memcpy(output[1], input[1], sample_length * sizeof(float));
	}
	else
	{
		if (_InputAudioPluginsPorts.size() >= 2 && _OutputAudioPluginsPorts.size() >= 2)
		{
			//memcpy(output[0], input[0], sample_length * sizeof(float));
			//memcpy(output[1], input[1], sample_length * sizeof(float));
			ProcessStereo(input, output, sample_length);
		}
		else
			ProcessMono(input, output, sample_length);
	}
}
Exemple #5
0
LADSPAInstance::LADSPAInstance(const LADSPA_Descriptor * descriptor, int slot)
{
    m_pDescriptor = descriptor;

    if (m_pControlObjectSampleRate == NULL)
    {
        m_pControlObjectSampleRate = new ControlObjectThreadMain(ControlObject::getControl(ConfigKey("[Master]", "samplerate")));
    }

    if (LADSPA_IS_INPLACE_BROKEN(m_pDescriptor->Properties))
    {
        qDebug() << "LADSPA: Inplace broken!";
    }

    remove = 0;

    QString slotString;
    slotString.setNum(slot);
    ConfigKey * key = new ConfigKey("[LADSPA]", "EnableEffect" + slotString);
    m_pControlObjectEnable = ControlObject::getControl(*key);
    key = new ConfigKey("[LADSPA]", "DryWet" + slotString);
    m_pControlObjectDryWet = ControlObject::getControl(*key);
}
/* Note that this function leaks memory and that dynamic libraries
   that are dlopen()ed are never dlclose()d. */
int 
main(const int iArgc, char * const ppcArgv[]) {

  char * pcEndPointer;
  const char * pcControlValue;
  const char * pcInputFilename;
  const char * pcOutputFilename;
  const LADSPA_Descriptor ** ppsPluginDescriptors;
  LADSPA_Data ** ppfPluginControlValues;
  LADSPA_Data fExtraSeconds;
  int bBadParameters;
  int bBadControls;
  LADSPA_Properties iProperties;
  unsigned long lArgumentIndex;
  unsigned long lControlValueCount;
  unsigned long lControlValueIndex;
  unsigned long lPluginCount;
  unsigned long lPluginCountUpperLimit;
  unsigned long lPluginIndex;
  void ** ppvPluginLibraries;

  bBadParameters = 0;
  fExtraSeconds = 0;

  /* Check for a -s flag, but only at the start. Cannot get use
     getopt() as it gets thoroughly confused when faced with negative
     numbers on the command line. */
  lArgumentIndex = 1;
  if (iArgc >= 3) {
    if (strcmp(ppcArgv[1], "-s") == 0) {
      fExtraSeconds = (LADSPA_Data)strtod(ppcArgv[2], &pcEndPointer);
      bBadControls = (ppcArgv[2] + strlen(ppcArgv[2]) 
		      != pcEndPointer);
      lArgumentIndex = 3;
    }
    else if (strncmp(ppcArgv[1], "-s", 2) == 0) {
      fExtraSeconds = (LADSPA_Data)strtod(ppcArgv[1] + 2, &pcEndPointer);
      bBadControls = (ppcArgv[1] + strlen(ppcArgv[1]) 
		      != pcEndPointer);
      lArgumentIndex = 2;
    }
  }
  
  /* We need to analyse the rest of the parameters. The first two
     should be input and output files involved. */
  if (lArgumentIndex + 4 > (unsigned long)iArgc) {
    /* There aren't enough parameters to include an input file, an
       output file and one plugin. */
    bBadParameters = 1;
  }
  else {

    pcInputFilename = ppcArgv[lArgumentIndex];
    pcOutputFilename = ppcArgv[lArgumentIndex + 1];

    /* Now we need to look through any plugins and plugin parameters
       present. At this stage we're loading plugins and parameters,
       but not attempting to wire them up.

       First we construct some arrays to contain the data we're
       hopefully about to extract. Note that these arrays are usually
       larger than is needed, however they will be large enough.

       WARNING: Note that there is no attempt to tidy up the memory at
       the end of this function and libraries are not unloaded under
       error conditions. This is only a toy program. */

    lPluginCountUpperLimit = (iArgc - lArgumentIndex - 1) / 2;

    ppvPluginLibraries = ((void **)
			  calloc(lPluginCountUpperLimit,
				 sizeof(void *)));
    ppsPluginDescriptors = ((const LADSPA_Descriptor **)
			    calloc(lPluginCountUpperLimit,
				   sizeof(LADSPA_Descriptor *)));
    ppfPluginControlValues = ((LADSPA_Data **)
			      calloc(lPluginCountUpperLimit,
				     sizeof(LADSPA_Data *)));
    lPluginIndex = 0;
    lArgumentIndex += 2;
    bBadControls = 0;
    while (lArgumentIndex < (unsigned long)iArgc && !bBadControls) {

      if (lArgumentIndex + 1 == (unsigned long)iArgc) {
	bBadParameters = 1;
	break;
      }

      /* Parameter should be a plugin file name followed by a
         label. Load the plugin. This call will exit() if the load
         fails. */
      ppvPluginLibraries[lPluginIndex]
	= loadLADSPAPluginLibrary(ppcArgv[lArgumentIndex]);
      ppsPluginDescriptors[lPluginIndex] 
	= findLADSPAPluginDescriptor(ppvPluginLibraries[lPluginIndex],
				     ppcArgv[lArgumentIndex],
				     ppcArgv[lArgumentIndex + 1]);

      /* Check the plugin is in-place compatible. */
      iProperties = ppsPluginDescriptors[lPluginIndex]->Properties;
      if (LADSPA_IS_INPLACE_BROKEN(iProperties)) {
	fprintf(stderr,
		"Plugin \"%s\" is not capable of in-place processing and "
		"therefore cannot be used by this program.\n",
		ppsPluginDescriptors[lPluginIndex]->Name);
	/* This is somewhat lazy - this isn't a difficult problem to
           get around. */
	return(1);
      }

      lControlValueCount
	= getPortCountByType(ppsPluginDescriptors[lPluginIndex],
			     LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL);
      
      bBadControls = (lControlValueCount + lArgumentIndex + 2 
		      > (unsigned long)iArgc);
      if (lControlValueCount > 0 && !bBadControls) {
	ppfPluginControlValues[lPluginIndex]
	  = (LADSPA_Data *)calloc(lControlValueCount, sizeof(LADSPA_Data));
	for (lControlValueIndex = 0; 
	     lControlValueIndex < lControlValueCount && !bBadControls;
	     lControlValueIndex++) {
	  pcControlValue = ppcArgv[lArgumentIndex + 2 + lControlValueIndex];

	  ppfPluginControlValues[lPluginIndex][lControlValueIndex]
	    = (LADSPA_Data)strtod(pcControlValue, &pcEndPointer);

	  bBadControls = (pcControlValue + strlen(pcControlValue) 
			  != pcEndPointer);
	}
      }

      if (bBadControls)
	listControlsForPlugin(ppsPluginDescriptors[lPluginIndex]);

      lArgumentIndex += (2 + lControlValueCount);
      lPluginIndex++;
    }

    lPluginCount = lPluginIndex;

    if (!bBadControls) {

      /* We have all the data we need. Go go go. If this function
	 fails it will exit(). */
      applyPlugin(pcInputFilename,
		  pcOutputFilename,
		  fExtraSeconds,
		  lPluginCount,
		  ppsPluginDescriptors,
		  ppfPluginControlValues);

      for (lPluginIndex = 0; lPluginIndex < lPluginCount; lPluginIndex++)
	unloadLADSPAPluginLibrary(ppvPluginLibraries[lPluginIndex]);
    }
  }

  if (bBadParameters) {
    fprintf(stderr,
	    "Usage:\tapplyplugin [flags] <input Wave file> "
	    "<output Wave file>\n"
	    "\t<LADSPA plugin file name> <plugin label> "
	    "<Control1> <Control2>...\n"
	    "\t[<LADSPA plugin file name> <plugin label> "
	    "<Control1> <Control2>...]...\n"
	    "Flags:"
	    "\t-s<seconds>  Add seconds of silence after end of input file.\n"
	    "\n"
	    "To find out what control values are needed by a plugin, "
	    "use the\n"
	    "\"analyseplugin\" program and check for control input ports.\n"
            "Note that the LADSPA_PATH environment variable is used "
            "to help find plugins.\n");
    return(1);
  }

  return(0);
}
Exemple #7
0
bool LADSPAInstance::isInplaceBroken()
{
    return LADSPA_IS_INPLACE_BROKEN(getDescriptor()->Properties);
}
int lp_ladspa_plugin::init(const LADSPA_Descriptor *descriptor, int channels, int buf_size, int samplerate)
{
	if(descriptor == 0){
		std::cerr << "lp_ladspa_plugin::" << __FUNCTION__ << ": descriptor is Null\n";
		return -1;
	}
	pv_descriptor = descriptor;

	if(pv_descriptor->activate != 0){
		pv_has_activate = true;
	}
	if(pv_descriptor->deactivate != 0){
		pv_has_deactivate = true;
	}

	int col = 2;

	// Layout
	layout = new QGridLayout(this);

	// Add the gain control
	gain_slider = new lp_ladspa_slider_float;
	gain_slider->init(-20.0, 10.0, 0.0, true);
	gain_slider->set_name(QObject::tr("Input gain"));
	layout->addWidget(gain_slider, 1, 0);

	// Add input meter
	in_peackmeter = new lp_peackmeter(this, channels, buf_size);
	in_pmc = in_peackmeter->get_core();
	layout->addWidget(in_peackmeter, 1, 1);


	// Plugin parameters here
	if(LADSPA_IS_REALTIME(pv_descriptor->Properties)){
		std::cerr << "lp_ladspa_plugin::" << __FUNCTION__ << ": Real time dependencies\n";
	}
	if(LADSPA_IS_INPLACE_BROKEN(pv_descriptor->Properties)){
		std::cerr << "lp_ladspa_plugin::" << __FUNCTION__ << ": INPLACE BROCKEN !\n";
	}
	if(LADSPA_IS_HARD_RT_CAPABLE(pv_descriptor->Properties)){
		std::cerr << "lp_ladspa_plugin::" << __FUNCTION__ << ": Hard RT\n";
	}


	txt_routing = new QLabel;
	layout->addWidget(txt_routing, 0, 0);

	unsigned long i, pcount, ctl_count = 0;
	pcount = descriptor->PortCount;

	// Audio ports - the pv_audio_ports instance manages all audio ports
	pv_audio_ports = new lp_ladspa_audio_ports;
	pv_audio_ports->init(descriptor, channels, buf_size, samplerate);
	txt_routing->setText("Routing mode: " + pv_audio_ports->get_merge_mode_name());
	pv_handles_count = pv_audio_ports->needed_handles_count();
	std::cout << "handles count: " << pv_handles_count << "\n";

	// Count ctl ports
	for(i=0; i<pcount; i++){
		if(LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i])) {
			ctl_count++;
			//std::cout << "Ctl port: " << ctl_count << std::endl;
		}
	}
	pv_ctl_ports = new lp_ladspa_ctl_port[ctl_count];
	// init each ctl port
	ctl_count = 0;
	for(i=0; i<pcount; i++){
		if(LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[i])) {
			if((pv_ctl_ports[ctl_count].init_port(descriptor, i, samplerate, layout, 1, col))<0){
				std::cerr << "lp_ladspa_plugin::" << __FUNCTION__ << ": initialisation failed !\n";
			}
			col++;
			ctl_count++;
		}
	}
	pv_ctl_count = (int)ctl_count;
	// Instanciate plugin
	int y;
	pv_instances = new lp_ladspa_handle[pv_handles_count];
	if(pv_instances == 0){
		std::cerr << "lp_ladspa_plugin::" << __FUNCTION__ << ": plugin instantiation failed\n";
	}
	for(y=0; y<pv_handles_count; y++){
		if(pv_instances[y].instantiate(pv_descriptor, (unsigned long)samplerate) < 0){
			std::cerr << "lp_ladspa_plugin::" << __FUNCTION__ << ": plugin instantiation failed\n";
			return -1;
		}
	}

	// call instantiate
	pv_audio_ports->instantiate(pv_instances);
	for(i=0; i<ctl_count; i++){
		pv_ctl_ports[i].instantiate(pv_instances, pv_handles_count);
	}

	// Add output meter
	out_peackmeter = new lp_peackmeter(this, channels, buf_size);
	out_pmc = out_peackmeter->get_core();
	layout->addWidget(out_peackmeter, 1, pv_ctl_count + 2);

	setLayout(layout);
	setWindowTitle(pv_descriptor->Name);

	return 0;
}
int pa__init(pa_module*m) {
    struct userdata *u;
    pa_sample_spec ss;
    pa_channel_map map;
    pa_modargs *ma;
    char *t;
    pa_sink *master;
    pa_sink_input_new_data sink_input_data;
    pa_sink_new_data sink_data;
    const char *plugin, *label, *input_ladspaport_map, *output_ladspaport_map;
    LADSPA_Descriptor_Function descriptor_func;
    unsigned long input_ladspaport[PA_CHANNELS_MAX], output_ladspaport[PA_CHANNELS_MAX];
    const char *e, *cdata;
    const LADSPA_Descriptor *d;
    unsigned long p, h, j, n_control, c;
    pa_bool_t *use_default = NULL;

    pa_assert(m);

    pa_assert_cc(sizeof(LADSPA_Data) == sizeof(float));

    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
        pa_log("Failed to parse module arguments.");
        goto fail;
    }

    if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
        pa_log("Master sink not found");
        goto fail;
    }

    ss = master->sample_spec;
    ss.format = PA_SAMPLE_FLOAT32;
    map = master->channel_map;
    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
        pa_log("Invalid sample format specification or channel map");
        goto fail;
    }

    if (!(plugin = pa_modargs_get_value(ma, "plugin", NULL))) {
        pa_log("Missing LADSPA plugin name");
        goto fail;
    }

    if (!(label = pa_modargs_get_value(ma, "label", NULL))) {
        pa_log("Missing LADSPA plugin label");
        goto fail;
    }

    if (!(input_ladspaport_map = pa_modargs_get_value(ma, "input_ladspaport_map", NULL)))
        pa_log_debug("Using default input ladspa port mapping");

    if (!(output_ladspaport_map = pa_modargs_get_value(ma, "output_ladspaport_map", NULL)))
        pa_log_debug("Using default output ladspa port mapping");

    cdata = pa_modargs_get_value(ma, "control", NULL);

    u = pa_xnew0(struct userdata, 1);
    u->module = m;
    m->userdata = u;
    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);
    u->max_ladspaport_count = 1; /*to avoid division by zero etc. in pa__done when failing before this value has been set*/
    u->channels = 0;
    u->input = NULL;
    u->output = NULL;

    if (!(e = getenv("LADSPA_PATH")))
        e = LADSPA_PATH;

    /* FIXME: This is not exactly thread safe */
    t = pa_xstrdup(lt_dlgetsearchpath());
    lt_dlsetsearchpath(e);
    m->dl = lt_dlopenext(plugin);
    lt_dlsetsearchpath(t);
    pa_xfree(t);

    if (!m->dl) {
        pa_log("Failed to load LADSPA plugin: %s", lt_dlerror());
        goto fail;
    }

    if (!(descriptor_func = (LADSPA_Descriptor_Function) pa_load_sym(m->dl, NULL, "ladspa_descriptor"))) {
        pa_log("LADSPA module lacks ladspa_descriptor() symbol.");
        goto fail;
    }

    for (j = 0;; j++) {

        if (!(d = descriptor_func(j))) {
            pa_log("Failed to find plugin label '%s' in plugin '%s'.", label, plugin);
            goto fail;
        }

        if (strcmp(d->Label, label) == 0)
            break;
    }

    u->descriptor = d;

    pa_log_debug("Module: %s", plugin);
    pa_log_debug("Label: %s", d->Label);
    pa_log_debug("Unique ID: %lu", d->UniqueID);
    pa_log_debug("Name: %s", d->Name);
    pa_log_debug("Maker: %s", d->Maker);
    pa_log_debug("Copyright: %s", d->Copyright);

    n_control = 0;
    u->channels = ss.channels;

    /*
    * Enumerate ladspa ports
    * Default mapping is in order given by the plugin
    */
    for (p = 0; p < d->PortCount; p++) {
        if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {
            if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p])) {
                pa_log_debug("Port %lu is input: %s", p, d->PortNames[p]);
                input_ladspaport[u->input_count] = p;
                u->input_count++;
            } else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) {
                pa_log_debug("Port %lu is output: %s", p, d->PortNames[p]);
                output_ladspaport[u->output_count] = p;
                u->output_count++;
            }
        } else if (LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]) && LADSPA_IS_PORT_INPUT(d->PortDescriptors[p])) {
            pa_log_debug("Port %lu is control: %s", p, d->PortNames[p]);
            n_control++;
        } else
            pa_log_debug("Ignored port %s", d->PortNames[p]);
        /* XXX: Has anyone ever seen an in-place plugin with non-equal number of input and output ports? */
        /* Could be if the plugin is for up-mixing stereo to 5.1 channels */
        /* Or if the plugin is down-mixing 5.1 to two channel stereo or binaural encoded signal */
        if (u->input_count > u->max_ladspaport_count)
            u->max_ladspaport_count = u->input_count;
        else
            u->max_ladspaport_count = u->output_count;
    }

    if (u->channels % u->max_ladspaport_count) {
        pa_log("Cannot handle non-integral number of plugins required for given number of channels");
        goto fail;
    }

    pa_log_debug("Will run %lu plugin instances", u->channels / u->max_ladspaport_count);

    /* Parse data for input ladspa port map */
    if (input_ladspaport_map) {
        const char *state = NULL;
        char *pname;
        c = 0;
        while ((pname = pa_split(input_ladspaport_map, ",", &state))) {
            if (c == u->input_count) {
                pa_log("Too many ports in input ladspa port map");
                goto fail;
            }


            for (p = 0; p < d->PortCount; p++) {
                if (strcmp(d->PortNames[p], pname) == 0) {
                    if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p]) && LADSPA_IS_PORT_INPUT(d->PortDescriptors[p])) {
                        input_ladspaport[c] = p;
                    } else {
                        pa_log("Port %s is not an audio input ladspa port", pname);
                        pa_xfree(pname);
                        goto fail;
                    }
                }
            }
            c++;
            pa_xfree(pname);
        }
    }

    /* Parse data for output port map */
    if (output_ladspaport_map) {
        const char *state = NULL;
        char *pname;
        c = 0;
        while ((pname = pa_split(output_ladspaport_map, ",", &state))) {
            if (c == u->output_count) {
                pa_log("Too many ports in output ladspa port map");
                goto fail;
            }
            for (p = 0; p < d->PortCount; p++) {
                if (strcmp(d->PortNames[p], pname) == 0) {
                    if (LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p]) && LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) {
                        output_ladspaport[c] = p;
                    } else {
                        pa_log("Port %s is not an output ladspa port", pname);
                        pa_xfree(pname);
                        goto fail;
                    }
                }
            }
            c++;
            pa_xfree(pname);
        }
    }


    u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss);

    /* Create buffers */
    if (LADSPA_IS_INPLACE_BROKEN(d->Properties)) {
        u->input = (LADSPA_Data**) pa_xnew(LADSPA_Data*, (unsigned) u->input_count);
        for (c = 0; c < u->input_count; c++)
            u->input[c] = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
        u->output = (LADSPA_Data**) pa_xnew(LADSPA_Data*, (unsigned) u->output_count);
        for (c = 0; c < u->output_count; c++)
            u->output[c] = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
    } else {
Exemple #10
0
static void
gst_ladspa_base_init (gpointer g_class)
{
  GstLADSPAClass *klass = (GstLADSPAClass *) g_class;
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
  GstSignalProcessorClass *gsp_class = GST_SIGNAL_PROCESSOR_CLASS (g_class);
  LADSPA_Descriptor *desc;
  guint j, audio_in_count, audio_out_count, control_in_count, control_out_count;
  const gchar *klass_tags;
  gchar *longname, *author;
#ifdef HAVE_LRDF
  gchar *uri;
#endif
  gchar *extra_klass_tags = NULL;

  GST_DEBUG ("base_init %p", g_class);

  desc = (LADSPA_Descriptor *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
      descriptor_quark);
  g_assert (desc);
  klass->descriptor = desc;

  /* 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 < desc->PortCount; j++) {
    LADSPA_PortDescriptor p = desc->PortDescriptors[j];

    if (LADSPA_IS_PORT_AUDIO (p)) {
      gchar *name = g_strdup ((gchar *) desc->PortNames[j]);

      /* FIXME: group stereo pairs into a stereo pad
       * ladspa-fx have "XXX (Left)" and "XXX (Right)"
       * where XXX={In,Input,Out,Output}
       */

      GST_DEBUG ("LADSPA port name: \"%s\"", name);
      /* replaces all spaces with underscores, and then remaining special chars
       * with '-'
       * FIXME: why, pads can have any name
       */
      g_strdelimit (name, " ", '_');
      g_strcanon (name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_-><=", '-');
      GST_DEBUG ("GStreamer pad name: \"%s\"", name);

      if (LADSPA_IS_PORT_INPUT (p))
        gst_signal_processor_class_add_pad_template (gsp_class, name,
            GST_PAD_SINK, gsp_class->num_audio_in++, 1);
      else
        gst_signal_processor_class_add_pad_template (gsp_class, name,
            GST_PAD_SRC, gsp_class->num_audio_out++, 1);

      g_free (name);
    } else if (LADSPA_IS_PORT_CONTROL (p)) {
      if (LADSPA_IS_PORT_INPUT (p))
        gsp_class->num_control_in++;
      else
        gsp_class->num_control_out++;
    }
  }

  longname = g_locale_to_utf8 (desc->Name, -1, NULL, NULL, NULL);
  if (!longname)
    longname = g_strdup ("no description available");
  author = g_locale_to_utf8 (desc->Maker, -1, NULL, NULL, NULL);
  if (!author)
    author = g_strdup ("no author available");

#ifdef HAVE_LRDF
  /* libldrf support, we want to get extra class information here */
  uri = g_strdup_printf (LADSPA_BASE "%ld", desc->UniqueID);
  if (uri) {
    lrdf_statement query = { 0, };
    lrdf_uris *uris;
    gchar *str, *base_type = NULL;

    GST_DEBUG ("uri (id=%d) : %s", desc->UniqueID, uri);
    /* we can take this directly from 'desc', keep this example for future
       attributes. 
       if ((str = lrdf_get_setting_metadata (uri, "title"))) {
       GST_DEBUG ("title : %s", str);
       }
       if ((str = lrdf_get_setting_metadata (uri, "creator"))) {
       GST_DEBUG ("creator : %s", str);
       }
     */

    /* get the rdf:type for this plugin */
    query.subject = uri;
    query.predicate = (char *) RDF_BASE "type";
    query.object = (char *) "?";
    query.next = NULL;
    uris = lrdf_match_multi (&query);
    if (uris) {
      if (uris->count == 1) {
        base_type = g_strdup (uris->items[0]);
        GST_DEBUG ("base_type :  %s", base_type);
      }
      lrdf_free_uris (uris);
    }

    /* query taxonomy */
    if (base_type) {
      uris = lrdf_get_all_superclasses (base_type);
      if (uris) {
        guint32 j;

        for (j = 0; j < uris->count; j++) {
          GST_LOG ("parent_type_uri : %s", uris->items[j]);
          if ((str = lrdf_get_label (uris->items[j]))) {
            GST_DEBUG ("parent_type_label : %s", str);
            if (extra_klass_tags) {
              gchar *old_tags = extra_klass_tags;
              extra_klass_tags = g_strconcat (extra_klass_tags, "/", str, NULL);
              g_free (old_tags);
            } else {
              extra_klass_tags = g_strconcat ("/", str, NULL);
            }
          }
        }
        lrdf_free_uris (uris);
      }
      g_free (base_type);
    }

    /* we can use this for the presets
       uris = lrdf_get_setting_uris (desc->UniqueID);
       if (uris) {
       guint32 j;

       for (j = 0; j < uris->count; j++) {
       GST_INFO ("setting_uri : %s", uris->items[j]);
       if ((str = lrdf_get_label (uris->items[j]))) {
       GST_INFO ("setting_label : %s", str);
       }
       }
       lrdf_free_uris (uris);
       }
     */

  }
  g_free (uri);
#endif

  if (gsp_class->num_audio_in == 0)
    klass_tags = "Source/Audio/LADSPA";
  else if (gsp_class->num_audio_out == 0) {
    if (gsp_class->num_control_out == 0)
      klass_tags = "Sink/Audio/LADSPA";
    else
      klass_tags = "Sink/Analyzer/Audio/LADSPA";
  } else
    klass_tags = "Filter/Effect/Audio/LADSPA";

#ifdef HAVE_LRDF
  if (extra_klass_tags) {
    char *s = g_strconcat (klass_tags, extra_klass_tags, NULL);
    g_free (extra_klass_tags);
    extra_klass_tags = s;
  }
#endif
  GST_INFO ("tags : %s", klass_tags);
  gst_element_class_set_metadata (element_class, longname,
      extra_klass_tags ? extra_klass_tags : klass_tags, longname, author);
  g_free (longname);
  g_free (author);
  g_free (extra_klass_tags);

  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 < desc->PortCount; j++) {
    LADSPA_PortDescriptor p = desc->PortDescriptors[j];

    if (LADSPA_IS_PORT_AUDIO (p)) {
      if (LADSPA_IS_PORT_INPUT (p))
        klass->audio_in_portnums[audio_in_count++] = j;
      else
        klass->audio_out_portnums[audio_out_count++] = j;
    } else if (LADSPA_IS_PORT_CONTROL (p)) {
      if (LADSPA_IS_PORT_INPUT (p))
        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 (!LADSPA_IS_INPLACE_BROKEN (desc->Properties))
    GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE (klass);

  klass->descriptor = desc;
}
Exemple #11
0
static void dump_info(const LADSPA_Descriptor *ldesc)
{
    int i = 0;

    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Plugin Name: \"%s\"\n", ldesc->Name);
    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Plugin Label: \"%s\"\n", ldesc->Label);
    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Plugin Unique ID: %lu\n", ldesc->UniqueID);
    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Maker: \"%s\"\n", ldesc->Maker);
    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Copyright: \"%s\"\n", ldesc->Copyright);

    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Must Run Real-Time: ");
    if (LADSPA_IS_REALTIME(ldesc->Properties))
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
    else
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");

    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Has activate() Function: ");
    if (ldesc->activate != NULL)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
    else
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Has deactivate() Function: ");
    if (ldesc->deactivate != NULL)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
    else
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");
    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Has run_adding() Function: ");
    if (ldesc->run_adding != NULL)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Yes\n");
    else
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "No\n");

    if (ldesc->instantiate == NULL)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO INSTANTIATE FUNCTION.\n");
    if (ldesc->connect_port == NULL)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO CONNECT_PORT FUNCTION.\n");
    if (ldesc->run == NULL)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO RUN FUNCTION.\n");
    if (ldesc->run_adding != NULL && ldesc->set_run_adding_gain == NULL)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS RUN_ADDING FUNCTION BUT " "NOT SET_RUN_ADDING_GAIN.\n");
    if (ldesc->run_adding == NULL && ldesc->set_run_adding_gain != NULL)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS SET_RUN_ADDING_GAIN FUNCTION BUT " "NOT RUN_ADDING.\n");
    if (ldesc->cleanup == NULL)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: PLUGIN HAS NO CLEANUP FUNCTION.\n");

    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Environment: ");
    if (LADSPA_IS_HARD_RT_CAPABLE(ldesc->Properties))
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Normal or Hard Real-Time\n");
    else
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Normal\n");

    if (LADSPA_IS_INPLACE_BROKEN(ldesc->Properties))
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "This plugin cannot use in-place processing. " "It will not work with all hosts.\n");

    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "Ports:");

    if (ldesc->PortCount == 0)
        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\tERROR: PLUGIN HAS NO PORTS.\n");

    for (i = 0; i < ldesc->PortCount; i++) {
        LADSPA_Data dft = 0.0f;
        int found = 0;

        if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i])) {
            found = find_default(ldesc, i, &dft);
        }

        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n  \"%s\" ", ldesc->PortNames[i]);

        if (LADSPA_IS_PORT_INPUT(ldesc->PortDescriptors[i])
                && LADSPA_IS_PORT_OUTPUT(ldesc->PortDescriptors[i]))
            switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: INPUT AND OUTPUT");
        else if (LADSPA_IS_PORT_INPUT(ldesc->PortDescriptors[i]))
            switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "input");
        else if (LADSPA_IS_PORT_OUTPUT(ldesc->PortDescriptors[i]))
            switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "output");
        else
            switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "ERROR: NEITHER INPUT NOR OUTPUT");

        if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i])
                && LADSPA_IS_PORT_AUDIO(ldesc->PortDescriptors[i]))
            switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", ERROR: CONTROL AND AUDIO");
        else if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i]))
            switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", control");
        else if (LADSPA_IS_PORT_AUDIO(ldesc->PortDescriptors[i]))
            switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", audio");
        else
            switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, ", ERROR: NEITHER CONTROL NOR AUDIO");

        if (LADSPA_IS_PORT_CONTROL(ldesc->PortDescriptors[i])) {
            if (found) {
                switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n    RANGE: %f-%f DEFAULT: %f\n",
                                  ldesc->PortRangeHints[i].LowerBound, ldesc->PortRangeHints[i].UpperBound, dft);
            } else {
                switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n    RANGE: %f-%f DEFAULT: none.\n",
                                  ldesc->PortRangeHints[i].LowerBound, ldesc->PortRangeHints[i].UpperBound);
            }
        }



    }

    switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, "\n\n");
}
Exemple #12
0
static void loadPluginLib(QFileInfo* fi, const PluginType t)
{
    if (debugMsg)
        qWarning("looking up %s", fi->filePath().toAscii().constData());

    void* handle = lib_open(fi->filePath().toAscii().constData());
	if (handle == 0)
	{
		fprintf(stderr, "dlopen(%s) failed: %s\n",
				fi->filePath().toAscii().constData(), dlerror());
		return;
	}

    if (t == PLUGIN_LADSPA)
	{
        LADSPA_Descriptor_Function ladspa = (LADSPA_Descriptor_Function) lib_symbol(handle, "ladspa_descriptor");
		if (!ladspa)
		{
			const char *txt = dlerror();
			if (txt)
			{
				fprintf(stderr,
						"Unable to find ladspa_descriptor() function in plugin "
						"library file \"%s\": %s.\n"
						"Are you sure this is a LADSPA plugin file?\n",
						fi->filePath().toAscii().constData(),
						txt);
			}
            lib_close(handle);
			return;
		}

		const LADSPA_Descriptor* descr;
		for (int i = 0;; ++i)
		{
			descr = ladspa(i);
			if (descr == NULL)
				break;

			// Make sure it doesn't already exist.
			if (plugins.find(fi->completeBaseName(), QString(descr->Label)) != 0)
				continue;

#ifdef PLUGIN_DEBUGIN
			fprintf(stderr, "loadPluginLib: ladspa effect name:%s inPlaceBroken:%d\n", descr->Name, LADSPA_IS_INPLACE_BROKEN(descr->Properties));
#endif
            plugins.add(PLUGIN_LADSPA, fi->absoluteFilePath(), QString(descr->Label), descr);
		}
	}
    else if (t == PLUGIN_VST)
    {
        VST_Function vstfn = (VST_Function) lib_symbol(handle, "VSTPluginMain");

        if (! vstfn)
        {
            vstfn = (VST_Function) lib_symbol(handle, "main");

    #ifdef TARGET_API_MAC_CARBON
            if (! vstfn)
                vstfn = (VST_Function)lib_symbol(lib_handle, "main_macho");
    #endif
        }

        if (! vstfn)
        {
            const char *txt = dlerror();
            if (txt)
            {
                fprintf(stderr,
                        "Unable to find vst entry function in plugin "
                        "library file \"%s\": %s.\n"
                        "Are you sure this is a VST plugin file?\n",
                        fi->filePath().toAscii().constData(),
                        txt);
            }
            lib_close(handle);
            return;
        }

        AEffect* effect = vstfn(VstHostCallback);

        if (effect && (effect->flags & effFlagsCanReplacing) > 0)
        {
            QString PluginLabel = fi->baseName();

            char buf_str[255] = { 0 };
            effect->dispatcher(effect, effOpen, 0, 0, 0, 0.0f);
            effect->dispatcher(effect, effGetProductString, 0, 0, buf_str, 0.0f);

            if (buf_str[0] != 0)
                PluginLabel = QString(buf_str);

            // Make sure it doesn't already exist.
            if (plugins.find(fi->completeBaseName(), QString(PluginLabel)) == 0)
            {
                plugins.add(PLUGIN_VST, fi->absoluteFilePath(), PluginLabel, effect);
            }

            effect->dispatcher(effect, effClose, 0, 0, 0, 0.0f);
        }
    }

    lib_close(handle);
}
int pa__init(pa_module*m) {
    struct userdata *u;
    pa_sample_spec ss;
    pa_channel_map map;
    pa_modargs *ma;
    char *t;
    pa_sink *master;
    pa_sink_input_new_data sink_input_data;
    pa_sink_new_data sink_data;
    const char *plugin, *label;
    LADSPA_Descriptor_Function descriptor_func;
    const char *e, *cdata;
    const LADSPA_Descriptor *d;
    unsigned long input_port, output_port, p, j, n_control;
    unsigned c;
    pa_bool_t *use_default = NULL;

    pa_assert(m);

    pa_assert_cc(sizeof(LADSPA_Data) == sizeof(float));

    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
        pa_log("Failed to parse module arguments.");
        goto fail;
    }

    if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
        pa_log("Master sink not found");
        goto fail;
    }

    ss = master->sample_spec;
    ss.format = PA_SAMPLE_FLOAT32;
    map = master->channel_map;
    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
        pa_log("Invalid sample format specification or channel map");
        goto fail;
    }

    if (!(plugin = pa_modargs_get_value(ma, "plugin", NULL))) {
        pa_log("Missing LADSPA plugin name");
        goto fail;
    }

    if (!(label = pa_modargs_get_value(ma, "label", NULL))) {
        pa_log("Missing LADSPA plugin label");
        goto fail;
    }

    cdata = pa_modargs_get_value(ma, "control", NULL);

    u = pa_xnew0(struct userdata, 1);
    u->module = m;
    m->userdata = u;
    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);

    if (!(e = getenv("LADSPA_PATH")))
        e = LADSPA_PATH;

    /* FIXME: This is not exactly thread safe */
    t = pa_xstrdup(lt_dlgetsearchpath());
    lt_dlsetsearchpath(e);
    m->dl = lt_dlopenext(plugin);
    lt_dlsetsearchpath(t);
    pa_xfree(t);

    if (!m->dl) {
        pa_log("Failed to load LADSPA plugin: %s", lt_dlerror());
        goto fail;
    }

    if (!(descriptor_func = (LADSPA_Descriptor_Function) pa_load_sym(m->dl, NULL, "ladspa_descriptor"))) {
        pa_log("LADSPA module lacks ladspa_descriptor() symbol.");
        goto fail;
    }

    for (j = 0;; j++) {

        if (!(d = descriptor_func(j))) {
            pa_log("Failed to find plugin label '%s' in plugin '%s'.", label, plugin);
            goto fail;
        }

        if (strcmp(d->Label, label) == 0)
            break;
    }

    u->descriptor = d;

    pa_log_debug("Module: %s", plugin);
    pa_log_debug("Label: %s", d->Label);
    pa_log_debug("Unique ID: %lu", d->UniqueID);
    pa_log_debug("Name: %s", d->Name);
    pa_log_debug("Maker: %s", d->Maker);
    pa_log_debug("Copyright: %s", d->Copyright);

    input_port = output_port = (unsigned long) -1;
    n_control = 0;

    for (p = 0; p < d->PortCount; p++) {

        if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {

            if (strcmp(d->PortNames[p], "Input") == 0) {
                pa_assert(input_port == (unsigned long) -1);
                input_port = p;
            } else {
                pa_log("Found audio input port on plugin we cannot handle: %s", d->PortNames[p]);
                goto fail;
            }

        } else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) {

            if (strcmp(d->PortNames[p], "Output") == 0) {
                pa_assert(output_port == (unsigned long) -1);
                output_port = p;
            } else {
                pa_log("Found audio output port on plugin we cannot handle: %s", d->PortNames[p]);
                goto fail;
            }

        } else if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
            n_control++;
        else {
            pa_assert(LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]));
            pa_log_debug("Ignored control output port \"%s\".", d->PortNames[p]);
        }
    }

    if ((input_port == (unsigned long) -1) || (output_port == (unsigned long) -1)) {
        pa_log("Failed to identify input and output ports. "
               "Right now this module can only deal with plugins which provide an 'Input' and an 'Output' audio port. "
               "Patches welcome!");
        goto fail;
    }

    u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss);

    u->input = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
    if (LADSPA_IS_INPLACE_BROKEN(d->Properties))
        u->output = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size);
    else
        u->output = u->input;

    u->channels = ss.channels;

    for (c = 0; c < ss.channels; c++) {
        if (!(u->handle[c] = d->instantiate(d, ss.rate))) {
            pa_log("Failed to instantiate plugin %s with label %s for channel %i", plugin, d->Label, c);
            goto fail;
        }

        d->connect_port(u->handle[c], input_port, u->input);
        d->connect_port(u->handle[c], output_port, u->output);
    }

    if (!cdata && n_control > 0) {
        pa_log("This plugin requires specification of %lu control parameters.", n_control);
        goto fail;
    }

    if (n_control > 0) {
        const char *state = NULL;
        char *k;
        unsigned long h;

        u->control = pa_xnew(LADSPA_Data, (unsigned) n_control);
        use_default = pa_xnew(pa_bool_t, (unsigned) n_control);
        p = 0;

        while ((k = pa_split(cdata, ",", &state)) && p < n_control) {
            double f;

            if (*k == 0) {
                use_default[p++] = TRUE;
                pa_xfree(k);
                continue;
            }

            if (pa_atod(k, &f) < 0) {
                pa_log("Failed to parse control value '%s'", k);
                pa_xfree(k);
                goto fail;
            }

            pa_xfree(k);

            use_default[p] = FALSE;
            u->control[p++] = (LADSPA_Data) f;
        }

        /* The previous loop doesn't take the last control value into account
           if it is left empty, so we do it here. */
        if (*cdata == 0 || cdata[strlen(cdata) - 1] == ',') {
            if (p < n_control)
                use_default[p] = TRUE;
            p++;
        }

        if (p > n_control || k) {
            pa_log("Too many control values passed, %lu expected.", n_control);
            pa_xfree(k);
            goto fail;
        }

        if (p < n_control) {
            pa_log("Not enough control values passed, %lu expected, %lu passed.", n_control, p);
            goto fail;
        }

        h = 0;
        for (p = 0; p < d->PortCount; p++) {
            LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor;

            if (!LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
                continue;

            if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) {
                for (c = 0; c < ss.channels; c++)
                    d->connect_port(u->handle[c], p, &u->control_out);
                continue;
            }

            pa_assert(h < n_control);

            if (use_default[h]) {
                LADSPA_Data lower, upper;

                if (!LADSPA_IS_HINT_HAS_DEFAULT(hint)) {
                    pa_log("Control port value left empty but plugin defines no default.");
                    goto fail;
                }

                lower = d->PortRangeHints[p].LowerBound;
                upper = d->PortRangeHints[p].UpperBound;

                if (LADSPA_IS_HINT_SAMPLE_RATE(hint)) {
                    lower *= (LADSPA_Data) ss.rate;
                    upper *= (LADSPA_Data) ss.rate;
                }

                switch (hint & LADSPA_HINT_DEFAULT_MASK) {

                    case LADSPA_HINT_DEFAULT_MINIMUM:
                        u->control[h] = lower;
                        break;

                    case LADSPA_HINT_DEFAULT_MAXIMUM:
                        u->control[h] = upper;
                        break;

                    case LADSPA_HINT_DEFAULT_LOW:
                        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
                            u->control[h] = (LADSPA_Data) exp(log(lower) * 0.75 + log(upper) * 0.25);
                        else
                            u->control[h] = (LADSPA_Data) (lower * 0.75 + upper * 0.25);
                        break;

                    case LADSPA_HINT_DEFAULT_MIDDLE:
                        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
                            u->control[h] = (LADSPA_Data) exp(log(lower) * 0.5 + log(upper) * 0.5);
                        else
                            u->control[h] = (LADSPA_Data) (lower * 0.5 + upper * 0.5);
                        break;

                    case LADSPA_HINT_DEFAULT_HIGH:
                        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
                            u->control[h] = (LADSPA_Data) exp(log(lower) * 0.25 + log(upper) * 0.75);
                        else
                            u->control[h] = (LADSPA_Data) (lower * 0.25 + upper * 0.75);
                        break;

                    case LADSPA_HINT_DEFAULT_0:
                        u->control[h] = 0;
                        break;

                    case LADSPA_HINT_DEFAULT_1:
                        u->control[h] = 1;
                        break;

                    case LADSPA_HINT_DEFAULT_100:
                        u->control[h] = 100;
                        break;

                    case LADSPA_HINT_DEFAULT_440:
                        u->control[h] = 440;
                        break;

                    default:
                        pa_assert_not_reached();
                }
            }

            if (LADSPA_IS_HINT_INTEGER(hint))
                u->control[h] = roundf(u->control[h]);

            pa_log_debug("Binding %f to port %s", u->control[h], d->PortNames[p]);

            for (c = 0; c < ss.channels; c++)
                d->connect_port(u->handle[c], p, &u->control[h]);

            h++;
        }

        pa_assert(h == n_control);
    }

    if (d->activate)
        for (c = 0; c < u->channels; c++)
            d->activate(u->handle[c]);

    /* Create sink */
    pa_sink_new_data_init(&sink_data);
    sink_data.driver = __FILE__;
    sink_data.module = m;
    if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
        sink_data.name = pa_sprintf_malloc("%s.ladspa", master->name);
    pa_sink_new_data_set_sample_spec(&sink_data, &ss);
    pa_sink_new_data_set_channel_map(&sink_data, &map);
    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
    pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.label", d->Label);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.name", d->Name);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.maker", d->Maker);
    pa_proplist_sets(sink_data.proplist, "device.ladspa.copyright", d->Copyright);
    pa_proplist_setf(sink_data.proplist, "device.ladspa.unique_id", "%lu", (unsigned long) d->UniqueID);

    if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
        pa_log("Invalid properties");
        pa_sink_new_data_done(&sink_data);
        goto fail;
    }

    if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) {
        const char *z;

        z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
        pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name);
    }

    u->sink = pa_sink_new(m->core, &sink_data,
                          PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
                          (master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
    pa_sink_new_data_done(&sink_data);

    if (!u->sink) {
        pa_log("Failed to create sink.");
        goto fail;
    }

    u->sink->parent.process_msg = sink_process_msg_cb;
    u->sink->set_state = sink_set_state_cb;
    u->sink->update_requested_latency = sink_update_requested_latency_cb;
    u->sink->request_rewind = sink_request_rewind_cb;
    u->sink->set_volume = sink_set_volume_cb;
    u->sink->set_mute = sink_set_mute_cb;
    u->sink->userdata = u;

    pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);

    /* Create sink input */
    pa_sink_input_new_data_init(&sink_input_data);
    sink_input_data.driver = __FILE__;
    sink_input_data.module = m;
    sink_input_data.sink = master;
    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "LADSPA Stream");
    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
    pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
    pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);

    pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
    pa_sink_input_new_data_done(&sink_input_data);

    if (!u->sink_input)
        goto fail;

    u->sink_input->pop = sink_input_pop_cb;
    u->sink_input->process_rewind = sink_input_process_rewind_cb;
    u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
    u->sink_input->update_max_request = sink_input_update_max_request_cb;
    u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
    u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
    u->sink_input->kill = sink_input_kill_cb;
    u->sink_input->attach = sink_input_attach_cb;
    u->sink_input->detach = sink_input_detach_cb;
    u->sink_input->state_change = sink_input_state_change_cb;
    u->sink_input->may_move_to = sink_input_may_move_to_cb;
    u->sink_input->moving = sink_input_moving_cb;
    u->sink_input->volume_changed = sink_input_volume_changed_cb;
    u->sink_input->mute_changed = sink_input_mute_changed_cb;
    u->sink_input->userdata = u;

    pa_sink_put(u->sink);
    pa_sink_input_put(u->sink_input);

    pa_modargs_free(ma);

    pa_xfree(use_default);

    return 0;

fail:
    if (ma)
        pa_modargs_free(ma);

    pa_xfree(use_default);

    pa__done(m);

    return -1;
}
Exemple #14
0
static void
gst_ladspa_base_init (gpointer g_class)
{
  GstLADSPAClass *klass = (GstLADSPAClass *) g_class;
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
  GstSignalProcessorClass *gsp_class = GST_SIGNAL_PROCESSOR_CLASS (g_class);
  GstElementDetails *details;
  LADSPA_Descriptor *desc;
  guint j, audio_in_count, audio_out_count, control_in_count, control_out_count;

  GST_DEBUG ("base_init %p", g_class);

  desc = (LADSPA_Descriptor *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
      GST_LADSPA_DESCRIPTOR_QDATA);
  g_assert (desc);
  klass->descriptor = desc;

  /* 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 < desc->PortCount; j++) {
    LADSPA_PortDescriptor p = desc->PortDescriptors[j];

    if (LADSPA_IS_PORT_AUDIO (p)) {
      gchar *name = g_strdup ((gchar *) desc->PortNames[j]);

      /* FIXME: group stereo pairs into a stereo pad
       * ladspa-fx have "XXX (Left)" and "XXX (Right)"
       * where XXX={In,Input,Out,Output}
       */

      GST_DEBUG ("LADSPA port name: \"%s\"", name);
      /* replaces all spaces with underscores, and then remaining special chars
       * with '-'
       * FIXME: why, pads can have any name
       */
      g_strdelimit (name, " ", '_');
      g_strcanon (name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_-><=", '-');
      GST_DEBUG ("GStreamer pad name: \"%s\"", name);

      if (LADSPA_IS_PORT_INPUT (p))
        gst_signal_processor_class_add_pad_template (gsp_class, name,
            GST_PAD_SINK, gsp_class->num_audio_in++);
      else
        gst_signal_processor_class_add_pad_template (gsp_class, name,
            GST_PAD_SRC, gsp_class->num_audio_out++);

      g_free (name);
    } else if (LADSPA_IS_PORT_CONTROL (p)) {
      if (LADSPA_IS_PORT_INPUT (p))
        gsp_class->num_control_in++;
      else
        gsp_class->num_control_out++;
    }
  }

  /* construct the element details struct */
  details = g_new0 (GstElementDetails, 1);
  details->longname = g_locale_to_utf8 (desc->Name, -1, NULL, NULL, NULL);
  if (!details->longname)
    details->longname = g_strdup ("no description available");
  details->description = details->longname;
  details->author = g_locale_to_utf8 (desc->Maker, -1, NULL, NULL, NULL);
  if (!details->author)
    details->author = g_strdup ("no author available");

  if (gsp_class->num_audio_in == 0)
    details->klass = "Source/Audio/LADSPA";
  else if (gsp_class->num_audio_out == 0) {
    if (gsp_class->num_control_out == 0)
      details->klass = "Sink/Audio/LADSPA";
    else
      details->klass = "Sink/Analyzer/Audio/LADSPA";
  } else
    details->klass = "Filter/Effect/Audio/LADSPA";
  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 < desc->PortCount; j++) {
    LADSPA_PortDescriptor p = desc->PortDescriptors[j];

    if (LADSPA_IS_PORT_AUDIO (p)) {
      if (LADSPA_IS_PORT_INPUT (p))
        klass->audio_in_portnums[audio_in_count++] = j;
      else
        klass->audio_out_portnums[audio_out_count++] = j;
    } else if (LADSPA_IS_PORT_CONTROL (p)) {
      if (LADSPA_IS_PORT_INPUT (p))
        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 (!LADSPA_IS_INPLACE_BROKEN (desc->Properties))
    GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE (klass);

  klass->descriptor = desc;
}