ladspa: Remove the sources from gst-plugins-good

It's disabled anyway and the latest version of it is in
gst-plugins-bad. Fixes bug #603779.
This commit is contained in:
Sebastian Dröge 2009-12-04 14:42:49 +01:00
parent ee6d7fd2db
commit 648f0f0b50
10 changed files with 0 additions and 2216 deletions

View file

@ -1102,7 +1102,6 @@ ext/flac/Makefile
ext/gconf/Makefile ext/gconf/Makefile
ext/gdk_pixbuf/Makefile ext/gdk_pixbuf/Makefile
ext/hal/Makefile ext/hal/Makefile
ext/ladspa/Makefile
ext/libcaca/Makefile ext/libcaca/Makefile
ext/libpng/Makefile ext/libpng/Makefile
ext/pulse/Makefile ext/pulse/Makefile

View file

@ -159,7 +159,6 @@ DIST_SUBDIRS = \
gdk_pixbuf \ gdk_pixbuf \
hal \ hal \
jpeg \ jpeg \
ladspa \
libcaca \ libcaca \
libpng \ libpng \
pulse \ pulse \

View file

@ -1,9 +0,0 @@
plugin_LTLIBRARIES = libgstladspa.la
libgstladspa_la_SOURCES = gstsignalprocessor.c gstladspa.c search.c load.c
libgstladspa_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
libgstladspa_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR)
libgstladspa_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstladspa_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstsignalprocessor.h gstladspa.h utils.h

View file

@ -1,635 +0,0 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* <2001> Steve Baker <stevebaker_org@yahoo.co.uk>
* 2003 Andy Wingo <wingo at pobox.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <math.h>
#include <gst/audio/audio.h>
#include "gstladspa.h"
#include <ladspa.h> /* main ladspa sdk include file */
#include "utils.h" /* ladspa sdk utility functions */
/* 1.0 and the 1.1 preliminary headers don't define a version, but 1.1 final
does */
#ifndef LADSPA_VERSION
#define LADSPA_VERSION "1.0"
#endif
GST_BOILERPLATE (GstLADSPA, gst_ladspa, GstSignalProcessor,
GST_TYPE_SIGNAL_PROCESSOR);
static void gst_ladspa_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_ladspa_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean gst_ladspa_setup (GstSignalProcessor * sigproc,
guint sample_rate);
static gboolean gst_ladspa_start (GstSignalProcessor * sigproc);
static void gst_ladspa_stop (GstSignalProcessor * sigproc);
static void gst_ladspa_cleanup (GstSignalProcessor * sigproc);
static void gst_ladspa_process (GstSignalProcessor * sigproc, guint nframes);
static GstPlugin *ladspa_plugin;
static GHashTable *ladspa_descriptors;
GST_DEBUG_CATEGORY_STATIC (ladspa_debug);
#define GST_CAT_DEFAULT ladspa_debug
static void
gst_ladspa_base_init (gpointer g_class)
{
GstLADSPAClass *klass = (GstLADSPAClass *) g_class;
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
GstSignalProcessorClass *gsp_class = GST_SIGNAL_PROCESSOR_CLASS (g_class);
GstElementDetails *details;
LADSPA_Descriptor *desc;
gint j, sinkcount, srccount;
GST_DEBUG ("base_init %p", g_class);
desc = g_hash_table_lookup (ladspa_descriptors,
GINT_TO_POINTER (G_TYPE_FROM_CLASS (klass)));
if (!desc)
desc = g_hash_table_lookup (ladspa_descriptors, GINT_TO_POINTER (0));
g_assert (desc);
klass->descriptor = desc;
g_assert (desc);
/* pad templates */
gsp_class->num_audio_in = 0;
gsp_class->num_audio_out = 0;
/* control gets set in the class init */
for (j = 0; j < desc->PortCount; j++) {
LADSPA_PortDescriptor p = desc->PortDescriptors[j];
if (LADSPA_IS_PORT_AUDIO (p)) {
gchar *name = g_strdup ((gchar *) desc->PortNames[j]);
GST_DEBUG ("LADSPA port name: \"%s\"", name);
g_strdelimit (name, " ", '_');
g_strcanon (name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_-><=", '-');
GST_DEBUG ("GStreamer pad name: \"%s\"", name);
if (LADSPA_IS_PORT_INPUT (p))
gst_signal_processor_class_add_pad_template (gsp_class, name,
GST_PAD_SINK, gsp_class->num_audio_in++);
else
gst_signal_processor_class_add_pad_template (gsp_class, name,
GST_PAD_SRC, gsp_class->num_audio_out++);
}
}
/* construct the element details struct */
details = g_new0 (GstElementDetails, 1);
details->longname = g_locale_to_utf8 (desc->Name, -1, NULL, NULL, NULL);
if (!details->longname)
details->longname = g_strdup ("no description available");
details->description = details->longname;
details->author = g_locale_to_utf8 (desc->Maker, -1, NULL, NULL, NULL);
if (!details->author)
details->author = g_strdup ("no author available");
if (gsp_class->num_audio_in == 0)
details->klass = "Source/Audio/LADSPA";
else if (gsp_class->num_audio_out == 0)
details->klass = "Sink/Audio/LADSPA";
else
details->klass = "Filter/Effect/Audio/LADSPA";
gst_element_class_set_details (element_class, details);
klass->audio_in_portnums = g_new0 (gint, gsp_class->num_audio_in);
klass->audio_out_portnums = g_new0 (gint, gsp_class->num_audio_out);
sinkcount = srccount = 0;
for (j = 0; j < desc->PortCount; j++) {
if (LADSPA_IS_PORT_AUDIO (desc->PortDescriptors[j])) {
if (LADSPA_IS_PORT_INPUT (desc->PortDescriptors[j]))
klass->audio_in_portnums[sinkcount++] = j;
else
klass->audio_out_portnums[srccount++] = j;
}
}
if (!LADSPA_IS_INPLACE_BROKEN (desc->Properties))
GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE (klass);
klass->descriptor = desc;
}
static gchar *
gst_ladspa_class_get_param_name (GstLADSPAClass * klass, gint portnum)
{
LADSPA_Descriptor *desc;
gchar *ret, *paren;
desc = klass->descriptor;
ret = g_strdup (desc->PortNames[portnum]);
paren = g_strrstr (ret, " (");
if (paren != NULL)
*paren = '\0';
/* this is the same thing that param_spec_* will do */
g_strcanon (ret, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
/* satisfy glib2 (argname[0] must be [A-Za-z]) */
if (!((ret[0] >= 'a' && ret[0] <= 'z') || (ret[0] >= 'A' && ret[0] <= 'Z'))) {
gchar *tempstr = ret;
ret = g_strconcat ("param-", ret, NULL);
g_free (tempstr);
}
/* check for duplicate property names */
if (g_object_class_find_property (G_OBJECT_CLASS (klass), ret)) {
gint n = 1;
gchar *nret = g_strdup_printf ("%s-%d", ret, n++);
while (g_object_class_find_property (G_OBJECT_CLASS (klass), nret)) {
g_free (nret);
nret = g_strdup_printf ("%s-%d", ret, n++);
}
ret = nret;
}
return ret;
}
static GParamSpec *
gst_ladspa_class_get_param_spec (GstLADSPAClass * klass, gint portnum)
{
LADSPA_Descriptor *desc;
GParamSpec *ret;
gchar *name;
gint hintdesc, perms;
gfloat lower, upper, def;
desc = klass->descriptor;
name = gst_ladspa_class_get_param_name (klass, portnum);
perms = G_PARAM_READABLE;
if (LADSPA_IS_PORT_INPUT (desc->PortDescriptors[portnum]))
perms |= G_PARAM_WRITABLE | G_PARAM_CONSTRUCT;
/* short name for hint descriptor */
hintdesc = desc->PortRangeHints[portnum].HintDescriptor;
if (LADSPA_IS_HINT_TOGGLED (hintdesc)) {
ret = g_param_spec_boolean (name, name, name, FALSE, perms);
g_free (name);
return ret;
}
if (LADSPA_IS_HINT_BOUNDED_BELOW (hintdesc))
lower = desc->PortRangeHints[portnum].LowerBound;
else
lower = -G_MAXFLOAT;
if (LADSPA_IS_HINT_BOUNDED_ABOVE (hintdesc))
upper = desc->PortRangeHints[portnum].UpperBound;
else
upper = G_MAXFLOAT;
if (LADSPA_IS_HINT_SAMPLE_RATE (hintdesc)) {
/* FIXME! */
lower *= 44100;
upper *= 44100;
}
if (LADSPA_IS_HINT_INTEGER (hintdesc)) {
lower = CLAMP (lower, G_MININT, G_MAXINT);
upper = CLAMP (upper, G_MININT, G_MAXINT);
}
/* default to lower bound */
def = lower;
#ifdef LADSPA_IS_HINT_HAS_DEFAULT
if (LADSPA_IS_HINT_HAS_DEFAULT (hintdesc)) {
if (LADSPA_IS_HINT_DEFAULT_0 (hintdesc))
def = 0.0;
else if (LADSPA_IS_HINT_DEFAULT_1 (hintdesc))
def = 1.0;
else if (LADSPA_IS_HINT_DEFAULT_100 (hintdesc))
def = 100.0;
else if (LADSPA_IS_HINT_DEFAULT_440 (hintdesc))
def = 440.0;
if (LADSPA_IS_HINT_DEFAULT_MINIMUM (hintdesc))
def = lower;
else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM (hintdesc))
def = upper;
else if (LADSPA_IS_HINT_LOGARITHMIC (hintdesc)) {
if (LADSPA_IS_HINT_DEFAULT_LOW (hintdesc))
def = exp (0.75 * log (lower) + 0.25 * log (upper));
else if (LADSPA_IS_HINT_DEFAULT_MIDDLE (hintdesc))
def = exp (0.5 * log (lower) + 0.5 * log (upper));
else if (LADSPA_IS_HINT_DEFAULT_HIGH (hintdesc))
def = exp (0.25 * log (lower) + 0.75 * log (upper));
} else {
if (LADSPA_IS_HINT_DEFAULT_LOW (hintdesc))
def = 0.75 * lower + 0.25 * upper;
else if (LADSPA_IS_HINT_DEFAULT_MIDDLE (hintdesc))
def = 0.5 * lower + 0.5 * upper;
else if (LADSPA_IS_HINT_DEFAULT_HIGH (hintdesc))
def = 0.25 * lower + 0.75 * upper;
}
}
#endif /* LADSPA_IS_HINT_HAS_DEFAULT */
if (lower > upper) {
gfloat tmp;
/* silently swap */
tmp = lower;
lower = upper;
upper = tmp;
}
def = CLAMP (def, lower, upper);
if (LADSPA_IS_HINT_INTEGER (hintdesc)) {
ret = g_param_spec_int (name, name, name, lower, upper, def, perms);
} else {
ret = g_param_spec_float (name, name, name, lower, upper, def, perms);
}
g_free (name);
return ret;
}
static void
gst_ladspa_class_init (GstLADSPAClass * klass)
{
GObjectClass *gobject_class;
GstSignalProcessorClass *gsp_class;
LADSPA_Descriptor *desc;
gint i, control_in_count, control_out_count;
GST_DEBUG ("class_init %p", klass);
gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_ladspa_set_property;
gobject_class->get_property = gst_ladspa_get_property;
gsp_class = GST_SIGNAL_PROCESSOR_CLASS (klass);
gsp_class->setup = gst_ladspa_setup;
gsp_class->start = gst_ladspa_start;
gsp_class->stop = gst_ladspa_stop;
gsp_class->cleanup = gst_ladspa_cleanup;
gsp_class->process = gst_ladspa_process;
desc = klass->descriptor;
g_assert (desc);
gsp_class->num_control_in = 0;
gsp_class->num_control_out = 0;
for (i = 0; i < desc->PortCount; i++) {
LADSPA_PortDescriptor p = desc->PortDescriptors[i];
if (!LADSPA_IS_PORT_AUDIO (p)) {
if (LADSPA_IS_PORT_INPUT (p))
gsp_class->num_control_in++;
else
gsp_class->num_control_out++;
}
}
klass->control_in_portnums = g_new0 (gint, gsp_class->num_control_in);
klass->control_out_portnums = g_new0 (gint, gsp_class->num_control_out);
control_in_count = control_out_count = 0;
for (i = 0; i < desc->PortCount; i++) {
LADSPA_PortDescriptor p = desc->PortDescriptors[i];
if (!LADSPA_IS_PORT_AUDIO (p)) {
if (LADSPA_IS_PORT_INPUT (p))
klass->control_in_portnums[control_in_count++] = i;
else
klass->control_out_portnums[control_out_count++] = i;
}
}
g_assert (control_in_count == gsp_class->num_control_in);
g_assert (control_out_count == gsp_class->num_control_out);
for (i = 0; i < gsp_class->num_control_in; i++) {
GParamSpec *p;
p = gst_ladspa_class_get_param_spec (klass, klass->control_in_portnums[i]);
/* properties have an offset of 1 */
g_object_class_install_property (G_OBJECT_CLASS (klass), i + 1, p);
}
for (i = 0; i < gsp_class->num_control_out; i++) {
GParamSpec *p;
p = gst_ladspa_class_get_param_spec (klass, klass->control_out_portnums[i]);
/* properties have an offset of 1, and we already added num_control_in */
g_object_class_install_property (G_OBJECT_CLASS (klass),
gsp_class->num_control_in + i + 1, p);
}
}
static void
gst_ladspa_init (GstLADSPA * ladspa, GstLADSPAClass * klass)
{
/* whoopee, nothing to do */
ladspa->descriptor = klass->descriptor;
ladspa->activated = FALSE;
ladspa->inplace_broken =
LADSPA_IS_INPLACE_BROKEN (ladspa->descriptor->Properties);
}
static void
gst_ladspa_set_property (GObject * object, guint prop_id, const GValue * value,
GParamSpec * pspec)
{
GstSignalProcessor *gsp;
GstSignalProcessorClass *gsp_class;
gsp = GST_SIGNAL_PROCESSOR (object);
gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (object);
/* remember, properties have an offset of 1 */
prop_id--;
/* only input ports */
g_return_if_fail (prop_id < gsp_class->num_control_in);
/* now see what type it is */
switch (pspec->value_type) {
case G_TYPE_BOOLEAN:
gsp->control_in[prop_id] = g_value_get_boolean (value) ? 1.f : 0.f;
break;
case G_TYPE_INT:
gsp->control_in[prop_id] = g_value_get_int (value);
break;
case G_TYPE_FLOAT:
gsp->control_in[prop_id] = g_value_get_float (value);
break;
default:
g_assert_not_reached ();
}
}
static void
gst_ladspa_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstSignalProcessor *gsp;
GstSignalProcessorClass *gsp_class;
gfloat *controls;
gsp = GST_SIGNAL_PROCESSOR (object);
gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (object);
/* remember, properties have an offset of 1 */
prop_id--;
if (prop_id < gsp_class->num_control_in) {
controls = gsp->control_in;
} else if (prop_id < gsp_class->num_control_in + gsp_class->num_control_out) {
controls = gsp->control_out;
prop_id -= gsp_class->num_control_in;
} else {
g_assert_not_reached ();
}
/* now see what type it is */
switch (pspec->value_type) {
case G_TYPE_BOOLEAN:
g_value_set_boolean (value, controls[prop_id] > 0.5);
break;
case G_TYPE_INT:
g_value_set_int (value, CLAMP (controls[prop_id], G_MININT, G_MAXINT));
break;
case G_TYPE_FLOAT:
g_value_set_float (value, controls[prop_id]);
break;
default:
g_assert_not_reached ();
}
}
static gboolean
gst_ladspa_setup (GstSignalProcessor * gsp, guint sample_rate)
{
GstLADSPA *ladspa;
GstLADSPAClass *oclass;
GstSignalProcessorClass *gsp_class;
LADSPA_Descriptor *desc;
int i;
gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (gsp);
ladspa = (GstLADSPA *) gsp;
oclass = (GstLADSPAClass *) gsp_class;
desc = ladspa->descriptor;
g_return_val_if_fail (ladspa->handle == NULL, FALSE);
g_return_val_if_fail (ladspa->activated == FALSE, FALSE);
GST_DEBUG_OBJECT (ladspa, "instantiating the plugin at %d Hz", sample_rate);
ladspa->handle = desc->instantiate (desc, sample_rate);
g_return_val_if_fail (ladspa->handle != NULL, FALSE);
/* connect the control ports */
for (i = 0; i < gsp_class->num_control_in; i++)
desc->connect_port (ladspa->handle,
oclass->control_in_portnums[i], &(gsp->control_in[i]));
for (i = 0; i < gsp_class->num_control_out; i++)
desc->connect_port (ladspa->handle,
oclass->control_out_portnums[i], &(gsp->control_out[i]));
return TRUE;
}
static gboolean
gst_ladspa_start (GstSignalProcessor * gsp)
{
GstLADSPA *ladspa;
LADSPA_Descriptor *desc;
ladspa = (GstLADSPA *) gsp;
desc = ladspa->descriptor;
g_return_val_if_fail (ladspa->activated == FALSE, FALSE);
g_return_val_if_fail (ladspa->handle != NULL, FALSE);
GST_DEBUG_OBJECT (ladspa, "activating");
if (desc->activate)
desc->activate (ladspa->handle);
ladspa->activated = TRUE;
return TRUE;
}
static void
gst_ladspa_stop (GstSignalProcessor * gsp)
{
GstLADSPA *ladspa;
LADSPA_Descriptor *desc;
ladspa = (GstLADSPA *) gsp;
desc = ladspa->descriptor;
g_return_if_fail (ladspa->activated == TRUE);
g_return_if_fail (ladspa->handle != NULL);
GST_DEBUG_OBJECT (ladspa, "deactivating");
if (desc->activate)
desc->activate (ladspa->handle);
ladspa->activated = FALSE;
}
static void
gst_ladspa_cleanup (GstSignalProcessor * gsp)
{
GstLADSPA *ladspa;
LADSPA_Descriptor *desc;
ladspa = (GstLADSPA *) gsp;
desc = ladspa->descriptor;
g_return_if_fail (ladspa->activated == FALSE);
g_return_if_fail (ladspa->handle != NULL);
GST_DEBUG_OBJECT (ladspa, "cleaning up");
if (desc->cleanup)
desc->cleanup (ladspa->handle);
ladspa->handle = NULL;
}
static void
gst_ladspa_process (GstSignalProcessor * gsp, guint nframes)
{
GstSignalProcessorClass *gsp_class;
GstLADSPA *ladspa;
GstLADSPAClass *oclass;
LADSPA_Descriptor *desc;
guint i;
gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (gsp);
ladspa = (GstLADSPA *) gsp;
oclass = (GstLADSPAClass *) gsp_class;
desc = ladspa->descriptor;
for (i = 0; i < gsp_class->num_audio_in; i++)
desc->connect_port (ladspa->handle, oclass->audio_in_portnums[i],
gsp->audio_in[i]);
for (i = 0; i < gsp_class->num_audio_out; i++)
desc->connect_port (ladspa->handle, oclass->audio_out_portnums[i],
gsp->audio_out[i]);
desc->run (ladspa->handle, nframes);
}
static void
ladspa_describe_plugin (const char *pcFullFilename,
void *pvPluginHandle, LADSPA_Descriptor_Function pfDescriptorFunction)
{
const LADSPA_Descriptor *desc;
gint i;
GTypeInfo typeinfo = {
sizeof (GstLADSPAClass),
(GBaseInitFunc) gst_ladspa_base_init,
NULL,
(GClassInitFunc) gst_ladspa_class_init,
NULL,
NULL,
sizeof (GstLADSPA),
0,
(GInstanceInitFunc) gst_ladspa_init,
};
GType type;
/* walk through all the plugins in this pluginlibrary */
i = 0;
while ((desc = pfDescriptorFunction (i++))) {
gchar *type_name;
/* construct the type */
type_name = g_strdup_printf ("ladspa-%s", desc->Label);
g_strcanon (type_name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-+", '-');
/* if it's already registered, drop it */
if (g_type_from_name (type_name)) {
g_free (type_name);
continue;
}
/* base-init temp alloc */
g_hash_table_insert (ladspa_descriptors,
GINT_TO_POINTER (0), (gpointer) desc);
/* create the type now */
type =
g_type_register_static (GST_TYPE_SIGNAL_PROCESSOR, type_name, &typeinfo,
0);
if (!gst_element_register (ladspa_plugin, type_name, GST_RANK_NONE, type))
continue;
/* add this plugin to the hash */
g_hash_table_insert (ladspa_descriptors,
GINT_TO_POINTER (type), (gpointer) desc);
}
g_hash_table_remove (ladspa_descriptors, GINT_TO_POINTER (0));
}
static gboolean
plugin_init (GstPlugin * plugin)
{
GST_DEBUG_CATEGORY_INIT (ladspa_debug, "ladspa",
GST_DEBUG_FG_GREEN | GST_DEBUG_BG_BLACK | GST_DEBUG_BOLD, "LADSPA");
ladspa_descriptors = g_hash_table_new (NULL, NULL);
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
ladspa_plugin = plugin;
LADSPAPluginSearch (ladspa_describe_plugin);
return TRUE;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"ladspa",
"All LADSPA plugins",
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

View file

@ -1,76 +0,0 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* gstladspa.h: Header for LADSPA plugin
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_LADSPA_H__
#define __GST_LADSPA_H__
#include <ladspa.h>
#include <gst/gst.h>
#include "gstsignalprocessor.h"
G_BEGIN_DECLS
typedef struct _ladspa_control_info {
gchar *name;
gchar *param_name;
gfloat lowerbound, upperbound;
gfloat def;
gboolean lower,upper,samplerate;
gboolean toggled, logarithmic, integer, writable;
} ladspa_control_info;
typedef struct _GstLADSPA GstLADSPA;
typedef struct _GstLADSPAClass GstLADSPAClass;
struct _GstLADSPA {
GstSignalProcessor parent;
LADSPA_Descriptor *descriptor;
LADSPA_Handle *handle;
gboolean activated;
gboolean inplace_broken;
};
struct _GstLADSPAClass {
GstSignalProcessorClass parent_class;
LADSPA_Descriptor *descriptor;
gint *audio_in_portnums;
gint *audio_out_portnums;
gint *control_in_portnums;
gint *control_out_portnums;
};
G_END_DECLS
#endif /* __GST_LADSPA_H__ */

View file

@ -1,976 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Wim Taymans <wim@fluendo.com>
*
* gstsignalprocessor.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gst/audio/audio.h>
#include "gstsignalprocessor.h"
GST_DEBUG_CATEGORY_STATIC (gst_signal_processor_debug);
#define GST_CAT_DEFAULT gst_signal_processor_debug
static GstStaticCaps template_caps =
GST_STATIC_CAPS (GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS);
#define GST_TYPE_SIGNAL_PROCESSOR_PAD_TEMPLATE \
(gst_signal_processor_pad_template_get_type ())
#define GST_SIGNAL_PROCESSOR_PAD_TEMPLATE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR_PAD_TEMPLATE,\
GstSignalProcessorPadTemplate))
typedef struct _GstSignalProcessorPadTemplate GstSignalProcessorPadTemplate;
typedef GstPadTemplateClass GstSignalProcessorPadTemplateClass;
struct _GstSignalProcessorPadTemplate
{
GstPadTemplate parent;
guint index;
};
static GType
gst_signal_processor_pad_template_get_type (void)
{
static GType type = 0;
if (!type) {
static const GTypeInfo info = {
sizeof (GstSignalProcessorPadTemplateClass), NULL, NULL, NULL, NULL,
NULL, sizeof (GstSignalProcessorPadTemplate), 0, NULL
};
type = g_type_register_static (GST_TYPE_PAD_TEMPLATE,
"GstSignalProcessorPadTemplate", &info, 0);
}
return type;
}
void
gst_signal_processor_class_add_pad_template (GstSignalProcessorClass * klass,
const gchar * name, GstPadDirection direction, guint index)
{
GstPadTemplate *new;
g_return_if_fail (GST_IS_SIGNAL_PROCESSOR_CLASS (klass));
g_return_if_fail (name != NULL);
g_return_if_fail (direction == GST_PAD_SRC || direction == GST_PAD_SINK);
new = g_object_new (gst_signal_processor_pad_template_get_type (),
"name", name, NULL);
GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (name);
GST_PAD_TEMPLATE_DIRECTION (new) = direction;
GST_PAD_TEMPLATE_PRESENCE (new) = GST_PAD_ALWAYS;
GST_PAD_TEMPLATE_CAPS (new) = gst_caps_copy (gst_static_caps_get
(&template_caps));
GST_SIGNAL_PROCESSOR_PAD_TEMPLATE (new)->index = index;
gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass), new);
gst_object_unref (new);
}
#define GST_TYPE_SIGNAL_PROCESSOR_PAD (gst_signal_processor_pad_get_type ())
#define GST_SIGNAL_PROCESSOR_PAD(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR_PAD,\
GstSignalProcessorPad))
typedef struct _GstSignalProcessorPad GstSignalProcessorPad;
typedef GstPadClass GstSignalProcessorPadClass;
struct _GstSignalProcessorPad
{
GstPad parent;
GstBuffer *pen;
guint index;
/* these are only used for sink pads */
guint samples_avail;
gfloat *data;
};
static GType
gst_signal_processor_pad_get_type (void)
{
static GType type = 0;
if (!type) {
static const GTypeInfo info = {
sizeof (GstSignalProcessorPadClass), NULL, NULL, NULL, NULL,
NULL, sizeof (GstSignalProcessorPad), 0, NULL
};
type = g_type_register_static (GST_TYPE_PAD,
"GstSignalProcessorPad", &info, 0);
}
return type;
}
GST_BOILERPLATE (GstSignalProcessor, gst_signal_processor, GstElement,
GST_TYPE_ELEMENT);
static void gst_signal_processor_finalize (GObject * object);
static void gst_signal_processor_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_signal_processor_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean gst_signal_processor_src_activate_pull (GstPad * pad,
gboolean active);
static gboolean gst_signal_processor_sink_activate_push (GstPad * pad,
gboolean active);
static GstStateChangeReturn gst_signal_processor_change_state (GstElement *
element, GstStateChange transition);
static gboolean gst_signal_processor_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_signal_processor_getrange (GstPad * pad,
guint64 offset, guint length, GstBuffer ** buffer);
static GstFlowReturn gst_signal_processor_chain (GstPad * pad,
GstBuffer * buffer);
static gboolean gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps);
static void
gst_signal_processor_base_init (gpointer g_class)
{
GST_DEBUG_CATEGORY_INIT (gst_signal_processor_debug, "gst-dsp", 0,
"signalprocessor element");
}
static void
gst_signal_processor_class_init (GstSignalProcessorClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = G_OBJECT_CLASS (klass);
gstelement_class = GST_ELEMENT_CLASS (klass);
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_signal_processor_finalize);
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_signal_processor_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_signal_processor_get_property);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_signal_processor_change_state);
}
static void
gst_signal_processor_add_pad_from_template (GstSignalProcessor * self,
GstPadTemplate * templ)
{
GstPad *new;
new = g_object_new (GST_TYPE_SIGNAL_PROCESSOR_PAD,
"name", GST_OBJECT_NAME (templ), "direction", templ->direction,
"template", templ, NULL);
GST_SIGNAL_PROCESSOR_PAD (new)->index =
GST_SIGNAL_PROCESSOR_PAD_TEMPLATE (templ)->index;
gst_pad_set_setcaps_function (new,
GST_DEBUG_FUNCPTR (gst_signal_processor_setcaps));
if (templ->direction == GST_PAD_SINK) {
GST_DEBUG ("added new sink pad");
gst_pad_set_event_function (new,
GST_DEBUG_FUNCPTR (gst_signal_processor_event));
gst_pad_set_chain_function (new,
GST_DEBUG_FUNCPTR (gst_signal_processor_chain));
gst_pad_set_activatepush_function (new,
GST_DEBUG_FUNCPTR (gst_signal_processor_sink_activate_push));
} else {
GST_DEBUG ("added new src pad");
gst_pad_set_getrange_function (new,
GST_DEBUG_FUNCPTR (gst_signal_processor_getrange));
gst_pad_set_activatepull_function (new,
GST_DEBUG_FUNCPTR (gst_signal_processor_src_activate_pull));
}
gst_element_add_pad (GST_ELEMENT (self), new);
}
static void
gst_signal_processor_init (GstSignalProcessor * self,
GstSignalProcessorClass * klass)
{
GList *templates;
templates =
gst_element_class_get_pad_template_list (GST_ELEMENT_CLASS (klass));
while (templates) {
GstPadTemplate *templ = GST_PAD_TEMPLATE (templates->data);
gst_signal_processor_add_pad_from_template (self, templ);
templates = templates->next;
}
self->state = GST_SIGNAL_PROCESSOR_STATE_NULL;
self->audio_in = g_new0 (gfloat *, klass->num_audio_in);
self->control_in = g_new0 (gfloat, klass->num_control_in);
self->audio_out = g_new0 (gfloat *, klass->num_audio_out);
self->control_out = g_new0 (gfloat, klass->num_control_out);
/* init */
self->pending_in = klass->num_audio_in;
self->pending_out = 0;
self->sample_rate = 0;
}
static void
gst_signal_processor_finalize (GObject * object)
{
GstSignalProcessor *self = GST_SIGNAL_PROCESSOR (object);
g_free (self->audio_in);
self->audio_in = NULL;
g_free (self->control_in);
self->control_in = NULL;
g_free (self->audio_out);
self->audio_out = NULL;
g_free (self->control_out);
self->control_out = NULL;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gboolean
gst_signal_processor_setup (GstSignalProcessor * self, guint sample_rate)
{
GstSignalProcessorClass *klass;
gboolean ret = TRUE;
klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
GST_INFO_OBJECT (self, "setup()");
g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_NULL, FALSE);
if (klass->setup)
ret = klass->setup (self, sample_rate);
if (!ret)
goto setup_failed;
self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED;
return ret;
setup_failed:
{
GST_INFO_OBJECT (self, "setup() failed at %u Hz", sample_rate);
return ret;
}
}
static gboolean
gst_signal_processor_start (GstSignalProcessor * self)
{
GstSignalProcessorClass *klass;
gboolean ret = TRUE;
klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED,
FALSE);
GST_INFO_OBJECT (self, "start()");
if (klass->start)
ret = klass->start (self);
if (!ret)
goto start_failed;
self->state = GST_SIGNAL_PROCESSOR_STATE_RUNNING;
return ret;
start_failed:
{
GST_INFO_OBJECT (self, "start() failed");
return ret;
}
}
static void
gst_signal_processor_stop (GstSignalProcessor * self)
{
GstSignalProcessorClass *klass;
GstElement *elem;
GList *sinks;
klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
elem = GST_ELEMENT (self);
GST_INFO_OBJECT (self, "stop()");
g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING);
if (klass->stop)
klass->stop (self);
for (sinks = elem->sinkpads; sinks; sinks = sinks->next)
/* force set_caps when going to RUNNING, see note in set_caps */
gst_pad_set_caps (GST_PAD (sinks->data), NULL);
/* should also flush our buffers perhaps? */
self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED;
}
static void
gst_signal_processor_cleanup (GstSignalProcessor * self)
{
GstSignalProcessorClass *klass;
klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
GST_INFO_OBJECT (self, "cleanup()");
g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED);
if (klass->cleanup)
klass->cleanup (self);
self->state = GST_SIGNAL_PROCESSOR_STATE_NULL;
}
static gboolean
gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps)
{
GstSignalProcessor *self;
self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad));
/* the whole processor has one caps; if the sample rate changes, let subclass
implementations know */
if (!gst_caps_is_equal (caps, self->caps)) {
GstStructure *s;
gint sample_rate;
GST_DEBUG_OBJECT (pad, "got caps %" GST_PTR_FORMAT, caps);
s = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (s, "rate", &sample_rate)) {
GST_WARNING ("got no sample-rate");
goto impossible;
}
GST_DEBUG_OBJECT (self, "Got rate=%d", sample_rate);
if (GST_SIGNAL_PROCESSOR_IS_RUNNING (self))
gst_signal_processor_stop (self);
if (GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self))
gst_signal_processor_cleanup (self);
if (!gst_signal_processor_setup (self, sample_rate))
goto start_failed;
self->sample_rate = sample_rate;
gst_caps_replace (&self->caps, caps);
} else {
GST_DEBUG_OBJECT (self, "skipping, have caps already");
}
/* we use this method to manage the processor's state, hence the caps clearing
in stop(). so it can be that we enter here just to manage the processor's
state, to take it to RUNNING from already being INITIALIZED with the right
sample rate (e.g., when having gone PLAYING->READY->PLAYING). make sure
when we leave that the processor is RUNNING. */
if (!GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self)
&& !gst_signal_processor_setup (self, self->sample_rate))
goto start_failed;
if (!GST_SIGNAL_PROCESSOR_IS_RUNNING (self)
&& !gst_signal_processor_start (self))
goto start_failed;
gst_object_unref (self);
return TRUE;
start_failed:
{
gst_object_unref (self);
return FALSE;
}
impossible:
{
g_critical ("something impossible happened");
gst_object_unref (self);
return FALSE;
}
}
static gboolean
gst_signal_processor_event (GstPad * pad, GstEvent * event)
{
GstSignalProcessor *self;
GstSignalProcessorClass *bclass;
gboolean ret;
self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad));
bclass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
/* this probably isn't the correct interface: what about return values, what
about overriding event_default */
if (bclass->event)
bclass->event (self, event);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
break;
case GST_EVENT_FLUSH_STOP:
/* clear errors now */
self->flow_state = GST_FLOW_OK;
break;
default:
break;
}
ret = gst_pad_event_default (pad, event);
gst_object_unref (self);
return ret;
}
static guint
gst_signal_processor_prepare (GstSignalProcessor * self)
{
GstElement *elem = (GstElement *) self;
GstSignalProcessorClass *klass;
GList *sinks, *srcs;
guint samples_avail = G_MAXUINT;
klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
/* first, assign audio_in pointers, and determine the number of samples that
* we can process */
for (sinks = elem->sinkpads; sinks; sinks = sinks->next) {
GstSignalProcessorPad *sinkpad;
sinkpad = (GstSignalProcessorPad *) sinks->data;
g_assert (sinkpad->samples_avail > 0);
samples_avail = MIN (samples_avail, sinkpad->samples_avail);
self->audio_in[sinkpad->index] = sinkpad->data;
}
if (samples_avail == G_MAXUINT) {
/* we don't have any sink pads, just choose a size -- should fix this
* function to have a suggested number of samples in the case of
* gst_pad_pull_range */
samples_avail = 256;
}
/* now assign output buffers. we can avoid allocation by reusing input
buffers, but only if process() can work in place, and if the input buffer
is the exact size of the number of samples we are processing. */
sinks = elem->sinkpads;
srcs = elem->srcpads;
if (GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE (klass)) {
while (sinks && srcs) {
GstSignalProcessorPad *sinkpad, *srcpad;
sinkpad = (GstSignalProcessorPad *) sinks->data;
srcpad = (GstSignalProcessorPad *) srcs->data;
if (GST_BUFFER_SIZE (sinkpad->pen) == samples_avail * sizeof (gfloat)) {
/* reusable, yay */
g_assert (sinkpad->samples_avail == samples_avail);
srcpad->pen = sinkpad->pen;
sinkpad->pen = NULL;
self->audio_out[srcpad->index] = sinkpad->data;
self->pending_out++;
srcs = srcs->next;
}
sinks = sinks->next;
}
}
/* now allocate for any remaining outputs */
while (srcs) {
GstSignalProcessorPad *srcpad;
GstFlowReturn ret;
srcpad = (GstSignalProcessorPad *) srcs->data;
ret =
gst_pad_alloc_buffer_and_set_caps (GST_PAD (srcpad), -1,
samples_avail * sizeof (gfloat), GST_PAD_CAPS (srcpad), &srcpad->pen);
if (ret != GST_FLOW_OK) {
self->flow_state = ret;
return 0;
} else {
self->audio_out[srcpad->index] = (gfloat *) GST_BUFFER_DATA (srcpad->pen);
self->pending_out++;
}
srcs = srcs->next;
}
return samples_avail;
}
static void
gst_signal_processor_update_inputs (GstSignalProcessor * self, guint nprocessed)
{
GstElement *elem = (GstElement *) self;
GList *sinks;
for (sinks = elem->sinkpads; sinks; sinks = sinks->next) {
GstSignalProcessorPad *sinkpad;
sinkpad = (GstSignalProcessorPad *) sinks->data;
g_assert (sinkpad->samples_avail >= nprocessed);
if (sinkpad->pen && sinkpad->samples_avail == nprocessed) {
/* used up this buffer, unpen */
gst_buffer_unref (sinkpad->pen);
sinkpad->pen = NULL;
}
if (!sinkpad->pen) {
/* this buffer was used up */
self->pending_in++;
sinkpad->data = NULL;
sinkpad->samples_avail = 0;
} else {
/* advance ->data pointers and decrement ->samples_avail, unreffing buffer
if no samples are left */
sinkpad->samples_avail -= nprocessed;
sinkpad->data += nprocessed; /* gfloat* arithmetic */
}
}
}
static void
gst_signal_processor_process (GstSignalProcessor * self)
{
GstElement *elem;
GstSignalProcessorClass *klass;
guint nframes;
g_return_if_fail (self->pending_in == 0);
g_return_if_fail (self->pending_out == 0);
elem = GST_ELEMENT (self);
nframes = gst_signal_processor_prepare (self);
if (G_UNLIKELY (nframes == 0))
goto flow_error;
klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
GST_LOG_OBJECT (self, "process(%u)", nframes);
klass->process (self, nframes);
gst_signal_processor_update_inputs (self, nframes);
return;
flow_error:
{
GST_WARNING ("gst_pad_alloc_buffer_and_set_caps() returned %d",
self->flow_state);
return;
}
}
static void
gst_signal_processor_pen_buffer (GstSignalProcessor * self, GstPad * pad,
GstBuffer * buffer)
{
GstSignalProcessorPad *spad = (GstSignalProcessorPad *) pad;
if (spad->pen)
goto had_buffer;
/* keep the reference */
spad->pen = buffer;
spad->data = (gfloat *) GST_BUFFER_DATA (buffer);
spad->samples_avail = GST_BUFFER_SIZE (buffer) / sizeof (float);
g_assert (self->pending_in != 0);
self->pending_in--;
return;
/* ERRORS */
had_buffer:
{
GST_WARNING ("Pad %s:%s already has penned buffer",
GST_DEBUG_PAD_NAME (pad));
gst_buffer_unref (buffer);
return;
}
}
static void
gst_signal_processor_flush (GstSignalProcessor * self)
{
GList *pads;
GstSignalProcessorClass *klass;
klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
GST_INFO_OBJECT (self, "flush()");
for (pads = GST_ELEMENT (self)->pads; pads; pads = pads->next) {
GstSignalProcessorPad *spad = (GstSignalProcessorPad *) pads->data;
if (spad->pen) {
gst_buffer_unref (spad->pen);
spad->pen = NULL;
spad->data = NULL;
spad->samples_avail = 0;
}
}
self->pending_out = 0;
self->pending_in = klass->num_audio_in;
}
static void
gst_signal_processor_do_pulls (GstSignalProcessor * self, guint nframes)
{
GList *sinkpads;
/* FIXME: not threadsafe atm */
sinkpads = GST_ELEMENT (self)->sinkpads;
for (; sinkpads; sinkpads = sinkpads->next) {
GstSignalProcessorPad *spad = (GstSignalProcessorPad *) sinkpads->data;
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *buf;
if (spad->pen) {
g_warning ("Unexpectedly full buffer pen for pad %s:%s",
GST_DEBUG_PAD_NAME (spad));
continue;
}
ret = gst_pad_pull_range (GST_PAD (spad), -1, nframes, &buf);
if (ret != GST_FLOW_OK) {
gst_signal_processor_flush (self);
self->flow_state = ret;
return;
} else if (!buf) {
g_critical ("Pull failed to make a buffer!");
self->flow_state = GST_FLOW_ERROR;
return;
} else {
gst_signal_processor_pen_buffer (self, GST_PAD (spad), buf);
}
}
if (self->pending_in != 0) {
g_critical ("Something wierd happened...");
self->flow_state = GST_FLOW_ERROR;
} else {
gst_signal_processor_process (self);
}
}
static GstFlowReturn
gst_signal_processor_getrange (GstPad * pad, guint64 offset,
guint length, GstBuffer ** buffer)
{
GstSignalProcessor *self;
GstSignalProcessorPad *spad = (GstSignalProcessorPad *) pad;
GstFlowReturn ret = GST_FLOW_ERROR;
self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad));
if (spad->pen) {
*buffer = spad->pen;
spad->pen = NULL;
g_assert (self->pending_out != 0);
self->pending_out--;
ret = GST_FLOW_OK;
} else {
gst_signal_processor_do_pulls (self, length);
if (!spad->pen) {
/* this is an error condition */
*buffer = NULL;
ret = self->flow_state;
} else {
*buffer = spad->pen;
spad->pen = NULL;
self->pending_out--;
ret = GST_FLOW_OK;
}
}
GST_DEBUG_OBJECT (self, "returns %s", gst_flow_get_name (ret));
gst_object_unref (self);
return ret;
}
static void
gst_signal_processor_do_pushes (GstSignalProcessor * self)
{
GList *srcpads;
/* not threadsafe atm */
srcpads = GST_ELEMENT (self)->srcpads;
for (; srcpads; srcpads = srcpads->next) {
GstSignalProcessorPad *spad = (GstSignalProcessorPad *) srcpads->data;
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *buffer;
if (!spad->pen) {
g_warning ("Unexpectedly empty buffer pen for pad %s:%s",
GST_DEBUG_PAD_NAME (spad));
continue;
}
/* take buffer from pen */
buffer = spad->pen;
spad->pen = NULL;
ret = gst_pad_push (GST_PAD (spad), buffer);
if (ret != GST_FLOW_OK) {
gst_signal_processor_flush (self);
self->flow_state = ret;
return;
} else {
g_assert (self->pending_out > 0);
self->pending_out--;
}
}
if (self->pending_out != 0) {
g_critical ("Something wierd happened...");
self->flow_state = GST_FLOW_ERROR;
}
}
static GstFlowReturn
gst_signal_processor_chain (GstPad * pad, GstBuffer * buffer)
{
GstSignalProcessor *self;
self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad));
gst_signal_processor_pen_buffer (self, pad, buffer);
if (self->pending_in == 0) {
gst_signal_processor_process (self);
gst_signal_processor_do_pushes (self);
}
gst_object_unref (self);
return self->flow_state;
}
static void
gst_signal_processor_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
/* GstSignalProcessor *self = GST_SIGNAL_PROCESSOR (object); */
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_signal_processor_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
/* GstSignalProcessor *self = GST_SIGNAL_PROCESSOR (object); */
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
gst_signal_processor_sink_activate_push (GstPad * pad, gboolean active)
{
gboolean result = TRUE;
GstSignalProcessor *self;
GstSignalProcessorClass *bclass;
self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad));
bclass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
if (active) {
if (self->mode == GST_ACTIVATE_NONE) {
self->mode = GST_ACTIVATE_PUSH;
result = TRUE;
} else if (self->mode == GST_ACTIVATE_PUSH) {
result = TRUE;
} else {
g_warning ("foo");
result = FALSE;
}
} else {
if (self->mode == GST_ACTIVATE_NONE) {
result = TRUE;
} else if (self->mode == GST_ACTIVATE_PUSH) {
self->mode = GST_ACTIVATE_NONE;
result = TRUE;
} else {
g_warning ("foo");
result = FALSE;
}
}
GST_DEBUG_OBJECT (self, "result : %d", result);
gst_object_unref (self);
return result;
}
static gboolean
gst_signal_processor_src_activate_pull (GstPad * pad, gboolean active)
{
gboolean result = TRUE;
GstSignalProcessor *self;
GstSignalProcessorClass *bclass;
self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad));
bclass = GST_SIGNAL_PROCESSOR_GET_CLASS (self);
if (active) {
if (self->mode == GST_ACTIVATE_NONE) {
GList *l;
for (l = GST_ELEMENT (self)->sinkpads; l; l = l->next)
result &= gst_pad_activate_pull (pad, active);
if (result)
self->mode = GST_ACTIVATE_PULL;
} else if (self->mode == GST_ACTIVATE_PULL) {
result = TRUE;
} else {
g_warning ("foo");
result = FALSE;
}
} else {
if (self->mode == GST_ACTIVATE_NONE) {
result = TRUE;
} else if (self->mode == GST_ACTIVATE_PULL) {
GList *l;
for (l = GST_ELEMENT (self)->sinkpads; l; l = l->next)
result &= gst_pad_activate_pull (pad, active);
if (result)
self->mode = GST_ACTIVATE_NONE;
result = TRUE;
} else {
g_warning ("foo");
result = FALSE;
}
}
GST_DEBUG_OBJECT (self, "result : %d", result);
gst_object_unref (self);
return result;
}
static GstStateChangeReturn
gst_signal_processor_change_state (GstElement * element,
GstStateChange transition)
{
GstSignalProcessor *self;
GstStateChangeReturn result;
self = GST_SIGNAL_PROCESSOR (element);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
self->flow_state = GST_FLOW_OK;
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
default:
break;
}
if ((result =
GST_ELEMENT_CLASS (parent_class)->change_state (element,
transition)) == GST_STATE_CHANGE_FAILURE)
goto failure;
switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
if (GST_SIGNAL_PROCESSOR_IS_RUNNING (self))
gst_signal_processor_stop (self);
gst_signal_processor_flush (self);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
if (GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self))
gst_signal_processor_cleanup (self);
break;
default:
break;
}
return result;
/* ERRORS */
failure:
{
GST_DEBUG_OBJECT (element, "parent failed state change");
return result;
}
}

View file

@ -1,122 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2005 Wim Taymans <wim@fluendo.com>
*
* gstsignalprocessor.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_SIGNAL_PROCESSOR_H__
#define __GST_SIGNAL_PROCESSOR_H__
#include <gst/gst.h>
G_BEGIN_DECLS
typedef enum
{
GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE = 1<<0
} GstSignalProcessorClassFlags;
#define GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE(klass) \
(GST_SIGNAL_PROCESSOR_CLASS (klass)->flags & \
GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE)
#define GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE(klass) \
GST_SIGNAL_PROCESSOR_CLASS (klass)->flags |= \
GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE
typedef enum
{
GST_SIGNAL_PROCESSOR_STATE_NULL,
GST_SIGNAL_PROCESSOR_STATE_INITIALIZED,
GST_SIGNAL_PROCESSOR_STATE_RUNNING
} GstSignalProcessorState;
#define GST_TYPE_SIGNAL_PROCESSOR (gst_signal_processor_get_type())
#define GST_SIGNAL_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessor))
#define GST_SIGNAL_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessorClass))
#define GST_SIGNAL_PROCESSOR_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessorClass))
#define GST_IS_SIGNAL_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SIGNAL_PROCESSOR))
#define GST_IS_SIGNAL_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SIGNAL_PROCESSOR))
#define GST_SIGNAL_PROCESSOR_IS_INITIALIZED(obj) \
(GST_SIGNAL_PROCESSOR (obj)->state >= GST_SIGNAL_PROCESSOR_STATE_INITIALIZED)
#define GST_SIGNAL_PROCESSOR_IS_RUNNING(obj) \
(GST_SIGNAL_PROCESSOR (obj)->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING)
typedef struct _GstSignalProcessor GstSignalProcessor;
typedef struct _GstSignalProcessorClass GstSignalProcessorClass;
struct _GstSignalProcessor {
GstElement element;
GstCaps *caps;
guint sample_rate;
GstSignalProcessorState state;
GstFlowReturn flow_state;
GstActivateMode mode;
guint pending_in;
guint pending_out;
gfloat *control_in;
gfloat **audio_in;
gfloat *control_out;
gfloat **audio_out;
};
struct _GstSignalProcessorClass {
GstElementClass parent_class;
/*< public >*/
guint num_control_in;
guint num_audio_in;
guint num_control_out;
guint num_audio_out;
guint flags;
/* virtual methods for subclasses */
gboolean (*setup) (GstSignalProcessor *self, guint sample_rate);
gboolean (*start) (GstSignalProcessor *self);
void (*stop) (GstSignalProcessor *self);
void (*cleanup) (GstSignalProcessor *self);
void (*process) (GstSignalProcessor *self, guint num_frames);
gboolean (*event) (GstSignalProcessor *self, GstEvent *event);
};
GType gst_signal_processor_get_type (void);
void gst_signal_processor_class_add_pad_template (GstSignalProcessorClass *klass,
const gchar *name, GstPadDirection direction, guint index);
G_END_DECLS
#endif /* __GST_SIGNAL_PROCESSOR_H__ */

View file

@ -1,195 +0,0 @@
/* load.c
Free software by Richard W.E. Furse. Do with as you will. No
warranty. */
/*****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
/*****************************************************************************/
#include "ladspa.h"
#include "utils.h"
/*****************************************************************************/
/* This function provides a wrapping of dlopen(). When the filename is
not an absolute path (i.e. does not begin with / character), this
routine will search the LADSPA_PATH for the file. */
static void *
dlopenLADSPA (const char *pcFilename, int iFlag)
{
char *pcBuffer;
const char *pcEnd;
const char *pcLADSPAPath;
const char *pcStart;
int iEndsInSO;
int iNeedSlash;
size_t iFilenameLength;
void *pvResult;
iFilenameLength = strlen (pcFilename);
pvResult = NULL;
if (pcFilename[0] == '/') {
/* The filename is absolute. Assume the user knows what he/she is
doing and simply dlopen() it. */
pvResult = dlopen (pcFilename, iFlag);
if (pvResult != NULL)
return pvResult;
} else {
/* If the filename is not absolute then we wish to check along the
LADSPA_PATH path to see if we can find the file there. We do
NOT call dlopen() directly as this would find plugins on the
LD_LIBRARY_PATH, whereas the LADSPA_PATH is the correct place
to search. */
/* thomasvs: I'm sorry, but I'm going to add glib stuff here.
* I'm appending logical values for LADSPA_PATH here
*/
pcLADSPAPath = g_strdup_printf ("%s:/usr/lib/ladspa:/usr/local/lib/ladspa",
getenv ("LADSPA_PATH"));
if (pcLADSPAPath) {
pcStart = pcLADSPAPath;
while (*pcStart != '\0') {
pcEnd = pcStart;
while (*pcEnd != ':' && *pcEnd != '\0')
pcEnd++;
pcBuffer = malloc (iFilenameLength + 2 + (pcEnd - pcStart));
if (pcEnd > pcStart)
strncpy (pcBuffer, pcStart, pcEnd - pcStart);
iNeedSlash = 0;
if (pcEnd > pcStart)
if (*(pcEnd - 1) != '/') {
iNeedSlash = 1;
pcBuffer[pcEnd - pcStart] = '/';
}
strcpy (pcBuffer + iNeedSlash + (pcEnd - pcStart), pcFilename);
pvResult = dlopen (pcBuffer, iFlag);
free (pcBuffer);
if (pvResult != NULL)
return pvResult;
pcStart = pcEnd;
if (*pcStart == ':')
pcStart++;
}
}
}
/* As a last ditch effort, check if filename does not end with
".so". In this case, add this suffix and recurse. */
iEndsInSO = 0;
if (iFilenameLength > 3)
iEndsInSO = (strcmp (pcFilename + iFilenameLength - 3, ".so") == 0);
if (!iEndsInSO) {
pcBuffer = malloc (iFilenameLength + 4);
strcpy (pcBuffer, pcFilename);
strcat (pcBuffer, ".so");
pvResult = dlopenLADSPA (pcBuffer, iFlag);
free (pcBuffer);
}
if (pvResult != NULL)
return pvResult;
/* If nothing has worked, then at least we can make sure we set the
correct error message - and this should correspond to a call to
dlopen() with the actual filename requested. The dlopen() manual
page does not specify whether the first or last error message
will be kept when multiple calls are made to dlopen(). We've
covered the former case - now we can handle the latter by calling
dlopen() again here. */
return dlopen (pcFilename, iFlag);
}
/*****************************************************************************/
void *
loadLADSPAPluginLibrary (const char *pcPluginFilename)
{
void *pvPluginHandle;
pvPluginHandle = dlopenLADSPA (pcPluginFilename, RTLD_NOW);
if (!pvPluginHandle) {
fprintf (stderr,
"Failed to load plugin \"%s\": %s\n", pcPluginFilename, dlerror ());
exit (1);
}
return pvPluginHandle;
}
/*****************************************************************************/
void
unloadLADSPAPluginLibrary (void *pvLADSPAPluginLibrary)
{
dlclose (pvLADSPAPluginLibrary);
}
/*****************************************************************************/
const LADSPA_Descriptor *
findLADSPAPluginDescriptor (void *pvLADSPAPluginLibrary,
const char *pcPluginLibraryFilename, const char *pcPluginLabel)
{
const LADSPA_Descriptor *psDescriptor;
LADSPA_Descriptor_Function pfDescriptorFunction;
unsigned long lPluginIndex;
dlerror ();
pfDescriptorFunction
= (LADSPA_Descriptor_Function) dlsym (pvLADSPAPluginLibrary,
"ladspa_descriptor");
if (!pfDescriptorFunction) {
const char *pcError = dlerror ();
if (pcError) {
fprintf (stderr,
"Unable to find ladspa_descriptor() function in plugin "
"library file \"%s\": %s.\n"
"Are you sure this is a LADSPA plugin file?\n",
pcPluginLibraryFilename, pcError);
exit (1);
}
}
for (lPluginIndex = 0;; lPluginIndex++) {
psDescriptor = pfDescriptorFunction (lPluginIndex);
if (psDescriptor == NULL) {
fprintf (stderr,
"Unable to find label \"%s\" in plugin library file \"%s\".\n",
pcPluginLabel, pcPluginLibraryFilename);
exit (1);
}
if (strcmp (psDescriptor->Label, pcPluginLabel) == 0)
return psDescriptor;
}
}
/*****************************************************************************/
/* EOF */

View file

@ -1,139 +0,0 @@
/* search.c
Free software by Richard W.E. Furse. Do with as you will. No
warranty. */
/*****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <dirent.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <glib.h>
/*****************************************************************************/
#include "ladspa.h"
#include "utils.h"
/*****************************************************************************/
/* Search just the one directory. */
static void
LADSPADirectoryPluginSearch
(const char *pcDirectory,
LADSPAPluginSearchCallbackFunction fCallbackFunction)
{
char *pcFilename;
DIR *psDirectory;
LADSPA_Descriptor_Function fDescriptorFunction;
long lDirLength;
long iNeedSlash;
struct dirent *psDirectoryEntry;
void *pvPluginHandle;
lDirLength = strlen (pcDirectory);
if (!lDirLength)
return;
if (pcDirectory[lDirLength - 1] == '/')
iNeedSlash = 0;
else
iNeedSlash = 1;
psDirectory = opendir (pcDirectory);
if (!psDirectory)
return;
while (1) {
psDirectoryEntry = readdir (psDirectory);
if (!psDirectoryEntry) {
closedir (psDirectory);
return;
}
pcFilename = malloc (lDirLength + strlen (psDirectoryEntry->d_name)
+ 1 + iNeedSlash);
strcpy (pcFilename, pcDirectory);
if (iNeedSlash)
strcat (pcFilename, "/");
strcat (pcFilename, psDirectoryEntry->d_name);
pvPluginHandle = dlopen (pcFilename, RTLD_LAZY);
if (pvPluginHandle) {
/* This is a file and the file is a shared library! */
dlerror ();
fDescriptorFunction
= (LADSPA_Descriptor_Function) dlsym (pvPluginHandle,
"ladspa_descriptor");
if (dlerror () == NULL && fDescriptorFunction) {
/* We've successfully found a ladspa_descriptor function. Pass
it to the callback function. */
fCallbackFunction (pcFilename, pvPluginHandle, fDescriptorFunction);
} else {
/* It was a library, but not a LADSPA one. Unload it. */
dlclose (pvPluginHandle);
}
}
free (pcFilename);
}
}
/*****************************************************************************/
void
LADSPAPluginSearch (LADSPAPluginSearchCallbackFunction fCallbackFunction)
{
char *pcBuffer;
const char *pcEnd;
const char *pcLADSPAPath;
const char *pcStart;
/* thomasvs: I'm sorry, but I'm going to add glib stuff here.
* I'm appending logical values for LADSPA_PATH here
*/
pcLADSPAPath = g_strdup_printf ("%s:/usr/lib/ladspa:/usr/local/lib/ladspa",
getenv ("LADSPA_PATH"));
if (!pcLADSPAPath) {
/* fprintf(stderr, */
/* "Warning: You do not have a LADSPA_PATH " */
/* "environment variable set.\n"); */
return;
}
pcStart = pcLADSPAPath;
while (*pcStart != '\0') {
pcEnd = pcStart;
while (*pcEnd != ':' && *pcEnd != '\0')
pcEnd++;
pcBuffer = malloc (1 + pcEnd - pcStart);
if (pcEnd > pcStart)
strncpy (pcBuffer, pcStart, pcEnd - pcStart);
pcBuffer[pcEnd - pcStart] = '\0';
LADSPADirectoryPluginSearch (pcBuffer, fCallbackFunction);
free (pcBuffer);
pcStart = pcEnd;
if (*pcStart == ':')
pcStart++;
}
g_free ((gpointer) pcLADSPAPath);
}
/*****************************************************************************/
/* EOF */

View file

@ -1,62 +0,0 @@
/* utils.h
Free software by Richard W.E. Furse. Do with as you will. No
warranty. */
#ifndef LADSPA_SDK_LOAD_PLUGIN_LIB
#define LADSPA_SDK_LOAD_PLUGIN_LIB
/*****************************************************************************/
#include <ladspa.h>
/*****************************************************************************/
/* Functions in load.c: */
/* This function call takes a plugin library filename, searches for
the library along the LADSPA_PATH, loads it with dlopen() and
returns a plugin handle for use with findPluginDescriptor() or
unloadLADSPAPluginLibrary(). Errors are handled by writing a
message to stderr and calling exit(1). It is alright (although
inefficient) to call this more than once for the same file. */
void * loadLADSPAPluginLibrary(const char * pcPluginFilename);
/* This function unloads a LADSPA plugin library. */
void unloadLADSPAPluginLibrary(void * pvLADSPAPluginLibrary);
/* This function locates a LADSPA plugin within a plugin library
loaded with loadLADSPAPluginLibrary(). Errors are handled by
writing a message to stderr and calling exit(1). Note that the
plugin library filename is only included to help provide
informative error messages. */
const LADSPA_Descriptor *
findLADSPAPluginDescriptor(void * pvLADSPAPluginLibrary,
const char * pcPluginLibraryFilename,
const char * pcPluginLabel);
/*****************************************************************************/
/* Functions in search.c: */
/* Callback function for use with LADSPAPluginSearch(). The callback
function passes the filename (full path), a plugin handle (dlopen()
style) and a LADSPA_DescriptorFunction (from which
LADSPA_Descriptors can be acquired). */
typedef void LADSPAPluginSearchCallbackFunction
(const char * pcFullFilename,
void * pvPluginHandle,
LADSPA_Descriptor_Function fDescriptorFunction);
/* Search through the $(LADSPA_PATH) (or a default path) for any
LADSPA plugin libraries. Each plugin library is tested using
dlopen() and dlsym(,"ladspa_descriptor"). After loading each
library, the callback function is called to process it. This
function leaves items passed to the callback function open. */
void LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction);
/*****************************************************************************/
#endif
/* EOF */