Example #1
0
int plugin_tilde_ladspa_open_plugin (Pd_Plugin_Tilde* x,
                                     const char* name,
                                     const char* lib_name,
                                     unsigned long sample_rate)
{
  /* precondition(s) */
  if (x == NULL || lib_name == NULL || name == NULL || sample_rate == 0)
  {
      pd_error(x, "NULL arguments when opening plugin");
      return;
  }

  /* Initialize object struct */
  x->plugin.ladspa.type = NULL;
  x->plugin.ladspa.instance = NULL;
  x->plugin.ladspa.control_input_values = NULL;
  x->plugin.ladspa.control_output_values = NULL;
  x->plugin.ladspa.control_input_ports = NULL;
  x->plugin.ladspa.control_output_ports = NULL;
  x->plugin.ladspa.prev_control_output_values = NULL;
  x->plugin.ladspa.prev_control_output_values_invalid = 1;
  x->plugin.ladspa.outofplace_audio_outputs = NULL;
  x->plugin.ladspa.actual_audio_outputs = NULL;
  x->plugin.ladspa.num_samples = 0;
  x->plugin.ladspa.sample_rate = sample_rate;

  /* Attempt to load the plugin. */
  plugin_tilde_pushlocale();
  x->plugin_library = loadLADSPAPluginLibrary (lib_name);
  if (x->plugin_library == NULL)
    {
      /* error */
      plugin_tilde_poplocale();
      error("plugin~: Unable to load LADSPA plugin library \"%s\"",
           lib_name);
      return 1;
    }
  x->plugin.ladspa.type = findLADSPAPluginDescriptor (x->plugin_library,
                                                      lib_name,
                                                      name);
  plugin_tilde_poplocale();
  if (x->plugin.ladspa.type == NULL)
    {
      error("plugin~: Unable to find LADSPA plugin \"%s\" within library \"%s\"",
           name, lib_name);
      return 1;
    }

  /* Construct the plugin. */
  x->plugin.ladspa.instance
    = x->plugin.ladspa.type->instantiate (x->plugin.ladspa.type,
                                          sample_rate);
  if (x->plugin.ladspa.instance == NULL)
    {
      /* error */
      error("plugin~: Unable to instantiate LADSPA plugin \"%s\"",
           x->plugin.ladspa.type->Name);
      return 1;
    }

  verbose(1, "plugin~: constructed plugin \"%s\" successfully", x->plugin.ladspa.type->Name);

  /* Find out the number of inputs and outputs needed. */
  plugin_tilde_ladspa_count_ports (x);

  /* Allocate memory for control values */
  if (plugin_tilde_ladspa_alloc_control_memory (x)) {
    error("plugin~: out of memory");
    return 1; /* error */
  }

  /* Connect control ports with buffers */
  plugin_tilde_ladspa_connect_control_ports (x);

  /* Activate the plugin. */
  if (x->plugin.ladspa.type->activate != NULL)
    {
      x->plugin.ladspa.type->activate (x->plugin.ladspa.instance);
    }

  /* success */
  return 0;
}
/* 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);
}
Example #3
0
static switch_bool_t ladspa_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
    switch_ladspa_t *pvt = (switch_ladspa_t *) user_data;
    //switch_frame_t *frame = NULL;
    switch_channel_t *channel = switch_core_session_get_channel(pvt->session);

    switch (type) {
    case SWITCH_ABC_TYPE_INIT:
    {
        switch_codec_implementation_t read_impl = { 0 };
        LADSPA_PortDescriptor port_desc;
        int i = 0, j = 0, k = 0, str_idx = 0;

        switch_core_session_get_read_impl(pvt->session, &read_impl);

        if (!(pvt->library_handle = loadLADSPAPluginLibrary(pvt->plugin_name))) {
            return SWITCH_FALSE;
        }

        if (!(pvt->ldesc = findLADSPAPluginDescriptor(pvt->library_handle, pvt->plugin_name, pvt->label_name))) {
            return SWITCH_FALSE;
        }


        pvt->handle = pvt->ldesc->instantiate(pvt->ldesc, read_impl.actual_samples_per_second);

        dump_info(pvt->ldesc);


        for (i = 0; i < pvt->ldesc->PortCount; i++) {
            port_desc = pvt->ldesc->PortDescriptors[i];

            if (LADSPA_IS_PORT_CONTROL(port_desc) && LADSPA_IS_PORT_INPUT(port_desc)) {
                LADSPA_Data dft = 0.0f;
                int found = find_default(pvt->ldesc, i, &dft);

                if (found && !pvt->has_config[j]) {
                    pvt->config[j] = dft;
                    pvt->has_config[j] = 1;
                }

                if (pvt->has_config[j]) {
                    if (!check_range(pvt->ldesc, i, pvt->config[j])) {
                        pvt->config[j] = dft;
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_WARNING, "FALLING TO DEFAULT PARAM %d [%s] (%f)\n",
                                          j+1,
                                          pvt->ldesc->PortNames[i],
                                          pvt->config[j]);
                    }

                    switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "ADDING PARAM %d [%s] (%f)\n",
                                      j+1,
                                      pvt->ldesc->PortNames[i],
                                      pvt->config[j]);
                    pvt->ldesc->connect_port(pvt->handle, i, &pvt->config[j++]);
                    usleep(10000);
                }
            }

            if (LADSPA_IS_PORT_INPUT(port_desc) && LADSPA_IS_PORT_AUDIO(port_desc)) {
                int mapped = 0;

                if (pvt->str_idx && !zstr(pvt->str_config[str_idx])) {

                    if (!strcasecmp(pvt->str_config[str_idx], "none")) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT NOTHING to port: %s\n",
                                          pvt->ldesc->PortNames[i]
                                         );
                        mapped = 1;
                    } else if (!strncasecmp(pvt->str_config[str_idx], "file:", 5)) {
                        char *file = pvt->str_config[str_idx] + 5;

                        if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) {
                            switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session),
                                              SWITCH_LOG_ERROR, "CAN'T CONNECT FILE [%s] File already mapped\n", file);
                        } else {
                            if (switch_core_file_open(&pvt->fh,
                                                      file,
                                                      read_impl.number_of_channels,
                                                      read_impl.actual_samples_per_second,
                                                      SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot open file: %s\n", file);
                                return SWITCH_FALSE;
                            }


                            switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT FILE [%s] to port: %s\n",
                                              file,
                                              pvt->ldesc->PortNames[i]
                                             );

                            pvt->ldesc->connect_port(pvt->handle, i, pvt->file_buf);
                            mapped = 1;
                        }
                    }

                    str_idx++;
                }

                if (!mapped) {
                    pvt->ldesc->connect_port(pvt->handle, i, pvt->in_buf);
                    switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "CONNECT CHANNEL AUDIO to port: %s\n",
                                      pvt->ldesc->PortNames[i]
                                     );
                }

            }

            if (LADSPA_IS_PORT_OUTPUT(port_desc)) {
                if (LADSPA_IS_PORT_AUDIO(port_desc)) {
                    pvt->ldesc->connect_port(pvt->handle, i, pvt->out_buf);
                } else if (k < MAX_INDEX) {
                    pvt->ldesc->connect_port(pvt->handle, i, &pvt->out_ports[k++]);
                }
            }
        }
    }

    break;

    case SWITCH_ABC_TYPE_CLOSE:
    {

        if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) {
            switch_core_file_close(&pvt->fh);
        }

        if (pvt->handle && pvt->ldesc) {
            pvt->ldesc->cleanup(pvt->handle);
        }

        if (pvt->library_handle) {
            unloadLADSPAPluginLibrary(pvt->library_handle);
        }
    }
    break;

    case SWITCH_ABC_TYPE_WRITE_REPLACE:
    case SWITCH_ABC_TYPE_READ_REPLACE:
    {
        switch_frame_t *rframe;
        int16_t *slin, abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] =  { 0 };
        switch_size_t olen = 0;


        if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
            rframe = switch_core_media_bug_get_read_replace_frame(bug);
        } else {
            rframe = switch_core_media_bug_get_write_replace_frame(bug);
        }

        slin = rframe->data;

        if (switch_channel_media_ready(channel)) {
            switch_short_to_float(slin, pvt->in_buf, rframe->samples);

            if (switch_test_flag((&pvt->fh), SWITCH_FILE_OPEN)) {
                olen = rframe->samples;
                if (switch_core_file_read(&pvt->fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
                    switch_codec_implementation_t read_impl = { 0 };
                    char *file = switch_core_session_strdup(pvt->session, pvt->fh.file_path);
                    switch_core_session_get_read_impl(pvt->session, &read_impl);

                    switch_core_file_close(&pvt->fh);

                    if (switch_core_file_open(&pvt->fh,
                                              file,
                                              read_impl.number_of_channels,
                                              read_impl.actual_samples_per_second,
                                              SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot open file: %s\n", file);
                        return SWITCH_FALSE;
                    }

                    olen = rframe->samples;
                    if (switch_core_file_read(&pvt->fh, abuf, &olen) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_ERROR, "Cannot READ file: %s\n", file);
                        return SWITCH_FALSE;
                    }
                }

                switch_short_to_float(abuf, pvt->file_buf, olen);
            }

            pvt->ldesc->run(pvt->handle, rframe->samples);

            switch_float_to_short(pvt->out_buf, slin, rframe->samples);
        }

        if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
            switch_core_media_bug_set_read_replace_frame(bug, rframe);
        } else {
            switch_core_media_bug_set_write_replace_frame(bug, rframe);
        }

        if (pvt->skip && !--pvt->skip) {
            return SWITCH_FALSE;
        }

    }
    break;
    case SWITCH_ABC_TYPE_WRITE:
    default:
        break;
    }

    return SWITCH_TRUE;
}