OSDN Git Service

Implement the channel mapping API
[android-x86/external-alsa-lib.git] / src / pcm / pcm_ladspa.c
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 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
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
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
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
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
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
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
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
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
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
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
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         
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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_channel, out_channel;
616         unsigned int in_channels, out_channels;
617         unsigned int in_ports, out_ports;
618         snd_pcm_ladspa_instance_t *instance = NULL;
619         int err;
620         
621         list = pcm->stream == SND_PCM_STREAM_PLAYBACK ? &ladspa->pplugins : &ladspa->cplugins;
622         in_channels = ladspa->channels > 0 ? ladspa->channels :
623                       (pcm->stream == SND_PCM_STREAM_PLAYBACK ? pcm->channels : ladspa->plug.gen.slave->channels);
624         depth = 0;
625         out_channels = 0;
626         list_for_each(pos, list) {
627                 snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
628                 if (pos->next == list)  /* last entry */
629                         out_channels = pcm->stream == SND_PCM_STREAM_PLAYBACK ? ladspa->plug.gen.slave->channels : pcm->channels;
630                 in_ports = snd_pcm_ladspa_count_ports(plugin, LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO);
631                 out_ports = snd_pcm_ladspa_count_ports(plugin, LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO);
632                 count = 1;
633                 if (plugin->policy == SND_PCM_LADSPA_POLICY_DUPLICATE) {
634                         if (in_ports == 1 && out_ports == 1)
635                                 count = in_channels;
636                         else
637                                 plugin->policy = SND_PCM_LADSPA_POLICY_NONE;
638                 }
639                 in_channel = 0;
640                 out_channel = 0;
641                 for (idx = 0; idx < count; idx++) {
642                         instance = (snd_pcm_ladspa_instance_t *)calloc(1, sizeof(snd_pcm_ladspa_instance_t));
643                         if (instance == NULL)
644                                 return -ENOMEM;
645                         instance->desc = plugin->desc;
646                         instance->handle = plugin->desc->instantiate(plugin->desc, pcm->rate);
647                         instance->depth = depth;
648                         if (instance->handle == NULL) {
649                                 SNDERR("Unable to create instance of LADSPA plugin '%s'", plugin->desc->Name);
650                                 free(instance);
651                                 return -EINVAL;
652                         }
653                         list_add_tail(&instance->list, &plugin->instances);
654                         if (plugin->desc->activate)
655                                 plugin->desc->activate(instance->handle);
656                         if (plugin->policy == SND_PCM_LADSPA_POLICY_DUPLICATE) {
657                                 err = snd_pcm_ladspa_connect_plugin_duplicate(plugin, &plugin->input, &plugin->output, instance, idx);
658                                 if (err < 0) {
659                                         SNDERR("Unable to connect duplicate port of plugin '%s' channel %u depth %u", plugin->desc->Name, idx, instance->depth);
660                                         return err;
661                                 }
662                         } else {
663                                 err = snd_pcm_ladspa_connect_plugin(plugin, instance);
664                                 if (err < 0) {
665                                         SNDERR("Unable to connect plugin '%s' depth %u", plugin->desc->Name, depth);
666                                         return err;
667                                 }
668                         }
669                         err = snd_pcm_ladspa_connect_controls(plugin, &plugin->input, instance);
670                         assert(err >= 0);
671                         err = snd_pcm_ladspa_connect_controls(plugin, &plugin->output, instance);
672                         assert(err >= 0);
673                 }
674                 err = snd_pcm_ladspa_check_connect(plugin, &plugin->input, &instance->input, depth);
675                 if (err < 0)
676                         return err;
677                 err = snd_pcm_ladspa_check_connect(plugin, &plugin->output, &instance->output, depth);
678                 if (err < 0)
679                         return err;
680                 depth++;
681         }
682         return 0;
683 }
684
685 static LADSPA_Data *snd_pcm_ladspa_allocate_zero(snd_pcm_ladspa_t *ladspa, unsigned int idx)
686 {
687         if (ladspa->zero[idx] == NULL)
688                 ladspa->zero[idx] = calloc(ladspa->allocated, sizeof(LADSPA_Data));
689         return ladspa->zero[idx];
690 }
691
692 static int snd_pcm_ladspa_allocate_memory(snd_pcm_t *pcm, snd_pcm_ladspa_t *ladspa)
693 {
694         struct list_head *list, *pos, *pos1;
695         snd_pcm_ladspa_instance_t *instance;
696         unsigned int channels = 16, nchannels;
697         unsigned int ichannels, ochannels;
698         void **pchannels, **npchannels;
699         unsigned int idx, chn;
700         
701         ladspa->allocated = 2048;
702         if (pcm->buffer_size > ladspa->allocated)
703                 ladspa->allocated = pcm->buffer_size;
704         if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
705                 ichannels = pcm->channels;
706                 ochannels = ladspa->plug.gen.slave->channels;
707         } else {
708                 ichannels = ladspa->plug.gen.slave->channels;
709                 ochannels = pcm->channels;
710         }
711         pchannels = calloc(1, sizeof(void *) * channels);
712         if (pchannels == NULL)
713                 return -ENOMEM;
714         list = pcm->stream == SND_PCM_STREAM_PLAYBACK ? &ladspa->pplugins : &ladspa->cplugins;
715         list_for_each(pos, list) {
716                 snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
717                 list_for_each(pos1, &plugin->instances) {
718                         instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
719                         nchannels = channels;
720                         for (idx = 0; idx < instance->input.channels.size; idx++) {
721                                 chn = instance->input.channels.array[idx];
722                                 assert(instance->input.ports.array[idx] != NO_ASSIGN);
723                                 if (chn >= nchannels)
724                                         nchannels = chn + 1;
725                         }
726                         for (idx = 0; idx < instance->output.channels.size; idx++) {
727                                 chn = instance->output.channels.array[idx];
728                                 assert(instance->output.ports.array[idx] != NO_ASSIGN);
729                                 if (chn >= nchannels)
730                                         nchannels = chn + 1;
731                         }
732                         if (nchannels != channels) {
733                                 npchannels = realloc(pchannels, nchannels * sizeof(void *));
734                                 if (npchannels == NULL) {
735                                         free(pchannels);
736                                         return -ENOMEM;
737                                 }
738                                 for (idx = channels; idx < nchannels; idx++)
739                                         npchannels[idx] = NULL;
740                                 pchannels = npchannels;
741                         }
742                         assert(instance->input.data == NULL);
743                         assert(instance->input.m_data == NULL);
744                         assert(instance->output.data == NULL);
745                         assert(instance->output.m_data == NULL);
746                         instance->input.data = calloc(instance->input.channels.size, sizeof(void *));
747                         instance->input.m_data = calloc(instance->input.channels.size, sizeof(void *));
748                         instance->output.data = calloc(instance->output.channels.size, sizeof(void *));
749                         instance->output.m_data = calloc(instance->output.channels.size, sizeof(void *));
750                         if (instance->input.data == NULL ||
751                             instance->input.m_data == NULL ||
752                             instance->output.data == NULL ||
753                             instance->output.m_data == NULL) {
754                                 free(pchannels);
755                                 return -ENOMEM;
756                         }
757                         for (idx = 0; idx < instance->input.channels.size; idx++) {
758                                 chn = instance->output.channels.array[idx];
759                                 if (pchannels[chn] == NULL && chn < ichannels) {
760                                         instance->input.data[idx] = NULL;
761                                         continue;
762                                 }
763                                 instance->input.data[idx] = pchannels[chn];
764                                 if (instance->input.data[idx] == NULL) {
765                                         instance->input.data[idx] = snd_pcm_ladspa_allocate_zero(ladspa, 0);
766                                         if (instance->input.data[idx] == NULL) {
767                                                 free(pchannels);
768                                                 return -ENOMEM;
769                                         }
770                                 }
771                         }
772                         for (idx = 0; idx < instance->output.channels.size; idx++) {
773                                 chn = instance->output.channels.array[idx];
774                                 /* FIXME/OPTIMIZE: check if we can remove double alloc */
775                                 /* if LADSPA plugin has no broken inplace */
776                                 instance->output.data[idx] = malloc(sizeof(LADSPA_Data) * ladspa->allocated);
777                                 if (instance->output.data[idx] == NULL) {
778                                         free(pchannels);
779                                         return -ENOMEM;
780                                 }
781                                 pchannels[chn] = instance->output.m_data[idx] = instance->output.data[idx];
782                         }
783                 }
784         }
785         /* OPTIMIZE: we have already allocated areas for ALSA output channels */
786         /* next loop deallocates the last output LADSPA areas and connects */
787         /* them to ALSA areas (NULL) or dummy area ladpsa->free[1] ; */
788         /* this algorithm might be optimized to not allocate the last LADSPA outputs */
789         list_for_each(pos, list) {
790                 snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
791                 list_for_each(pos1, &plugin->instances) {
792                         instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
793                         for (idx = 0; idx < instance->output.channels.size; idx++) {
794                                 chn = instance->output.channels.array[idx];
795                                 if (instance->output.data[idx] == pchannels[chn]) {
796                                         free(instance->output.m_data[idx]);
797                                         instance->output.m_data[idx] = NULL;
798                                         if (chn < ochannels) {
799                                                 instance->output.data[idx] = NULL;
800                                         } else {
801                                                 instance->output.data[idx] = snd_pcm_ladspa_allocate_zero(ladspa, 1);
802                                                 if (instance->output.data[idx] == NULL) {
803                                                         free(pchannels);
804                                                         return -ENOMEM;
805                                                 }
806                                         }
807                                 }
808                         }
809                 }
810         }
811 #if 0
812         printf("zero[0] = %p\n", ladspa->zero[0]);
813         printf("zero[1] = %p\n", ladspa->zero[1]);
814         list_for_each(pos, list) {
815                 snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
816                 list_for_each(pos1, &plugin->instances) {
817                         instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
818                         for (idx = 0; idx < instance->input.channels.size; idx++)
819                                 printf("%i:alloc-input%i:  data = %p, m_data = %p\n", instance->depth, idx, instance->input.data[idx], instance->input.m_data[idx]);
820                         for (idx = 0; idx < instance->output.channels.size; idx++)
821                                 printf("%i:alloc-output%i:  data = %p, m_data = %p\n", instance->depth, idx, instance->output.data[idx], instance->output.m_data[idx]);
822                 }
823         }
824 #endif
825         free(pchannels);
826         return 0;
827 }
828
829 static int snd_pcm_ladspa_init(snd_pcm_t *pcm)
830 {
831         snd_pcm_ladspa_t *ladspa = pcm->private_data;
832         int err;
833         
834         snd_pcm_ladspa_free_instances(pcm, ladspa, 1);
835         err = snd_pcm_ladspa_allocate_instances(pcm, ladspa);
836         if (err < 0) {
837                 snd_pcm_ladspa_free_instances(pcm, ladspa, 1);
838                 return err;
839         }
840         err = snd_pcm_ladspa_allocate_memory(pcm, ladspa);
841         if (err < 0) {
842                 snd_pcm_ladspa_free_instances(pcm, ladspa, 1);
843                 return err;
844         }
845         return 0;
846 }
847
848 static int snd_pcm_ladspa_hw_free(snd_pcm_t *pcm)
849 {
850         snd_pcm_ladspa_t *ladspa = pcm->private_data;
851
852         snd_pcm_ladspa_free_instances(pcm, ladspa, 1);
853         return snd_pcm_generic_hw_free(pcm);
854 }
855
856 static snd_pcm_uframes_t
857 snd_pcm_ladspa_write_areas(snd_pcm_t *pcm,
858                            const snd_pcm_channel_area_t *areas,
859                            snd_pcm_uframes_t offset,
860                            snd_pcm_uframes_t size,
861                            const snd_pcm_channel_area_t *slave_areas,
862                            snd_pcm_uframes_t slave_offset,
863                            snd_pcm_uframes_t *slave_sizep)
864 {
865         snd_pcm_ladspa_t *ladspa = pcm->private_data;
866         snd_pcm_ladspa_instance_t *instance;
867         struct list_head *pos, *pos1;
868         LADSPA_Data *data;
869         unsigned int idx, chn, size1, size2;
870         
871         if (size > *slave_sizep)
872                 size = *slave_sizep;
873         size2 = size;
874 #if 0   /* no processing - for testing purposes only */
875         snd_pcm_areas_copy(slave_areas, slave_offset,
876                            areas, offset,
877                            pcm->channels, size, pcm->format);
878 #else
879         while (size > 0) {
880                 size1 = size;
881                 if (size1 > ladspa->allocated)
882                         size1 = ladspa->allocated;
883                 list_for_each(pos, &ladspa->pplugins) {
884                         snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
885                         list_for_each(pos1, &plugin->instances) {
886                                 instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
887                                 for (idx = 0; idx < instance->input.channels.size; idx++) {
888                                         chn = instance->input.channels.array[idx];
889                                         data = instance->input.data[idx];
890                                         if (data == NULL) {
891                                                 data = (LADSPA_Data *)((char *)areas[chn].addr + (areas[chn].first / 8));
892                                                 data += offset;
893                                         }
894                                         instance->desc->connect_port(instance->handle, instance->input.ports.array[idx], data);
895                                 }
896                                 for (idx = 0; idx < instance->output.channels.size; idx++) {
897                                         chn = instance->output.channels.array[idx];
898                                         data = instance->output.data[idx];
899                                         if (data == NULL) {
900                                                 data = (LADSPA_Data *)((char *)slave_areas[chn].addr + (areas[chn].first / 8));
901                                                 data += slave_offset;
902                                         }
903                                         instance->desc->connect_port(instance->handle, instance->output.ports.array[idx], data);
904                                 }
905                                 instance->desc->run(instance->handle, size1);
906                         }
907                 }
908                 offset += size1;
909                 slave_offset += size1;
910                 size -= size1;
911         }
912 #endif
913         *slave_sizep = size2;
914         return size2;
915 }
916
917 static snd_pcm_uframes_t
918 snd_pcm_ladspa_read_areas(snd_pcm_t *pcm,
919                           const snd_pcm_channel_area_t *areas,
920                           snd_pcm_uframes_t offset,
921                           snd_pcm_uframes_t size,
922                           const snd_pcm_channel_area_t *slave_areas,
923                           snd_pcm_uframes_t slave_offset,
924                           snd_pcm_uframes_t *slave_sizep)
925 {
926         snd_pcm_ladspa_t *ladspa = pcm->private_data;
927         snd_pcm_ladspa_instance_t *instance;
928         struct list_head *pos, *pos1;
929         LADSPA_Data *data;
930         unsigned int idx, chn, size1, size2;;
931
932         if (size > *slave_sizep)
933                 size = *slave_sizep;
934         size2 = size;
935 #if 0   /* no processing - for testing purposes only */
936         snd_pcm_areas_copy(areas, offset,
937                            slave_areas, slave_offset,
938                            pcm->channels, size, pcm->format);
939 #else
940         while (size > 0) {
941                 size1 = size;
942                 if (size1 > ladspa->allocated)
943                         size1 = ladspa->allocated;
944                 list_for_each(pos, &ladspa->cplugins) {
945                         snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
946                         list_for_each(pos1, &plugin->instances) {
947                                 instance = list_entry(pos1, snd_pcm_ladspa_instance_t, list);
948                                 for (idx = 0; idx < instance->input.channels.size; idx++) {
949                                         chn = instance->input.channels.array[idx];
950                                         data = instance->input.data[idx];
951                                         if (data == NULL) {
952                                                 data = (LADSPA_Data *)((char *)slave_areas[chn].addr + (areas[chn].first / 8));
953                                                 data += slave_offset;
954                                         }       
955                                         instance->desc->connect_port(instance->handle, instance->input.ports.array[idx], data);
956                                 }
957                                 for (idx = 0; idx < instance->output.channels.size; idx++) {
958                                         chn = instance->output.channels.array[idx];
959                                         data = instance->output.data[idx];
960                                         if (data == NULL) {
961                                                 data = (LADSPA_Data *)((char *)areas[chn].addr + (areas[chn].first / 8));
962                                                 data += offset;
963                                         }
964                                         instance->desc->connect_port(instance->handle, instance->output.ports.array[idx], data);
965                                 }
966                                 instance->desc->run(instance->handle, size1);
967                         }
968                 }
969                 offset += size1;
970                 slave_offset += size1;
971                 size -= size1;
972         }
973 #endif
974         *slave_sizep = size2;
975         return size2;
976 }
977
978 static void snd_pcm_ladspa_dump_direction(snd_pcm_ladspa_plugin_t *plugin,
979                                           snd_pcm_ladspa_plugin_io_t *io,
980                                           snd_output_t *out)
981 {
982         unsigned int idx, midx;
983
984         if (io->port_bindings_size == 0)
985                 goto __control;
986         snd_output_printf(out, "    Audio %s port bindings:\n", io->pdesc == LADSPA_PORT_INPUT ? "input" : "output");
987         for (idx = 0; idx < io->port_bindings_size; idx++) {
988                 if (io->port_bindings[idx] == NO_ASSIGN) 
989                         snd_output_printf(out, "      %i -> NONE\n", idx);
990                 else
991                         snd_output_printf(out, "      %i -> %i\n", idx, io->port_bindings[idx]);
992         }
993       __control:
994         if (io->controls_size == 0)
995                 return;
996         snd_output_printf(out, "    Control %s port initial values:\n", io->pdesc == LADSPA_PORT_INPUT ? "input" : "output");
997         for (idx = midx = 0; idx < plugin->desc->PortCount; idx++) {
998                 if ((plugin->desc->PortDescriptors[idx] & (io->pdesc | LADSPA_PORT_CONTROL)) == (io->pdesc | LADSPA_PORT_CONTROL)) {
999                         snd_output_printf(out, "      %i \"%s\" = %.8f\n", idx, plugin->desc->PortNames[idx], io->controls[midx]);
1000                         midx++;
1001                 }
1002         }
1003 }
1004
1005 static void snd_pcm_ladspa_dump_array(snd_output_t *out,
1006                                       snd_pcm_ladspa_array_t *array,
1007                                       snd_pcm_ladspa_plugin_t *plugin)
1008 {
1009         unsigned int size = array->size;
1010         unsigned int val, idx = 0;
1011
1012         while (size-- > 0) {
1013                 if (idx > 0) {
1014                         snd_output_putc(out, ',');
1015                         snd_output_putc(out, ' ');
1016                 }
1017                 val = array->array[idx++];
1018                 if (val == NO_ASSIGN)
1019                         snd_output_putc(out, '-');
1020                 else
1021                         snd_output_printf(out, "%u", val);
1022                 if (plugin && val != NO_ASSIGN)
1023                         snd_output_printf(out, " \"%s\"", plugin->desc->PortNames[val]);
1024         }
1025 }
1026
1027 static void snd_pcm_ladspa_plugins_dump(struct list_head *list, snd_output_t *out)
1028 {
1029         struct list_head *pos, *pos2;
1030         
1031         list_for_each(pos, list) {
1032                 snd_pcm_ladspa_plugin_t *plugin = list_entry(pos, snd_pcm_ladspa_plugin_t, list);
1033                 snd_output_printf(out, "    Policy: %s\n", plugin->policy == SND_PCM_LADSPA_POLICY_NONE ? "none" : "duplicate");
1034                 snd_output_printf(out, "    Filename: %s\n", plugin->filename);
1035                 snd_output_printf(out, "    Plugin Name: %s\n", plugin->desc->Name);
1036                 snd_output_printf(out, "    Plugin Label: %s\n", plugin->desc->Label);
1037                 snd_output_printf(out, "    Plugin Unique ID: %lu\n", plugin->desc->UniqueID);
1038                 snd_output_printf(out, "    Instances:\n");
1039                 list_for_each(pos2, &plugin->instances) {
1040                         snd_pcm_ladspa_instance_t *in = (snd_pcm_ladspa_instance_t *) pos2;
1041                         snd_output_printf(out, "      Depth: %i\n", in->depth);
1042                         snd_output_printf(out, "         InChannels: ");
1043                         snd_pcm_ladspa_dump_array(out, &in->input.channels, NULL);
1044                         snd_output_printf(out, "\n         InPorts: ");
1045                         snd_pcm_ladspa_dump_array(out, &in->input.ports, plugin);
1046                         snd_output_printf(out, "\n         OutChannels: ");
1047                         snd_pcm_ladspa_dump_array(out, &in->output.channels, NULL);
1048                         snd_output_printf(out, "\n         OutPorts: ");
1049                         snd_pcm_ladspa_dump_array(out, &in->output.ports, plugin);
1050                         snd_output_printf(out, "\n");
1051                 }
1052                 snd_pcm_ladspa_dump_direction(plugin, &plugin->input, out);
1053                 snd_pcm_ladspa_dump_direction(plugin, &plugin->output, out);
1054         }
1055 }
1056
1057 static void snd_pcm_ladspa_dump(snd_pcm_t *pcm, snd_output_t *out)
1058 {
1059         snd_pcm_ladspa_t *ladspa = pcm->private_data;
1060
1061         snd_output_printf(out, "LADSPA PCM\n");
1062         snd_output_printf(out, "  Playback:\n");
1063         snd_pcm_ladspa_plugins_dump(&ladspa->pplugins, out);
1064         snd_output_printf(out, "  Capture:\n");
1065         snd_pcm_ladspa_plugins_dump(&ladspa->cplugins, out);
1066         if (pcm->setup) {
1067                 snd_output_printf(out, "Its setup is:\n");
1068                 snd_pcm_dump_setup(pcm, out);
1069         }
1070         snd_output_printf(out, "Slave: ");
1071         snd_pcm_dump(ladspa->plug.gen.slave, out);
1072 }
1073
1074 static const snd_pcm_ops_t snd_pcm_ladspa_ops = {
1075         .close = snd_pcm_ladspa_close,
1076         .info = snd_pcm_generic_info,
1077         .hw_refine = snd_pcm_ladspa_hw_refine,
1078         .hw_params = snd_pcm_ladspa_hw_params,
1079         .hw_free = snd_pcm_ladspa_hw_free,
1080         .sw_params = snd_pcm_generic_sw_params,
1081         .channel_info = snd_pcm_generic_channel_info,
1082         .dump = snd_pcm_ladspa_dump,
1083         .nonblock = snd_pcm_generic_nonblock,
1084         .async = snd_pcm_generic_async,
1085         .mmap = snd_pcm_generic_mmap,
1086         .munmap = snd_pcm_generic_munmap,
1087         .query_chmaps = snd_pcm_generic_query_chmaps,
1088         .get_chmap = snd_pcm_generic_get_chmap,
1089         .set_chmap = snd_pcm_generic_set_chmap,
1090 };
1091
1092 static int snd_pcm_ladspa_check_file(snd_pcm_ladspa_plugin_t * const plugin,
1093                                      const char *filename,
1094                                      const char *label,
1095                                      const unsigned long ladspa_id)
1096 {
1097         void *handle;
1098
1099         assert(filename);
1100         handle = dlopen(filename, RTLD_LAZY);
1101         if (handle) {
1102                 LADSPA_Descriptor_Function fcn = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor");
1103                 if (fcn) {
1104                         long idx;
1105                         const LADSPA_Descriptor *d;
1106                         for (idx = 0; (d = fcn(idx)) != NULL; idx++) {
1107 /*
1108  * avoid locale problems - see ALSA bug#1553
1109  */
1110 #if 0
1111                                 if (strcmp(label, d->Label))
1112                                         continue;
1113 #else
1114                                 char *labellocale;
1115                                 struct lconv *lc;
1116                                 if (label != NULL) {
1117                                         lc = localeconv ();
1118                                         labellocale = malloc (strlen (label) + 1);
1119                                         if (labellocale == NULL) {
1120                                                 dlclose(handle);
1121                                                 return -ENOMEM;
1122                                         }
1123                                         strcpy (labellocale, label);
1124                                         if (strrchr(labellocale, '.'))
1125                                                 *strrchr (labellocale, '.') = *lc->decimal_point;
1126                                         if (strcmp(label, d->Label) && strcmp(labellocale, d->Label)) {
1127                                                 free(labellocale);
1128                                                 continue;
1129                                         }
1130                                         free (labellocale);
1131                                 }
1132 #endif
1133                                 if (ladspa_id > 0 && d->UniqueID != ladspa_id)
1134                                         continue;
1135                                 plugin->filename = strdup(filename);
1136                                 if (plugin->filename == NULL) {
1137                                         dlclose(handle);
1138                                         return -ENOMEM;
1139                                 }
1140                                 plugin->dl_handle = handle;
1141                                 plugin->desc = d;
1142                                 return 1;
1143                         }
1144                 }
1145                 dlclose(handle);
1146         }
1147         return -ENOENT;
1148 }
1149
1150 static int snd_pcm_ladspa_check_dir(snd_pcm_ladspa_plugin_t * const plugin,
1151                                     const char *path,
1152                                     const char *label,
1153                                     const unsigned long ladspa_id)
1154 {
1155         DIR *dir;
1156         struct dirent * dirent;
1157         int len = strlen(path), err;
1158         int need_slash;
1159         char *filename;
1160         
1161         if (len < 1)
1162                 return 0;
1163         need_slash = path[len - 1] != '/';
1164         
1165         dir = opendir(path);
1166         if (!dir)
1167                 return -ENOENT;
1168                 
1169         while (1) {
1170                 dirent = readdir(dir);
1171                 if (!dirent) {
1172                         closedir(dir);
1173                         return 0;
1174                 }
1175                 
1176                 filename = malloc(len + strlen(dirent->d_name) + 1 + need_slash);
1177                 if (filename == NULL) {
1178                         closedir(dir);
1179                         return -ENOMEM;
1180                 }
1181                 strcpy(filename, path);
1182                 if (need_slash)
1183                         strcat(filename, "/");
1184                 strcat(filename, dirent->d_name);
1185                 err = snd_pcm_ladspa_check_file(plugin, filename, label, ladspa_id);
1186                 free(filename);
1187                 if (err < 0 && err != -ENOENT) {
1188                         closedir(dir);
1189                         return err;
1190                 }
1191                 if (err > 0) {
1192                         closedir(dir);
1193                         return 1;
1194                 }
1195         }
1196         /* never reached */
1197         return 0;
1198 }
1199
1200 static int snd_pcm_ladspa_look_for_plugin(snd_pcm_ladspa_plugin_t * const plugin,
1201                                           const char *path,
1202                                           const char *label,
1203                                           const long ladspa_id)
1204 {
1205         const char *c;
1206         size_t l;
1207         int err;
1208         
1209         for (c = path; (l = strcspn(c, ": ")) > 0; ) {
1210                 char name[l + 1];
1211                 char *fullpath;
1212                 memcpy(name, c, l);
1213                 name[l] = 0;
1214                 err = snd_user_file(name, &fullpath);
1215                 if (err < 0)
1216                         return err;
1217                 err = snd_pcm_ladspa_check_dir(plugin, fullpath, label, ladspa_id);
1218                 free(fullpath);
1219                 if (err < 0)
1220                         return err;
1221                 if (err > 0)
1222                         return 0;
1223                 c += l;
1224                 if (!*c)
1225                         break;
1226                 c++;
1227         }
1228         return -ENOENT;
1229 }                                         
1230
1231 static int snd_pcm_ladspa_add_default_controls(snd_pcm_ladspa_plugin_t *lplug,
1232                                                snd_pcm_ladspa_plugin_io_t *io) 
1233 {
1234         unsigned int count = 0;
1235         LADSPA_Data *array;
1236         unsigned char *initialized;
1237         unsigned long idx;
1238
1239         for (idx = 0; idx < lplug->desc->PortCount; idx++)
1240                 if ((lplug->desc->PortDescriptors[idx] & (io->pdesc | LADSPA_PORT_CONTROL)) == (io->pdesc | LADSPA_PORT_CONTROL))
1241                         count++;
1242         array = (LADSPA_Data *)calloc(count, sizeof(LADSPA_Data));
1243         if (!array)
1244                 return -ENOMEM;
1245         initialized = (unsigned char *)calloc(count, sizeof(unsigned char));
1246         if (!initialized) {
1247                 free(array);
1248                 return -ENOMEM;
1249         }
1250         io->controls_size = count;
1251         io->controls_initialized = initialized;
1252         io->controls = array;
1253
1254         return 0;
1255 }       
1256
1257 static int snd_pcm_ladspa_parse_controls(snd_pcm_ladspa_plugin_t *lplug,
1258                                          snd_pcm_ladspa_plugin_io_t *io,
1259                                          snd_config_t *controls) 
1260 {
1261         snd_config_iterator_t i, next;
1262         int err;
1263
1264         if (snd_config_get_type(controls) != SND_CONFIG_TYPE_COMPOUND) {
1265                 SNDERR("controls definition must be a compound");
1266                 return -EINVAL;
1267         }
1268
1269         snd_config_for_each(i, next, controls) {
1270                 snd_config_t *n = snd_config_iterator_entry(i);
1271                 const char *id;
1272                 long lval;
1273                 unsigned int port, uval;
1274                 double dval;
1275                 if (snd_config_get_id(n, &id) < 0)
1276                         continue;
1277                 err = safe_strtol(id, &lval);
1278                 if (err >= 0) {
1279                         err = snd_pcm_ladspa_find_port(&port, lplug, io->pdesc | LADSPA_PORT_CONTROL, lval);
1280                 } else {
1281                         err = snd_pcm_ladspa_find_sport(&port, lplug, io->pdesc | LADSPA_PORT_CONTROL, id);
1282                 }
1283                 if (err < 0) {
1284                         SNDERR("Unable to find an control port (%s)", id);
1285                         return err;
1286                 }
1287                 if (snd_config_get_ireal(n, &dval) < 0) {
1288                         SNDERR("Control port %s has not an float or integer value", id);
1289                         return err;
1290                 }
1291                 err = snd_pcm_ladspa_find_port_idx(&uval, lplug, io->pdesc | LADSPA_PORT_CONTROL, port);
1292                 if (err < 0) {
1293                         SNDERR("internal error");
1294                         return err;
1295                 }
1296                 io->controls_initialized[uval] = 1;
1297                 io->controls[uval] = (LADSPA_Data)dval;
1298         }
1299
1300         return 0;
1301 }
1302
1303 static int snd_pcm_ladspa_parse_bindings(snd_pcm_ladspa_plugin_t *lplug,
1304                                          snd_pcm_ladspa_plugin_io_t *io,
1305                                          snd_config_t *bindings) 
1306 {
1307         unsigned int count = 0;
1308         unsigned int *array;
1309         snd_config_iterator_t i, next;
1310         int err;
1311
1312         if (snd_config_get_type(bindings) != SND_CONFIG_TYPE_COMPOUND) {
1313                 SNDERR("bindings definition must be a compound");
1314                 return -EINVAL;
1315         }
1316         snd_config_for_each(i, next, bindings) {
1317                 snd_config_t *n = snd_config_iterator_entry(i);
1318                 const char *id;
1319                 long channel;
1320                 if (snd_config_get_id(n, &id) < 0)
1321                         continue;
1322                 err = safe_strtol(id, &channel);
1323                 if (err < 0 || channel < 0) {
1324                         SNDERR("Invalid channel number: %s", id);
1325                         return -EINVAL;
1326                 }
1327                 if (lplug->policy == SND_PCM_LADSPA_POLICY_DUPLICATE && channel > 0) {
1328                         SNDERR("Wrong channel specification for duplicate policy");
1329                         return -EINVAL;
1330                 }
1331                 if (count < (unsigned int)(channel + 1))
1332                         count = (unsigned int)(channel + 1);
1333         }
1334         if (count > 0) {
1335                 array = (unsigned int *)calloc(count, sizeof(unsigned int));
1336                 if (! array)
1337                         return -ENOMEM;
1338                 memset(array, 0xff, count * sizeof(unsigned int));
1339                 io->port_bindings_size = count;
1340                 io->port_bindings = array;
1341                 snd_config_for_each(i, next, bindings) {
1342                         snd_config_t *n = snd_config_iterator_entry(i);
1343                         const char *id, *sport;
1344                         long channel, port;
1345                         if (snd_config_get_id(n, &id) < 0)
1346                                 continue;
1347                         err = safe_strtol(id, &channel);
1348                         if (err < 0 || channel < 0) {
1349                                 assert(0);      /* should never happen */
1350                                 return -EINVAL;
1351                         }
1352                         err = snd_config_get_integer(n, &port);
1353                         if (err >= 0) {
1354                                 err = snd_pcm_ladspa_find_port(&array[channel], lplug, io->pdesc | LADSPA_PORT_AUDIO, port);
1355                                 if (err < 0) {
1356                                         SNDERR("Unable to find an audio port (%li) for channel %s", port, id);
1357                                         return err;
1358                                 }
1359                                 continue;
1360                         }
1361                         err = snd_config_get_string(n, &sport);
1362                         if (err < 0) {
1363                                 SNDERR("Invalid LADSPA port field type for %s", id);
1364                                 return -EINVAL;
1365                         }
1366                         err = snd_pcm_ladspa_find_sport(&array[channel], lplug, io->pdesc | LADSPA_PORT_AUDIO, sport);
1367                         if (err < 0) {
1368                                 SNDERR("Unable to find an audio port (%s) for channel %s", sport, id);
1369                                 return err;
1370                         }
1371                 }
1372         }
1373
1374         return 0;
1375 }
1376
1377 static int snd_pcm_ladspa_parse_ioconfig(snd_pcm_ladspa_plugin_t *lplug,
1378                                          snd_pcm_ladspa_plugin_io_t *io,
1379                                          snd_config_t *conf)
1380 {
1381         snd_config_iterator_t i, next;
1382         snd_config_t *bindings = NULL, *controls = NULL;
1383         int err;
1384
1385         /* always add default controls for both input and output */
1386         err = snd_pcm_ladspa_add_default_controls(lplug, io);
1387         if (err < 0) {
1388                 SNDERR("error adding default controls");
1389                 return err;
1390         }
1391                 
1392         if (conf == NULL) {
1393                 return 0;
1394         }
1395
1396         if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
1397                 SNDERR("input or output definition must be a compound");
1398                 return -EINVAL;
1399         }
1400         snd_config_for_each(i, next, conf) {
1401                 snd_config_t *n = snd_config_iterator_entry(i);
1402                 const char *id;
1403                 if (snd_config_get_id(n, &id) < 0)
1404                         continue;
1405                 if (strcmp(id, "bindings") == 0) {
1406                         bindings = n;
1407                         continue;
1408                 }
1409                 if (strcmp(id, "controls") == 0) {
1410                         controls = n;
1411                         continue;
1412                 }
1413         }
1414
1415         /* ignore values of parameters for output controls */
1416         if (controls && !(io->pdesc & LADSPA_PORT_OUTPUT)) {
1417                 err = snd_pcm_ladspa_parse_controls(lplug, io, controls);
1418                 if (err < 0) 
1419                         return err;
1420         }
1421
1422         if (bindings) {
1423                 err = snd_pcm_ladspa_parse_bindings(lplug, io, bindings);
1424                 if (err < 0) 
1425                         return err;
1426         }
1427
1428
1429         return 0;
1430 }
1431
1432 static int snd_pcm_ladspa_add_plugin(struct list_head *list,
1433                                      const char *path,
1434                                      snd_config_t *plugin,
1435                                      int reverse)
1436 {
1437         snd_config_iterator_t i, next;
1438         const char *label = NULL, *filename = NULL;
1439         long ladspa_id = 0;
1440         int err;
1441         snd_pcm_ladspa_plugin_t *lplug;
1442         snd_pcm_ladspa_policy_t policy = SND_PCM_LADSPA_POLICY_DUPLICATE;
1443         snd_config_t *input = NULL, *output = NULL;
1444
1445         snd_config_for_each(i, next, plugin) {
1446                 snd_config_t *n = snd_config_iterator_entry(i);
1447                 const char *id;
1448                 if (snd_config_get_id(n, &id) < 0)
1449                         continue;
1450                 if (strcmp(id, "label") == 0) {
1451                         err = snd_config_get_string(n, &label);
1452                         if (err < 0)
1453                                 return err;
1454                         continue;
1455                 }
1456                 if (strcmp(id, "id") == 0) {
1457                         err = snd_config_get_integer(n, &ladspa_id);
1458                         if (err < 0)
1459                                 return err;
1460                         continue;
1461                 }
1462                 if (strcmp(id, "filename") == 0) {
1463                         err = snd_config_get_string(n, &filename);
1464                         if (err < 0)
1465                                 return err;
1466                         continue;
1467                 }
1468                 if (strcmp(id, "input") == 0) {
1469                         input = n;
1470                         continue;
1471                 }
1472                 if (strcmp(id, "output") == 0) {
1473                         output = n;
1474                         continue;
1475                 }
1476                 if (strcmp(id, "policy") == 0) {
1477                         const char *str;
1478                         err = snd_config_get_string(n, &str);
1479                         if (err < 0) {
1480                                 SNDERR("policy field must be a string");
1481                                 return err;
1482                         }
1483                         if (strcmp(str, "none") == 0)
1484                                 policy = SND_PCM_LADSPA_POLICY_NONE;
1485                         else if (strcmp(str, "duplicate") == 0)
1486                                 policy = SND_PCM_LADSPA_POLICY_DUPLICATE;
1487                         else {
1488                                 SNDERR("unknown policy definition");
1489                                 return -EINVAL;
1490                         }
1491                         continue;
1492                 }
1493         }
1494         if (label == NULL && ladspa_id <= 0) {
1495                 SNDERR("no plugin label or id");
1496                 return -EINVAL;
1497         }
1498         lplug = (snd_pcm_ladspa_plugin_t *)calloc(1, sizeof(snd_pcm_ladspa_plugin_t));
1499         if (lplug == NULL)
1500                 return -ENOMEM;
1501         lplug->policy = policy;
1502         lplug->input.pdesc = LADSPA_PORT_INPUT;
1503         lplug->output.pdesc = LADSPA_PORT_OUTPUT;
1504         INIT_LIST_HEAD(&lplug->instances);
1505         if (filename) {
1506                 err = snd_pcm_ladspa_check_file(lplug, filename, label, ladspa_id);
1507                 if (err < 0) {
1508                         SNDERR("Unable to load plugin '%s' ID %li, filename '%s'", label, ladspa_id, filename);
1509                         free(lplug);
1510                         return err;
1511                 }
1512         } else {
1513                 err = snd_pcm_ladspa_look_for_plugin(lplug, path, label, ladspa_id);
1514                 if (err < 0) {
1515                         SNDERR("Unable to find or load plugin '%s' ID %li, path '%s'", label, ladspa_id, path);
1516                         free(lplug);
1517                         return err;
1518                 }
1519         }
1520         if (!reverse) {
1521                 list_add_tail(&lplug->list, list);
1522         } else {
1523                 list_add(&lplug->list, list);
1524         }
1525         err = snd_pcm_ladspa_parse_ioconfig(lplug, &lplug->input, input);
1526         if (err < 0)
1527                 return err;
1528         err = snd_pcm_ladspa_parse_ioconfig(lplug, &lplug->output, output);
1529         if (err < 0)
1530                 return err;
1531         return 0;
1532 }
1533
1534 static int snd_pcm_ladspa_build_plugins(struct list_head *list,
1535                                         const char *path,
1536                                         snd_config_t *plugins,
1537                                         int reverse)
1538 {
1539         snd_config_iterator_t i, next;
1540         int idx = 0, hit, err;
1541
1542         if (plugins == NULL)    /* nothing TODO */
1543                 return 0;
1544         if (snd_config_get_type(plugins) != SND_CONFIG_TYPE_COMPOUND) {
1545                 SNDERR("plugins must be defined inside a compound");
1546                 return -EINVAL;
1547         }
1548         do {
1549                 hit = 0;
1550                 snd_config_for_each(i, next, plugins) {
1551                         snd_config_t *n = snd_config_iterator_entry(i);
1552                         const char *id;
1553                         long i;
1554                         if (snd_config_get_id(n, &id) < 0)
1555                                 continue;
1556                         err = safe_strtol(id, &i);
1557                         if (err < 0) {
1558                                 SNDERR("id of field %s is not an integer", id);
1559                                 return err;
1560                         }
1561                         if (i == idx) {
1562                                 idx++;
1563                                 err = snd_pcm_ladspa_add_plugin(list, path, n, reverse);
1564                                 if (err < 0)
1565                                         return err;
1566                                 hit = 1;
1567                         }
1568                 }
1569         } while (hit);
1570         if (list_empty(list)) {
1571                 SNDERR("empty plugin list is not accepted");
1572                 return -EINVAL;
1573         }
1574         return 0;
1575 }
1576
1577 /**
1578  * \brief Creates a new LADSPA<->ALSA Plugin
1579  * \param pcmp Returns created PCM handle
1580  * \param name Name of PCM
1581  * \param ladspa_path The path for LADSPA plugins
1582  * \param channels Force input channel count to LADSPA plugin chain, 0 = no force (auto)
1583  * \param ladspa_pplugins The playback configuration
1584  * \param ladspa_cplugins The capture configuration
1585  * \param slave Slave PCM handle
1586  * \param close_slave When set, the slave PCM handle is closed with copy PCM
1587  * \retval zero on success otherwise a negative error code
1588  * \warning Using of this function might be dangerous in the sense
1589  *          of compatibility reasons. The prototype might be freely
1590  *          changed in future.
1591  */
1592 int snd_pcm_ladspa_open(snd_pcm_t **pcmp, const char *name,
1593                         const char *ladspa_path,
1594                         unsigned int channels,
1595                         snd_config_t *ladspa_pplugins,
1596                         snd_config_t *ladspa_cplugins,
1597                         snd_pcm_t *slave, int close_slave)
1598 {
1599         snd_pcm_t *pcm;
1600         snd_pcm_ladspa_t *ladspa;
1601         int err, reverse = 0;
1602
1603         assert(pcmp && (ladspa_pplugins || ladspa_cplugins) && slave);
1604
1605         if (!ladspa_path && !(ladspa_path = getenv("LADSPA_PATH")))
1606                 return -ENOENT;
1607         ladspa = calloc(1, sizeof(snd_pcm_ladspa_t));
1608         if (!ladspa)
1609                 return -ENOMEM;
1610         snd_pcm_plugin_init(&ladspa->plug);
1611         ladspa->plug.init = snd_pcm_ladspa_init;
1612         ladspa->plug.read = snd_pcm_ladspa_read_areas;
1613         ladspa->plug.write = snd_pcm_ladspa_write_areas;
1614         ladspa->plug.undo_read = snd_pcm_plugin_undo_read_generic;
1615         ladspa->plug.undo_write = snd_pcm_plugin_undo_write_generic;
1616         ladspa->plug.gen.slave = slave;
1617         ladspa->plug.gen.close_slave = close_slave;
1618
1619         INIT_LIST_HEAD(&ladspa->pplugins);
1620         INIT_LIST_HEAD(&ladspa->cplugins);
1621         ladspa->channels = channels;
1622
1623         if (slave->stream == SND_PCM_STREAM_PLAYBACK) {
1624                 err = snd_pcm_ladspa_build_plugins(&ladspa->pplugins, ladspa_path, ladspa_pplugins, reverse);
1625                 if (err < 0) {
1626                         snd_pcm_ladspa_free(ladspa);
1627                         return err;
1628                 }
1629         }
1630         if (slave->stream == SND_PCM_STREAM_CAPTURE) {
1631                 if (ladspa_cplugins == ladspa_pplugins)
1632                         reverse = 1;
1633                 err = snd_pcm_ladspa_build_plugins(&ladspa->cplugins, ladspa_path, ladspa_cplugins, reverse);
1634                 if (err < 0) {
1635                         snd_pcm_ladspa_free(ladspa);
1636                         return err;
1637                 }
1638         }
1639
1640         err = snd_pcm_new(&pcm, SND_PCM_TYPE_LADSPA, name, slave->stream, slave->mode);
1641         if (err < 0) {
1642                 snd_pcm_ladspa_free(ladspa);
1643                 return err;
1644         }
1645         pcm->ops = &snd_pcm_ladspa_ops;
1646         pcm->fast_ops = &snd_pcm_plugin_fast_ops;
1647         pcm->private_data = ladspa;
1648         pcm->poll_fd = slave->poll_fd;
1649         pcm->poll_events = slave->poll_events;
1650         pcm->monotonic = slave->monotonic;
1651         snd_pcm_set_hw_ptr(pcm, &ladspa->plug.hw_ptr, -1, 0);
1652         snd_pcm_set_appl_ptr(pcm, &ladspa->plug.appl_ptr, -1, 0);
1653         *pcmp = pcm;
1654
1655         return 0;
1656 }
1657
1658 /*! \page pcm_plugins
1659
1660 \section pcm_plugins_ladpsa Plugin: LADSPA <-> ALSA
1661
1662 This plugin allows to apply a set of LADPSA plugins.
1663 The input and output format is always #SND_PCM_FORMAT_FLOAT (note: this type
1664 can be either little or big-endian depending on architecture).
1665
1666 The policy duplicate means that there must be only one binding definition for
1667 channel zero. This definition is automatically duplicated for all channels.
1668 If the LADSPA plugin has multiple audio inputs or outputs the policy duplicate
1669 is automatically switched to policy none.
1670
1671 The plugin serialization works as expected. You can eventually use more
1672 channels (inputs / outputs) inside the LADPSA plugin chain than processed
1673 in the ALSA plugin chain. If ALSA channel does not exist for given LADSPA
1674 input audio port, zero samples are given to this LADSPA port. On the output
1675 side (ALSA next plugin input), the valid channels are checked, too.
1676 If specific ALSA channel does not exist, the LADSPA output port is
1677 connected to a dummy sample area.
1678
1679 Instances of LADSPA plugins are created dynamically.
1680
1681 \code
1682 pcm.name {
1683         type ladspa             # ALSA<->LADSPA PCM
1684         slave STR               # Slave name
1685         # or
1686         slave {                 # Slave definition
1687                 pcm STR         # Slave PCM name
1688                 # or
1689                 pcm { }         # Slave PCM definition
1690         }
1691         [channels INT]          # count input channels (input to LADSPA plugin chain)
1692         [path STR]              # Path (directory) with LADSPA plugins
1693         plugins |               # Definition for both directions
1694         playback_plugins |      # Definition for playback direction
1695         capture_plugins {       # Definition for capture direction
1696                 N {             # Configuration for LADPSA plugin N
1697                         [id INT]        # LADSPA plugin ID (for example 1043)
1698                         [label STR]     # LADSPA plugin label (for example 'delay_5s')
1699                         [filename STR]  # Full filename of .so library with LADSPA plugin code
1700                         [policy STR]    # Policy can be 'none' or 'duplicate'
1701                         input | output {
1702                                 bindings {
1703                                         C INT or STR    # C - channel, INT - audio port index, STR - audio port name
1704                                 }
1705                                 controls {
1706                                         # valid only in the input block
1707                                         I INT or REAL   # I - control port index, INT or REAL - control value
1708                                         # or
1709                                         STR INT or REAL # STR - control port name, INT or REAL - control value
1710                                 }
1711                         }
1712                 }
1713         }
1714 }
1715 \endcode
1716
1717 \subsection pcm_plugins_ladspa_funcref Function reference
1718
1719 <UL>
1720   <LI>snd_pcm_ladspa_open()
1721   <LI>_snd_pcm_ladspa_open()
1722 </UL>
1723
1724 */
1725
1726 /**
1727  * \brief Creates a new LADSPA<->ALSA PCM
1728  * \param pcmp Returns created PCM handle
1729  * \param name Name of PCM
1730  * \param root Root configuration node
1731  * \param conf Configuration node with LADSPA<->ALSA PCM description
1732  * \param stream Stream type
1733  * \param mode Stream mode
1734  * \retval zero on success otherwise a negative error code
1735  * \warning Using of this function might be dangerous in the sense
1736  *          of compatibility reasons. The prototype might be freely
1737  *          changed in future.
1738  */
1739 int _snd_pcm_ladspa_open(snd_pcm_t **pcmp, const char *name,
1740                          snd_config_t *root, snd_config_t *conf, 
1741                          snd_pcm_stream_t stream, int mode)
1742 {
1743         snd_config_iterator_t i, next;
1744         int err;
1745         snd_pcm_t *spcm;
1746         snd_config_t *slave = NULL, *sconf;
1747         const char *path = NULL;
1748         long channels = 0;
1749         snd_config_t *plugins = NULL, *pplugins = NULL, *cplugins = NULL;
1750         snd_config_for_each(i, next, conf) {
1751                 snd_config_t *n = snd_config_iterator_entry(i);
1752                 const char *id;
1753                 if (snd_config_get_id(n, &id) < 0)
1754                         continue;
1755                 if (snd_pcm_conf_generic_id(id))
1756                         continue;
1757                 if (strcmp(id, "slave") == 0) {
1758                         slave = n;
1759                         continue;
1760                 }
1761                 if (strcmp(id, "path") == 0) {
1762                         snd_config_get_string(n, &path);
1763                         continue;
1764                 }
1765                 if (strcmp(id, "channels") == 0) {
1766                         snd_config_get_integer(n, &channels);
1767                         if (channels > 1024)
1768                                 channels = 1024;
1769                         if (channels < 0)
1770                                 channels = 0;
1771                         continue;
1772                 }
1773                 if (strcmp(id, "plugins") == 0) {
1774                         plugins = n;
1775                         continue;
1776                 }
1777                 if (strcmp(id, "playback_plugins") == 0) {
1778                         pplugins = n;
1779                         continue;
1780                 }
1781                 if (strcmp(id, "capture_plugins") == 0) {
1782                         cplugins = n;
1783                         continue;
1784                 }
1785                 SNDERR("Unknown field %s", id);
1786                 return -EINVAL;
1787         }
1788         if (!slave) {
1789                 SNDERR("slave is not defined");
1790                 return -EINVAL;
1791         }
1792         if (plugins) {
1793                 if (pplugins || cplugins) {
1794                         SNDERR("'plugins' definition cannot be combined with 'playback_plugins' or 'capture_plugins'");
1795                         return -EINVAL;
1796                 }
1797                 pplugins = plugins;
1798                 cplugins = plugins;
1799         }
1800         err = snd_pcm_slave_conf(root, slave, &sconf, 0);
1801         if (err < 0)
1802                 return err;
1803         err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
1804         snd_config_delete(sconf);
1805         if (err < 0)
1806                 return err;
1807         err = snd_pcm_ladspa_open(pcmp, name, path, channels, pplugins, cplugins, spcm, 1);
1808         if (err < 0)
1809                 snd_pcm_close(spcm);
1810         return err;
1811 }
1812 #ifndef DOC_HIDDEN
1813 SND_DLSYM_BUILD_VERSION(_snd_pcm_ladspa_open, SND_PCM_DLSYM_VERSION);
1814 #endif