4 * Written by Ivo van Poorten <ivop@euronet.nl>
5 * Copyright (C) 2004, 2005
7 * This file is part of MPlayer.
9 * MPlayer is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * MPlayer is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 /* ------------------------------------------------------------------------- */
39 /* ------------------------------------------------------------------------- */
45 /* ------------------------------------------------------------------------- */
47 /* Filter specific data */
49 typedef struct af_ladspa_s
51 int status
; /**< Status of the filter.
52 * Either AF_OK or AF_ERROR
53 * Because MPlayer re-inits audio filters that
54 * _clearly_ returned AF_ERROR anyway, I use this
55 * in play() to skip the processing and return
59 int activated
; /**< 0 or 1. Activate LADSPA filters only once, even
60 * if the buffers get resized, to avoid a stuttering
67 char *myname
; /**< It's easy to have a concatenation of file and label */
70 const LADSPA_Descriptor
*plugin_descriptor
;
81 int *inputcontrolsmap
; /**< Map input port number [0-] to actual port */
85 int *outputcontrolsmap
;
86 float *outputcontrols
;
88 int nch
; /**< number of channels */
92 LADSPA_Handle
*chhandles
;
96 /* ------------------------------------------------------------------------- */
98 static int af_open(af_instance_t
*af
);
99 static int af_ladspa_malloc_failed(char*);
101 /* ------------------------------------------------------------------------- */
105 af_info_t af_info_ladspa
= {
106 "LADSPA plugin loader",
114 /* ------------------------------------------------------------------------- */
116 /* By lack of a better word (in my vocabulary) this is called 'parse'.
117 * Feel free to suggest an alternative.
120 /** \brief Check for inputs, outputs and controls of a given filter.
122 * This function counts and checks all input, output and control ports
123 * of the filter that was loaded. If it turns out to be a valid
124 * filter for MPlayer use, it prints out a list of all controls and
125 * the corresponding range of its value at message level MSGL_V.
127 * \param setup Current setup of the filter. Must have its
128 * plugin_descriptor set!
130 * \return Returns AF_OK if it has a valid input/output/controls
131 * configuration. Else, it returns AF_ERROR.
134 static int af_ladspa_parse_plugin(af_ladspa_t
*setup
) {
136 const LADSPA_Descriptor
*pdes
= setup
->plugin_descriptor
;
137 LADSPA_PortDescriptor d
;
138 LADSPA_PortRangeHint hint
;
140 if (!setup
->libhandle
)
141 return AF_ERROR
; /* only call parse after a succesful load */
142 if (!setup
->plugin_descriptor
)
143 return AF_ERROR
; /* same as above */
147 setup
->nports
= pdes
->PortCount
;
149 /* allocate memory for all inputs/outputs/controls */
151 setup
->inputs
= calloc(setup
->nports
, sizeof(int));
152 if (!setup
->inputs
) return af_ladspa_malloc_failed(setup
->myname
);
154 setup
->outputs
= calloc(setup
->nports
, sizeof(int));
155 if (!setup
->outputs
) return af_ladspa_malloc_failed(setup
->myname
);
157 setup
->inputcontrolsmap
= calloc(setup
->nports
, sizeof(int));
158 if (!setup
->inputcontrolsmap
) return af_ladspa_malloc_failed(setup
->myname
);
160 setup
->inputcontrols
= calloc(setup
->nports
, sizeof(float));
161 if (!setup
->inputcontrols
) return af_ladspa_malloc_failed(setup
->myname
);
163 setup
->outputcontrolsmap
= calloc(setup
->nports
, sizeof(int));
164 if (!setup
->outputcontrolsmap
) return af_ladspa_malloc_failed(setup
->myname
);
166 setup
->outputcontrols
= calloc(setup
->nports
, sizeof(float));
167 if (!setup
->outputcontrols
) return af_ladspa_malloc_failed(setup
->myname
);
169 /* set counts to zero */
173 setup
->ninputcontrols
= 0;
174 setup
->noutputcontrols
= 0;
176 /* check all ports, see what type it is and set variables according to
180 for (p
=0; p
<setup
->nports
; p
++) {
181 d
= pdes
->PortDescriptors
[p
];
183 if (LADSPA_IS_PORT_AUDIO(d
)) {
184 if (LADSPA_IS_PORT_INPUT(d
)) {
185 setup
->inputs
[setup
->ninputs
] = p
;
187 } else if (LADSPA_IS_PORT_OUTPUT(d
)) {
188 setup
->outputs
[setup
->noutputs
] = p
;
193 if (LADSPA_IS_PORT_CONTROL(d
)) {
194 if (LADSPA_IS_PORT_INPUT(d
)) {
195 setup
->inputcontrolsmap
[setup
->ninputcontrols
] = p
;
196 setup
->ninputcontrols
++;
197 /* set control to zero. set values after reading the rest
198 * of the suboptions and check LADSPA_?_HINT's later.
200 setup
->inputcontrols
[p
] = 0.0f
;
201 } else if (LADSPA_IS_PORT_OUTPUT(d
)) {
202 /* read and handle these too, otherwise filters that have them
205 setup
->outputcontrolsmap
[setup
->noutputcontrols
]=p
;
206 setup
->noutputcontrols
++;
207 setup
->outputcontrols
[p
] = 0.0f
;
213 if (setup
->ninputs
== 0) {
214 mp_msg(MSGT_AFILTER
, MSGL_WARN
, "%s: %s\n", setup
->myname
,
215 _("WARNING! This LADSPA plugin has no audio inputs.\n The incoming audio signal will be lost."));
216 } else if (setup
->ninputs
== 1) {
217 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: this is a mono effect\n", setup
->myname
);
218 } else if (setup
->ninputs
== 2) {
219 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: this is a stereo effect\n", setup
->myname
);
221 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: this is a %i-channel effect, "
222 "support is experimental\n", setup
->myname
, setup
->ninputs
);
225 if (setup
->noutputs
== 0) {
226 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s\n", setup
->myname
,
227 _("This LADSPA plugin has no audio outputs."));
231 if (setup
->noutputs
!= setup
->ninputs
) {
232 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s\n", setup
->myname
,
233 _("The number of audio inputs and audio outputs of the LADSPA plugin differ."));
237 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: this plugin has %d input control(s)\n",
238 setup
->myname
, setup
->ninputcontrols
);
240 /* Print list of controls and its range of values it accepts */
242 for (i
=0; i
<setup
->ninputcontrols
; i
++) {
243 p
= setup
->inputcontrolsmap
[i
];
244 hint
= pdes
->PortRangeHints
[p
];
245 mp_msg(MSGT_AFILTER
, MSGL_V
, " --- %d %s [", i
, pdes
->PortNames
[p
]);
247 if (LADSPA_IS_HINT_BOUNDED_BELOW(hint
.HintDescriptor
)) {
248 mp_msg(MSGT_AFILTER
, MSGL_V
, "%0.2f , ", hint
.LowerBound
);
250 mp_msg(MSGT_AFILTER
, MSGL_V
, "... , ");
253 if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint
.HintDescriptor
)) {
254 mp_msg(MSGT_AFILTER
, MSGL_V
, "%0.2f]\n", hint
.UpperBound
);
256 mp_msg(MSGT_AFILTER
, MSGL_V
, "...]\n");
264 /* ------------------------------------------------------------------------- */
266 /* This function might "slightly" look like dlopenLADSPA in the LADSPA SDK :-)
267 * But, I changed a few things, because imho it was broken. It did not support
268 * relative paths, only absolute paths that start with a /
269 * I think ../../some/dir/foobar.so is just as valid. And if one wants to call
270 * his library '...somename...so' he's crazy, but it should be allowed.
271 * So, search the path first, try plain *filename later.
272 * Also, try adding .so first! I like the recursion the SDK did, but it's
273 * better the other way around. -af ladspa=cmt:amp_stereo:0.5 is easier to type
274 * than -af ladspa=cmt.so:amp_stereo:0.5 :-))
277 /** \brief dlopen() wrapper
279 * This is a wrapper around dlopen(). It tries various variations of the
280 * filename (with or without the addition of the .so extension) in various
281 * directories specified by the LADSPA_PATH environment variable. If all fails
282 * it tries the filename directly as an absolute path to the library.
284 * \param filename filename of the library to load.
285 * \param flag see dlopen(3) for a description of the flags.
287 * \return returns a pointer to the loaded library on success, or
288 * NULL if it fails to load.
291 static void* mydlopen(const char *filename
, int flag
) {
293 const char *end
, *start
, *ladspapath
;
294 int endsinso
, needslash
;
298 #if defined(__MINGW32__) || defined(__CYGWIN__)
299 /* For Windows there's only absolute path support.
300 * If you have a Windows machine, feel free to fix this.
301 * (path separator, shared objects extension, et cetera). */
302 mp_msg(MSGT_AFILTER
, MSGL_V
, "\ton windows, only absolute pathnames "
304 mp_msg(MSGT_AFILTER
, MSGL_V
, "\ttrying %s\n", filename
);
305 return dlopen(filename
, flag
);
308 filenamelen
= strlen(filename
);
312 endsinso
= (strcmp(filename
+filenamelen
-3, ".so") == 0);
314 buf
=malloc(filenamelen
+4);
315 strcpy(buf
, filename
);
317 result
=mydlopen(buf
, flag
);
324 ladspapath
=getenv("LADSPA_PATH");
329 while (*start
!= '\0') {
331 while ( (*end
!= ':') && (*end
!= '\0') )
334 buf
=malloc(filenamelen
+ 2 + (end
-start
) );
336 strncpy(buf
, start
, end
-start
);
339 if (*(end
-1) != '/') {
341 buf
[end
-start
] = '/';
343 strcpy(buf
+needslash
+(end
-start
), filename
);
345 mp_msg(MSGT_AFILTER
, MSGL_V
, "\ttrying %s\n", buf
);
346 result
=dlopen(buf
, flag
);
355 } /* end while there's still more in the path */
356 } /* end if there's a ladspapath */
358 /* last resort, just open it again, so the dlerror() message is correct */
359 mp_msg(MSGT_AFILTER
, MSGL_V
, "\ttrying %s\n", filename
);
360 return dlopen(filename
,flag
);
363 /* ------------------------------------------------------------------------- */
365 /** \brief Load a LADSPA Plugin
367 * This function loads the LADSPA plugin specified by the file and label
368 * that are present in the setup variable. First, it loads the library.
369 * If it fails, it returns AF_ERROR. If not, it continues to look for the
370 * specified label. If it finds it, it sets the plugin_descriptor inside
371 * setup and returns AF_OK. If it doesn't, it returns AF_ERROR. Special case
372 * is a label called 'help'. In that case, it prints a list of all available
373 * labels (filters) in the library specified by file.
375 * \param setup Current setup of the filter. Contains filename and label.
377 * \return Either AF_ERROR or AF_OK, depending on the success of the operation.
380 static int af_ladspa_load_plugin(af_ladspa_t
*setup
) {
381 const LADSPA_Descriptor
*ladspa_descriptor
;
382 LADSPA_Descriptor_Function descriptor_function
;
386 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: loading ladspa plugin library %s\n",
387 setup
->myname
, setup
->file
);
389 setup
->libhandle
= mydlopen(setup
->file
, RTLD_NOW
);
391 if (!setup
->libhandle
) {
392 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s %s\n\t%s\n", setup
->myname
,
393 _("failed to load"), setup
->file
, dlerror() );
397 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: library found.\n", setup
->myname
);
399 /* find descriptor function */
401 descriptor_function
= (LADSPA_Descriptor_Function
) dlsym (setup
->libhandle
,
402 "ladspa_descriptor");
404 if (!descriptor_function
) {
405 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s\n\t%s\n", setup
->myname
,
406 _("Couldn't find ladspa_descriptor() function in the specified library file."), dlerror());
410 /* if label == help, list all labels in library and exit */
412 if (strcmp(setup
->label
, "help") == 0) {
413 mp_msg(MSGT_AFILTER
, MSGL_INFO
, "%s: %s %s:\n", setup
->myname
,
414 _("available labels in"), setup
->file
);
416 ladspa_descriptor
= descriptor_function(i
);
417 if (ladspa_descriptor
== NULL
) {
420 mp_msg(MSGT_AFILTER
, MSGL_INFO
, " %-16s - %s (%lu)\n",
421 ladspa_descriptor
->Label
,
422 ladspa_descriptor
->Name
,
423 ladspa_descriptor
->UniqueID
);
427 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: looking for label\n", setup
->myname
);
429 /* find label in library */
431 ladspa_descriptor
= descriptor_function(i
);
432 if (ladspa_descriptor
== NULL
) {
433 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s\n", setup
->myname
,
434 _("Couldn't find label in plugin library."));
437 if (strcmp(ladspa_descriptor
->Label
, setup
->label
) == 0) {
438 setup
->plugin_descriptor
= ladspa_descriptor
;
439 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: %s found\n", setup
->myname
,
448 /* ------------------------------------------------------------------------- */
450 /** \brief Print a malloc() failed error message.
452 * Generic function which can be called if a call to malloc(), calloc(),
453 * strdup(), et cetera, failed. It prints a message to the console and
459 static int af_ladspa_malloc_failed(char *myname
) {
460 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s", myname
, "Memory allocation failed.\n");
464 /* ------------------------------------------------------------------------- */
466 /** \brief Controls the filter.
468 * Control the behaviour of the filter.
471 * CONTROL_REINIT Sets the af structure with proper values for number
472 * of channels, rate, format, et cetera.
473 * CONTROL_COMMAND_LINE Parses the suboptions given to this filter
474 * through arg. It first parses the filename and
475 * the label. After that, it loads the filter
476 * and finds out its proprties. Then in continues
477 * parsing the controls given on the commandline,
480 * \param af Audio filter instance
481 * \param cmd The command to execute
482 * \param arg Arguments to the command
484 * \return Either AF_ERROR or AF_OK, depending on the succes of the
488 static int control(struct af_instance_s
*af
, int cmd
, void *arg
) {
489 af_ladspa_t
*setup
= (af_ladspa_t
*) af
->setup
;
494 case AF_CONTROL_REINIT
:
495 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: (re)init\n", setup
->myname
);
497 if (!arg
) return AF_ERROR
;
499 /* accept FLOAT, let af_format do conversion */
501 af
->data
->rate
= ((af_data_t
*)arg
)->rate
;
502 af
->data
->nch
= ((af_data_t
*)arg
)->nch
;
503 af
->data
->format
= AF_FORMAT_FLOAT_NE
;
506 /* arg->len is not set here yet, so init of buffers and connecting the
507 * filter, has to be done in play() :-/
510 return af_test_output(af
, (af_data_t
*)arg
);
511 case AF_CONTROL_COMMAND_LINE
: {
514 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: parse suboptions\n", setup
->myname
);
516 /* suboption parser here!
517 * format is (ladspa=)file:label:controls....
521 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s\n", setup
->myname
,
522 _("No suboptions specified."));
526 buf
= malloc(strlen(arg
)+1);
527 if (!buf
) return af_ladspa_malloc_failed(setup
->myname
);
531 sscanf(arg
, "%[^:]", buf
);
532 if (buf
[0] == '\0') {
533 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s\n", setup
->myname
,
534 _("No library file specified."));
539 setup
->file
= strdup(buf
);
540 if (!setup
->file
) return af_ladspa_malloc_failed(setup
->myname
);
541 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: file --> %s\n", setup
->myname
,
543 if (*(char*)arg
!= '\0') arg
++; /* read ':' */
547 sscanf(arg
, "%[^:]", buf
);
548 if (buf
[0] == '\0') {
549 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s\n", setup
->myname
,
550 _("No filter label specified."));
555 setup
->label
= strdup(buf
);
556 if (!setup
->label
) return af_ladspa_malloc_failed(setup
->myname
);
557 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: label --> %s\n", setup
->myname
,
559 /* if (*(char*)arg != '0') arg++; */ /* read ':' */
561 free(buf
); /* no longer needed */
563 /* set new setup->myname */
566 setup
->myname
= calloc(strlen(af_info_ladspa
.name
)+strlen(setup
->file
)+
567 strlen(setup
->label
)+6, 1);
568 snprintf(setup
->myname
, strlen(af_info_ladspa
.name
)+
569 strlen(setup
->file
)+strlen(setup
->label
)+6, "%s: (%s:%s)",
570 af_info_ladspa
.name
, setup
->file
, setup
->label
);
574 if ( af_ladspa_load_plugin(setup
) != AF_OK
)
577 /* see what inputs, outputs and controls this plugin has */
578 if ( af_ladspa_parse_plugin(setup
) != AF_OK
)
581 /* ninputcontrols is set by now, read control values from arg */
583 for(i
=0; i
<setup
->ninputcontrols
; i
++) {
584 if (!arg
|| (*(char*)arg
!= ':') ) {
585 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s\n", setup
->myname
,
586 _("Not enough controls specified on the command line."));
590 r
= sscanf(arg
, "%f", &val
);
592 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "%s: %s\n", setup
->myname
,
593 _("Not enough controls specified on the command line."));
596 setup
->inputcontrols
[setup
->inputcontrolsmap
[i
]] = val
;
597 arg
= strchr(arg
, ':');
600 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: input controls: ", setup
->myname
);
601 for(i
=0; i
<setup
->ninputcontrols
; i
++) {
602 mp_msg(MSGT_AFILTER
, MSGL_V
, "%0.4f ",
603 setup
->inputcontrols
[setup
->inputcontrolsmap
[i
]]);
605 mp_msg(MSGT_AFILTER
, MSGL_V
, "\n");
607 /* check boundaries of inputcontrols */
609 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: checking boundaries of input controls\n",
611 for(i
=0; i
<setup
->ninputcontrols
; i
++) {
612 int p
= setup
->inputcontrolsmap
[i
];
613 LADSPA_PortRangeHint hint
=
614 setup
->plugin_descriptor
->PortRangeHints
[p
];
615 val
= setup
->inputcontrols
[p
];
617 if (LADSPA_IS_HINT_BOUNDED_BELOW(hint
.HintDescriptor
) &&
618 val
< hint
.LowerBound
) {
619 mp_tmsg(MSGT_AFILTER
, MSGL_ERR
, "%s: Input control #%d is below lower boundary of %0.4f.\n",
620 setup
->myname
, i
, hint
.LowerBound
);
623 if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint
.HintDescriptor
) &&
624 val
> hint
.UpperBound
) {
625 mp_tmsg(MSGT_AFILTER
, MSGL_ERR
, "%s: Input control #%d is above upper boundary of %0.4f.\n",
626 setup
->myname
, i
, hint
.UpperBound
);
630 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: all controls have sane values\n",
634 setup
->status
= AF_OK
;
642 /* ------------------------------------------------------------------------- */
644 /** \brief Uninitialise the LADSPA Plugin Loader filter.
646 * This function deactivates the plugin(s), cleans up, frees all allocated
649 * \return No return value.
652 static void uninit(struct af_instance_s
*af
) {
657 af_ladspa_t
*setup
= (af_ladspa_t
*) af
->setup
;
658 const LADSPA_Descriptor
*pdes
= setup
->plugin_descriptor
;
661 mp_msg(MSGT_AFILTER
, MSGL_V
, "%s: cleaning up\n", setup
->myname
);
665 if (setup
->chhandles
) {
666 for(i
=0; i
<setup
->nch
; i
+=setup
->ninputs
) {
667 if (pdes
->deactivate
) pdes
->deactivate(setup
->chhandles
[i
]);
668 if (pdes
->cleanup
) pdes
->cleanup(setup
->chhandles
[i
]);
670 free(setup
->chhandles
);
675 free(setup
->inputcontrolsmap
);
676 free(setup
->inputcontrols
);
677 free(setup
->outputcontrolsmap
);
678 free(setup
->outputcontrols
);
680 free(setup
->outputs
);
683 for(i
=0; i
<setup
->nch
; i
++)
684 free(setup
->inbufs
[i
]);
688 if (setup
->outbufs
) {
689 for(i
=0; i
<setup
->nch
; i
++)
690 free(setup
->outbufs
[i
]);
691 free(setup
->outbufs
);
694 if (setup
->libhandle
)
695 dlclose(setup
->libhandle
);
702 /* ------------------------------------------------------------------------- */
704 /** \brief Process chunk of audio data through the selected LADSPA Plugin.
706 * \param af Pointer to audio filter instance
707 * \param data Pointer to chunk of audio data
709 * \return Either AF_ERROR or AF_OK
712 static af_data_t
* play(struct af_instance_s
*af
, af_data_t
*data
) {
713 af_ladspa_t
*setup
= af
->setup
;
714 const LADSPA_Descriptor
*pdes
= setup
->plugin_descriptor
;
715 float *audio
= (float*)data
->audio
;
716 int nsamples
= data
->len
/4; /* /4 because it's 32-bit float */
718 int rate
= data
->rate
;
721 if (setup
->status
!=AF_OK
)
724 /* See if it's the first call. If so, setup inbufs/outbufs, instantiate
725 * plugin, connect ports and activate plugin
728 /* 2004-12-07: Also check if the buffersize has to be changed!
729 * data->len is not constant per se! re-init buffers.
732 if ( (setup
->bufsize
!= nsamples
/nch
) || (setup
->nch
!= nch
) ) {
734 /* if setup->nch==0, it's the first call, if not, something has
735 * changed and all previous mallocs have to be freed
738 if (setup
->nch
!= 0) {
739 mp_msg(MSGT_AFILTER
, MSGL_DBG3
, "%s: bufsize change; free old buffer\n",
743 for(i
=0; i
<setup
->nch
; i
++)
744 free(setup
->inbufs
[i
]);
748 for(i
=0; i
<setup
->nch
; i
++)
749 free(setup
->outbufs
[i
]);
750 free(setup
->outbufs
);
752 } /* everything is freed */
754 setup
->bufsize
= nsamples
/nch
;
757 setup
->inbufs
= calloc(nch
, sizeof(float*));
758 setup
->outbufs
= calloc(nch
, sizeof(float*));
760 mp_msg(MSGT_AFILTER
, MSGL_DBG3
, "%s: bufsize = %d\n",
761 setup
->myname
, setup
->bufsize
);
763 for(i
=0; i
<nch
; i
++) {
764 setup
->inbufs
[i
] = calloc(setup
->bufsize
, sizeof(float));
765 setup
->outbufs
[i
] = calloc(setup
->bufsize
, sizeof(float));
768 /* only on the first call, there are no handles. */
770 if (!setup
->chhandles
) {
771 setup
->chhandles
= calloc(nch
, sizeof(LADSPA_Handle
));
774 * for stereo effects, create one handle for two channels
777 for(i
=0; i
<nch
; i
++) {
779 if (i
% setup
->ninputs
) { /* stereo effect */
780 /* copy the handle from previous channel */
781 setup
->chhandles
[i
] = setup
->chhandles
[i
-1];
785 setup
->chhandles
[i
] = pdes
->instantiate(pdes
, rate
);
789 /* connect input/output ports for each channel/filter instance
791 * always (re)connect ports
794 for(i
=0; i
<nch
; i
++) {
795 pdes
->connect_port(setup
->chhandles
[i
],
796 setup
->inputs
[i
% setup
->ninputs
],
798 pdes
->connect_port(setup
->chhandles
[i
],
799 setup
->outputs
[i
% setup
->ninputs
],
802 /* connect (input) controls */
804 for (p
=0; p
<setup
->nports
; p
++) {
805 LADSPA_PortDescriptor d
= pdes
->PortDescriptors
[p
];
806 if (LADSPA_IS_PORT_CONTROL(d
)) {
807 if (LADSPA_IS_PORT_INPUT(d
)) {
808 pdes
->connect_port(setup
->chhandles
[i
], p
,
809 &(setup
->inputcontrols
[p
]) );
811 pdes
->connect_port(setup
->chhandles
[i
], p
,
812 &(setup
->outputcontrols
[p
]) );
817 /* Activate filter (if it isn't already :) ) */
819 if (pdes
->activate
&& !setup
->activated
&& i
% setup
->ninputs
== 0)
820 pdes
->activate(setup
->chhandles
[i
]);
822 } /* All channels/filters done! except for... */
823 setup
->activated
= 1;
825 /* Stereo effect with one channel left. Use same buffer for left
826 * and right. connect it to the second port.
829 for (p
= i
; p
% setup
->ninputs
; p
++) {
830 pdes
->connect_port(setup
->chhandles
[i
-1],
831 setup
->inputs
[p
% setup
->ninputs
],
833 pdes
->connect_port(setup
->chhandles
[i
-1],
834 setup
->outputs
[p
% setup
->ninputs
],
835 setup
->outbufs
[i
-1]);
838 } /* setup for first call/change of bufsize is done.
839 * normal playing routine follows...
842 /* Right now, I use a separate input and output buffer.
843 * I could change this to in-place processing (inbuf==outbuf), but some
844 * ladspa filters are broken and are not able to handle that. This seems
845 * fast enough, so unless somebody complains, it stays this way :)
850 for (p
=0; p
<setup
->bufsize
; p
++) {
851 for (i
=0; i
<nch
; i
++) {
852 setup
->inbufs
[i
][p
] = audio
[p
*nch
+ i
];
858 for (i
=0; i
<nch
; i
+=setup
->ninputs
) {
859 pdes
->run(setup
->chhandles
[i
], setup
->bufsize
);
862 /* Extract outbufs */
864 for (p
=0; p
<setup
->bufsize
; p
++) {
865 for (i
=0; i
<nch
; i
++) {
866 audio
[p
*nch
+ i
] = setup
->outbufs
[i
][p
];
875 /* ------------------------------------------------------------------------- */
877 /** \brief Open LADSPA Plugin Loader Filter
879 * \param af Audio Filter instance
881 * \return Either AF_ERROR or AF_OK
884 static int af_open(af_instance_t
*af
) {
891 af
->data
= calloc(1, sizeof(af_data_t
));
892 if (af
->data
== NULL
)
893 return af_ladspa_malloc_failed((char*)af_info_ladspa
.name
);
895 af
->setup
= calloc(1, sizeof(af_ladspa_t
));
896 if (af
->setup
== NULL
) {
899 return af_ladspa_malloc_failed((char*)af_info_ladspa
.name
);
902 ((af_ladspa_t
*)af
->setup
)->status
= AF_ERROR
; /* will be set to AF_OK if
903 * all went OK and play()
907 ((af_ladspa_t
*)af
->setup
)->myname
= strdup(af_info_ladspa
.name
);
908 if (!((af_ladspa_t
*)af
->setup
)->myname
)
909 return af_ladspa_malloc_failed((char*)af_info_ladspa
.name
);
914 /* ------------------------------------------------------------------------- */