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