• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * \file pcm/pcm_ladspa.c
3  * \ingroup PCM_Plugins
4  * \brief ALSA Plugin <-> LADSPA Plugin Interface
5  * \author Jaroslav Kysela <perex@perex.cz>
6  * \author Jaroslav Kysela <perex@perex.cz>
7  * \date 2001,2006
8  */
9 /*
10  *  PCM - LADSPA integration plugin
11  *  Copyright (c) 2001-2006 by Jaroslav Kysela <perex@perex.cz>
12  *  Copyright (c) 2005 by Jaroslav Kysela <perex@perex.cz>
13  *
14  *
15  *   This library is free software; you can redistribute it and/or modify
16  *   it under the terms of the GNU Lesser General Public License as
17  *   published by the Free Software Foundation; either version 2.1 of
18  *   the License, or (at your option) any later version.
19  *
20  *   This program is distributed in the hope that it will be useful,
21  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
22  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  *   GNU Lesser General Public License for more details.
24  *
25  *   You should have received a copy of the GNU Lesser General Public
26  *   License along with this library; if not, write to the Free Software
27  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28  *
29  *
30  * perex@perex.cz 2005/12/13
31  *   The LADSPA plugin rewrite was sponsored by MediaNet AG
32  *   http://www.medianet.ag
33  */
34 
35 #include <dirent.h>
36 #include <locale.h>
37 #include <math.h>
38 #include "pcm_local.h"
39 #include "pcm_plugin.h"
40 
41 #include "ladspa.h"
42 
43 #ifndef PIC
44 /* entry for static linking */
45 const char *_snd_module_pcm_ladspa = "";
46 #endif
47 
48 #ifndef DOC_HIDDEN
49 
50 #define NO_ASSIGN	0xffffffff
51 
52 typedef enum _snd_pcm_ladspa_policy {
53 	SND_PCM_LADSPA_POLICY_NONE,		/* use bindings only */
54 	SND_PCM_LADSPA_POLICY_DUPLICATE		/* duplicate bindings for all channels */
55 } snd_pcm_ladspa_policy_t;
56 
57 typedef struct {
58 	/* This field need to be the first */
59 	snd_pcm_plugin_t plug;
60 	/* Plugin custom fields */
61 	struct list_head pplugins;
62 	struct list_head cplugins;
63 	unsigned int channels;			/* forced input channels, 0 = auto */
64 	unsigned int allocated;			/* count of allocated samples */
65 	LADSPA_Data *zero[2];			/* zero input or dummy output */
66 } snd_pcm_ladspa_t;
67 
68 typedef struct {
69         unsigned int size;
70         unsigned int *array;
71 } snd_pcm_ladspa_array_t;
72 
73 typedef struct {
74         snd_pcm_ladspa_array_t channels;
75         snd_pcm_ladspa_array_t ports;
76 	LADSPA_Data **m_data;
77         LADSPA_Data **data;
78 } snd_pcm_ladspa_eps_t;
79 
80 typedef struct snd_pcm_ladspa_instance {
81 	struct list_head list;
82 	const LADSPA_Descriptor *desc;
83 	LADSPA_Handle *handle;
84 	unsigned int depth;
85 	snd_pcm_ladspa_eps_t input;
86 	snd_pcm_ladspa_eps_t output;
87 	struct snd_pcm_ladspa_instance *prev;
88 	struct snd_pcm_ladspa_instance *next;
89 } snd_pcm_ladspa_instance_t;
90 
91 typedef struct {
92 	LADSPA_PortDescriptor pdesc;		/* port description */
93 	unsigned int port_bindings_size;	/* size of array */
94 	unsigned int *port_bindings;		/* index = channel number, value = LADSPA port */
95 	unsigned int controls_size;		/* size of array */
96 	unsigned char *controls_initialized;	/* initialized by ALSA user */
97 	LADSPA_Data *controls;			/* index = LADSPA control port index */
98 } snd_pcm_ladspa_plugin_io_t;
99 
100 typedef struct {
101 	struct list_head list;
102 	snd_pcm_ladspa_policy_t policy;
103 	char *filename;
104 	void *dl_handle;
105 	const LADSPA_Descriptor *desc;
106 	snd_pcm_ladspa_plugin_io_t input;
107 	snd_pcm_ladspa_plugin_io_t output;
108 	struct list_head instances;		/* one LADSPA plugin might be used multiple times */
109 } snd_pcm_ladspa_plugin_t;
110 
111 #endif /* DOC_HIDDEN */
112 
snd_pcm_ladspa_count_ports(snd_pcm_ladspa_plugin_t * lplug,LADSPA_PortDescriptor pdesc)113 static unsigned int snd_pcm_ladspa_count_ports(snd_pcm_ladspa_plugin_t *lplug,
114                                                LADSPA_PortDescriptor pdesc)
115 {
116         unsigned int res = 0, idx;
117         for (idx = 0; idx < lplug->desc->PortCount; idx++) {
118                 if ((lplug->desc->PortDescriptors[idx] & pdesc) == pdesc)
119                         res++;
120         }
121         return res;
122 }
123 
snd_pcm_ladspa_find_port(unsigned int * res,snd_pcm_ladspa_plugin_t * lplug,LADSPA_PortDescriptor pdesc,unsigned int port_idx)124 static int snd_pcm_ladspa_find_port(unsigned int *res,
125 				    snd_pcm_ladspa_plugin_t *lplug,
126 				    LADSPA_PortDescriptor pdesc,
127 				    unsigned int port_idx)
128 {
129 	unsigned long idx;
130 
131 	for (idx = 0; idx < lplug->desc->PortCount; idx++)
132 		if ((lplug->desc->PortDescriptors[idx] & pdesc) == pdesc) {
133 			if (port_idx == 0) {
134 				*res = idx;
135 				return 0;
136 			}
137 			port_idx--;
138 		}
139 	return -EINVAL;
140 }
141 
snd_pcm_ladspa_find_sport(unsigned int * res,snd_pcm_ladspa_plugin_t * lplug,LADSPA_PortDescriptor pdesc,const char * port_name)142 static int snd_pcm_ladspa_find_sport(unsigned int *res,
143 				     snd_pcm_ladspa_plugin_t *lplug,
144 				     LADSPA_PortDescriptor pdesc,
145 				     const char *port_name)
146 {
147 	unsigned long idx;
148 
149 	for (idx = 0; idx < lplug->desc->PortCount; idx++)
150 		if ((lplug->desc->PortDescriptors[idx] & pdesc) == pdesc &&
151 		    !strcmp(lplug->desc->PortNames[idx], port_name)) {
152 			*res = idx;
153 			return 0;
154 		}
155 	return -EINVAL;
156 }
157 
snd_pcm_ladspa_find_port_idx(unsigned int * res,snd_pcm_ladspa_plugin_t * lplug,LADSPA_PortDescriptor pdesc,unsigned int port)158 static int snd_pcm_ladspa_find_port_idx(unsigned int *res,
159 					snd_pcm_ladspa_plugin_t *lplug,
160 					LADSPA_PortDescriptor pdesc,
161 					unsigned int port)
162 {
163 	unsigned long idx;
164 	unsigned int r = 0;
165 
166 	if (port >= lplug->desc->PortCount)
167 		return -EINVAL;
168 	for (idx = 0; idx < port; idx++)
169 		if ((lplug->desc->PortDescriptors[idx] & pdesc) == pdesc)
170 			r++;
171 	*res = r;
172 	return 0;
173 }
174 
snd_pcm_ladspa_free_io(snd_pcm_ladspa_plugin_io_t * io)175 static void snd_pcm_ladspa_free_io(snd_pcm_ladspa_plugin_io_t *io)
176 {
177 	free(io->controls);
178 	free(io->controls_initialized);
179 }
180 
snd_pcm_ladspa_free_plugins(struct list_head * plugins)181 static void snd_pcm_ladspa_free_plugins(struct list_head *plugins)
182 {
183 	while (!list_empty(plugins)) {
184 		snd_pcm_ladspa_plugin_t *plugin = list_entry(plugins->next, snd_pcm_ladspa_plugin_t, list);
185                 snd_pcm_ladspa_free_io(&plugin->input);
186                 snd_pcm_ladspa_free_io(&plugin->output);
187 		if (plugin->dl_handle)
188 			dlclose(plugin->dl_handle);
189 		free(plugin->filename);
190 		list_del(&plugin->list);
191 		free(plugin);
192 	}
193 }
194 
snd_pcm_ladspa_free(snd_pcm_ladspa_t * ladspa)195 static void snd_pcm_ladspa_free(snd_pcm_ladspa_t *ladspa)
196 {
197         unsigned int idx;
198 
199 	snd_pcm_ladspa_free_plugins(&ladspa->pplugins);
200 	snd_pcm_ladspa_free_plugins(&ladspa->cplugins);
201 	for (idx = 0; idx < 2; idx++) {
202 		free(ladspa->zero[idx]);
203                 ladspa->zero[idx] = NULL;
204         }
205         ladspa->allocated = 0;
206 }
207 
snd_pcm_ladspa_close(snd_pcm_t * pcm)208 static int snd_pcm_ladspa_close(snd_pcm_t *pcm)
209 {
210 	snd_pcm_ladspa_t *ladspa = pcm->private_data;
211 
212 	snd_pcm_ladspa_free(ladspa);
213 	return snd_pcm_generic_close(pcm);
214 }
215 
snd_pcm_ladspa_hw_refine_cprepare(snd_pcm_t * pcm ATTRIBUTE_UNUSED,snd_pcm_hw_params_t * params)216 static int snd_pcm_ladspa_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
217 {
218 	snd_pcm_ladspa_t *ladspa = pcm->private_data;
219 	int err;
220 	snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_SHMN };
221 	err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS,
222 					 &access_mask);
223 	if (err < 0)
224 		return err;
225 	err = _snd_pcm_hw_params_set_format(params, SND_PCM_FORMAT_FLOAT);
226 	if (err < 0)
227 		return err;
228 	err = _snd_pcm_hw_params_set_subformat(params, SND_PCM_SUBFORMAT_STD);
229 	if (err < 0)
230 		return err;
231         if (ladspa->channels > 0 && pcm->stream == SND_PCM_STREAM_PLAYBACK) {
232         	err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS, ladspa->channels, 0);
233         	if (err < 0)
234         		return err;
235         }
236 	params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
237 	return 0;
238 }
239 
snd_pcm_ladspa_hw_refine_sprepare(snd_pcm_t * pcm ATTRIBUTE_UNUSED,snd_pcm_hw_params_t * sparams)240 static int snd_pcm_ladspa_hw_refine_sprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *sparams)
241 {
242 	snd_pcm_ladspa_t *ladspa = pcm->private_data;
243 	snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAPN };
244 	_snd_pcm_hw_params_any(sparams);
245 	_snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
246 				   &saccess_mask);
247 	_snd_pcm_hw_params_set_format(sparams, SND_PCM_FORMAT_FLOAT);
248 	_snd_pcm_hw_params_set_subformat(sparams, SND_PCM_SUBFORMAT_STD);
249         if (ladspa->channels > 0 && pcm->stream == SND_PCM_STREAM_CAPTURE)
250                 _snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_CHANNELS, ladspa->channels, 0);
251 	return 0;
252 }
253 
snd_pcm_ladspa_hw_refine_schange(snd_pcm_t * pcm ATTRIBUTE_UNUSED,snd_pcm_hw_params_t * params,snd_pcm_hw_params_t * sparams)254 static int snd_pcm_ladspa_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
255 					    snd_pcm_hw_params_t *sparams)
256 {
257 	int err;
258 	unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
259 			      SND_PCM_HW_PARBIT_RATE |
260 			      SND_PCM_HW_PARBIT_PERIOD_SIZE |
261 			      SND_PCM_HW_PARBIT_BUFFER_SIZE |
262 			      SND_PCM_HW_PARBIT_PERIODS |
263 			      SND_PCM_HW_PARBIT_PERIOD_TIME |
264 			      SND_PCM_HW_PARBIT_BUFFER_TIME |
265 			      SND_PCM_HW_PARBIT_TICK_TIME);
266 	err = _snd_pcm_hw_params_refine(sparams, links, params);
267 	if (err < 0)
268 		return err;
269 	return 0;
270 }
271 
snd_pcm_ladspa_hw_refine_cchange(snd_pcm_t * pcm ATTRIBUTE_UNUSED,snd_pcm_hw_params_t * params,snd_pcm_hw_params_t * sparams)272 static int snd_pcm_ladspa_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
273 					    snd_pcm_hw_params_t *sparams)
274 {
275 	int err;
276 	unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
277 			      SND_PCM_HW_PARBIT_RATE |
278 			      SND_PCM_HW_PARBIT_PERIOD_SIZE |
279 			      SND_PCM_HW_PARBIT_BUFFER_SIZE |
280 			      SND_PCM_HW_PARBIT_PERIODS |
281 			      SND_PCM_HW_PARBIT_PERIOD_TIME |
282 			      SND_PCM_HW_PARBIT_BUFFER_TIME |
283 			      SND_PCM_HW_PARBIT_TICK_TIME);
284 	err = _snd_pcm_hw_params_refine(params, links, sparams);
285 	if (err < 0)
286 		return err;
287 	return 0;
288 }
289 
snd_pcm_ladspa_hw_refine(snd_pcm_t * pcm,snd_pcm_hw_params_t * params)290 static int snd_pcm_ladspa_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
291 {
292 	return snd_pcm_hw_refine_slave(pcm, params,
293 				       snd_pcm_ladspa_hw_refine_cprepare,
294 				       snd_pcm_ladspa_hw_refine_cchange,
295 				       snd_pcm_ladspa_hw_refine_sprepare,
296 				       snd_pcm_ladspa_hw_refine_schange,
297 				       snd_pcm_generic_hw_refine);
298 }
299 
snd_pcm_ladspa_hw_params(snd_pcm_t * pcm,snd_pcm_hw_params_t * params)300 static int snd_pcm_ladspa_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
301 {
302 	// snd_pcm_ladspa_t *ladspa = pcm->private_data;
303 	int err = snd_pcm_hw_params_slave(pcm, params,
304 					  snd_pcm_ladspa_hw_refine_cchange,
305 					  snd_pcm_ladspa_hw_refine_sprepare,
306 					  snd_pcm_ladspa_hw_refine_schange,
307 					  snd_pcm_generic_hw_params);
308 	if (err < 0)
309 		return err;
310 	return 0;
311 }
312 
snd_pcm_ladspa_free_eps(snd_pcm_ladspa_eps_t * eps)313 static void snd_pcm_ladspa_free_eps(snd_pcm_ladspa_eps_t *eps)
314 {
315 	free(eps->channels.array);
316 	free(eps->ports.array);
317 }
318 
snd_pcm_ladspa_free_instances(snd_pcm_t * pcm,snd_pcm_ladspa_t * ladspa,int cleanup)319 static void snd_pcm_ladspa_free_instances(snd_pcm_t *pcm, snd_pcm_ladspa_t *ladspa, int cleanup)
320 {
321 	struct list_head *list, *pos, *pos1, *next1;
322 	unsigned int idx;
323 
324 	list = pcm->stream == SND_PCM_STREAM_PLAYBACK ? &ladspa->pplugins : &ladspa->cplugins;
325 	list_for_each(pos, list) {
326 		snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
327 		list_for_each_safe(pos1, next1, &plugin->instances) {
328 			snd_pcm_ladspa_instance_t *instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
329 			if (plugin->desc->deactivate)
330 				plugin->desc->deactivate(instance->handle);
331 			if (cleanup) {
332 				if (plugin->desc->cleanup)
333 					plugin->desc->cleanup(instance->handle);
334 				if (instance->input.m_data) {
335 				        for (idx = 0; idx < instance->input.channels.size; idx++)
336 						free(instance->input.m_data[idx]);
337 					free(instance->input.m_data);
338                                 }
339 				if (instance->output.m_data) {
340 				        for (idx = 0; idx < instance->output.channels.size; idx++)
341 						free(instance->output.m_data[idx]);
342 					free(instance->output.m_data);
343                                 }
344                                 free(instance->input.data);
345                                 free(instance->output.data);
346 				list_del(&(instance->list));
347 				snd_pcm_ladspa_free_eps(&instance->input);
348 				snd_pcm_ladspa_free_eps(&instance->output);
349 				free(instance);
350 			} else {
351 				if (plugin->desc->activate)
352 					plugin->desc->activate(instance->handle);
353 			}
354 		}
355 		if (cleanup) {
356 			assert(list_empty(&plugin->instances));
357 		}
358 	}
359 }
360 
snd_pcm_ladspa_add_to_carray(snd_pcm_ladspa_array_t * array,unsigned int idx,unsigned int val)361 static int snd_pcm_ladspa_add_to_carray(snd_pcm_ladspa_array_t *array,
362                                         unsigned int idx,
363                                         unsigned int val)
364 {
365         unsigned int *narray;
366         unsigned int idx1;
367 
368         if (idx >= array->size) {
369                 narray = realloc(array->array, sizeof(unsigned int) * (idx + 1));
370                 if (narray == NULL)
371                         return -ENOMEM;
372                 for (idx1 = array->size; idx1 < idx; idx1++)
373                         narray[idx1] = NO_ASSIGN;
374                 array->array = narray;
375                 array->size = idx + 1;
376                 array->array[idx] = val;
377                 return 0;
378         }
379         if (array->array[idx] == NO_ASSIGN)
380                 array->array[idx] = val;
381         else
382                 return -EINVAL;
383         return 0;
384 }
385 
snd_pcm_ladspa_add_to_array(snd_pcm_ladspa_array_t * array,unsigned int idx,unsigned int val)386 static int snd_pcm_ladspa_add_to_array(snd_pcm_ladspa_array_t *array,
387                                        unsigned int idx,
388                                        unsigned int val)
389 {
390         unsigned int *narray;
391         unsigned int idx1;
392 
393         if (idx >= array->size) {
394                 narray = realloc(array->array, sizeof(unsigned int) * (idx + 1));
395                 if (narray == NULL)
396                         return -ENOMEM;
397                 for (idx1 = array->size; idx1 < idx; idx1++)
398                         narray[idx1] = NO_ASSIGN;
399                 array->array = narray;
400                 array->size = idx + 1;
401         }
402         array->array[idx] = val;
403         return 0;
404 }
405 
snd_pcm_ladspa_connect_plugin1(snd_pcm_ladspa_plugin_t * plugin,snd_pcm_ladspa_plugin_io_t * io,snd_pcm_ladspa_eps_t * eps)406 static int snd_pcm_ladspa_connect_plugin1(snd_pcm_ladspa_plugin_t *plugin,
407 					  snd_pcm_ladspa_plugin_io_t *io,
408 					  snd_pcm_ladspa_eps_t *eps)
409 {
410 	unsigned int port, channels, idx, idx1;
411 	int err;
412 
413 	assert(plugin->policy == SND_PCM_LADSPA_POLICY_NONE);
414 	channels = io->port_bindings_size > 0 ?
415 	                io->port_bindings_size :
416 	                snd_pcm_ladspa_count_ports(plugin, io->pdesc | LADSPA_PORT_AUDIO);
417 	for (idx = idx1 = 0; idx < channels; idx++) {
418 		if (io->port_bindings_size > 0)
419         		port = io->port_bindings[idx];
420                 else {
421         		err = snd_pcm_ladspa_find_port(&port, plugin, io->pdesc | LADSPA_PORT_AUDIO, idx);
422         		if (err < 0) {
423         		        SNDERR("unable to find audio %s port %u plugin '%s'", io->pdesc & LADSPA_PORT_INPUT ? "input" : "output", idx, plugin->desc->Name);
424         			return err;
425                         }
426                 }
427                 if (port == NO_ASSIGN)
428                 	continue;
429         	err = snd_pcm_ladspa_add_to_carray(&eps->channels, idx1, idx);
430         	if (err < 0) {
431         		SNDERR("unable to add channel %u for audio %s plugin '%s'", idx, io->pdesc & LADSPA_PORT_INPUT ? "input" : "output", plugin->desc->Name);
432         	        return err;
433                 }
434         	err = snd_pcm_ladspa_add_to_array(&eps->ports, idx1, port);
435         	if (err < 0) {
436         		SNDERR("unable to add port %u for audio %s plugin '%s'", port, io->pdesc & LADSPA_PORT_INPUT ? "input" : "output", plugin->desc->Name);
437         	        return err;
438                 }
439                 idx1++;
440 	}
441 	return 0;
442 }
443 
snd_pcm_ladspa_connect_plugin(snd_pcm_ladspa_plugin_t * plugin,snd_pcm_ladspa_instance_t * instance)444 static int snd_pcm_ladspa_connect_plugin(snd_pcm_ladspa_plugin_t *plugin,
445 					 snd_pcm_ladspa_instance_t *instance)
446 {
447         int err;
448 
449         err = snd_pcm_ladspa_connect_plugin1(plugin, &plugin->input, &instance->input);
450         if (err < 0)
451                 return err;
452         err = snd_pcm_ladspa_connect_plugin1(plugin, &plugin->output, &instance->output);
453         if (err < 0)
454                 return err;
455         return 0;
456 }
457 
snd_pcm_ladspa_connect_plugin_duplicate1(snd_pcm_ladspa_plugin_t * plugin,snd_pcm_ladspa_plugin_io_t * io,snd_pcm_ladspa_eps_t * eps,unsigned int idx)458 static int snd_pcm_ladspa_connect_plugin_duplicate1(snd_pcm_ladspa_plugin_t *plugin,
459                                                     snd_pcm_ladspa_plugin_io_t *io,
460                                                     snd_pcm_ladspa_eps_t *eps,
461                                                     unsigned int idx)
462 {
463 	unsigned int port;
464 	int err;
465 
466 	assert(plugin->policy == SND_PCM_LADSPA_POLICY_DUPLICATE);
467 	if (io->port_bindings_size > 0) {
468 		port = io->port_bindings[0];
469 	} else {
470 		err = snd_pcm_ladspa_find_port(&port, plugin, io->pdesc | LADSPA_PORT_AUDIO, 0);
471 		if (err < 0) {
472 		        SNDERR("unable to find audio %s port %u plugin '%s'", io->pdesc & LADSPA_PORT_INPUT ? "input" : "output", (unsigned int)0, plugin->desc->Name);
473 			return err;
474                 }
475 	}
476 	err = snd_pcm_ladspa_add_to_carray(&eps->channels, 0, idx);
477 	if (err < 0) {
478         	SNDERR("unable to add channel %u for audio %s plugin '%s'", idx, io->pdesc & LADSPA_PORT_INPUT ? "input" : "output", plugin->desc->Name);
479 	        return err;
480         }
481         err = snd_pcm_ladspa_add_to_array(&eps->ports, 0, port);
482         if (err < 0) {
483         	SNDERR("unable to add port %u for audio %s plugin '%s'", port, io->pdesc & LADSPA_PORT_INPUT ? "input" : "output", plugin->desc->Name);
484         	return err;
485         }
486         return 0;
487 }
488 
snd_pcm_ladspa_connect_plugin_duplicate(snd_pcm_ladspa_plugin_t * plugin,snd_pcm_ladspa_plugin_io_t * in_io,snd_pcm_ladspa_plugin_io_t * out_io,snd_pcm_ladspa_instance_t * instance,unsigned int idx)489 static int snd_pcm_ladspa_connect_plugin_duplicate(snd_pcm_ladspa_plugin_t *plugin,
490 						   snd_pcm_ladspa_plugin_io_t *in_io,
491 						   snd_pcm_ladspa_plugin_io_t *out_io,
492 						   snd_pcm_ladspa_instance_t *instance,
493 						   unsigned int idx)
494 {
495 	int err;
496 
497 	err = snd_pcm_ladspa_connect_plugin_duplicate1(plugin, in_io, &instance->input, idx);
498 	if (err < 0)
499 	        return err;
500 	err = snd_pcm_ladspa_connect_plugin_duplicate1(plugin, out_io, &instance->output, idx);
501 	if (err < 0)
502 	        return err;
503         return 0;
504 }
505 
snd_pcm_ladspa_get_default_cvalue(const LADSPA_Descriptor * desc,unsigned int port,LADSPA_Data * val)506 static void snd_pcm_ladspa_get_default_cvalue(const LADSPA_Descriptor * desc, unsigned int port, LADSPA_Data *val)
507 {
508         LADSPA_PortRangeHintDescriptor hdesc;
509 
510         hdesc = desc->PortRangeHints[port].HintDescriptor;
511         switch (hdesc & LADSPA_HINT_DEFAULT_MASK) {
512         case LADSPA_HINT_DEFAULT_MINIMUM:
513                 *val = desc->PortRangeHints[port].LowerBound;
514                 break;
515         case LADSPA_HINT_DEFAULT_LOW:
516                 if (LADSPA_IS_HINT_LOGARITHMIC(hdesc)) {
517                         *val = exp(log(desc->PortRangeHints[port].LowerBound)
518                                         * 0.75
519                                         + log(desc->PortRangeHints[port].UpperBound)
520                                         * 0.25);
521                 } else {
522                         *val = (desc->PortRangeHints[port].LowerBound * 0.75) +
523                                (desc->PortRangeHints[port].UpperBound * 0.25);
524                 }
525                 break;
526         case LADSPA_HINT_DEFAULT_MIDDLE:
527                 if (LADSPA_IS_HINT_LOGARITHMIC(hdesc)) {
528                         *val = sqrt(desc->PortRangeHints[port].LowerBound *
529                                     desc->PortRangeHints[port].UpperBound);
530                 } else {
531                         *val = 0.5 *
532                                (desc->PortRangeHints[port].LowerBound +
533                                 desc->PortRangeHints[port].UpperBound);
534                 }
535                 break;
536         case LADSPA_HINT_DEFAULT_HIGH:
537                 if (LADSPA_IS_HINT_LOGARITHMIC(hdesc)) {
538                         *val = exp(log(desc->PortRangeHints[port].LowerBound)
539                                         * 0.25
540                                         + log(desc->PortRangeHints[port].UpperBound)
541                                         * 0.75);
542                 } else {
543                         *val = (desc->PortRangeHints[port].LowerBound * 0.25) +
544                                (desc->PortRangeHints[port].UpperBound * 0.75);
545                 }
546                 break;
547         case LADSPA_HINT_DEFAULT_MAXIMUM:
548                 *val = desc->PortRangeHints[port].UpperBound;
549                 break;
550         case LADSPA_HINT_DEFAULT_0:
551                 *val = 0;
552                 break;
553         case LADSPA_HINT_DEFAULT_1:
554                 *val = 1;
555                 break;
556         case LADSPA_HINT_DEFAULT_100:
557                 *val = 100;
558                 break;
559         case LADSPA_HINT_DEFAULT_440:
560                 *val = 440;
561                 break;
562         default:
563                 *val = 0;	/* reasonable default, if everything fails */
564                 break;
565         }
566 }
567 
snd_pcm_ladspa_connect_controls(snd_pcm_ladspa_plugin_t * plugin,snd_pcm_ladspa_plugin_io_t * io,snd_pcm_ladspa_instance_t * instance)568 static int snd_pcm_ladspa_connect_controls(snd_pcm_ladspa_plugin_t *plugin,
569 					   snd_pcm_ladspa_plugin_io_t *io,
570 					   snd_pcm_ladspa_instance_t *instance)
571 {
572 	unsigned long idx, midx;
573 
574 	for (idx = midx = 0; idx < plugin->desc->PortCount; idx++)
575 		if ((plugin->desc->PortDescriptors[idx] & (io->pdesc | LADSPA_PORT_CONTROL)) == (io->pdesc | LADSPA_PORT_CONTROL)) {
576 			if (io->controls_size > midx) {
577 			        if (!io->controls_initialized[midx])
578 			                snd_pcm_ladspa_get_default_cvalue(plugin->desc, idx, &io->controls[midx]);
579 				plugin->desc->connect_port(instance->handle, idx, &io->controls[midx]);
580 			} else {
581 				return -EINVAL;
582 			}
583 			midx++;
584 		}
585 	return 0;
586 }
587 
snd_pcm_ladspa_check_connect(snd_pcm_ladspa_plugin_t * plugin,snd_pcm_ladspa_plugin_io_t * io,snd_pcm_ladspa_eps_t * eps,unsigned int depth)588 static int snd_pcm_ladspa_check_connect(snd_pcm_ladspa_plugin_t *plugin,
589                                         snd_pcm_ladspa_plugin_io_t *io,
590                                         snd_pcm_ladspa_eps_t *eps,
591                                         unsigned int depth)
592 {
593         unsigned int idx, midx;
594         int err = 0;
595 
596 	for (idx = midx = 0; idx < plugin->desc->PortCount; idx++)
597 		if ((plugin->desc->PortDescriptors[idx] & (io->pdesc | LADSPA_PORT_AUDIO)) == (io->pdesc | LADSPA_PORT_AUDIO)) {
598                         if (eps->channels.array[midx] == NO_ASSIGN) {
599                                 SNDERR("%s port for plugin %s depth %u is not connected", io->pdesc & LADSPA_PORT_INPUT ? "input" : "output", plugin->desc->Name, depth);
600                                 err++;
601                         }
602 			midx++;
603 		}
604         if (err > 0) {
605                 SNDERR("%i connection errors total", err);
606                 return -EINVAL;
607         }
608         return 0;
609 }
610 
snd_pcm_ladspa_allocate_instances(snd_pcm_t * pcm,snd_pcm_ladspa_t * ladspa)611 static int snd_pcm_ladspa_allocate_instances(snd_pcm_t *pcm, snd_pcm_ladspa_t *ladspa)
612 {
613 	struct list_head *list, *pos;
614 	unsigned int depth, idx, count;
615         unsigned int in_channels;
616 	unsigned int in_ports, out_ports;
617 	snd_pcm_ladspa_instance_t *instance = NULL;
618 	int err;
619 
620 	list = pcm->stream == SND_PCM_STREAM_PLAYBACK ? &ladspa->pplugins : &ladspa->cplugins;
621 	in_channels = ladspa->channels > 0 ? ladspa->channels :
622 	              (pcm->stream == SND_PCM_STREAM_PLAYBACK ? pcm->channels : ladspa->plug.gen.slave->channels);
623 	depth = 0;
624 	list_for_each(pos, list) {
625 		snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
626                 in_ports = snd_pcm_ladspa_count_ports(plugin, LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO);
627                 out_ports = snd_pcm_ladspa_count_ports(plugin, LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO);
628 		count = 1;
629 		if (plugin->policy == SND_PCM_LADSPA_POLICY_DUPLICATE) {
630                         if (in_ports == 1 && out_ports == 1)
631                                 count = in_channels;
632                         else
633                                 plugin->policy = SND_PCM_LADSPA_POLICY_NONE;
634                 }
635         	for (idx = 0; idx < count; idx++) {
636 			instance = (snd_pcm_ladspa_instance_t *)calloc(1, sizeof(snd_pcm_ladspa_instance_t));
637 			if (instance == NULL)
638 				return -ENOMEM;
639 			instance->desc = plugin->desc;
640 			instance->handle = plugin->desc->instantiate(plugin->desc, pcm->rate);
641 			instance->depth = depth;
642 			if (instance->handle == NULL) {
643 				SNDERR("Unable to create instance of LADSPA plugin '%s'", plugin->desc->Name);
644 				free(instance);
645 				return -EINVAL;
646 			}
647 			list_add_tail(&instance->list, &plugin->instances);
648 			if (plugin->policy == SND_PCM_LADSPA_POLICY_DUPLICATE) {
649 				err = snd_pcm_ladspa_connect_plugin_duplicate(plugin, &plugin->input, &plugin->output, instance, idx);
650 				if (err < 0) {
651 					SNDERR("Unable to connect duplicate port of plugin '%s' channel %u depth %u", plugin->desc->Name, idx, instance->depth);
652 					return err;
653 				}
654 			} else {
655                 		err = snd_pcm_ladspa_connect_plugin(plugin, instance);
656                 		if (err < 0) {
657 	                		SNDERR("Unable to connect plugin '%s' depth %u", plugin->desc->Name, depth);
658 		                	return err;
659                 		}
660 			}
661 			err = snd_pcm_ladspa_connect_controls(plugin, &plugin->input, instance);
662 			assert(err >= 0);
663 			err = snd_pcm_ladspa_connect_controls(plugin, &plugin->output, instance);
664 			assert(err >= 0);
665 			if (plugin->desc->activate)
666 				plugin->desc->activate(instance->handle);
667 		}
668 		err = snd_pcm_ladspa_check_connect(plugin, &plugin->input, &instance->input, depth);
669 		if (err < 0)
670 		        return err;
671 		err = snd_pcm_ladspa_check_connect(plugin, &plugin->output, &instance->output, depth);
672 		if (err < 0)
673 		        return err;
674 		depth++;
675 	}
676 	return 0;
677 }
678 
snd_pcm_ladspa_allocate_zero(snd_pcm_ladspa_t * ladspa,unsigned int idx)679 static LADSPA_Data *snd_pcm_ladspa_allocate_zero(snd_pcm_ladspa_t *ladspa, unsigned int idx)
680 {
681         if (ladspa->zero[idx] == NULL)
682                 ladspa->zero[idx] = calloc(ladspa->allocated, sizeof(LADSPA_Data));
683         return ladspa->zero[idx];
684 }
685 
snd_pcm_ladspa_allocate_memory(snd_pcm_t * pcm,snd_pcm_ladspa_t * ladspa)686 static int snd_pcm_ladspa_allocate_memory(snd_pcm_t *pcm, snd_pcm_ladspa_t *ladspa)
687 {
688 	struct list_head *list, *pos, *pos1;
689 	snd_pcm_ladspa_instance_t *instance;
690 	unsigned int channels = 16, nchannels;
691 	unsigned int ichannels, ochannels;
692 	void **pchannels, **npchannels;
693 	unsigned int idx, chn;
694 
695         ladspa->allocated = 2048;
696         if (pcm->buffer_size > ladspa->allocated)
697                 ladspa->allocated = pcm->buffer_size;
698         if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
699                 ichannels = pcm->channels;
700                 ochannels = ladspa->plug.gen.slave->channels;
701         } else {
702                 ichannels = ladspa->plug.gen.slave->channels;
703                 ochannels = pcm->channels;
704         }
705 	pchannels = calloc(1, sizeof(void *) * channels);
706 	if (pchannels == NULL)
707 	        return -ENOMEM;
708 	list = pcm->stream == SND_PCM_STREAM_PLAYBACK ? &ladspa->pplugins : &ladspa->cplugins;
709 	list_for_each(pos, list) {
710 		snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
711 		list_for_each(pos1, &plugin->instances) {
712 			instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
713 			nchannels = channels;
714 			for (idx = 0; idx < instance->input.channels.size; idx++) {
715 			        chn = instance->input.channels.array[idx];
716 			        assert(instance->input.ports.array[idx] != NO_ASSIGN);
717         			if (chn >= nchannels)
718         			        nchannels = chn + 1;
719                         }
720 			for (idx = 0; idx < instance->output.channels.size; idx++) {
721 			        chn = instance->output.channels.array[idx];
722 			        assert(instance->output.ports.array[idx] != NO_ASSIGN);
723         			if (chn >= nchannels)
724         			        nchannels = chn + 1;
725                         }
726                         if (nchannels != channels) {
727                                 npchannels = realloc(pchannels, nchannels * sizeof(void *));
728                                 if (npchannels == NULL) {
729                                         free(pchannels);
730                                         return -ENOMEM;
731                                 }
732                                 for (idx = channels; idx < nchannels; idx++)
733                                         npchannels[idx] = NULL;
734                                 pchannels = npchannels;
735                         }
736                         assert(instance->input.data == NULL);
737                         assert(instance->input.m_data == NULL);
738                         assert(instance->output.data == NULL);
739                         assert(instance->output.m_data == NULL);
740                         instance->input.data = calloc(instance->input.channels.size, sizeof(void *));
741                         instance->input.m_data = calloc(instance->input.channels.size, sizeof(void *));
742                         instance->output.data = calloc(instance->output.channels.size, sizeof(void *));
743                         instance->output.m_data = calloc(instance->output.channels.size, sizeof(void *));
744                         if (instance->input.data == NULL ||
745                             instance->input.m_data == NULL ||
746                             instance->output.data == NULL ||
747                             instance->output.m_data == NULL) {
748                                 free(pchannels);
749                                 return -ENOMEM;
750                         }
751 			for (idx = 0; idx < instance->input.channels.size; idx++) {
752 			        chn = instance->input.channels.array[idx];
753 			        if (pchannels[chn] == NULL && chn < ichannels) {
754 			                instance->input.data[idx] = NULL;
755 			                continue;
756                                 }
757 			        instance->input.data[idx] = pchannels[chn];
758 			        if (instance->input.data[idx] == NULL) {
759                                         instance->input.data[idx] = snd_pcm_ladspa_allocate_zero(ladspa, 0);
760                                         if (instance->input.data[idx] == NULL) {
761                                                 free(pchannels);
762                                                 return -ENOMEM;
763                                         }
764                                 }
765                         }
766                         for (idx = 0; idx < instance->output.channels.size; idx++) {
767 			        chn = instance->output.channels.array[idx];
768                                 /* FIXME/OPTIMIZE: check if we can remove double alloc */
769                                 /* if LADSPA plugin has no broken inplace */
770                                 instance->output.data[idx] = malloc(sizeof(LADSPA_Data) * ladspa->allocated);
771                                 if (instance->output.data[idx] == NULL) {
772                                         free(pchannels);
773                                         return -ENOMEM;
774                                 }
775                                 pchannels[chn] = instance->output.m_data[idx] = instance->output.data[idx];
776                         }
777 		}
778 	}
779 	/* OPTIMIZE: we have already allocated areas for ALSA output channels */
780 	/* next loop deallocates the last output LADSPA areas and connects */
781 	/* them to ALSA areas (NULL) or dummy area ladpsa->free[1] ; */
782 	/* this algorithm might be optimized to not allocate the last LADSPA outputs */
783 	list_for_each(pos, list) {
784 		snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
785 		list_for_each(pos1, &plugin->instances) {
786 			instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
787                         for (idx = 0; idx < instance->output.channels.size; idx++) {
788         			chn = instance->output.channels.array[idx];
789                                 if (instance->output.data[idx] == pchannels[chn]) {
790 					free(instance->output.m_data[idx]);
791 					instance->output.m_data[idx] = NULL;
792                                         if (chn < ochannels) {
793                                                 instance->output.data[idx] = NULL;
794                                         } else {
795                                                 instance->output.data[idx] = snd_pcm_ladspa_allocate_zero(ladspa, 1);
796                                                 if (instance->output.data[idx] == NULL) {
797                                                         free(pchannels);
798                                                         return -ENOMEM;
799                                                 }
800                                         }
801                                 }
802                         }
803                 }
804         }
805 #if 0
806         printf("zero[0] = %p\n", ladspa->zero[0]);
807         printf("zero[1] = %p\n", ladspa->zero[1]);
808 	list_for_each(pos, list) {
809 		snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
810 		list_for_each(pos1, &plugin->instances) {
811 			instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
812                         for (idx = 0; idx < instance->input.channels.size; idx++)
813                                 printf("%i:alloc-input%i:  data = %p, m_data = %p\n", instance->depth, idx, instance->input.data[idx], instance->input.m_data[idx]);
814                         for (idx = 0; idx < instance->output.channels.size; idx++)
815                                 printf("%i:alloc-output%i:  data = %p, m_data = %p\n", instance->depth, idx, instance->output.data[idx], instance->output.m_data[idx]);
816 		}
817 	}
818 #endif
819 	free(pchannels);
820 	return 0;
821 }
822 
snd_pcm_ladspa_init(snd_pcm_t * pcm)823 static int snd_pcm_ladspa_init(snd_pcm_t *pcm)
824 {
825 	snd_pcm_ladspa_t *ladspa = pcm->private_data;
826 	int err;
827 
828 	snd_pcm_ladspa_free_instances(pcm, ladspa, 1);
829 	err = snd_pcm_ladspa_allocate_instances(pcm, ladspa);
830 	if (err < 0) {
831 		snd_pcm_ladspa_free_instances(pcm, ladspa, 1);
832 		return err;
833 	}
834 	err = snd_pcm_ladspa_allocate_memory(pcm, ladspa);
835 	if (err < 0) {
836 		snd_pcm_ladspa_free_instances(pcm, ladspa, 1);
837 		return err;
838 	}
839 	return 0;
840 }
841 
snd_pcm_ladspa_hw_free(snd_pcm_t * pcm)842 static int snd_pcm_ladspa_hw_free(snd_pcm_t *pcm)
843 {
844 	snd_pcm_ladspa_t *ladspa = pcm->private_data;
845 
846 	snd_pcm_ladspa_free_instances(pcm, ladspa, 1);
847 	return snd_pcm_generic_hw_free(pcm);
848 }
849 
850 static snd_pcm_uframes_t
snd_pcm_ladspa_write_areas(snd_pcm_t * pcm,const snd_pcm_channel_area_t * areas,snd_pcm_uframes_t offset,snd_pcm_uframes_t size,const snd_pcm_channel_area_t * slave_areas,snd_pcm_uframes_t slave_offset,snd_pcm_uframes_t * slave_sizep)851 snd_pcm_ladspa_write_areas(snd_pcm_t *pcm,
852 			   const snd_pcm_channel_area_t *areas,
853 			   snd_pcm_uframes_t offset,
854 			   snd_pcm_uframes_t size,
855 			   const snd_pcm_channel_area_t *slave_areas,
856 			   snd_pcm_uframes_t slave_offset,
857 			   snd_pcm_uframes_t *slave_sizep)
858 {
859 	snd_pcm_ladspa_t *ladspa = pcm->private_data;
860 	snd_pcm_ladspa_instance_t *instance;
861 	struct list_head *pos, *pos1;
862 	LADSPA_Data *data;
863 	unsigned int idx, chn, size1, size2;
864 
865 	if (size > *slave_sizep)
866 		size = *slave_sizep;
867         size2 = size;
868 #if 0	/* no processing - for testing purposes only */
869 	snd_pcm_areas_copy(slave_areas, slave_offset,
870 			   areas, offset,
871 			   pcm->channels, size, pcm->format);
872 #else
873         while (size > 0) {
874                 size1 = size;
875                 if (size1 > ladspa->allocated)
876                         size1 = ladspa->allocated;
877         	list_for_each(pos, &ladspa->pplugins) {
878         		snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
879         		list_for_each(pos1, &plugin->instances) {
880         			instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
881         			for (idx = 0; idx < instance->input.channels.size; idx++) {
882                                         chn = instance->input.channels.array[idx];
883                                         data = instance->input.data[idx];
884                                         if (data == NULL) {
885                                 		data = (LADSPA_Data *)((char *)areas[chn].addr + (areas[chn].first / 8));
886                                        		data += offset;
887                                         }
888                                         instance->desc->connect_port(instance->handle, instance->input.ports.array[idx], data);
889         			}
890         			for (idx = 0; idx < instance->output.channels.size; idx++) {
891                                         chn = instance->output.channels.array[idx];
892                                         data = instance->output.data[idx];
893                                         if (data == NULL) {
894                                 		data = (LADSPA_Data *)((char *)slave_areas[chn].addr + (areas[chn].first / 8));
895                                 		data += slave_offset;
896                                         }
897 					instance->desc->connect_port(instance->handle, instance->output.ports.array[idx], data);
898         			}
899         			instance->desc->run(instance->handle, size1);
900         		}
901         	}
902         	offset += size1;
903         	slave_offset += size1;
904         	size -= size1;
905 	}
906 #endif
907 	*slave_sizep = size2;
908 	return size2;
909 }
910 
911 static snd_pcm_uframes_t
snd_pcm_ladspa_read_areas(snd_pcm_t * pcm,const snd_pcm_channel_area_t * areas,snd_pcm_uframes_t offset,snd_pcm_uframes_t size,const snd_pcm_channel_area_t * slave_areas,snd_pcm_uframes_t slave_offset,snd_pcm_uframes_t * slave_sizep)912 snd_pcm_ladspa_read_areas(snd_pcm_t *pcm,
913 			  const snd_pcm_channel_area_t *areas,
914 			  snd_pcm_uframes_t offset,
915 			  snd_pcm_uframes_t size,
916 			  const snd_pcm_channel_area_t *slave_areas,
917 			  snd_pcm_uframes_t slave_offset,
918 			  snd_pcm_uframes_t *slave_sizep)
919 {
920 	snd_pcm_ladspa_t *ladspa = pcm->private_data;
921 	snd_pcm_ladspa_instance_t *instance;
922 	struct list_head *pos, *pos1;
923 	LADSPA_Data *data;
924 	unsigned int idx, chn, size1, size2;;
925 
926 	if (size > *slave_sizep)
927 		size = *slave_sizep;
928         size2 = size;
929 #if 0	/* no processing - for testing purposes only */
930 	snd_pcm_areas_copy(areas, offset,
931 			   slave_areas, slave_offset,
932 			   pcm->channels, size, pcm->format);
933 #else
934         while (size > 0) {
935                 size1 = size;
936                 if (size1 > ladspa->allocated)
937                         size1 = ladspa->allocated;
938         	list_for_each(pos, &ladspa->cplugins) {
939         		snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
940         		list_for_each(pos1, &plugin->instances) {
941         			instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
942         			for (idx = 0; idx < instance->input.channels.size; idx++) {
943                                         chn = instance->input.channels.array[idx];
944                                         data = instance->input.data[idx];
945                                         if (data == NULL) {
946                                 		data = (LADSPA_Data *)((char *)slave_areas[chn].addr + (areas[chn].first / 8));
947                                 		data += slave_offset;
948                                         }
949                 			instance->desc->connect_port(instance->handle, instance->input.ports.array[idx], data);
950         			}
951         			for (idx = 0; idx < instance->output.channels.size; idx++) {
952                                         chn = instance->output.channels.array[idx];
953                                         data = instance->output.data[idx];
954                                         if (data == NULL) {
955                                 		data = (LADSPA_Data *)((char *)areas[chn].addr + (areas[chn].first / 8));
956                                        		data += offset;
957                                         }
958         		        	instance->desc->connect_port(instance->handle, instance->output.ports.array[idx], data);
959         			}
960         			instance->desc->run(instance->handle, size1);
961         		}
962         	}
963         	offset += size1;
964         	slave_offset += size1;
965         	size -= size1;
966 	}
967 #endif
968 	*slave_sizep = size2;
969 	return size2;
970 }
971 
snd_pcm_ladspa_dump_direction(snd_pcm_ladspa_plugin_t * plugin,snd_pcm_ladspa_plugin_io_t * io,snd_output_t * out)972 static void snd_pcm_ladspa_dump_direction(snd_pcm_ladspa_plugin_t *plugin,
973                                           snd_pcm_ladspa_plugin_io_t *io,
974                                           snd_output_t *out)
975 {
976 	unsigned int idx, midx;
977 
978 	if (io->port_bindings_size == 0)
979 		goto __control;
980 	snd_output_printf(out, "    Audio %s port bindings:\n", io->pdesc == LADSPA_PORT_INPUT ? "input" : "output");
981 	for (idx = 0; idx < io->port_bindings_size; idx++) {
982 		if (io->port_bindings[idx] == NO_ASSIGN)
983 			snd_output_printf(out, "      %i -> NONE\n", idx);
984                 else
985         		snd_output_printf(out, "      %i -> %i\n", idx, io->port_bindings[idx]);
986 	}
987       __control:
988       	if (io->controls_size == 0)
989       		return;
990 	snd_output_printf(out, "    Control %s port initial values:\n", io->pdesc == LADSPA_PORT_INPUT ? "input" : "output");
991 	for (idx = midx = 0; idx < plugin->desc->PortCount; idx++) {
992 		if ((plugin->desc->PortDescriptors[idx] & (io->pdesc | LADSPA_PORT_CONTROL)) == (io->pdesc | LADSPA_PORT_CONTROL)) {
993         		snd_output_printf(out, "      %i \"%s\" = %.8f\n", idx, plugin->desc->PortNames[idx], io->controls[midx]);
994         		midx++;
995                 }
996         }
997 }
998 
snd_pcm_ladspa_dump_array(snd_output_t * out,snd_pcm_ladspa_array_t * array,snd_pcm_ladspa_plugin_t * plugin)999 static void snd_pcm_ladspa_dump_array(snd_output_t *out,
1000                                       snd_pcm_ladspa_array_t *array,
1001                                       snd_pcm_ladspa_plugin_t *plugin)
1002 {
1003         unsigned int size = array->size;
1004         unsigned int val, idx = 0;
1005 
1006         while (size-- > 0) {
1007                 if (idx > 0) {
1008                         snd_output_putc(out, ',');
1009                         snd_output_putc(out, ' ');
1010                 }
1011                 val = array->array[idx++];
1012                 if (val == NO_ASSIGN)
1013                         snd_output_putc(out, '-');
1014                 else
1015                         snd_output_printf(out, "%u", val);
1016                 if (plugin && val != NO_ASSIGN)
1017                         snd_output_printf(out, " \"%s\"", plugin->desc->PortNames[val]);
1018         }
1019 }
1020 
snd_pcm_ladspa_plugins_dump(struct list_head * list,snd_output_t * out)1021 static void snd_pcm_ladspa_plugins_dump(struct list_head *list, snd_output_t *out)
1022 {
1023 	struct list_head *pos, *pos2;
1024 
1025 	list_for_each(pos, list) {
1026 		snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
1027 		snd_output_printf(out, "    Policy: %s\n", plugin->policy == SND_PCM_LADSPA_POLICY_NONE ? "none" : "duplicate");
1028 		snd_output_printf(out, "    Filename: %s\n", plugin->filename);
1029 		snd_output_printf(out, "    Plugin Name: %s\n", plugin->desc->Name);
1030 		snd_output_printf(out, "    Plugin Label: %s\n", plugin->desc->Label);
1031 		snd_output_printf(out, "    Plugin Unique ID: %lu\n", plugin->desc->UniqueID);
1032                 snd_output_printf(out, "    Instances:\n");
1033 		list_for_each(pos2, &plugin->instances) {
1034 		        snd_pcm_ladspa_instance_t *in = (snd_pcm_ladspa_instance_t *) pos2;
1035 		        snd_output_printf(out, "      Depth: %i\n", in->depth);
1036 		        snd_output_printf(out, "         InChannels: ");
1037                         snd_pcm_ladspa_dump_array(out, &in->input.channels, NULL);
1038                         snd_output_printf(out, "\n         InPorts: ");
1039                         snd_pcm_ladspa_dump_array(out, &in->input.ports, plugin);
1040                         snd_output_printf(out, "\n         OutChannels: ");
1041                         snd_pcm_ladspa_dump_array(out, &in->output.channels, NULL);
1042                         snd_output_printf(out, "\n         OutPorts: ");
1043                         snd_pcm_ladspa_dump_array(out, &in->output.ports, plugin);
1044                         snd_output_printf(out, "\n");
1045 		}
1046 		snd_pcm_ladspa_dump_direction(plugin, &plugin->input, out);
1047 		snd_pcm_ladspa_dump_direction(plugin, &plugin->output, out);
1048 	}
1049 }
1050 
snd_pcm_ladspa_dump(snd_pcm_t * pcm,snd_output_t * out)1051 static void snd_pcm_ladspa_dump(snd_pcm_t *pcm, snd_output_t *out)
1052 {
1053 	snd_pcm_ladspa_t *ladspa = pcm->private_data;
1054 
1055 	snd_output_printf(out, "LADSPA PCM\n");
1056 	snd_output_printf(out, "  Playback:\n");
1057 	snd_pcm_ladspa_plugins_dump(&ladspa->pplugins, out);
1058 	snd_output_printf(out, "  Capture:\n");
1059 	snd_pcm_ladspa_plugins_dump(&ladspa->cplugins, out);
1060 	if (pcm->setup) {
1061 		snd_output_printf(out, "Its setup is:\n");
1062 		snd_pcm_dump_setup(pcm, out);
1063 	}
1064 	snd_output_printf(out, "Slave: ");
1065 	snd_pcm_dump(ladspa->plug.gen.slave, out);
1066 }
1067 
1068 static const snd_pcm_ops_t snd_pcm_ladspa_ops = {
1069 	.close = snd_pcm_ladspa_close,
1070 	.info = snd_pcm_generic_info,
1071 	.hw_refine = snd_pcm_ladspa_hw_refine,
1072 	.hw_params = snd_pcm_ladspa_hw_params,
1073 	.hw_free = snd_pcm_ladspa_hw_free,
1074 	.sw_params = snd_pcm_generic_sw_params,
1075 	.channel_info = snd_pcm_generic_channel_info,
1076 	.dump = snd_pcm_ladspa_dump,
1077 	.nonblock = snd_pcm_generic_nonblock,
1078 	.async = snd_pcm_generic_async,
1079 	.mmap = snd_pcm_generic_mmap,
1080 	.munmap = snd_pcm_generic_munmap,
1081 	.query_chmaps = snd_pcm_generic_query_chmaps,
1082 	.get_chmap = snd_pcm_generic_get_chmap,
1083 	.set_chmap = snd_pcm_generic_set_chmap,
1084 };
1085 
snd_pcm_ladspa_check_file(snd_pcm_ladspa_plugin_t * const plugin,const char * filename,const char * label,const unsigned long ladspa_id)1086 static int snd_pcm_ladspa_check_file(snd_pcm_ladspa_plugin_t * const plugin,
1087 				     const char *filename,
1088 				     const char *label,
1089 				     const unsigned long ladspa_id)
1090 {
1091 	void *handle;
1092 
1093 	assert(filename);
1094 	handle = dlopen(filename, RTLD_LAZY);
1095 	if (handle) {
1096 		LADSPA_Descriptor_Function fcn = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor");
1097 		if (fcn) {
1098 			long idx;
1099 			const LADSPA_Descriptor *d;
1100 			for (idx = 0; (d = fcn(idx)) != NULL; idx++) {
1101 /*
1102  * avoid locale problems - see ALSA bug#1553
1103  */
1104 #if 0
1105 				if (strcmp(label, d->Label))
1106 					continue;
1107 #else
1108                                 char *labellocale;
1109                                 struct lconv *lc;
1110                                 if (label != NULL) {
1111                                         lc = localeconv ();
1112                                         labellocale = malloc (strlen (label) + 1);
1113                                         if (labellocale == NULL) {
1114                                         	dlclose(handle);
1115                                                 return -ENOMEM;
1116 					}
1117                                         strcpy (labellocale, label);
1118                                         if (strrchr(labellocale, '.'))
1119                                                 *strrchr (labellocale, '.') = *lc->decimal_point;
1120                                         if (strcmp(label, d->Label) && strcmp(labellocale, d->Label)) {
1121                                                 free(labellocale);
1122                                                 continue;
1123                                         }
1124                                         free (labellocale);
1125                                 }
1126 #endif
1127 				if (ladspa_id > 0 && d->UniqueID != ladspa_id)
1128 					continue;
1129 				plugin->filename = strdup(filename);
1130 				if (plugin->filename == NULL) {
1131 					dlclose(handle);
1132 					return -ENOMEM;
1133 				}
1134 				plugin->dl_handle = handle;
1135 				plugin->desc = d;
1136 				return 1;
1137 			}
1138 		}
1139 		dlclose(handle);
1140 	}
1141 	return -ENOENT;
1142 }
1143 
snd_pcm_ladspa_check_dir(snd_pcm_ladspa_plugin_t * const plugin,const char * path,const char * label,const unsigned long ladspa_id)1144 static int snd_pcm_ladspa_check_dir(snd_pcm_ladspa_plugin_t * const plugin,
1145 				    const char *path,
1146 				    const char *label,
1147 				    const unsigned long ladspa_id)
1148 {
1149 	DIR *dir;
1150 	struct dirent * dirent;
1151 	int len = strlen(path), err;
1152 	int need_slash;
1153 	char *filename;
1154 
1155 	if (len < 1)
1156 		return 0;
1157 	need_slash = path[len - 1] != '/';
1158 
1159 	dir = opendir(path);
1160 	if (!dir)
1161 		return -ENOENT;
1162 
1163 	while (1) {
1164 		dirent = readdir(dir);
1165 		if (!dirent) {
1166 			closedir(dir);
1167 			return 0;
1168 		}
1169 
1170 		filename = malloc(len + strlen(dirent->d_name) + 1 + need_slash);
1171 		if (filename == NULL) {
1172 			closedir(dir);
1173 			return -ENOMEM;
1174 		}
1175 		strcpy(filename, path);
1176 		if (need_slash)
1177 			strcat(filename, "/");
1178 		strcat(filename, dirent->d_name);
1179 		err = snd_pcm_ladspa_check_file(plugin, filename, label, ladspa_id);
1180 		free(filename);
1181 		if (err < 0 && err != -ENOENT) {
1182 			closedir(dir);
1183 			return err;
1184 		}
1185 		if (err > 0) {
1186 			closedir(dir);
1187 			return 1;
1188 		}
1189 	}
1190 	/* never reached */
1191 	return 0;
1192 }
1193 
snd_pcm_ladspa_look_for_plugin(snd_pcm_ladspa_plugin_t * const plugin,const char * path,const char * label,const long ladspa_id)1194 static int snd_pcm_ladspa_look_for_plugin(snd_pcm_ladspa_plugin_t * const plugin,
1195 					  const char *path,
1196 					  const char *label,
1197 					  const long ladspa_id)
1198 {
1199 	const char *c;
1200 	size_t l;
1201 	int err;
1202 
1203 	for (c = path; (l = strcspn(c, ": ")) > 0; ) {
1204 		char name[l + 1];
1205 		char *fullpath;
1206 		memcpy(name, c, l);
1207 		name[l] = 0;
1208 		err = snd_user_file(name, &fullpath);
1209 		if (err < 0)
1210 			return err;
1211 		err = snd_pcm_ladspa_check_dir(plugin, fullpath, label, ladspa_id);
1212 		free(fullpath);
1213 		if (err < 0)
1214 			return err;
1215 		if (err > 0)
1216 			return 0;
1217 		c += l;
1218 		if (!*c)
1219 			break;
1220 		c++;
1221 	}
1222 	return -ENOENT;
1223 }
1224 
snd_pcm_ladspa_add_default_controls(snd_pcm_ladspa_plugin_t * lplug,snd_pcm_ladspa_plugin_io_t * io)1225 static int snd_pcm_ladspa_add_default_controls(snd_pcm_ladspa_plugin_t *lplug,
1226 					       snd_pcm_ladspa_plugin_io_t *io)
1227 {
1228 	unsigned int count = 0;
1229 	LADSPA_Data *array;
1230 	unsigned char *initialized;
1231 	unsigned long idx;
1232 
1233 	for (idx = 0; idx < lplug->desc->PortCount; idx++)
1234 		if ((lplug->desc->PortDescriptors[idx] & (io->pdesc | LADSPA_PORT_CONTROL)) == (io->pdesc | LADSPA_PORT_CONTROL))
1235 			count++;
1236 	array = (LADSPA_Data *)calloc(count, sizeof(LADSPA_Data));
1237 	if (!array)
1238 		return -ENOMEM;
1239 	initialized = (unsigned char *)calloc(count, sizeof(unsigned char));
1240 	if (!initialized) {
1241 		free(array);
1242 		return -ENOMEM;
1243 	}
1244 	io->controls_size = count;
1245 	io->controls_initialized = initialized;
1246 	io->controls = array;
1247 
1248 	return 0;
1249 }
1250 
snd_pcm_ladspa_parse_controls(snd_pcm_ladspa_plugin_t * lplug,snd_pcm_ladspa_plugin_io_t * io,snd_config_t * controls)1251 static int snd_pcm_ladspa_parse_controls(snd_pcm_ladspa_plugin_t *lplug,
1252 					 snd_pcm_ladspa_plugin_io_t *io,
1253 					 snd_config_t *controls)
1254 {
1255 	snd_config_iterator_t i, next;
1256 	int err;
1257 
1258 	if (snd_config_get_type(controls) != SND_CONFIG_TYPE_COMPOUND) {
1259 		SNDERR("controls definition must be a compound");
1260 		return -EINVAL;
1261 	}
1262 
1263 	snd_config_for_each(i, next, controls) {
1264 		snd_config_t *n = snd_config_iterator_entry(i);
1265 		const char *id;
1266 		long lval;
1267 		unsigned int port, uval;
1268 		double dval;
1269 		if (snd_config_get_id(n, &id) < 0)
1270 			continue;
1271 		err = safe_strtol(id, &lval);
1272 		if (err >= 0) {
1273 			err = snd_pcm_ladspa_find_port(&port, lplug, io->pdesc | LADSPA_PORT_CONTROL, lval);
1274 		} else {
1275 			err = snd_pcm_ladspa_find_sport(&port, lplug, io->pdesc | LADSPA_PORT_CONTROL, id);
1276 		}
1277 		if (err < 0) {
1278 			SNDERR("Unable to find an control port (%s)", id);
1279 			return err;
1280 		}
1281 		if (snd_config_get_ireal(n, &dval) < 0) {
1282 			SNDERR("Control port %s has not an float or integer value", id);
1283 			return err;
1284 		}
1285 		err = snd_pcm_ladspa_find_port_idx(&uval, lplug, io->pdesc | LADSPA_PORT_CONTROL, port);
1286 		if (err < 0) {
1287 			SNDERR("internal error");
1288 			return err;
1289 		}
1290 		io->controls_initialized[uval] = 1;
1291 		io->controls[uval] = (LADSPA_Data)dval;
1292 	}
1293 
1294 	return 0;
1295 }
1296 
snd_pcm_ladspa_parse_bindings(snd_pcm_ladspa_plugin_t * lplug,snd_pcm_ladspa_plugin_io_t * io,snd_config_t * bindings)1297 static int snd_pcm_ladspa_parse_bindings(snd_pcm_ladspa_plugin_t *lplug,
1298 					 snd_pcm_ladspa_plugin_io_t *io,
1299 					 snd_config_t *bindings)
1300 {
1301 	unsigned int count = 0;
1302 	unsigned int *array;
1303 	snd_config_iterator_t i, next;
1304 	int err;
1305 
1306 	if (snd_config_get_type(bindings) != SND_CONFIG_TYPE_COMPOUND) {
1307 		SNDERR("bindings definition must be a compound");
1308 		return -EINVAL;
1309 	}
1310 	snd_config_for_each(i, next, bindings) {
1311 		snd_config_t *n = snd_config_iterator_entry(i);
1312 		const char *id;
1313 		long channel;
1314 		if (snd_config_get_id(n, &id) < 0)
1315 			continue;
1316 		err = safe_strtol(id, &channel);
1317 		if (err < 0 || channel < 0) {
1318 			SNDERR("Invalid channel number: %s", id);
1319 			return -EINVAL;
1320 		}
1321 		if (lplug->policy == SND_PCM_LADSPA_POLICY_DUPLICATE && channel > 0) {
1322 			SNDERR("Wrong channel specification for duplicate policy");
1323 			return -EINVAL;
1324 		}
1325 		if (count < (unsigned int)(channel + 1))
1326 			count = (unsigned int)(channel + 1);
1327 	}
1328 	if (count > 0) {
1329 		array = (unsigned int *)malloc(count * sizeof(unsigned int));
1330 		if (! array)
1331 			return -ENOMEM;
1332 		memset(array, 0xff, count * sizeof(unsigned int));
1333 		io->port_bindings_size = count;
1334 		io->port_bindings = array;
1335 		snd_config_for_each(i, next, bindings) {
1336 			snd_config_t *n = snd_config_iterator_entry(i);
1337 			const char *id, *sport;
1338 			long channel, port;
1339 			if (snd_config_get_id(n, &id) < 0)
1340 				continue;
1341 			err = safe_strtol(id, &channel);
1342 			if (err < 0 || channel < 0) {
1343 				assert(0);	/* should never happen */
1344 				return -EINVAL;
1345 			}
1346 			err = snd_config_get_integer(n, &port);
1347 			if (err >= 0) {
1348 				err = snd_pcm_ladspa_find_port(&array[channel], lplug, io->pdesc | LADSPA_PORT_AUDIO, port);
1349 				if (err < 0) {
1350 					SNDERR("Unable to find an audio port (%li) for channel %s", port, id);
1351 					return err;
1352 				}
1353 				continue;
1354 			}
1355 			err = snd_config_get_string(n, &sport);
1356 			if (err < 0) {
1357 				SNDERR("Invalid LADSPA port field type for %s", id);
1358 				return -EINVAL;
1359 			}
1360 			err = snd_pcm_ladspa_find_sport(&array[channel], lplug, io->pdesc | LADSPA_PORT_AUDIO, sport);
1361 			if (err < 0) {
1362 				SNDERR("Unable to find an audio port (%s) for channel %s", sport, id);
1363 				return err;
1364 			}
1365 		}
1366 	}
1367 
1368 	return 0;
1369 }
1370 
snd_pcm_ladspa_parse_ioconfig(snd_pcm_ladspa_plugin_t * lplug,snd_pcm_ladspa_plugin_io_t * io,snd_config_t * conf)1371 static int snd_pcm_ladspa_parse_ioconfig(snd_pcm_ladspa_plugin_t *lplug,
1372 					 snd_pcm_ladspa_plugin_io_t *io,
1373 					 snd_config_t *conf)
1374 {
1375 	snd_config_iterator_t i, next;
1376 	snd_config_t *bindings = NULL, *controls = NULL;
1377 	int err;
1378 
1379 	/* always add default controls for both input and output */
1380 	err = snd_pcm_ladspa_add_default_controls(lplug, io);
1381 	if (err < 0) {
1382 		SNDERR("error adding default controls");
1383 		return err;
1384 	}
1385 
1386 	if (conf == NULL) {
1387 		return 0;
1388 	}
1389 
1390 	if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
1391 		SNDERR("input or output definition must be a compound");
1392 		return -EINVAL;
1393 	}
1394 	snd_config_for_each(i, next, conf) {
1395 		snd_config_t *n = snd_config_iterator_entry(i);
1396 		const char *id;
1397 		if (snd_config_get_id(n, &id) < 0)
1398 			continue;
1399 		if (strcmp(id, "bindings") == 0) {
1400 			bindings = n;
1401 			continue;
1402 		}
1403 		if (strcmp(id, "controls") == 0) {
1404 			controls = n;
1405 			continue;
1406 		}
1407 	}
1408 
1409 	/* ignore values of parameters for output controls */
1410 	if (controls && !(io->pdesc & LADSPA_PORT_OUTPUT)) {
1411  		err = snd_pcm_ladspa_parse_controls(lplug, io, controls);
1412 		if (err < 0)
1413 			return err;
1414 	}
1415 
1416 	if (bindings) {
1417  		err = snd_pcm_ladspa_parse_bindings(lplug, io, bindings);
1418 		if (err < 0)
1419 			return err;
1420 	}
1421 
1422 
1423 	return 0;
1424 }
1425 
snd_pcm_ladspa_add_plugin(struct list_head * list,const char * path,snd_config_t * plugin,int reverse)1426 static int snd_pcm_ladspa_add_plugin(struct list_head *list,
1427 				     const char *path,
1428 				     snd_config_t *plugin,
1429 				     int reverse)
1430 {
1431 	snd_config_iterator_t i, next;
1432 	const char *label = NULL, *filename = NULL;
1433 	long ladspa_id = 0;
1434 	int err;
1435 	snd_pcm_ladspa_plugin_t *lplug;
1436 	snd_pcm_ladspa_policy_t policy = SND_PCM_LADSPA_POLICY_DUPLICATE;
1437 	snd_config_t *input = NULL, *output = NULL;
1438 
1439 	snd_config_for_each(i, next, plugin) {
1440 		snd_config_t *n = snd_config_iterator_entry(i);
1441 		const char *id;
1442 		if (snd_config_get_id(n, &id) < 0)
1443 			continue;
1444 		if (strcmp(id, "label") == 0) {
1445 			err = snd_config_get_string(n, &label);
1446 			if (err < 0)
1447 				return err;
1448 			continue;
1449 		}
1450 		if (strcmp(id, "id") == 0) {
1451 			err = snd_config_get_integer(n, &ladspa_id);
1452 			if (err < 0)
1453 				return err;
1454 			continue;
1455 		}
1456 		if (strcmp(id, "filename") == 0) {
1457 			err = snd_config_get_string(n, &filename);
1458 			if (err < 0)
1459 				return err;
1460 			continue;
1461 		}
1462 		if (strcmp(id, "input") == 0) {
1463 			input = n;
1464 			continue;
1465 		}
1466 		if (strcmp(id, "output") == 0) {
1467 			output = n;
1468 			continue;
1469 		}
1470 		if (strcmp(id, "policy") == 0) {
1471 			const char *str;
1472 			err = snd_config_get_string(n, &str);
1473 			if (err < 0) {
1474 				SNDERR("policy field must be a string");
1475 				return err;
1476 			}
1477 			if (strcmp(str, "none") == 0)
1478 				policy = SND_PCM_LADSPA_POLICY_NONE;
1479 			else if (strcmp(str, "duplicate") == 0)
1480 				policy = SND_PCM_LADSPA_POLICY_DUPLICATE;
1481 			else {
1482 				SNDERR("unknown policy definition");
1483 				return -EINVAL;
1484 			}
1485 			continue;
1486 		}
1487 	}
1488 	if (label == NULL && ladspa_id <= 0) {
1489 		SNDERR("no plugin label or id");
1490 		return -EINVAL;
1491 	}
1492 	lplug = (snd_pcm_ladspa_plugin_t *)calloc(1, sizeof(snd_pcm_ladspa_plugin_t));
1493 	if (lplug == NULL)
1494 		return -ENOMEM;
1495 	lplug->policy = policy;
1496 	lplug->input.pdesc = LADSPA_PORT_INPUT;
1497 	lplug->output.pdesc = LADSPA_PORT_OUTPUT;
1498 	INIT_LIST_HEAD(&lplug->instances);
1499 	if (filename) {
1500 		err = snd_pcm_ladspa_check_file(lplug, filename, label, ladspa_id);
1501 		if (err < 0) {
1502 			SNDERR("Unable to load plugin '%s' ID %li, filename '%s'", label, ladspa_id, filename);
1503 			free(lplug);
1504 			return err;
1505 		}
1506 	} else {
1507 		err = snd_pcm_ladspa_look_for_plugin(lplug, path, label, ladspa_id);
1508 		if (err < 0) {
1509 			SNDERR("Unable to find or load plugin '%s' ID %li, path '%s'", label, ladspa_id, path);
1510 			free(lplug);
1511 			return err;
1512 		}
1513 	}
1514 	if (!reverse) {
1515 		list_add_tail(&lplug->list, list);
1516 	} else {
1517 		list_add(&lplug->list, list);
1518 	}
1519 	err = snd_pcm_ladspa_parse_ioconfig(lplug, &lplug->input, input);
1520 	if (err < 0)
1521 		return err;
1522 	err = snd_pcm_ladspa_parse_ioconfig(lplug, &lplug->output, output);
1523 	if (err < 0)
1524 		return err;
1525 	return 0;
1526 }
1527 
snd_pcm_ladspa_build_plugins(struct list_head * list,const char * path,snd_config_t * plugins,int reverse)1528 static int snd_pcm_ladspa_build_plugins(struct list_head *list,
1529 					const char *path,
1530 					snd_config_t *plugins,
1531 					int reverse)
1532 {
1533 	snd_config_iterator_t i, next;
1534 	int idx = 0, hit, err;
1535 
1536 	if (plugins == NULL)	/* nothing TODO */
1537 		return 0;
1538 	if (snd_config_get_type(plugins) != SND_CONFIG_TYPE_COMPOUND) {
1539 		SNDERR("plugins must be defined inside a compound");
1540 		return -EINVAL;
1541 	}
1542 	do {
1543 		hit = 0;
1544 		snd_config_for_each(i, next, plugins) {
1545 			snd_config_t *n = snd_config_iterator_entry(i);
1546 			const char *id;
1547 			long i;
1548 			if (snd_config_get_id(n, &id) < 0)
1549 				continue;
1550 			err = safe_strtol(id, &i);
1551 			if (err < 0) {
1552 				SNDERR("id of field %s is not an integer", id);
1553 				return err;
1554 			}
1555 			if (i == idx) {
1556 				idx++;
1557 				err = snd_pcm_ladspa_add_plugin(list, path, n, reverse);
1558 				if (err < 0)
1559 					return err;
1560 				hit = 1;
1561 			}
1562 		}
1563 	} while (hit);
1564 	if (list_empty(list)) {
1565 		SNDERR("empty plugin list is not accepted");
1566 		return -EINVAL;
1567 	}
1568 	return 0;
1569 }
1570 
1571 /**
1572  * \brief Creates a new LADSPA<->ALSA Plugin
1573  * \param pcmp Returns created PCM handle
1574  * \param name Name of PCM
1575  * \param ladspa_path The path for LADSPA plugins
1576  * \param channels Force input channel count to LADSPA plugin chain, 0 = no force (auto)
1577  * \param ladspa_pplugins The playback configuration
1578  * \param ladspa_cplugins The capture configuration
1579  * \param slave Slave PCM handle
1580  * \param close_slave When set, the slave PCM handle is closed with copy PCM
1581  * \retval zero on success otherwise a negative error code
1582  * \warning Using of this function might be dangerous in the sense
1583  *          of compatibility reasons. The prototype might be freely
1584  *          changed in future.
1585  */
snd_pcm_ladspa_open(snd_pcm_t ** pcmp,const char * name,const char * ladspa_path,unsigned int channels,snd_config_t * ladspa_pplugins,snd_config_t * ladspa_cplugins,snd_pcm_t * slave,int close_slave)1586 int snd_pcm_ladspa_open(snd_pcm_t **pcmp, const char *name,
1587 			const char *ladspa_path,
1588 			unsigned int channels,
1589 			snd_config_t *ladspa_pplugins,
1590 			snd_config_t *ladspa_cplugins,
1591 			snd_pcm_t *slave, int close_slave)
1592 {
1593 	snd_pcm_t *pcm;
1594 	snd_pcm_ladspa_t *ladspa;
1595 	int err, reverse = 0;
1596 
1597 	assert(pcmp && (ladspa_pplugins || ladspa_cplugins) && slave);
1598 
1599 	if (!ladspa_path && !(ladspa_path = getenv("LADSPA_PATH")))
1600 		return -ENOENT;
1601 	ladspa = calloc(1, sizeof(snd_pcm_ladspa_t));
1602 	if (!ladspa)
1603 		return -ENOMEM;
1604 	snd_pcm_plugin_init(&ladspa->plug);
1605 	ladspa->plug.init = snd_pcm_ladspa_init;
1606 	ladspa->plug.read = snd_pcm_ladspa_read_areas;
1607 	ladspa->plug.write = snd_pcm_ladspa_write_areas;
1608 	ladspa->plug.undo_read = snd_pcm_plugin_undo_read_generic;
1609 	ladspa->plug.undo_write = snd_pcm_plugin_undo_write_generic;
1610 	ladspa->plug.gen.slave = slave;
1611 	ladspa->plug.gen.close_slave = close_slave;
1612 
1613 	INIT_LIST_HEAD(&ladspa->pplugins);
1614 	INIT_LIST_HEAD(&ladspa->cplugins);
1615 	ladspa->channels = channels;
1616 
1617 	if (slave->stream == SND_PCM_STREAM_PLAYBACK) {
1618 		err = snd_pcm_ladspa_build_plugins(&ladspa->pplugins, ladspa_path, ladspa_pplugins, reverse);
1619 		if (err < 0) {
1620 			snd_pcm_ladspa_free(ladspa);
1621 			return err;
1622 		}
1623 	}
1624 	if (slave->stream == SND_PCM_STREAM_CAPTURE) {
1625 		if (ladspa_cplugins == ladspa_pplugins)
1626 			reverse = 1;
1627 		err = snd_pcm_ladspa_build_plugins(&ladspa->cplugins, ladspa_path, ladspa_cplugins, reverse);
1628 		if (err < 0) {
1629 			snd_pcm_ladspa_free(ladspa);
1630 			return err;
1631 		}
1632 	}
1633 
1634 	err = snd_pcm_new(&pcm, SND_PCM_TYPE_LADSPA, name, slave->stream, slave->mode);
1635 	if (err < 0) {
1636 		snd_pcm_ladspa_free(ladspa);
1637 		return err;
1638 	}
1639 	pcm->ops = &snd_pcm_ladspa_ops;
1640 	pcm->fast_ops = &snd_pcm_plugin_fast_ops;
1641 	pcm->private_data = ladspa;
1642 	pcm->poll_fd = slave->poll_fd;
1643 	pcm->poll_events = slave->poll_events;
1644 	pcm->tstamp_type = slave->tstamp_type;
1645 	snd_pcm_set_hw_ptr(pcm, &ladspa->plug.hw_ptr, -1, 0);
1646 	snd_pcm_set_appl_ptr(pcm, &ladspa->plug.appl_ptr, -1, 0);
1647 	*pcmp = pcm;
1648 
1649 	return 0;
1650 }
1651 
1652 /*! \page pcm_plugins
1653 
1654 \section pcm_plugins_ladpsa Plugin: LADSPA <-> ALSA
1655 
1656 This plugin allows to apply a set of LADPSA plugins.
1657 The input and output format is always #SND_PCM_FORMAT_FLOAT (note: this type
1658 can be either little or big-endian depending on architecture).
1659 
1660 The policy duplicate means that there must be only one binding definition for
1661 channel zero. This definition is automatically duplicated for all channels.
1662 If the LADSPA plugin has multiple audio inputs or outputs the policy duplicate
1663 is automatically switched to policy none.
1664 
1665 The plugin serialization works as expected. You can eventually use more
1666 channels (inputs / outputs) inside the LADPSA plugin chain than processed
1667 in the ALSA plugin chain. If ALSA channel does not exist for given LADSPA
1668 input audio port, zero samples are given to this LADSPA port. On the output
1669 side (ALSA next plugin input), the valid channels are checked, too.
1670 If specific ALSA channel does not exist, the LADSPA output port is
1671 connected to a dummy sample area.
1672 
1673 Instances of LADSPA plugins are created dynamically.
1674 
1675 \code
1676 pcm.name {
1677         type ladspa             # ALSA<->LADSPA PCM
1678         slave STR               # Slave name
1679         # or
1680         slave {                 # Slave definition
1681                 pcm STR         # Slave PCM name
1682                 # or
1683                 pcm { }         # Slave PCM definition
1684         }
1685         [channels INT]		# count input channels (input to LADSPA plugin chain)
1686 	[path STR]		# Path (directory) with LADSPA plugins
1687 	plugins |		# Definition for both directions
1688         playback_plugins |	# Definition for playback direction
1689 	capture_plugins {	# Definition for capture direction
1690 		N {		# Configuration for LADPSA plugin N
1691 			[id INT]	# LADSPA plugin ID (for example 1043)
1692 			[label STR]	# LADSPA plugin label (for example 'delay_5s')
1693 			[filename STR]	# Full filename of .so library with LADSPA plugin code
1694 			[policy STR]	# Policy can be 'none' or 'duplicate'
1695 			input | output {
1696 				bindings {
1697 					C INT or STR	# C - channel, INT - audio port index, STR - audio port name
1698 				}
1699 				controls {
1700 				        # valid only in the input block
1701 					I INT or REAL	# I - control port index, INT or REAL - control value
1702 					# or
1703 					STR INT or REAL	# STR - control port name, INT or REAL - control value
1704 				}
1705 			}
1706 		}
1707 	}
1708 }
1709 \endcode
1710 
1711 \subsection pcm_plugins_ladspa_funcref Function reference
1712 
1713 <UL>
1714   <LI>snd_pcm_ladspa_open()
1715   <LI>_snd_pcm_ladspa_open()
1716 </UL>
1717 
1718 */
1719 
1720 /**
1721  * \brief Creates a new LADSPA<->ALSA PCM
1722  * \param pcmp Returns created PCM handle
1723  * \param name Name of PCM
1724  * \param root Root configuration node
1725  * \param conf Configuration node with LADSPA<->ALSA PCM description
1726  * \param stream Stream type
1727  * \param mode Stream mode
1728  * \retval zero on success otherwise a negative error code
1729  * \warning Using of this function might be dangerous in the sense
1730  *          of compatibility reasons. The prototype might be freely
1731  *          changed in future.
1732  */
_snd_pcm_ladspa_open(snd_pcm_t ** pcmp,const char * name,snd_config_t * root,snd_config_t * conf,snd_pcm_stream_t stream,int mode)1733 int _snd_pcm_ladspa_open(snd_pcm_t **pcmp, const char *name,
1734 			 snd_config_t *root, snd_config_t *conf,
1735 			 snd_pcm_stream_t stream, int mode)
1736 {
1737 	snd_config_iterator_t i, next;
1738 	int err;
1739 	snd_pcm_t *spcm;
1740 	snd_config_t *slave = NULL, *sconf;
1741 	const char *path = NULL;
1742 	long channels = 0;
1743 	snd_config_t *plugins = NULL, *pplugins = NULL, *cplugins = NULL;
1744 	snd_config_for_each(i, next, conf) {
1745 		snd_config_t *n = snd_config_iterator_entry(i);
1746 		const char *id;
1747 		if (snd_config_get_id(n, &id) < 0)
1748 			continue;
1749 		if (snd_pcm_conf_generic_id(id))
1750 			continue;
1751 		if (strcmp(id, "slave") == 0) {
1752 			slave = n;
1753 			continue;
1754 		}
1755 		if (strcmp(id, "path") == 0) {
1756 			snd_config_get_string(n, &path);
1757 			continue;
1758 		}
1759 		if (strcmp(id, "channels") == 0) {
1760 			snd_config_get_integer(n, &channels);
1761 			if (channels > 1024)
1762 			        channels = 1024;
1763                         if (channels < 0)
1764                                 channels = 0;
1765 			continue;
1766 		}
1767 		if (strcmp(id, "plugins") == 0) {
1768 			plugins = n;
1769 			continue;
1770 		}
1771 		if (strcmp(id, "playback_plugins") == 0) {
1772 			pplugins = n;
1773 			continue;
1774 		}
1775 		if (strcmp(id, "capture_plugins") == 0) {
1776 			cplugins = n;
1777 			continue;
1778 		}
1779 		SNDERR("Unknown field %s", id);
1780 		return -EINVAL;
1781 	}
1782 	if (!slave) {
1783 		SNDERR("slave is not defined");
1784 		return -EINVAL;
1785 	}
1786 	if (plugins) {
1787 		if (pplugins || cplugins) {
1788 			SNDERR("'plugins' definition cannot be combined with 'playback_plugins' or 'capture_plugins'");
1789 			return -EINVAL;
1790 		}
1791 		pplugins = plugins;
1792 		cplugins = plugins;
1793 	}
1794 	err = snd_pcm_slave_conf(root, slave, &sconf, 0);
1795 	if (err < 0)
1796 		return err;
1797 	err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
1798 	snd_config_delete(sconf);
1799 	if (err < 0)
1800 		return err;
1801 	err = snd_pcm_ladspa_open(pcmp, name, path, channels, pplugins, cplugins, spcm, 1);
1802 	if (err < 0)
1803 		snd_pcm_close(spcm);
1804 	return err;
1805 }
1806 #ifndef DOC_HIDDEN
1807 SND_DLSYM_BUILD_VERSION(_snd_pcm_ladspa_open, SND_PCM_DLSYM_VERSION);
1808 #endif
1809