static PluginData * open_plugin (const char * path, const LADSPA_Descriptor * desc) { const char * slash = strrchr (path, G_DIR_SEPARATOR); g_return_val_if_fail (slash && slash[1], NULL); g_return_val_if_fail (desc->Label && desc->Name, NULL); PluginData * plugin = g_slice_new (PluginData); plugin->path = g_strdup (slash + 1); plugin->desc = desc; plugin->controls = index_new (); plugin->in_ports = g_array_new (0, 0, sizeof (int)); plugin->out_ports = g_array_new (0, 0, sizeof (int)); plugin->selected = 0; for (int i = 0; i < desc->PortCount; i ++) { if (LADSPA_IS_PORT_CONTROL (desc->PortDescriptors[i])) { ControlData * control = parse_control (desc, i); if (control) index_append (plugin->controls, control); } else if (LADSPA_IS_PORT_AUDIO (desc->PortDescriptors[i]) && LADSPA_IS_PORT_INPUT (desc->PortDescriptors[i])) g_array_append_val (plugin->in_ports, i); else if (LADSPA_IS_PORT_AUDIO (desc->PortDescriptors[i]) && LADSPA_IS_PORT_OUTPUT (desc->PortDescriptors[i])) g_array_append_val (plugin->out_ports, i); } return plugin; }
LadspaPluginInfo::LadspaPluginInfo (const QString &path, const LADSPA_Descriptor *desc) : PluginInfo(), m_path(path), m_descriptor(desc) { printf("PATH %s %s\n",qPrintable(path), desc->Name); setName(desc->Name); setAuthorName(desc->Maker); setUniqueId(QString("%1%2").arg( UriRoot ).arg( m_descriptor->UniqueID )); int inCnt = 0, outCnt = 0; for (unsigned long i=0; i < desc->PortCount; ++i) { LADSPA_PortDescriptor p = desc->PortDescriptors[i]; if (LADSPA_IS_PORT_AUDIO(p)) { if (LADSPA_IS_PORT_INPUT(p)) { ++inCnt; } else if (LADSPA_IS_PORT_OUTPUT(p)) { ++outCnt; } } } setAudioInputCount(inCnt); setAudioOutputCount(outCnt); }
static void plugin_tilde_ladspa_connect_control_ports (Pd_Plugin_Tilde* x) { unsigned port_index = 0; unsigned input_count = 0; unsigned output_count = 0; input_count = 0; output_count = 0; for (port_index = 0; port_index < x->plugin.ladspa.type->PortCount; port_index++) { LADSPA_PortDescriptor port_type; port_type = x->plugin.ladspa.type->PortDescriptors[port_index]; if (LADSPA_IS_PORT_CONTROL (port_type)) { if (LADSPA_IS_PORT_INPUT (port_type)) { x->plugin.ladspa.type->connect_port (x->plugin.ladspa.instance, port_index, &x->plugin.ladspa.control_input_values[input_count]); x->plugin.ladspa.control_input_ports[input_count] = port_index; input_count++; } else if (LADSPA_IS_PORT_OUTPUT (port_type)) { x->plugin.ladspa.type->connect_port (x->plugin.ladspa.instance, port_index, &x->plugin.ladspa.control_output_values[output_count]); x->plugin.ladspa.control_output_ports[output_count] = port_index; output_count++; } } } }
static void plugin_tilde_ladspa_count_ports (Pd_Plugin_Tilde* x) { unsigned i = 0; x->num_audio_inputs = 0; x->num_audio_outputs = 0; x->num_control_inputs = 0; x->num_control_outputs = 0; for (i = 0; i < x->plugin.ladspa.type->PortCount; i++) { LADSPA_PortDescriptor port_type; port_type = x->plugin.ladspa.type->PortDescriptors[i]; if (LADSPA_IS_PORT_AUDIO (port_type)) { if (LADSPA_IS_PORT_INPUT (port_type)) { x->num_audio_inputs++; } else if (LADSPA_IS_PORT_OUTPUT (port_type)) { x->num_audio_outputs++; } } else if (LADSPA_IS_PORT_CONTROL (port_type)) { if (LADSPA_IS_PORT_INPUT (port_type)) { x->num_control_inputs++; } else if (LADSPA_IS_PORT_OUTPUT (port_type)) { x->num_control_outputs++; } } } verbose(1, "plugin~: plugin ports: audio %d/%d ctrl %d/%d", x->num_audio_inputs, x->num_audio_outputs, x->num_control_inputs, x->num_control_outputs); }
// Derived methods. bool qtractorLadspaPluginType::open (void) { // Do we have a descriptor already? if (m_pLadspaDescriptor == NULL) m_pLadspaDescriptor = ladspa_descriptor(file(), index()); if (m_pLadspaDescriptor == NULL) return false; #ifdef CONFIG_DEBUG qDebug("qtractorLadspaPluginType[%p]::open() filename=\"%s\" index=%lu", this, filename().toUtf8().constData(), index()); #endif // Retrieve plugin type names. m_sName = m_pLadspaDescriptor->Name; m_sLabel = m_pLadspaDescriptor->Label; // Retrieve plugin unique identifier. m_iUniqueID = m_pLadspaDescriptor->UniqueID; // Compute and cache port counts... m_iControlIns = 0; m_iControlOuts = 0; m_iAudioIns = 0; m_iAudioOuts = 0; m_iMidiIns = 0; m_iMidiOuts = 0; for (unsigned long i = 0; i < m_pLadspaDescriptor->PortCount; ++i) { const LADSPA_PortDescriptor portType = m_pLadspaDescriptor->PortDescriptors[i]; if (LADSPA_IS_PORT_INPUT(portType)) { if (LADSPA_IS_PORT_AUDIO(portType)) ++m_iAudioIns; else if (LADSPA_IS_PORT_CONTROL(portType)) ++m_iControlIns; } else if (LADSPA_IS_PORT_OUTPUT(portType)) { if (LADSPA_IS_PORT_AUDIO(portType)) ++m_iAudioOuts; else if (LADSPA_IS_PORT_CONTROL(portType)) ++m_iControlOuts; } } // Cache flags. m_bRealtime = LADSPA_IS_HARD_RT_CAPABLE(m_pLadspaDescriptor->Properties); // Done. return true; }
// Constructors. qtractorLadspaPlugin::qtractorLadspaPlugin ( qtractorPluginList *pList, qtractorLadspaPluginType *pLadspaType ) : qtractorPlugin(pList, pLadspaType), m_phInstances(NULL), m_piControlOuts(NULL), m_pfControlOuts(NULL), m_piAudioIns(NULL), m_piAudioOuts(NULL) { #ifdef CONFIG_DEBUG qDebug("qtractorLadspaPlugin[%p] filename=\"%s\" index=%lu typeHint=%d", this, type()->filename().toUtf8().constData(), type()->index(), int(type()->typeHint())); #endif // Get some structural data first... const LADSPA_Descriptor *pLadspaDescriptor = pLadspaType->ladspa_descriptor(); if (pLadspaDescriptor) { unsigned short iControlOuts = pLadspaType->controlOuts(); unsigned short iAudioIns = pLadspaType->audioIns(); unsigned short iAudioOuts = pLadspaType->audioOuts(); if (iAudioIns > 0) m_piAudioIns = new unsigned long [iAudioIns]; if (iAudioOuts > 0) m_piAudioOuts = new unsigned long [iAudioOuts]; if (iControlOuts > 0) { m_piControlOuts = new unsigned long [iControlOuts]; m_pfControlOuts = new float [iControlOuts]; } iControlOuts = iAudioIns = iAudioOuts = 0; for (unsigned long i = 0; i < pLadspaDescriptor->PortCount; ++i) { const LADSPA_PortDescriptor portType = pLadspaDescriptor->PortDescriptors[i]; if (LADSPA_IS_PORT_INPUT(portType)) { if (LADSPA_IS_PORT_AUDIO(portType)) m_piAudioIns[iAudioIns++] = i; else if (LADSPA_IS_PORT_CONTROL(portType)) addParam(new qtractorLadspaPluginParam(this, i)); } else if (LADSPA_IS_PORT_OUTPUT(portType)) { if (LADSPA_IS_PORT_AUDIO(portType)) m_piAudioOuts[iAudioOuts++] = i; else if (LADSPA_IS_PORT_CONTROL(portType)) { m_piControlOuts[iControlOuts] = i; m_pfControlOuts[iControlOuts] = 0.0f; ++iControlOuts; } } } // FIXME: instantiate each instance properly... qtractorLadspaPlugin::setChannels(channels()); } }
LadspaEffect::LadspaEffect(const LADSPA_Descriptor *data) { mData = data; pluginName = data->Name; buffer = NULL; fInBuffer = NULL; fOutBuffer = NULL; inputs = 0; outputs = 0; numInputControls = 0; unsigned long p; inputPorts = new unsigned long [mData->PortCount]; outputPorts = new unsigned long [mData->PortCount]; inputControls = new float [mData->PortCount]; outputControls = new float [mData->PortCount]; for(p=0; p<mData->PortCount; p++) { LADSPA_PortDescriptor d = mData->PortDescriptors[p]; if (LADSPA_IS_PORT_AUDIO(d)) { if (LADSPA_IS_PORT_INPUT(d)) { inputPorts[inputs] = p; inputs++; } else if (LADSPA_IS_PORT_OUTPUT(d)) { outputPorts[outputs] = p; outputs++; } } if (LADSPA_IS_PORT_CONTROL(d) && LADSPA_IS_PORT_INPUT(d)) { numInputControls++; float val = 1.0; LADSPA_PortRangeHint hint = mData->PortRangeHints[p]; if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) && val < hint.LowerBound) val = hint.LowerBound; if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) && val > hint.UpperBound) val = hint.UpperBound; if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor)) val *= 44100; inputControls[p] = val; } } }
static int ladspa_open(void *arg) { struct lp *plu = arg; void *dl_handle; LADSPA_Descriptor_Function pfDescriptorFunction; const LADSPA_Descriptor *psDescriptor; int i; struct lads *lad = &ladspas[num_ladspas]; assert(plu->plugin && plu->name); dl_handle = loadLADSPAPluginLibrary(plu->plugin); if (!dl_handle) { error("ladspa: failed to load %s\n", plu->plugin); return 0; } pfDescriptorFunction = (LADSPA_Descriptor_Function) dlsym(dl_handle, "ladspa_descriptor"); if (!pfDescriptorFunction) { error("ladspa: %s: %s\n", plu->plugin, dlerror()); goto out_err; } for (i = 0;; i++) { psDescriptor = pfDescriptorFunction(i); if (!psDescriptor) break; if (strcmp(plu->name, psDescriptor->Label) == 0) break; } if (!psDescriptor) { error("ladspa: failed to find %s\n", plu->name); goto out_err; } assert(num_ladspas < MAX_LADSPAS); for (i = 0; i < psDescriptor->PortCount; i++) { if (LADSPA_IS_PORT_INPUT(psDescriptor->PortDescriptors[i]) && LADSPA_IS_PORT_AUDIO(psDescriptor->PortDescriptors[i])) lad->in = i; else if (LADSPA_IS_PORT_OUTPUT(psDescriptor->PortDescriptors[i]) && LADSPA_IS_PORT_AUDIO(psDescriptor->PortDescriptors[i])) lad->out = i; else if (LADSPA_IS_PORT_CONTROL(psDescriptor->PortDescriptors[i])) lad->ctrl = i; } lad->descriptor = psDescriptor; lad->dl_handle = dl_handle; lad->link = arg; num_ladspas++; return 1; out_err: dlclose(dl_handle); return 0; }
int PluginAClientLAD::get_outchannels() { int result = 0; const LADSPA_Descriptor *lad_desc = server->lad_descriptor; const LADSPA_PortDescriptor *port_desc = lad_desc->PortDescriptors; int port_count = lad_desc->PortCount; for( int i = 0; i < port_count; ++i ) { if( !LADSPA_IS_PORT_OUTPUT(port_desc[i]) ) continue; if( !LADSPA_IS_PORT_AUDIO(port_desc[i]) ) continue; ++result; } return result; }
static void plugin_init_holder (plugin_t * plugin, guint copy, LADSPA_Handle instance, jack_rack_t * jack_rack) { unsigned long i; plugin_desc_t * desc; ladspa_holder_t * holder; desc = plugin->desc; holder = plugin->holders + copy; holder->instance = instance; if (desc->control_port_count > 0) { holder->ui_control_fifos = g_malloc (sizeof (lff_t) * desc->control_port_count); holder->control_memory = g_malloc (sizeof (LADSPA_Data) * desc->control_port_count); } else { holder->ui_control_fifos = NULL; holder->control_memory = NULL; } for (i = 0; i < desc->control_port_count; i++) { lff_init (holder->ui_control_fifos + i, CONTROL_FIFO_SIZE, sizeof (LADSPA_Data)); holder->control_memory[i] = plugin_desc_get_default_control_value (desc, desc->control_port_indicies[i], sample_rate); plugin->descriptor-> connect_port (instance, desc->control_port_indicies[i], holder->control_memory + i); } for (i = 0; i < desc->port_count; i++) { if (!LADSPA_IS_PORT_CONTROL (desc->port_descriptors[i])) continue; if (LADSPA_IS_PORT_OUTPUT (desc->port_descriptors[i])) plugin->descriptor-> connect_port (instance, i, &unused_control_port_output); } if (jack_rack->procinfo->jack_client && plugin->desc->aux_channels > 0) plugin_create_aux_ports (plugin, copy, jack_rack); if (plugin->descriptor->activate) plugin->descriptor->activate (instance); }
void plugin_tilde_ladspa_connect_audio (Pd_Plugin_Tilde* x, float** audio_inputs, float** audio_outputs, unsigned long num_samples) { unsigned port_index = 0; unsigned input_count = 0; unsigned output_count = 0; if(!plugin_tilde_have_plugin(x))return; /* Allocate out-of-place memory if needed */ if (plugin_tilde_ladspa_alloc_outofplace_memory (x, num_samples)) { error("plugin~: out of memory"); return; } if (x->plugin.ladspa.outofplace_audio_outputs != NULL) { x->plugin.ladspa.actual_audio_outputs = audio_outputs; audio_outputs = x->plugin.ladspa.outofplace_audio_outputs; } input_count = 0; output_count = 0; for (port_index = 0; port_index < x->plugin.ladspa.type->PortCount; port_index++) { LADSPA_PortDescriptor port_type; port_type = x->plugin.ladspa.type->PortDescriptors[port_index]; if (LADSPA_IS_PORT_AUDIO (port_type)) { if (LADSPA_IS_PORT_INPUT (port_type)) { x->plugin.ladspa.type->connect_port (x->plugin.ladspa.instance, port_index, (LADSPA_Data*)audio_inputs[input_count]); input_count++; } else if (LADSPA_IS_PORT_OUTPUT (port_type)) { x->plugin.ladspa.type->connect_port (x->plugin.ladspa.instance, port_index, (LADSPA_Data*)audio_outputs[output_count]); output_count++; } } } x->plugin.ladspa.num_samples = num_samples; }
static void plugin_tilde_info (Pd_Plugin_Tilde* x) { unsigned port_index = 0; t_atom at[5]; LADSPA_PortDescriptor port_type; LADSPA_PortRangeHintDescriptor iHintDescriptor; if(!plugin_tilde_have_plugin(x))return; for (port_index = 0; port_index < x->plugin.ladspa.type->PortCount; port_index++) { port_type = x->plugin.ladspa.type->PortDescriptors[port_index]; iHintDescriptor = x->plugin.ladspa.type->PortRangeHints[port_index].HintDescriptor; t_symbol*xlet=gensym("unknown"); t_symbol*type=gensym("unknown"); t_symbol*name=gensym("unknown"); t_float bound_lo=0.; t_float bound_hi=1.; if(LADSPA_IS_PORT_INPUT (port_type)) xlet=gensym("in"); else if (LADSPA_IS_PORT_OUTPUT (port_type)) xlet=gensym("out"); if (LADSPA_IS_PORT_CONTROL (port_type)) type=gensym("control"); else if (LADSPA_IS_PORT_AUDIO (port_type)) type=gensym("audio"); name=gensym(x->plugin.ladspa.type->PortNames[port_index]); if (LADSPA_IS_HINT_BOUNDED_BELOW(iHintDescriptor)) bound_lo=x->plugin.ladspa.type->PortRangeHints[port_index].LowerBound; if (LADSPA_IS_HINT_BOUNDED_ABOVE(iHintDescriptor)) bound_hi=x->plugin.ladspa.type->PortRangeHints[port_index].UpperBound; // post("port#%d: %s %s %s %f..%f", port_index, xlet->s_name, type->s_name, name->s_name, bound_lo, bound_hi); SETSYMBOL(at+0, xlet); SETSYMBOL(at+1, type); SETSYMBOL(at+2, name); SETFLOAT (at+3, bound_lo); SETFLOAT (at+4, bound_hi); outlet_anything (x->control_outlet, gensym ("port"), 5, at); } }
void LADSPA_Ctor(LADSPA *unit) { LADSPA_Descriptor key, *keyp = &key; const LADSPA_Descriptor **found; unit->desc = NULL; unit->handle = NULL; unit->requested_channels = (int) IN0(0); if(unit->requested_channels < 1) { Print("LADSPA: Must request more than 0 channels\n"); unit->mDone = true; SETCALC(ClearUnitOutputs); return; } key.UniqueID = (unsigned long) IN0(1); found = (const LADSPA_Descriptor**) bsearch(&keyp, &plugins[0], plugins_index, sizeof(LADSPA_Descriptor*), desc_cmp); if(!found) { Print("LADSPA: ERROR, plugin %lu not found!\n",key.UniqueID); unit->mDone = true; SETCALC(ClearUnitOutputs); return; } else { unit->desc = *found; } unit->handle = unit->desc->instantiate(unit->desc,SAMPLERATE); int in_index = 2, out_index = 0; for(unsigned long i = 0; i < unit->desc->PortCount; i++) { if(LADSPA_IS_PORT_INPUT(unit->desc->PortDescriptors[i])) { unit->desc->connect_port(unit->handle,i,IN(in_index++)); } else if(LADSPA_IS_PORT_OUTPUT(unit->desc->PortDescriptors[i])) { if(out_index<unit->requested_channels && LADSPA_IS_PORT_AUDIO(unit->desc->PortDescriptors[i])) unit->desc->connect_port(unit->handle,i,OUT(out_index++)); } } unit->plugin_channels = out_index; // printf("output channels: ladspa: %d ugen: %d\n",unit->plugin_channels,unit->requested_channels); if(unit->desc->activate) unit->desc->activate(unit->handle); SETCALC(LADSPA_next); }
unsigned long lp_ladspa_audio_ports::get_lad_output_pos(int pos) { // Set the ports and descriptor int out_count = 0; unsigned long i; for(i=0; i<pv_descriptor->PortCount; i++){ if((LADSPA_IS_PORT_AUDIO(pv_descriptor->PortDescriptors[i]))&&(LADSPA_IS_PORT_OUTPUT(pv_descriptor->PortDescriptors[i]))){ if(out_count == pos){ return i; } out_count++; } } return -1; }
static void count_ports(const LADSPA_Descriptor *desc, unsigned long *nb_inputs, unsigned long *nb_outputs) { LADSPA_PortDescriptor pd; int i; for (i = 0; i < desc->PortCount; i++) { pd = desc->PortDescriptors[i]; if (LADSPA_IS_PORT_AUDIO(pd)) { if (LADSPA_IS_PORT_INPUT(pd)) { (*nb_inputs)++; } else if (LADSPA_IS_PORT_OUTPUT(pd)) { (*nb_outputs)++; } } } }
void WiredLADSPAInstance::LoadPorts() { unsigned long pos; t_ladspa_port CurrentPort; UnLoadPorts(); for (pos = 0, CurrentPort.Descriptor = 0, CurrentPort.Id = 0, CurrentPort.RangeHint.LowerBound = 0, CurrentPort.RangeHint.UpperBound = 0, CurrentPort.RangeHint.HintDescriptor = 0; pos < _Descriptor->PortCount; pos ++, CurrentPort.Descriptor = 0, CurrentPort.Id = 0, CurrentPort.RangeHint.LowerBound = 0, CurrentPort.RangeHint.UpperBound = 0, CurrentPort.RangeHint.HintDescriptor = 0) { CurrentPort.Descriptor = _Descriptor->PortDescriptors[pos]; CurrentPort.RangeHint = _Descriptor->PortRangeHints[pos]; CurrentPort.Id = pos; CurrentPort.Name = wxString(_Descriptor->PortNames[pos], *wxConvCurrent); if (LADSPA_IS_PORT_INPUT(CurrentPort.Descriptor)) { if (LADSPA_IS_PORT_CONTROL(CurrentPort.Descriptor)) { _InputDataPluginsPorts.insert(_InputDataPluginsPorts.end(), CurrentPort); AddGuiControl(&CurrentPort); } else if (LADSPA_IS_PORT_AUDIO(CurrentPort.Descriptor)) { _InputAudioPluginsPorts.insert(_InputAudioPluginsPorts.end(), CurrentPort); _Type |= TYPE_PLUGINS_EFFECT; } } else if (LADSPA_IS_PORT_OUTPUT(CurrentPort.Descriptor)) { if (LADSPA_IS_PORT_CONTROL(CurrentPort.Descriptor)) { ConnectMonoOutput((float *) new LADSPA_Data, pos); _OutputDataPluginsPorts.insert(_OutputDataPluginsPorts.end(), CurrentPort); } else if (LADSPA_IS_PORT_AUDIO(CurrentPort.Descriptor)) _OutputAudioPluginsPorts.insert(_OutputAudioPluginsPorts.end(), CurrentPort); } } if (!(_Type & TYPE_PLUGINS_EFFECT)) _Type |= TYPE_PLUGINS_INSTR; //DumpPorts(); }
bool LadspaManager::isPortOutput( const ladspa_key_t & _plugin, uint32_t _port ) { if( m_ladspaManagerMap.contains( _plugin ) && _port < getPortCount( _plugin ) ) { LADSPA_Descriptor_Function descriptorFunction = m_ladspaManagerMap[_plugin]->descriptorFunction; const LADSPA_Descriptor * descriptor = descriptorFunction( m_ladspaManagerMap[_plugin]->index ); return( LADSPA_IS_PORT_OUTPUT ( descriptor->PortDescriptors[_port] ) ); } else { return( false ); } }
uint16_t LadspaManager::getPluginOutputs( const LADSPA_Descriptor * _descriptor ) { uint16_t outputs = 0; for( uint16_t port = 0; port < _descriptor->PortCount; port++ ) { if( LADSPA_IS_PORT_OUTPUT( _descriptor->PortDescriptors[port] ) && LADSPA_IS_PORT_AUDIO( _descriptor->PortDescriptors[port] ) ) { QString name = QString( _descriptor->PortNames[port] ); if( name.toUpper().contains( "OUT" ) ) { outputs++; } } } return outputs; }
static void plugin_desc_set_port_counts (plugin_desc_t * pd) { unsigned long i; unsigned long icount = 0; unsigned long ocount = 0; for (i = 0; i < pd->port_count; i++) { if (LADSPA_IS_PORT_AUDIO (pd->port_descriptors[i])) { if (LADSPA_IS_PORT_INPUT (pd->port_descriptors[i])) plugin_desc_add_audio_port_index (&pd->audio_input_port_indicies, &icount, i); else plugin_desc_add_audio_port_index (&pd->audio_output_port_indicies, &ocount, i); } else { if (LADSPA_IS_PORT_OUTPUT (pd->port_descriptors[i])) continue; pd->control_port_count++; if (pd->control_port_count == 0) pd->control_port_indicies = g_malloc (sizeof (unsigned long) * pd->control_port_count); else pd->control_port_indicies = g_realloc (pd->control_port_indicies, sizeof (unsigned long) * pd->control_port_count); pd->control_port_indicies[pd->control_port_count - 1] = i; } } if (icount == ocount) pd->channels = icount; else if( icount == 0 ) { pd->channels = ocount; pd->has_input = FALSE; } else { /* deal with auxilliary ports */ unsigned long ** port_indicies; unsigned long port_count; unsigned long i, j; if (icount > ocount) { pd->channels = ocount; pd->aux_channels = icount - ocount; pd->aux_are_input = TRUE; port_indicies = &pd->audio_input_port_indicies; port_count = icount; } else { pd->channels = icount; pd->aux_channels = ocount - icount; pd->aux_are_input = FALSE; port_indicies = &pd->audio_output_port_indicies; port_count = ocount; } /* allocate indicies */ pd->audio_aux_port_indicies = g_malloc (sizeof (unsigned long) * pd->aux_channels); /* copy indicies */ for (i = pd->channels, j = 0; i < port_count; i++, j++) pd->audio_aux_port_indicies[j] = (*port_indicies)[i]; /* shrink the main indicies to only have channels indicies */ *port_indicies = g_realloc (*port_indicies, sizeof (unsigned long) * pd->channels); } }
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; }
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"); }
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; }
/** * ags_recall_dssi_run_load_ports: * @recall_dssi_run: the #AgsRecallDssiRun * * Set up DSSI ports. * * Since: 2.0.0 */ void ags_recall_dssi_run_load_ports(AgsRecallDssiRun *recall_dssi_run) { AgsRecallDssi *recall_dssi; AgsRecallChannelRun *recall_channel_run; AgsRecallRecycling *recall_recycling; AgsPort *current_port; AgsDssiPlugin *dssi_plugin; GList *list_start, *list; gchar *specifier, *current_specifier; guint output_lines, input_lines; guint port_count; guint i, j, j_stop; DSSI_Descriptor *plugin_descriptor; LADSPA_PortDescriptor *port_descriptor; LADSPA_PortDescriptor current_port_descriptor; void (*connect_port)(LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation); pthread_mutex_t *recall_dssi_mutex; pthread_mutex_t *base_plugin_mutex; pthread_mutex_t *port_mutex; if(!AGS_IS_RECALL_DSSI_RUN(recall_dssi_run)){ return; } g_object_get(recall_dssi_run, "parent", &recall_recycling, NULL); g_object_get(recall_recycling, "parent", &recall_channel_run, NULL); g_object_get(recall_channel_run, "recall-channel", &recall_dssi, NULL); /* get recall dssi mutex */ pthread_mutex_lock(ags_recall_get_class_mutex()); recall_dssi_mutex = AGS_RECALL(recall_dssi)->obj_mutex; pthread_mutex_unlock(ags_recall_get_class_mutex()); /* get some fields */ pthread_mutex_lock(recall_dssi_mutex); output_lines = recall_dssi->output_lines; input_lines = recall_dssi->input_lines; list_start = g_list_copy(AGS_RECALL(recall_dssi)->port); dssi_plugin = recall_dssi->plugin; plugin_descriptor = recall_dssi->plugin_descriptor; pthread_mutex_unlock(recall_dssi_mutex); /* base plugin mutex */ pthread_mutex_lock(ags_base_plugin_get_class_mutex()); base_plugin_mutex = AGS_BASE_PLUGIN(dssi_plugin)->obj_mutex; pthread_mutex_unlock(ags_base_plugin_get_class_mutex()); /* get some fields */ pthread_mutex_lock(base_plugin_mutex); port_count = plugin_descriptor->LADSPA_Plugin->PortCount; port_descriptor = plugin_descriptor->LADSPA_Plugin->PortDescriptors; connect_port = plugin_descriptor->LADSPA_Plugin->connect_port; pthread_mutex_unlock(base_plugin_mutex); /* match port */ if(input_lines < output_lines){ j_stop = output_lines; }else{ j_stop = input_lines; } for(i = 0; i < port_count; i++){ pthread_mutex_lock(base_plugin_mutex); current_port_descriptor = port_descriptor[i]; pthread_mutex_unlock(base_plugin_mutex); if(LADSPA_IS_PORT_CONTROL(current_port_descriptor)){ if(LADSPA_IS_PORT_INPUT(current_port_descriptor) || LADSPA_IS_PORT_OUTPUT(current_port_descriptor)){ LADSPA_Data *port_pointer; pthread_mutex_lock(base_plugin_mutex); specifier = g_strdup(plugin_descriptor->LADSPA_Plugin->PortNames[i]); pthread_mutex_unlock(base_plugin_mutex); list = ags_port_find_specifier(list_start, specifier); g_free(specifier); if(list != NULL){ current_port = list->data; /* get port mutex */ pthread_mutex_lock(ags_port_get_class_mutex()); port_mutex = current_port->obj_mutex; pthread_mutex_unlock(ags_port_get_class_mutex()); /* get port pointer */ pthread_mutex_lock(port_mutex); port_pointer = (LADSPA_Data *) &(current_port->port_value.ags_port_ladspa); pthread_mutex_unlock(port_mutex); for(j = 0; j < j_stop; j++){ #ifdef AGS_DEBUG g_message("connecting port[%d]: %d/%d - %f", j, i, port_count, current->port_value.ags_port_ladspa); #endif connect_port(recall_dssi_run->ladspa_handle[j], (unsigned long) i, port_pointer); } } } } } g_list_free(list_start); /* connect audio port */ for(j = 0; j < input_lines; j++){ connect_port(recall_dssi_run->ladspa_handle[j], (unsigned long) (recall_dssi->input_port[j]), &(recall_dssi_run->input[j])); } for(j = 0; j < recall_dssi->output_lines; j++){ connect_port(recall_dssi_run->ladspa_handle[j], (unsigned long) (recall_dssi->output_port[j]), &(recall_dssi_run->output[j])); } g_object_unref(recall_recycling); g_object_unref(recall_channel_run); g_object_unref(recall_dssi); }
static av_cold int init(AVFilterContext *ctx) { LADSPAContext *s = ctx->priv; LADSPA_Descriptor_Function descriptor_fn; const LADSPA_Descriptor *desc; LADSPA_PortDescriptor pd; AVFilterPad pad = { NULL }; char *p, *arg, *saveptr = NULL; unsigned long nb_ports; int i; if (!s->dl_name) { av_log(ctx, AV_LOG_ERROR, "No plugin name provided\n"); return AVERROR(EINVAL); } if (s->dl_name[0] == '/' || s->dl_name[0] == '.') { // argument is a path s->dl_handle = dlopen(s->dl_name, RTLD_LOCAL|RTLD_NOW); } else { // argument is a shared object name char *paths = av_strdup(getenv("LADSPA_PATH")); const char *separator = ":"; if (paths) { p = paths; while ((arg = av_strtok(p, separator, &saveptr)) && !s->dl_handle) { s->dl_handle = try_load(arg, s->dl_name); p = NULL; } } av_free(paths); if (!s->dl_handle && (paths = av_asprintf("%s/.ladspa/lib", getenv("HOME")))) { s->dl_handle = try_load(paths, s->dl_name); av_free(paths); } if (!s->dl_handle) s->dl_handle = try_load("/usr/local/lib/ladspa", s->dl_name); if (!s->dl_handle) s->dl_handle = try_load("/usr/lib/ladspa", s->dl_name); } if (!s->dl_handle) { av_log(ctx, AV_LOG_ERROR, "Failed to load '%s'\n", s->dl_name); return AVERROR(EINVAL); } descriptor_fn = dlsym(s->dl_handle, "ladspa_descriptor"); if (!descriptor_fn) { av_log(ctx, AV_LOG_ERROR, "Could not find ladspa_descriptor: %s\n", dlerror()); return AVERROR(EINVAL); } // Find the requested plugin, or list plugins if (!s->plugin) { av_log(ctx, AV_LOG_INFO, "The '%s' library contains the following plugins:\n", s->dl_name); av_log(ctx, AV_LOG_INFO, "I = Input Channels\n"); av_log(ctx, AV_LOG_INFO, "O = Output Channels\n"); av_log(ctx, AV_LOG_INFO, "I:O %-25s %s\n", "Plugin", "Description"); av_log(ctx, AV_LOG_INFO, "\n"); for (i = 0; desc = descriptor_fn(i); i++) { unsigned long inputs = 0, outputs = 0; count_ports(desc, &inputs, &outputs); av_log(ctx, AV_LOG_INFO, "%lu:%lu %-25s %s\n", inputs, outputs, desc->Label, av_x_if_null(desc->Name, "?")); av_log(ctx, AV_LOG_VERBOSE, "Maker: %s\n", av_x_if_null(desc->Maker, "?")); av_log(ctx, AV_LOG_VERBOSE, "Copyright: %s\n", av_x_if_null(desc->Copyright, "?")); } return AVERROR_EXIT; } else { for (i = 0;; i++) { desc = descriptor_fn(i); if (!desc) { av_log(ctx, AV_LOG_ERROR, "Could not find plugin: %s\n", s->plugin); return AVERROR(EINVAL); } if (desc->Label && !strcmp(desc->Label, s->plugin)) break; } } s->desc = desc; nb_ports = desc->PortCount; s->ipmap = av_calloc(nb_ports, sizeof(*s->ipmap)); s->opmap = av_calloc(nb_ports, sizeof(*s->opmap)); s->icmap = av_calloc(nb_ports, sizeof(*s->icmap)); s->ocmap = av_calloc(nb_ports, sizeof(*s->ocmap)); s->ictlv = av_calloc(nb_ports, sizeof(*s->ictlv)); s->octlv = av_calloc(nb_ports, sizeof(*s->octlv)); s->ctl_needs_value = av_calloc(nb_ports, sizeof(*s->ctl_needs_value)); if (!s->ipmap || !s->opmap || !s->icmap || !s->ocmap || !s->ictlv || !s->octlv || !s->ctl_needs_value) return AVERROR(ENOMEM); for (i = 0; i < nb_ports; i++) { pd = desc->PortDescriptors[i]; if (LADSPA_IS_PORT_AUDIO(pd)) { if (LADSPA_IS_PORT_INPUT(pd)) { s->ipmap[s->nb_inputs] = i; s->nb_inputs++; } else if (LADSPA_IS_PORT_OUTPUT(pd)) { s->opmap[s->nb_outputs] = i; s->nb_outputs++; } } else if (LADSPA_IS_PORT_CONTROL(pd)) { if (LADSPA_IS_PORT_INPUT(pd)) { s->icmap[s->nb_inputcontrols] = i; if (LADSPA_IS_HINT_HAS_DEFAULT(desc->PortRangeHints[i].HintDescriptor)) set_default_ctl_value(s, s->nb_inputcontrols, s->icmap, s->ictlv); else s->ctl_needs_value[s->nb_inputcontrols] = 1; s->nb_inputcontrols++; } else if (LADSPA_IS_PORT_OUTPUT(pd)) { s->ocmap[s->nb_outputcontrols] = i; s->nb_outputcontrols++; } } } // List Control Ports if "help" is specified if (s->options && !strcmp(s->options, "help")) { if (!s->nb_inputcontrols) { av_log(ctx, AV_LOG_INFO, "The '%s' plugin does not have any input controls.\n", desc->Label); } else { av_log(ctx, AV_LOG_INFO, "The '%s' plugin has the following input controls:\n", desc->Label); for (i = 0; i < s->nb_inputcontrols; i++) print_ctl_info(ctx, AV_LOG_INFO, s, i, s->icmap, s->ictlv, 0); } return AVERROR_EXIT; } // Parse control parameters p = s->options; while (s->options) { LADSPA_Data val; int ret; if (!(arg = av_strtok(p, "|", &saveptr))) break; p = NULL; if (sscanf(arg, "c%d=%f", &i, &val) != 2) { av_log(ctx, AV_LOG_ERROR, "Invalid syntax.\n"); return AVERROR(EINVAL); } if ((ret = set_control(ctx, i, val)) < 0) return ret; s->ctl_needs_value[i] = 0; } // Check if any controls are not set for (i = 0; i < s->nb_inputcontrols; i++) { if (s->ctl_needs_value[i]) { av_log(ctx, AV_LOG_ERROR, "Control c%d must be set.\n", i); print_ctl_info(ctx, AV_LOG_ERROR, s, i, s->icmap, s->ictlv, 0); return AVERROR(EINVAL); } } pad.type = AVMEDIA_TYPE_AUDIO; if (s->nb_inputs) { pad.name = av_asprintf("in0:%s%lu", desc->Label, s->nb_inputs); if (!pad.name) return AVERROR(ENOMEM); pad.filter_frame = filter_frame; pad.config_props = config_input; if (ff_insert_inpad(ctx, ctx->nb_inputs, &pad) < 0) { av_freep(&pad.name); return AVERROR(ENOMEM); } } av_log(ctx, AV_LOG_DEBUG, "ports: %lu\n", nb_ports); av_log(ctx, AV_LOG_DEBUG, "inputs: %lu outputs: %lu\n", s->nb_inputs, s->nb_outputs); av_log(ctx, AV_LOG_DEBUG, "input controls: %lu output controls: %lu\n", s->nb_inputcontrols, s->nb_outputcontrols); return 0; }
LadspaEffect::LadspaEffect(const LADSPA_Descriptor *data, const std::set<wxString>& categories) : mCategories(categories) { mData = data; pluginName = LAT1CTOWX(mData->Name); fInBuffer = NULL; fOutBuffer = NULL; inputs = 0; outputs = 0; numInputControls = 0; mLength = 0; unsigned long p; inputPorts = new unsigned long [mData->PortCount]; outputPorts = new unsigned long [mData->PortCount]; inputControls = new float [mData->PortCount]; outputControls = new float [mData->PortCount]; for(p=0; p<mData->PortCount; p++) { LADSPA_PortDescriptor d = mData->PortDescriptors[p]; if (LADSPA_IS_PORT_AUDIO(d)) { if (LADSPA_IS_PORT_INPUT(d)) { inputPorts[inputs] = p; inputs++; } else if (LADSPA_IS_PORT_OUTPUT(d)) { outputPorts[outputs] = p; outputs++; } } if (LADSPA_IS_PORT_CONTROL(d) && LADSPA_IS_PORT_INPUT(d)) { numInputControls++; float val = float(1.0); LADSPA_PortRangeHint hint = mData->PortRangeHints[p]; if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) && val < hint.LowerBound) val = hint.LowerBound; if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) && val > hint.UpperBound) val = hint.UpperBound; if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint.HintDescriptor)) val = hint.LowerBound; if (LADSPA_IS_HINT_DEFAULT_LOW(hint.HintDescriptor)) val = hint.LowerBound * 0.75f + hint.UpperBound * 0.25f; if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint.HintDescriptor)) val = hint.LowerBound * 0.5f + hint.UpperBound * 0.5f; if (LADSPA_IS_HINT_DEFAULT_HIGH(hint.HintDescriptor)) val = hint.LowerBound * 0.25f + hint.UpperBound * 0.75f; if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint.HintDescriptor)) val = hint.UpperBound; if (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor)) val *= mProjectRate; if (LADSPA_IS_HINT_DEFAULT_0(hint.HintDescriptor)) val = 0.0f; if (LADSPA_IS_HINT_DEFAULT_1(hint.HintDescriptor)) val = 1.0f; if (LADSPA_IS_HINT_DEFAULT_100(hint.HintDescriptor)) val = 100.0f; if (LADSPA_IS_HINT_DEFAULT_440(hint.HintDescriptor)) val = 440.0f; inputControls[p] = val; } } flags = PLUGIN_EFFECT; if (inputs == 0) flags |= INSERT_EFFECT; else if (outputs == 0) flags |= ANALYZE_EFFECT; else flags |= PROCESS_EFFECT; }
static int af_ladspa_parse_plugin(af_ladspa_t *setup) { int p, i; const LADSPA_Descriptor *pdes = setup->plugin_descriptor; LADSPA_PortDescriptor d; LADSPA_PortRangeHint hint; if (!setup->libhandle) return AF_ERROR; /* only call parse after a succesful load */ if (!setup->plugin_descriptor) return AF_ERROR; /* same as above */ /* let's do it */ setup->nports = pdes->PortCount; /* allocate memory for all inputs/outputs/controls */ setup->inputs = calloc(setup->nports, sizeof(int)); if (!setup->inputs) return af_ladspa_malloc_failed(setup->myname); setup->outputs = calloc(setup->nports, sizeof(int)); if (!setup->outputs) return af_ladspa_malloc_failed(setup->myname); setup->inputcontrolsmap = calloc(setup->nports, sizeof(int)); if (!setup->inputcontrolsmap) return af_ladspa_malloc_failed(setup->myname); setup->inputcontrols = calloc(setup->nports, sizeof(float)); if (!setup->inputcontrols) return af_ladspa_malloc_failed(setup->myname); setup->outputcontrolsmap = calloc(setup->nports, sizeof(int)); if (!setup->outputcontrolsmap) return af_ladspa_malloc_failed(setup->myname); setup->outputcontrols = calloc(setup->nports, sizeof(float)); if (!setup->outputcontrols) return af_ladspa_malloc_failed(setup->myname); /* set counts to zero */ setup->ninputs = 0; setup->noutputs = 0; setup->ninputcontrols = 0; setup->noutputcontrols = 0; /* check all ports, see what type it is and set variables according to * what we have found */ for (p=0; p<setup->nports; p++) { d = pdes->PortDescriptors[p]; if (LADSPA_IS_PORT_AUDIO(d)) { if (LADSPA_IS_PORT_INPUT(d)) { setup->inputs[setup->ninputs] = p; setup->ninputs++; } else if (LADSPA_IS_PORT_OUTPUT(d)) { setup->outputs[setup->noutputs] = p; setup->noutputs++; } } if (LADSPA_IS_PORT_CONTROL(d)) { if (LADSPA_IS_PORT_INPUT(d)) { setup->inputcontrolsmap[setup->ninputcontrols] = p; setup->ninputcontrols++; /* set control to zero. set values after reading the rest * of the suboptions and check LADSPA_?_HINT's later. */ setup->inputcontrols[p] = 0.0f; } else if (LADSPA_IS_PORT_OUTPUT(d)) { /* read and handle these too, otherwise filters that have them * will sig11 */ setup->outputcontrolsmap[setup->noutputcontrols]=p; setup->noutputcontrols++; setup->outputcontrols[p] = 0.0f; } } } if (setup->ninputs == 0) { mp_msg(MSGT_AFILTER, MSGL_WARN, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_WarnNoInputs); } else if (setup->ninputs == 1) { mp_msg(MSGT_AFILTER, MSGL_V, "%s: this is a mono effect\n", setup->myname); } else if (setup->ninputs == 2) { mp_msg(MSGT_AFILTER, MSGL_V, "%s: this is a stereo effect\n", setup->myname); } else { mp_msg(MSGT_AFILTER, MSGL_V, "%s: this is a %i-channel effect, " "support is experimental\n", setup->myname, setup->ninputs); } if (setup->noutputs == 0) { mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrNoOutputs); return AF_ERROR; } if (setup->noutputs != setup->ninputs ) { mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname, MSGTR_AF_LADSPA_ErrInOutDiff); return AF_ERROR; } mp_msg(MSGT_AFILTER, MSGL_V, "%s: this plugin has %d input control(s)\n", setup->myname, setup->ninputcontrols); /* Print list of controls and its range of values it accepts */ for (i=0; i<setup->ninputcontrols; i++) { p = setup->inputcontrolsmap[i]; hint = pdes->PortRangeHints[p]; mp_msg(MSGT_AFILTER, MSGL_V, " --- %d %s [", i, pdes->PortNames[p]); if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) { mp_msg(MSGT_AFILTER, MSGL_V, "%0.2f , ", hint.LowerBound); } else { mp_msg(MSGT_AFILTER, MSGL_V, "... , "); } if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) { mp_msg(MSGT_AFILTER, MSGL_V, "%0.2f]\n", hint.UpperBound); } else { mp_msg(MSGT_AFILTER, MSGL_V, "...]\n"); } } return AF_OK; }
/* Note that this procedure leaks memory like mad. */ static void applyPlugin(const char * pcInputFilename, const char * pcOutputFilename, const LADSPA_Data fExtraSeconds, const unsigned long lPluginCount, const LADSPA_Descriptor ** ppsPluginDescriptors, LADSPA_Data ** ppfPluginControlValues) { LADSPA_PortDescriptor iPortDescriptor; LADSPA_Handle * ppsPlugins; LADSPA_Data ** ppfBuffers; long lFrameSize; unsigned long lAudioInputCount; unsigned long lAudioOutputCount; unsigned long lPreviousAudioOutputCount; unsigned long lBufferCount; unsigned long lBufferIndex; unsigned long lControlIndex; unsigned long lInputFileChannelCount; unsigned long lInputFileLength; unsigned long lOutputFileChannelCount; unsigned long lOutputFileLength; unsigned long lPluginIndex; unsigned long lPortIndex; unsigned long lSampleRate; unsigned long lTimeAt; LADSPA_Data fDummyControlOutput; /* Open input file and output file: -------------------------------- */ lOutputFileChannelCount = getPortCountByType(ppsPluginDescriptors[lPluginCount - 1], LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT); if (lOutputFileChannelCount == 0) { fprintf(stderr, "The last plugin in the chain has no audio outputs.\n"); exit(1); } openWaveFile(pcInputFilename, &lInputFileChannelCount, &lSampleRate, &lInputFileLength); if (lInputFileChannelCount != getPortCountByType(ppsPluginDescriptors[0], LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT)) { fprintf(stderr, "Mismatch between channel count in input file and audio inputs " "on first plugin in chain.\n"); exit(1); } lOutputFileLength = lInputFileLength + (unsigned long)(fExtraSeconds * lSampleRate); createWaveFile(pcOutputFilename, lOutputFileChannelCount, lSampleRate, lOutputFileLength); /* Count buffers and sanity-check the flow graph: ---------------------------------------------- */ lBufferCount = 0; lPreviousAudioOutputCount = 0; for (lPluginIndex = 0; lPluginIndex < lPluginCount; lPluginIndex++) { lAudioInputCount = getPortCountByType(ppsPluginDescriptors[lPluginIndex], LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT); lAudioOutputCount = getPortCountByType(ppsPluginDescriptors[lPluginIndex], LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT); if (lBufferCount < lAudioInputCount) lBufferCount = lAudioInputCount; if (lPluginIndex > 0) if (lAudioInputCount != lPreviousAudioOutputCount) { fprintf(stderr, "There is a mismatch between the number of output channels " "on plugin \"%s\" (%ld) and the number of input channels on " "plugin \"%s\" (%ld).\n", ppsPluginDescriptors[lPluginIndex - 1]->Name, lPreviousAudioOutputCount, ppsPluginDescriptors[lPluginIndex]->Name, lAudioInputCount); exit(1); } lPreviousAudioOutputCount = lAudioOutputCount; if (lBufferCount < lAudioOutputCount) lBufferCount = lAudioOutputCount; } /* Create the buffers, create instances, wire them up: --------------------------------------------------- */ ppsPlugins = (LADSPA_Handle *)calloc(lPluginCount, sizeof(LADSPA_Handle)); ppfBuffers = (LADSPA_Data **)calloc(lBufferCount, sizeof(LADSPA_Data *)); for (lBufferIndex = 0; lBufferIndex < lBufferCount; lBufferIndex++) ppfBuffers[lBufferIndex] = (LADSPA_Data *)calloc(BUFFER_SIZE, sizeof(LADSPA_Data)); for (lPluginIndex = 0; lPluginIndex < lPluginCount; lPluginIndex++) { ppsPlugins[lPluginIndex] = ppsPluginDescriptors[lPluginIndex] ->instantiate(ppsPluginDescriptors[lPluginIndex], lSampleRate); if (!ppsPlugins[lPluginIndex]) { fprintf(stderr, "Failed to instantiate plugin of type \"%s\".\n", ppsPluginDescriptors[lPluginIndex]->Name); exit(1); } /* Controls: --------- */ lControlIndex = 0; for (lPortIndex = 0; lPortIndex < ppsPluginDescriptors[lPluginIndex]->PortCount; lPortIndex++) { iPortDescriptor = ppsPluginDescriptors[lPluginIndex]->PortDescriptors[lPortIndex]; if (LADSPA_IS_PORT_CONTROL(iPortDescriptor)) { if (LADSPA_IS_PORT_INPUT(iPortDescriptor)) ppsPluginDescriptors[lPluginIndex]->connect_port (ppsPlugins[lPluginIndex], lPortIndex, ppfPluginControlValues[lPluginIndex] + (lControlIndex++)); if (LADSPA_IS_PORT_OUTPUT(iPortDescriptor)) ppsPluginDescriptors[lPluginIndex]->connect_port (ppsPlugins[lPluginIndex], lPortIndex, &fDummyControlOutput); } } /* Input Buffers: -------------- */ lBufferIndex = 0; for (lPortIndex = 0; lPortIndex < ppsPluginDescriptors[lPluginIndex]->PortCount; lPortIndex++) { iPortDescriptor = ppsPluginDescriptors[lPluginIndex]->PortDescriptors[lPortIndex]; if (LADSPA_IS_PORT_INPUT(iPortDescriptor) && LADSPA_IS_PORT_AUDIO(iPortDescriptor)) ppsPluginDescriptors[lPluginIndex]->connect_port (ppsPlugins[lPluginIndex], lPortIndex, ppfBuffers[lBufferIndex++]); } /* Output Buffers: --------------- */ lBufferIndex = 0; for (lPortIndex = 0; lPortIndex < ppsPluginDescriptors[lPluginIndex]->PortCount; lPortIndex++) { iPortDescriptor = ppsPluginDescriptors[lPluginIndex]->PortDescriptors[lPortIndex]; if (LADSPA_IS_PORT_OUTPUT(iPortDescriptor) && LADSPA_IS_PORT_AUDIO(iPortDescriptor)) ppsPluginDescriptors[lPluginIndex]->connect_port (ppsPlugins[lPluginIndex], lPortIndex, ppfBuffers[lBufferIndex++]); } } /* Activate: --------- */ for (lPluginIndex = 0; lPluginIndex < lPluginCount; lPluginIndex++) if (ppsPluginDescriptors[lPluginIndex]->activate != NULL) ppsPluginDescriptors[lPluginIndex]->activate(ppsPlugins[lPluginIndex]); /* Run: ---- */ lTimeAt = 0; while (lTimeAt < lOutputFileLength) { lFrameSize = lInputFileLength - lTimeAt; if (lFrameSize > BUFFER_SIZE) lFrameSize = BUFFER_SIZE; else { /* We've reached or are reaching the end of the file. We're not going to fill the buffer from file. Could just memset the end part, but there's only one frame where this is worth the effort. */ for (lBufferIndex = 0; lBufferIndex < lBufferCount; lBufferIndex++) memset(ppfBuffers[lBufferIndex], 0, sizeof(LADSPA_Data) * BUFFER_SIZE); } if (lFrameSize > 0) { /* Read from disk. */ readIntoBuffers(ppfBuffers, lFrameSize); } /* Run the plugins: */ lFrameSize = lOutputFileLength - lTimeAt; if (lFrameSize > BUFFER_SIZE) lFrameSize = BUFFER_SIZE; for (lPluginIndex = 0; lPluginIndex < lPluginCount; lPluginIndex++) ppsPluginDescriptors[lPluginIndex] ->run(ppsPlugins[lPluginIndex], lFrameSize); /* Write the output to disk. */ writeFromBuffers(ppfBuffers, lFrameSize); lTimeAt += lFrameSize; } /* Deactivate: ----------- */ for (lPluginIndex = 0; lPluginIndex < lPluginCount; lPluginIndex++) if (ppsPluginDescriptors[lPluginIndex]->deactivate != NULL) ppsPluginDescriptors[lPluginIndex]->deactivate(ppsPlugins[lPluginIndex]); /* Cleanup: -------- */ for (lPluginIndex = 0; lPluginIndex < lPluginCount; lPluginIndex++) ppsPluginDescriptors[lPluginIndex]->cleanup(ppsPlugins[lPluginIndex]); /* Close the input and output files: --------------------------------- */ closeFiles(); }
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 {
CAMLprim value ocaml_ladspa_port_is_output(value d, value n) { return Val_bool(LADSPA_IS_PORT_OUTPUT(LADSPA_descr_val(d)->PortDescriptors[Int_val(n)])); }
int lp_ladspa_audio_ports::init(const LADSPA_Descriptor *descriptor, int channels, int buf_size, int samplerate) { //mutex.lock(); if(descriptor == 0){ std::cerr << "lp_ladspa_audio_ports::" << __FUNCTION__ << ": descriptor is Null\n"; return -1; } // Only 1 and 2 channels are possible if((channels < 1)||(channels > 2)){ std::cerr << "lp_ladspa_ctl_port::" << __FUNCTION__ << ": only 1 or 2 channels are supported\n"; return -1; } pv_channels = channels; if(buf_size == 0){ std::cerr << "lp_ladspa_audio_ports::" << __FUNCTION__ << ": buffer size is not set\n"; return -1; } if(samplerate == 0){ std::cerr << "lp_ladspa_audio_ports::" << __FUNCTION__ << ": samplerate is not set\n"; return -1; } pv_descriptor = descriptor; // Count audio ports unsigned long pcount, i; int nb_in, nb_out; pcount = pv_descriptor->PortCount; nb_in = 0; nb_out = 0; for(i=0; i<pcount; i++){ if((LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[i]))&&(LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[i]))){ nb_in++; } if((LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[i]))&&(LADSPA_IS_PORT_OUTPUT(descriptor->PortDescriptors[i]))){ nb_out++; } } pv_nb_in = nb_in; pv_nb_out = nb_out; std::cout << "Audio in: " << pv_nb_in << " - out: " << pv_nb_out << std::endl; // Search the best routing type if(channels == 1){ // 1 channel mode if((nb_in == 1)&&(nb_out == 1)){ pv_routing = MONO_NORMAL; // One handle - 1 I/O port pv_handles_count = 1; pv_nb_in = 1; pv_nb_out = 1; }else if((nb_in == 2)&&(nb_out == 2)){ pv_routing = MONO_HALF_USED; // One handle - 2 I/O ports pv_handles_count = 1; pv_nb_in = 2; pv_nb_out = 2; }else if((nb_in == 1)&&(nb_out == 2)){ pv_routing = MONO_1H_MERGE_OUTPUT; // One handle - One I port - 2 O ports pv_handles_count = 1; pv_nb_in = 1; pv_nb_out = 2; }else if((nb_in == 2)&&(nb_out == 1)){ pv_routing = MONO_1H_SPLIT_INPUT; // One handle - 2 I ports - One O port pv_handles_count = 1; pv_nb_in = 2; pv_nb_out = 1; }else if((nb_in == 0)&&(nb_out == 1)){ pv_routing = MONO_1H_NO_INPUT; // One handle - 0 I port - 1 O port pv_handles_count = 1; pv_nb_in = 0; pv_nb_out = 1; }else if((nb_in == 0)&&(nb_out == 2)){ pv_routing = MONO_1H_NO_INPUT_MERGE_OUTPUT; // One handle - 0 I port - 2 O ports pv_handles_count = 1; pv_nb_in = 0; pv_nb_out = 2; }else{ pv_routing = UNSUPPORTED; std::cerr << "lp_ladspa_audio_ports::" << __FUNCTION__ << ": cannot find audio routing\n"; } }else if(channels == 2){ // 2 channels mode if((nb_in == 2)&&(nb_out == 2)){ pv_routing = STEREO_NORMAL; // One handle - 2 I/O ports pv_handles_count = 1; pv_nb_in = 2; pv_nb_out = 2; }else if((nb_in == 1)&&(nb_out == 1)){ pv_routing = STEREO_2H; // Two handles - 2 I/O ports pv_handles_count = 2; pv_nb_in = 2; pv_nb_out = 2; }else if((nb_in == 1)&&(nb_out == 2)){ pv_routing = STEREO_2H_MERGE_OUTPUT; // Two handles - 2 I ports - 4 O ports pv_handles_count = 2; pv_nb_in = 2; pv_nb_out = 4; pv_nb_tmp = 2; }else if((nb_in == 2)&&(nb_out == 1)){ pv_routing = STEREO_2H_MERGE_INPUT; // Two handles - 4 I ports - 2 O port pv_handles_count = 2; pv_nb_in = 4; pv_nb_out = 2; }else if((nb_in == 0)&&(nb_out == 1)){ pv_routing = STEREO_2H_NO_INPUT; // Two handles - 0 I port - 2 O ports pv_handles_count = 2; pv_nb_in = 0; pv_nb_out = 2; }else if((nb_in == 0)&&(nb_out == 2)){ pv_routing = STEREO_1H_NO_INPUT; // One handle - 0 I port - 2 O ports pv_handles_count = 1; pv_nb_in = 0; pv_nb_out = 2; }else{ pv_routing = UNSUPPORTED; std::cerr << "lp_ladspa_audio_ports::" << __FUNCTION__ << ": cannot find audio routing\n"; } }else{ pv_routing = UNSUPPORTED; std::cerr << "lp_ladspa_audio_ports::" << __FUNCTION__ << ": cannot find audio routing\n"; } // Allocate in and out tabs NOTE: review buffer size ! To big in stereo mode ! if(pv_nb_in > 0){ pv_in_data = new lp_ladspa_audio_data[pv_nb_in]; if(pv_in_data == 0){ std::cerr << "lp_ladspa_audio_ports::" << __FUNCTION__ << ": memory allocation failed\n"; return -1; } for(i=0; i<(unsigned long)pv_nb_in; i++){ if(pv_in_data[i].alloc(buf_size)<0){ return -1; } pv_in_data[i].set_descriptor(pv_descriptor); } } if(pv_nb_out > 0){ pv_out_data = new lp_ladspa_audio_data[pv_nb_out]; if(pv_out_data == 0){ std::cerr << "lp_ladspa_audio_ports::" << __FUNCTION__ << ": memory allocation failed\n"; return -1; } for(i=0; i<(unsigned long)pv_nb_out; i++){ if(pv_out_data[i].alloc(buf_size)<0){ return -1; } pv_out_data[i].set_descriptor(pv_descriptor); } } if(pv_nb_tmp > 0){ pv_tmp_data = new lp_ladspa_audio_data[pv_nb_tmp]; if(pv_tmp_data == 0){ std::cerr << "lp_ladspa_audio_ports::" << __FUNCTION__ << ": memory allocation failed\n"; return -1; } for(i=0; i<(unsigned long)pv_nb_tmp; i++){ if(pv_tmp_data[i].alloc(buf_size)<0){ return -1; } } } //mutex.unlock(); return 0; }