summaryrefslogtreecommitdiffstats
path: root/libaf/af_ladspa.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-11-05 17:02:04 +0100
committerwm4 <wm4@nowhere>2012-11-12 20:06:14 +0100
commitd4bdd0473d6f43132257c9fb3848d829755167a3 (patch)
tree8021c2f7da1841393c8c832105e20cd527826d6c /libaf/af_ladspa.c
parentbd48deba77bd5582c5829d6fe73a7d2571088aba (diff)
downloadmpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.bz2
mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.xz
Rename directories, move files (step 1 of 2) (does not compile)
Tis drops the silly lib prefixes, and attempts to organize the tree in a more logical way. Make the top-level directory less cluttered as well. Renames the following directories: libaf -> audio/filter libao2 -> audio/out libvo -> video/out libmpdemux -> demux Split libmpcodecs: vf* -> video/filter vd*, dec_video.* -> video/decode mp_image*, img_format*, ... -> video/ ad*, dec_audio.* -> audio/decode libaf/format.* is moved to audio/ - this is similar to how mp_image.* is located in video/. Move most top-level .c/.h files to core. (talloc.c/.h is left on top- level, because it's external.) Park some of the more annoying files in compat/. Some of these are relicts from the time mplayer used ffmpeg internals. sub/ is not split, because it's too much of a mess (subtitle code is mixed with OSD display and rendering). Maybe the organization of core is not ideal: it mixes playback core (like mplayer.c) and utility helpers (like bstr.c/h). Should the need arise, the playback core will be moved somewhere else, while core contains all helper and common code.
Diffstat (limited to 'libaf/af_ladspa.c')
-rw-r--r--libaf/af_ladspa.c915
1 files changed, 0 insertions, 915 deletions
diff --git a/libaf/af_ladspa.c b/libaf/af_ladspa.c
deleted file mode 100644
index c1b3f24360..0000000000
--- a/libaf/af_ladspa.c
+++ /dev/null
@@ -1,915 +0,0 @@
-/*
- * LADSPA plugin loader
- *
- * Written by Ivo van Poorten <ivop@euronet.nl>
- * Copyright (C) 2004, 2005
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/* ------------------------------------------------------------------------- */
-
-/* Global Includes */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <inttypes.h>
-#include <math.h>
-#include <limits.h>
-
-#include <dlfcn.h>
-#include <ladspa.h>
-
-/* ------------------------------------------------------------------------- */
-
-/* Local Includes */
-
-#include "af.h"
-
-/* ------------------------------------------------------------------------- */
-
-/* Filter specific data */
-
-typedef struct af_ladspa_s
-{
- int status; /**< Status of the filter.
- * Either AF_OK or AF_ERROR
- * Because MPlayer re-inits audio filters that
- * _clearly_ returned AF_ERROR anyway, I use this
- * in play() to skip the processing and return
- * the data unchanged.
- */
-
- int activated; /**< 0 or 1. Activate LADSPA filters only once, even
- * if the buffers get resized, to avoid a stuttering
- * filter.
- */
-
- char *file;
- char *label;
-
- char *myname; /**< It's easy to have a concatenation of file and label */
-
- void *libhandle;
- const LADSPA_Descriptor *plugin_descriptor;
-
- int nports;
-
- int ninputs;
- int *inputs;
-
- int noutputs;
- int *outputs;
-
- int ninputcontrols;
- int *inputcontrolsmap; /**< Map input port number [0-] to actual port */
- float *inputcontrols;
-
- int noutputcontrols;
- int *outputcontrolsmap;
- float *outputcontrols;
-
- int nch; /**< number of channels */
- int bufsize;
- float **inbufs;
- float **outbufs;
- LADSPA_Handle *chhandles;
-
-} af_ladspa_t;
-
-/* ------------------------------------------------------------------------- */
-
-static int af_open(struct af_instance *af);
-static int af_ladspa_malloc_failed(char*);
-
-/* ------------------------------------------------------------------------- */
-
-/* Description */
-
-struct af_info af_info_ladspa = {
- "LADSPA plugin loader",
- "ladspa",
- "Ivo van Poorten",
- "",
- AF_FLAGS_REENTRANT,
- af_open
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* By lack of a better word (in my vocabulary) this is called 'parse'.
- * Feel free to suggest an alternative.
- */
-
-/** \brief Check for inputs, outputs and controls of a given filter.
- *
- * This function counts and checks all input, output and control ports
- * of the filter that was loaded. If it turns out to be a valid
- * filter for MPlayer use, it prints out a list of all controls and
- * the corresponding range of its value at message level MSGL_V.
- *
- * \param setup Current setup of the filter. Must have its
- * plugin_descriptor set!
- *
- * \return Returns AF_OK if it has a valid input/output/controls
- * configuration. Else, it returns AF_ERROR.
- */
-
-static int af_ladspa_parse_plugin(af_ladspa_t *setup) {
- int p, i;
- const LADSPA_Descriptor *pdes = setup->plugin_descriptor;
- LADSPA_PortDescriptor d;
- LADSPA_PortRangeHint hint;
-
- if (!setup->libhandle)
- return AF_ERROR; /* only call parse after a succesful load */
- if (!setup->plugin_descriptor)
- return AF_ERROR; /* same as above */
-
- /* let's do it */
-
- setup->nports = pdes->PortCount;
-
- /* allocate memory for all inputs/outputs/controls */
-
- setup->inputs = calloc(setup->nports, sizeof(int));
- if (!setup->inputs) return af_ladspa_malloc_failed(setup->myname);
-
- setup->outputs = calloc(setup->nports, sizeof(int));
- if (!setup->outputs) return af_ladspa_malloc_failed(setup->myname);
-
- setup->inputcontrolsmap = calloc(setup->nports, sizeof(int));
- if (!setup->inputcontrolsmap) return af_ladspa_malloc_failed(setup->myname);
-
- setup->inputcontrols = calloc(setup->nports, sizeof(float));
- if (!setup->inputcontrols) return af_ladspa_malloc_failed(setup->myname);
-
- setup->outputcontrolsmap = calloc(setup->nports, sizeof(int));
- if (!setup->outputcontrolsmap) return af_ladspa_malloc_failed(setup->myname);
-
- setup->outputcontrols = calloc(setup->nports, sizeof(float));
- if (!setup->outputcontrols) return af_ladspa_malloc_failed(setup->myname);
-
- /* set counts to zero */
-
- setup->ninputs = 0;
- setup->noutputs = 0;
- setup->ninputcontrols = 0;
- setup->noutputcontrols = 0;
-
- /* check all ports, see what type it is and set variables according to
- * what we have found
- */
-
- for (p=0; p<setup->nports; p++) {
- d = pdes->PortDescriptors[p];
-
- if (LADSPA_IS_PORT_AUDIO(d)) {
- if (LADSPA_IS_PORT_INPUT(d)) {
- setup->inputs[setup->ninputs] = p;
- setup->ninputs++;
- } else if (LADSPA_IS_PORT_OUTPUT(d)) {
- setup->outputs[setup->noutputs] = p;
- setup->noutputs++;
- }
- }
-
- if (LADSPA_IS_PORT_CONTROL(d)) {
- if (LADSPA_IS_PORT_INPUT(d)) {
- setup->inputcontrolsmap[setup->ninputcontrols] = p;
- setup->ninputcontrols++;
- /* set control to zero. set values after reading the rest
- * of the suboptions and check LADSPA_?_HINT's later.
- */
- setup->inputcontrols[p] = 0.0f;
- } else if (LADSPA_IS_PORT_OUTPUT(d)) {
- /* read and handle these too, otherwise filters that have them
- * will sig11
- */
- setup->outputcontrolsmap[setup->noutputcontrols]=p;
- setup->noutputcontrols++;
- setup->outputcontrols[p] = 0.0f;
- }
- }
-
- }
-
- if (setup->ninputs == 0) {
- mp_msg(MSGT_AFILTER, MSGL_WARN, "%s: %s\n", setup->myname,
- _("WARNING! This LADSPA plugin has no audio inputs.\n The incoming audio signal will be lost."));
- } else if (setup->ninputs == 1) {
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: this is a mono effect\n", setup->myname);
- } else if (setup->ninputs == 2) {
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: this is a stereo effect\n", setup->myname);
- } else {
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: this is a %i-channel effect, "
- "support is experimental\n", setup->myname, setup->ninputs);
- }
-
- if (setup->noutputs == 0) {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname,
- _("This LADSPA plugin has no audio outputs."));
- return AF_ERROR;
- }
-
- if (setup->noutputs != setup->ninputs ) {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname,
- _("The number of audio inputs and audio outputs of the LADSPA plugin differ."));
- return AF_ERROR;
- }
-
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: this plugin has %d input control(s)\n",
- setup->myname, setup->ninputcontrols);
-
- /* Print list of controls and its range of values it accepts */
-
- for (i=0; i<setup->ninputcontrols; i++) {
- p = setup->inputcontrolsmap[i];
- hint = pdes->PortRangeHints[p];
- mp_msg(MSGT_AFILTER, MSGL_V, " --- %d %s [", i, pdes->PortNames[p]);
-
- if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) {
- mp_msg(MSGT_AFILTER, MSGL_V, "%0.2f , ", hint.LowerBound);
- } else {
- mp_msg(MSGT_AFILTER, MSGL_V, "... , ");
- }
-
- if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) {
- mp_msg(MSGT_AFILTER, MSGL_V, "%0.2f]\n", hint.UpperBound);
- } else {
- mp_msg(MSGT_AFILTER, MSGL_V, "...]\n");
- }
-
- }
-
- return AF_OK;
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* This function might "slightly" look like dlopenLADSPA in the LADSPA SDK :-)
- * But, I changed a few things, because imho it was broken. It did not support
- * relative paths, only absolute paths that start with a /
- * I think ../../some/dir/foobar.so is just as valid. And if one wants to call
- * his library '...somename...so' he's crazy, but it should be allowed.
- * So, search the path first, try plain *filename later.
- * Also, try adding .so first! I like the recursion the SDK did, but it's
- * better the other way around. -af ladspa=cmt:amp_stereo:0.5 is easier to type
- * than -af ladspa=cmt.so:amp_stereo:0.5 :-))
- */
-
-/** \brief dlopen() wrapper
- *
- * This is a wrapper around dlopen(). It tries various variations of the
- * filename (with or without the addition of the .so extension) in various
- * directories specified by the LADSPA_PATH environment variable. If all fails
- * it tries the filename directly as an absolute path to the library.
- *
- * \param filename filename of the library to load.
- * \param flag see dlopen(3) for a description of the flags.
- *
- * \return returns a pointer to the loaded library on success, or
- * NULL if it fails to load.
- */
-
-static void* mydlopen(const char *filename, int flag) {
- char *buf;
- const char *end, *start, *ladspapath;
- int endsinso, needslash;
- size_t filenamelen;
- void *result = NULL;
-
-#if defined(__MINGW32__) || defined(__CYGWIN__)
- /* For Windows there's only absolute path support.
- * If you have a Windows machine, feel free to fix this.
- * (path separator, shared objects extension, et cetera). */
- mp_msg(MSGT_AFILTER, MSGL_V, "\ton windows, only absolute pathnames "
- "are supported\n");
- mp_msg(MSGT_AFILTER, MSGL_V, "\ttrying %s\n", filename);
- return dlopen(filename, flag);
-#endif
-
- filenamelen = strlen(filename);
-
- endsinso = 0;
- if (filenamelen > 3)
- endsinso = (strcmp(filename+filenamelen-3, ".so") == 0);
- if (!endsinso) {
- buf=malloc(filenamelen+4);
- strcpy(buf, filename);
- strcat(buf, ".so");
- result=mydlopen(buf, flag);
- free(buf);
- }
-
- if (result)
- return result;
-
- ladspapath=getenv("LADSPA_PATH");
-
- if (ladspapath) {
-
- start=ladspapath;
- while (*start != '\0') {
- end=start;
- while ( (*end != ':') && (*end != '\0') )
- end++;
-
- buf=malloc(filenamelen + 2 + (end-start) );
- if (end > start)
- strncpy(buf, start, end-start);
- needslash=0;
- if (end > start)
- if (*(end-1) != '/') {
- needslash = 1;
- buf[end-start] = '/';
- }
- strcpy(buf+needslash+(end-start), filename);
-
- mp_msg(MSGT_AFILTER, MSGL_V, "\ttrying %s\n", buf);
- result=dlopen(buf, flag);
-
- free(buf);
- if (result)
- return result;
-
- start = end;
- if (*start == ':')
- start++;
- } /* end while there's still more in the path */
- } /* end if there's a ladspapath */
-
- /* last resort, just open it again, so the dlerror() message is correct */
- mp_msg(MSGT_AFILTER, MSGL_V, "\ttrying %s\n", filename);
- return dlopen(filename,flag);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/** \brief Load a LADSPA Plugin
- *
- * This function loads the LADSPA plugin specified by the file and label
- * that are present in the setup variable. First, it loads the library.
- * If it fails, it returns AF_ERROR. If not, it continues to look for the
- * specified label. If it finds it, it sets the plugin_descriptor inside
- * setup and returns AF_OK. If it doesn't, it returns AF_ERROR. Special case
- * is a label called 'help'. In that case, it prints a list of all available
- * labels (filters) in the library specified by file.
- *
- * \param setup Current setup of the filter. Contains filename and label.
- *
- * \return Either AF_ERROR or AF_OK, depending on the success of the operation.
- */
-
-static int af_ladspa_load_plugin(af_ladspa_t *setup) {
- const LADSPA_Descriptor *ladspa_descriptor;
- LADSPA_Descriptor_Function descriptor_function;
- int i;
-
- /* load library */
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: loading ladspa plugin library %s\n",
- setup->myname, setup->file);
-
- setup->libhandle = mydlopen(setup->file, RTLD_NOW);
-
- if (!setup->libhandle) {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s %s\n\t%s\n", setup->myname,
- _("failed to load"), setup->file, dlerror() );
- return AF_ERROR;
- }
-
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: library found.\n", setup->myname);
-
- /* find descriptor function */
- dlerror();
- descriptor_function = (LADSPA_Descriptor_Function) dlsym (setup->libhandle,
- "ladspa_descriptor");
-
- if (!descriptor_function) {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n\t%s\n", setup->myname,
- _("Couldn't find ladspa_descriptor() function in the specified library file."), dlerror());
- return AF_ERROR;
- }
-
- /* if label == help, list all labels in library and exit */
-
- if (strcmp(setup->label, "help") == 0) {
- mp_msg(MSGT_AFILTER, MSGL_INFO, "%s: %s %s:\n", setup->myname,
- _("available labels in"), setup->file);
- for (i=0; ; i++) {
- ladspa_descriptor = descriptor_function(i);
- if (ladspa_descriptor == NULL) {
- return AF_ERROR;
- }
- mp_msg(MSGT_AFILTER, MSGL_INFO, " %-16s - %s (%lu)\n",
- ladspa_descriptor->Label,
- ladspa_descriptor->Name,
- ladspa_descriptor->UniqueID);
- }
- }
-
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: looking for label\n", setup->myname);
-
- /* find label in library */
- for (i=0; ; i++) {
- ladspa_descriptor = descriptor_function(i);
- if (ladspa_descriptor == NULL) {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname,
- _("Couldn't find label in plugin library."));
- return AF_ERROR;
- }
- if (strcmp(ladspa_descriptor->Label, setup->label) == 0) {
- setup->plugin_descriptor = ladspa_descriptor;
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: %s found\n", setup->myname,
- setup->label);
- return AF_OK;
- }
- }
-
- return AF_OK;
-}
-
-/* ------------------------------------------------------------------------- */
-
-/** \brief Print a malloc() failed error message.
- *
- * Generic function which can be called if a call to malloc(), calloc(),
- * strdup(), et cetera, failed. It prints a message to the console and
- * returns AF_ERROR.
- *
- * \return AF_ERROR
- */
-
-static int af_ladspa_malloc_failed(char *myname) {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s", myname, "Memory allocation failed.\n");
- return AF_ERROR;
-}
-
-/* ------------------------------------------------------------------------- */
-
-/** \brief Controls the filter.
- *
- * Control the behaviour of the filter.
- *
- * Commands:
- * CONTROL_REINIT Sets the af structure with proper values for number
- * of channels, rate, format, et cetera.
- * CONTROL_COMMAND_LINE Parses the suboptions given to this filter
- * through arg. It first parses the filename and
- * the label. After that, it loads the filter
- * and finds out its proprties. Then in continues
- * parsing the controls given on the commandline,
- * if any are needed.
- *
- * \param af Audio filter instance
- * \param cmd The command to execute
- * \param arg Arguments to the command
- *
- * \return Either AF_ERROR or AF_OK, depending on the succes of the
- * operation.
- */
-
-static int control(struct af_instance *af, int cmd, void *arg) {
- af_ladspa_t *setup = (af_ladspa_t*) af->setup;
- int i, r;
- float val;
-
- switch(cmd) {
- case AF_CONTROL_REINIT:
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: (re)init\n", setup->myname);
-
- if (!arg) return AF_ERROR;
-
- /* accept FLOAT, let af_format do conversion */
-
- af->data->rate = ((struct mp_audio*)arg)->rate;
- af->data->nch = ((struct mp_audio*)arg)->nch;
- af->data->format = AF_FORMAT_FLOAT_NE;
- af->data->bps = 4;
-
- /* arg->len is not set here yet, so init of buffers and connecting the
- * filter, has to be done in play() :-/
- */
-
- return af_test_output(af, (struct mp_audio*)arg);
- case AF_CONTROL_COMMAND_LINE: {
- char *buf;
- char *line = arg;
-
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: parse suboptions\n", setup->myname);
-
- /* suboption parser here!
- * format is (ladspa=)file:label:controls....
- */
-
- if (!line) {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname,
- _("No suboptions specified."));
- return AF_ERROR;
- }
-
- buf = malloc(strlen(line)+1);
- if (!buf) return af_ladspa_malloc_failed(setup->myname);
-
- /* file... */
- buf[0] = '\0';
- sscanf(line, "%[^:]", buf);
- if (buf[0] == '\0') {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname,
- _("No library file specified."));
- free(buf);
- return AF_ERROR;
- }
- line += strlen(buf);
- setup->file = strdup(buf);
- if (!setup->file) return af_ladspa_malloc_failed(setup->myname);
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: file --> %s\n", setup->myname,
- setup->file);
- if (*line != '\0') line++; /* read ':' */
-
- /* label... */
- buf[0] = '\0';
- sscanf(line, "%[^:]", buf);
- if (buf[0] == '\0') {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname,
- _("No filter label specified."));
- free(buf);
- return AF_ERROR;
- }
- line += strlen(buf);
- setup->label = strdup(buf);
- if (!setup->label) return af_ladspa_malloc_failed(setup->myname);
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: label --> %s\n", setup->myname,
- setup->label);
-/* if (*line != '0') line++; */ /* read ':' */
-
- free(buf); /* no longer needed */
-
- /* set new setup->myname */
-
- free(setup->myname);
- setup->myname = calloc(strlen(af_info_ladspa.name)+strlen(setup->file)+
- strlen(setup->label)+6, 1);
- snprintf(setup->myname, strlen(af_info_ladspa.name)+
- strlen(setup->file)+strlen(setup->label)+6, "%s: (%s:%s)",
- af_info_ladspa.name, setup->file, setup->label);
-
- /* load plugin :) */
-
- if ( af_ladspa_load_plugin(setup) != AF_OK )
- return AF_ERROR;
-
- /* see what inputs, outputs and controls this plugin has */
- if ( af_ladspa_parse_plugin(setup) != AF_OK )
- return AF_ERROR;
-
- /* ninputcontrols is set by now, read control values from arg */
-
- for(i=0; i<setup->ninputcontrols; i++) {
- if (!line || *line != ':') {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname,
- _("Not enough controls specified on the command line."));
- return AF_ERROR;
- }
- line++;
- r = sscanf(line, "%f", &val);
- if (r!=1) {
- mp_msg(MSGT_AFILTER, MSGL_ERR, "%s: %s\n", setup->myname,
- _("Not enough controls specified on the command line."));
- return AF_ERROR;
- }
- setup->inputcontrols[setup->inputcontrolsmap[i]] = val;
- line = strchr(line, ':');
- }
-
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: input controls: ", setup->myname);
- for(i=0; i<setup->ninputcontrols; i++) {
- mp_msg(MSGT_AFILTER, MSGL_V, "%0.4f ",
- setup->inputcontrols[setup->inputcontrolsmap[i]]);
- }
- mp_msg(MSGT_AFILTER, MSGL_V, "\n");
-
- /* check boundaries of inputcontrols */
-
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: checking boundaries of input controls\n",
- setup->myname);
- for(i=0; i<setup->ninputcontrols; i++) {
- int p = setup->inputcontrolsmap[i];
- LADSPA_PortRangeHint hint =
- setup->plugin_descriptor->PortRangeHints[p];
- val = setup->inputcontrols[p];
-
- if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) &&
- val < hint.LowerBound) {
- mp_tmsg(MSGT_AFILTER, MSGL_ERR, "%s: Input control #%d is below lower boundary of %0.4f.\n",
- setup->myname, i, hint.LowerBound);
- return AF_ERROR;
- }
- if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) &&
- val > hint.UpperBound) {
- mp_tmsg(MSGT_AFILTER, MSGL_ERR, "%s: Input control #%d is above upper boundary of %0.4f.\n",
- setup->myname, i, hint.UpperBound);
- return AF_ERROR;
- }
- }
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: all controls have sane values\n",
- setup->myname);
-
- /* All is well! */
- setup->status = AF_OK;
-
- return AF_OK; }
- }
-
- return AF_UNKNOWN;
-}
-
-/* ------------------------------------------------------------------------- */
-
-/** \brief Uninitialise the LADSPA Plugin Loader filter.
- *
- * This function deactivates the plugin(s), cleans up, frees all allocated
- * memory and exits.
- *
- * \return No return value.
- */
-
-static void uninit(struct af_instance *af) {
- int i;
-
- free(af->data);
- if (af->setup) {
- af_ladspa_t *setup = (af_ladspa_t*) af->setup;
- const LADSPA_Descriptor *pdes = setup->plugin_descriptor;
-
- if (setup->myname) {
- mp_msg(MSGT_AFILTER, MSGL_V, "%s: cleaning up\n", setup->myname);
- free(setup->myname);
- }
-
- if (setup->chhandles) {
- for(i=0; i<setup->nch; i+=setup->ninputs) {
- if (pdes->deactivate) pdes->deactivate(setup->chhandles[i]);
- if (pdes->cleanup) pdes->cleanup(setup->chhandles[i]);
- }
- free(setup->chhandles);
- }
-
- free(setup->file);
- free(setup->label);
- free(setup->inputcontrolsmap);
- free(setup->inputcontrols);
- free(setup->outputcontrolsmap);
- free(setup->outputcontrols);
- free(setup->inputs);
- free(setup->outputs);
-
- if (setup->inbufs) {
- for(i=0; i<setup->nch; i++)
- free(setup->inbufs[i]);
- free(setup->inbufs);
- }
-
- if (setup->outbufs) {
- for(i=0; i<setup->nch; i++)
- free(setup->outbufs[i]);
- free(setup->outbufs);
- }
-
- if (setup->libhandle)
- dlclose(setup->libhandle);
-
- free(setup);
- setup = NULL;
- }
-}
-
-/* ------------------------------------------------------------------------- */
-
-/** \brief Process chunk of audio data through the selected LADSPA Plugin.
- *
- * \param af Pointer to audio filter instance
- * \param data Pointer to chunk of audio data
- *
- * \return Either AF_ERROR or AF_OK
- */
-
-static struct mp_audio* play(struct af_instance *af, struct mp_audio *data) {
- af_ladspa_t *setup = af->setup;
- const LADSPA_Descriptor *pdes = setup->plugin_descriptor;
- float *audio = (float*)data->audio;
- int nsamples = data->len/4; /* /4 because it's 32-bit float */
- int nch = data->nch;
- int rate = data->rate;
- int i, p;
-
- if (setup->status !=AF_OK)
- return data;
-
- /* See if it's the first call. If so, setup inbufs/outbufs, instantiate
- * plugin, connect ports and activate plugin
- */
-
- /* 2004-12-07: Also check if the buffersize has to be changed!
- * data->len is not constant per se! re-init buffers.
- */
-
- if ( (setup->bufsize != nsamples/nch) || (setup->nch != nch) ) {
-
- /* if setup->nch==0, it's the first call, if not, something has
- * changed and all previous mallocs have to be freed
- */
-
- if (setup->nch != 0) {
- mp_msg(MSGT_AFILTER, MSGL_DBG3, "%s: bufsize change; free old buffer\n",
- setup->myname);
-
- if(setup->inbufs) {
- for(i=0; i<setup->nch; i++)
- free(setup->inbufs[i]);
- free(setup->inbufs);
- }
- if(setup->outbufs) {
- for(i=0; i<setup->nch; i++)
- free(setup->outbufs[i]);
- free(setup->outbufs);
- }
- } /* everything is freed */
-
- setup->bufsize = nsamples/nch;
- setup->nch = nch;
-
- setup->inbufs = calloc(nch, sizeof(float*));
- setup->outbufs = calloc(nch, sizeof(float*));
-
- mp_msg(MSGT_AFILTER, MSGL_DBG3, "%s: bufsize = %d\n",
- setup->myname, setup->bufsize);
-
- for(i=0; i<nch; i++) {
- setup->inbufs[i] = calloc(setup->bufsize, sizeof(float));
- setup->outbufs[i] = calloc(setup->bufsize, sizeof(float));
- }
-
- /* only on the first call, there are no handles. */
-
- if (!setup->chhandles) {
- setup->chhandles = calloc(nch, sizeof(LADSPA_Handle));
-
- /* create handles
- * for stereo effects, create one handle for two channels
- */
-
- for(i=0; i<nch; i++) {
-
- if (i % setup->ninputs) { /* stereo effect */
- /* copy the handle from previous channel */
- setup->chhandles[i] = setup->chhandles[i-1];
- continue;
- }
-
- setup->chhandles[i] = pdes->instantiate(pdes, rate);
- }
- }
-
- /* connect input/output ports for each channel/filter instance
- *
- * always (re)connect ports
- */
-
- for(i=0; i<nch; i++) {
- pdes->connect_port(setup->chhandles[i],
- setup->inputs[i % setup->ninputs],
- setup->inbufs[i]);
- pdes->connect_port(setup->chhandles[i],
- setup->outputs[i % setup->ninputs],
- setup->outbufs[i]);
-
- /* connect (input) controls */
-
- for (p=0; p<setup->nports; p++) {
- LADSPA_PortDescriptor d = pdes->PortDescriptors[p];
- if (LADSPA_IS_PORT_CONTROL(d)) {
- if (LADSPA_IS_PORT_INPUT(d)) {
- pdes->connect_port(setup->chhandles[i], p,
- &(setup->inputcontrols[p]) );
- } else {
- pdes->connect_port(setup->chhandles[i], p,
- &(setup->outputcontrols[p]) );
- }
- }
- }
-
- /* Activate filter (if it isn't already :) ) */
-
- if (pdes->activate && !setup->activated && i % setup->ninputs == 0)
- pdes->activate(setup->chhandles[i]);
-
- } /* All channels/filters done! except for... */
- setup->activated = 1;
-
- /* Stereo effect with one channel left. Use same buffer for left
- * and right. connect it to the second port.
- */
-
- for (p = i; p % setup->ninputs; p++) {
- pdes->connect_port(setup->chhandles[i-1],
- setup->inputs[p % setup->ninputs],
- setup->inbufs[i-1]);
- pdes->connect_port(setup->chhandles[i-1],
- setup->outputs[p % setup->ninputs],
- setup->outbufs[i-1]);
- } /* done! */
-
- } /* setup for first call/change of bufsize is done.
- * normal playing routine follows...
- */
-
- /* Right now, I use a separate input and output buffer.
- * I could change this to in-place processing (inbuf==outbuf), but some
- * ladspa filters are broken and are not able to handle that. This seems
- * fast enough, so unless somebody complains, it stays this way :)
- */
-
- /* Fill inbufs */
-
- for (p=0; p<setup->bufsize; p++) {
- for (i=0; i<nch; i++) {
- setup->inbufs[i][p] = audio[p*nch + i];
- }
- }
-
- /* Run filter(s) */
-
- for (i=0; i<nch; i+=setup->ninputs) {
- pdes->run(setup->chhandles[i], setup->bufsize);
- }
-
- /* Extract outbufs */
-
- for (p=0; p<setup->bufsize; p++) {
- for (i=0; i<nch; i++) {
- audio[p*nch + i] = setup->outbufs[i][p];
- }
- }
-
- /* done */
-
- return data;
-}
-
-/* ------------------------------------------------------------------------- */
-
-/** \brief Open LADSPA Plugin Loader Filter
- *
- * \param af Audio Filter instance
- *
- * \return Either AF_ERROR or AF_OK
- */
-
-static int af_open(struct af_instance *af) {
-
- af->control=control;
- af->uninit=uninit;
- af->play=play;
- af->mul=1;
-
- af->data = calloc(1, sizeof(struct mp_audio));
- if (af->data == NULL)
- return af_ladspa_malloc_failed((char*)af_info_ladspa.name);
-
- af->setup = calloc(1, sizeof(af_ladspa_t));
- if (af->setup == NULL) {
- free(af->data);
- af->data=NULL;
- return af_ladspa_malloc_failed((char*)af_info_ladspa.name);
- }
-
- ((af_ladspa_t*)af->setup)->status = AF_ERROR; /* will be set to AF_OK if
- * all went OK and play()
- * should proceed.
- */
-
- ((af_ladspa_t*)af->setup)->myname = strdup(af_info_ladspa.name);
- if (!((af_ladspa_t*)af->setup)->myname)
- return af_ladspa_malloc_failed((char*)af_info_ladspa.name);
-
- return AF_OK;
-}
-
-/* ------------------------------------------------------------------------- */