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; }
// 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()); } }
// 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; }
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; }
static void ladspa_count_ports (const LADSPA_Descriptor * descriptor, guint * audio_in, guint * audio_out, guint * control_in, guint * control_out) { guint i; *audio_in = *audio_out = *control_in = *control_out = 0; for (i = 0; i < descriptor->PortCount; i++) { LADSPA_PortDescriptor p = descriptor->PortDescriptors[i]; if (LADSPA_IS_PORT_AUDIO (p)) { if (LADSPA_IS_PORT_INPUT (p)) (*audio_in)++; else (*audio_out)++; } else if (LADSPA_IS_PORT_CONTROL (p)) { if (LADSPA_IS_PORT_INPUT (p)) (*control_in)++; else (*control_out)++; } } }
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); }
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(); }
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; } } }
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; }
unsigned long lp_ladspa_audio_ports::get_lad_input_pos(int pos) { int in_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_INPUT(pv_descriptor->PortDescriptors[i]))){ if(in_count == pos){ return i; } in_count++; } } return -1; }
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)++; } } } }
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); }
bool LadspaManager::isPortAudio( 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_AUDIO ( 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 gboolean plugin_is_valid (const LADSPA_Descriptor * descriptor) { unsigned long i; unsigned long icount = 0; unsigned long ocount = 0; for (i = 0; i < descriptor->PortCount; i++) { if (!LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[i])) continue; if (LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[i])) icount++; else ocount++; } if (ocount == 0) return FALSE; return TRUE; }
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); } }
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; }
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; }
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_audio(value d, value n) { return Val_bool(LADSPA_IS_PORT_AUDIO(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; }