diff --git a/Makefile.am b/Makefile.am index 4d74b8a882..099534f71d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS=sys +SUBDIRS=sys ext -DIST_SUBDIRS=sys +DIST_SUBDIRS=sys ext diff --git a/autogen.sh b/autogen.sh index 78c2cac12c..73793c6145 100755 --- a/autogen.sh +++ b/autogen.sh @@ -152,6 +152,21 @@ automake -a -c || { CONFIGURE_OPT='--enable-maintainer-mode --enable-plugin-builddir --enable-debug --enable-DEBUG' +# if enable exists, add an -enable option for each of the lines in that file +if test -f enable; then + for a in `cat enable`; do + CONFIGURE_OPT="$CONFIGURE_OPT --enable-$a" + done +fi + +# if disable exists, add an -disable option for each of the lines in that file +if test -f disable; then + for a in `cat disable`; do + CONFIGURE_OPT="$CONFIGURE_OPT --disable-$a" + done +fi + + echo "+ running configure ... " echo "./configure default flags: $CONFIGURE_OPT" echo "using: $CONFIGURE_OPT $@" diff --git a/configure.ac b/configure.ac index 14386a4bbe..22a88db4c1 100644 --- a/configure.ac +++ b/configure.ac @@ -460,9 +460,9 @@ GST_CHECK_FEATURE(LIBDVDREAD, [dvdread library], libdvdread, [ ]) dnl **** ESound **** -translit(dnm, m, l) AM_CONDITIONAL(USE_LIBESD, true) -GST_CHECK_FEATURE(LIBESD, [esound plugins], esdsrc esdsink, [ - AM_PATH_ESD(0.2.12, HAVE_LIBESD=yes, HAVE_LIBESD=no) +translit(dnm, m, l) AM_CONDITIONAL(USE_ESD, true) +GST_CHECK_FEATURE(ESD, [esound plugins], esdsrc esdsink, [ + AM_PATH_ESD(0.2.12, HAVE_ESD=yes, HAVE_ESD=no) ]) dnl *** FLAC *** @@ -523,10 +523,11 @@ GST_CHECK_FEATURE(LIBJPEG, [libjpeg], jpegenc jpegdec, [ dnl *** mad *** dnl FIXME: we could use header checks here as well IMO -translit(dnm, m, l) AM_CONDITIONAL(USE_LIBMAD, true) -GST_CHECK_FEATURE(LIBMAD, [mad], mad, [ -AC_CHECK_LIB(mad, mad_decoder_finish, HAVE_LIBMAD="yes") +translit(dnm, m, l) AM_CONDITIONAL(USE_MAD, true) +GST_CHECK_FEATURE(MAD, [mad mp3 decoder], mad, [ + AC_CHECK_LIB(mad, mad_decoder_finish, HAVE_MAD="yes" MAD_LIBS="-lmad") ]) +AC_SUBST(MAD_LIBS) dnl *** mikmod *** translit(dnm, m, l) AM_CONDITIONAL(USE_LIBMIKMOD, true) @@ -930,14 +931,6 @@ dnl dnl AC_SUBST(FOMIT_FRAME_POINTER) dnl -if test "x$HAVE_LIBXV" = xyes; then - AC_DEFINE(HAVE_LIBXV) -fi - -if test "x$HAVE_LIBMAD" = xyes; then - AC_DEFINE(HAVE_LIBMAD) -fi - if test "x$HAVE_LIBMIKMOD" = xyes; then AC_DEFINE(HAVE_LIBMIKMOD) fi @@ -1008,9 +1001,6 @@ AM_CONDITIONAL(HAVE_ATOMIC_H, test "x$USE_ATOMIC_H" = "xyes") AM_CONDITIONAL(EXPERIMENTAL, test "$EXPERIMENTAL" = "$xyes") AM_CONDITIONAL(BROKEN, test "$BROKEN" = "$xyes") -AM_CONDITIONAL(HAVE_OSS, test "x$HAVE_OSS" = "xyes") -AM_CONDITIONAL(HAVE_XAUDIO, test "x$HAVE_XAUDIO" = "xyes") -AM_CONDITIONAL(HAVE_LIBMAD, test "x$HAVE_LIBMAD" = "xyes") AM_CONDITIONAL(HAVE_LIBMIKMOD, test "x$HAVE_LIBMIKMOD" = "xyes") AM_CONDITIONAL(HAVE_LINUX_CDROM, test "x$HAVE_LINUX_CDROM" = "xyes") AM_CONDITIONAL(HAVE_LINUX_VIDEODEV, test "x$HAVE_LINUX_VIDEODEV" = "xyes") @@ -1022,7 +1012,6 @@ AM_CONDITIONAL(HAVE_LIBHERMES, test "x$HAVE_LIBHERMES" = "xyes") AM_CONDITIONAL(HAVE_NASM, test "x$HAVE_NASM" = "xyes") AM_CONDITIONAL(HAVE_LIBGLADE_GNOME, test "x$HAVE_LIBGLADE_GNOME" = "xyes") AM_CONDITIONAL(HAVE_GNOME, test "x$HAVE_GNOME" = "xyes") -AM_CONDITIONAL(HAVE_LIBXV, test "x$HAVE_LIBXV" = "xyes") AM_CONDITIONAL(HAVE_GTK, test "x$HAVE_GTK" = "xyes") AM_CONDITIONAL(HAVE_GTK_DOC, $HAVE_GTK_DOC) AM_CONDITIONAL(BUILD_DOCS, test "x$BUILD_DOCS" = "xyes") @@ -1155,6 +1144,10 @@ sys/v4l/Makefile sys/vcd/Makefile sys/vga/Makefile sys/xvideo/Makefile +ext/Makefile +ext/esd/Makefile +ext/mad/Makefile +ext/vorbis/Makefile ) echo -e "configure: *** Plugins that will be built : $GST_PLUGINS_YES" diff --git a/ext/esd/Makefile.am b/ext/esd/Makefile.am new file mode 100644 index 0000000000..0e3e92fb28 --- /dev/null +++ b/ext/esd/Makefile.am @@ -0,0 +1,11 @@ +filterdir = $(libdir)/gst + +filter_LTLIBRARIES = libesdsink.la + +libesdsink_la_SOURCES = esdsink.c +noinst_HEADERS = esdsink.h + +libesdsink_la_CFLAGS = $(ESD_CFLAGS) $(GST_CFLAGS) +libesdsink_la_LIBADD = $(ESD_LIBS) + +EXTRA_DIST = README diff --git a/ext/esd/README b/ext/esd/README new file mode 100644 index 0000000000..27973122db --- /dev/null +++ b/ext/esd/README @@ -0,0 +1,12 @@ +The esdsink plugin +================== + +The esdsink plugin is for outputting an audio atream to an esd soundserver, whether local or on a remote machine + +esdsink has 2 arguments that it accepts: + - 'mute' (boolean value) + - 'depth' (sample depth in bits- defaults to 16) + - 'host' (used only if you want to connect to a remote esd soundserver) + - 'frequency' (integer value in Hz) + - 'channels' (number of channels - 2 for stereo) + diff --git a/ext/esd/esdsink.c b/ext/esd/esdsink.c new file mode 100644 index 0000000000..16a056b7af --- /dev/null +++ b/ext/esd/esdsink.c @@ -0,0 +1,415 @@ +/* Gnome-Streamer + * Copyright (C) <2001> Richard Boulton + * + * Based on example.c: + * Copyright (C) <1999> Erik Walthinsen + * + * 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 "esdsink.h" +#include + +/* elementfactory information */ +static GstElementDetails esdsink_details = { + "Esound audio sink", + "Sink/Esdsink", + "Plays audio to an esound server", + VERSION, + "Richard Boulton ", + "(C) 2001", +}; + +/* Signals and args */ +enum { + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + ARG_MUTE, + ARG_DEPTH, + ARG_CHANNELS, + ARG_RATE, + ARG_HOST, +}; + +GST_PADTEMPLATE_FACTORY (sink_factory, + "sink", /* the name of the pads */ + GST_PAD_SINK, /* type of the pad */ + GST_PAD_ALWAYS, /* ALWAYS/SOMETIMES */ + GST_CAPS_NEW ( + "esdsink_sink8", /* the name of the caps */ + "audio/raw", /* the mime type of the caps */ + /* Properties follow: */ + "format", GST_PROPS_STRING ("int"), + "law", GST_PROPS_INT (0), + "endianness", GST_PROPS_INT (G_BYTE_ORDER), + "width", GST_PROPS_INT (8), + "depth", GST_PROPS_INT (8), + "rate", GST_PROPS_INT_RANGE (8000, 96000), + "channels", GST_PROPS_LIST (GST_PROPS_INT (1), GST_PROPS_INT (2)) + ), + GST_CAPS_NEW ( + "esdsink_sink16", /* the name of the caps */ + "audio/raw", /* the mime type of the caps */ + /* Properties follow: */ + "format", GST_PROPS_STRING ("int"), + "law", GST_PROPS_INT (0), + "endianness", GST_PROPS_INT (G_BYTE_ORDER), + "signed", GST_PROPS_BOOLEAN (TRUE), + "width", GST_PROPS_INT (16), + "depth", GST_PROPS_INT (16), + "rate", GST_PROPS_INT_RANGE (8000, 96000), + "channels", GST_PROPS_LIST (GST_PROPS_INT (1), GST_PROPS_INT (2)) + ) +); + +static void gst_esdsink_class_init (GstEsdsinkClass *klass); +static void gst_esdsink_init (GstEsdsink *esdsink); + +static gboolean gst_esdsink_open_audio (GstEsdsink *sink); +static void gst_esdsink_close_audio (GstEsdsink *sink); +static GstElementStateReturn gst_esdsink_change_state (GstElement *element); +static gboolean gst_esdsink_sync_parms (GstEsdsink *esdsink); +static void gst_esdsink_newcaps (GstPad *pad, GstCaps *caps); + +static void gst_esdsink_chain (GstPad *pad, GstBuffer *buf); + +static void gst_esdsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); +static void gst_esdsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); + +#define GST_TYPE_ESDSINK_DEPTHS (gst_esdsink_depths_get_type()) +static GType +gst_esdsink_depths_get_type (void) +{ + static GType esdsink_depths_type = 0; + static GEnumValue esdsink_depths[] = { + {8, "8", "8 Bits"}, + {16, "16", "16 Bits"}, + {0, NULL, NULL}, + }; + if (!esdsink_depths_type) { + esdsink_depths_type = g_enum_register_static("GstEsdsinkDepths", esdsink_depths); + } + return esdsink_depths_type; +} + +#define GST_TYPE_ESDSINK_CHANNELS (gst_esdsink_channels_get_type()) +static GType +gst_esdsink_channels_get_type (void) +{ + static GType esdsink_channels_type = 0; + static GEnumValue esdsink_channels[] = { + {1, "1", "Mono"}, + {2, "2", "Stereo"}, + {0, NULL, NULL}, + }; + if (!esdsink_channels_type) { + esdsink_channels_type = g_enum_register_static("GstEsdsinkChannels", esdsink_channels); + } + return esdsink_channels_type; +} + + +static GstElementClass *parent_class = NULL; +//static guint gst_esdsink_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_esdsink_get_type (void) +{ + static GType esdsink_type = 0; + + if (!esdsink_type) { + static const GTypeInfo esdsink_info = { + sizeof(GstEsdsinkClass), NULL, + NULL, + (GClassInitFunc)gst_esdsink_class_init, + NULL, + NULL, + sizeof(GstEsdsink), + 0, + (GInstanceInitFunc)gst_esdsink_init, + }; + esdsink_type = g_type_register_static(GST_TYPE_ELEMENT, "GstEsdsink", &esdsink_info, 0); + } + return esdsink_type; +} + +static void +gst_esdsink_class_init (GstEsdsinkClass *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass*)klass; + gstelement_class = (GstElementClass*)klass; + + parent_class = g_type_class_ref(GST_TYPE_ELEMENT); + + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MUTE, + g_param_spec_boolean("mute","mute","mute", + TRUE,G_PARAM_READWRITE)); // CHECKME + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEPTH, + g_param_spec_enum("depth","depth","depth", + GST_TYPE_ESDSINK_DEPTHS,16,G_PARAM_READWRITE)); // CHECKME! + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNELS, + g_param_spec_enum("channels","channels","channels", + GST_TYPE_ESDSINK_CHANNELS,2,G_PARAM_READWRITE)); // CHECKME! + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_RATE, + g_param_spec_int("frequency","frequency","frequency", + G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HOST, + g_param_spec_string("host","host","host", + NULL, G_PARAM_READWRITE)); // CHECKME + + gobject_class->set_property = gst_esdsink_set_property; + gobject_class->get_property = gst_esdsink_get_property; + + gstelement_class->change_state = gst_esdsink_change_state; +} + +static void +gst_esdsink_init(GstEsdsink *esdsink) +{ + esdsink->sinkpad = gst_pad_new_from_template ( + GST_PADTEMPLATE_GET (sink_factory), "sink"); + gst_element_add_pad(GST_ELEMENT(esdsink), esdsink->sinkpad); + gst_pad_set_chain_function(esdsink->sinkpad, GST_DEBUG_FUNCPTR(gst_esdsink_chain)); + gst_pad_set_newcaps_function(esdsink->sinkpad, gst_esdsink_newcaps); + + esdsink->mute = FALSE; + esdsink->fd = -1; + // FIXME: get default from somewhere better than just putting them inline. + esdsink->format = 16; + esdsink->depth = 16; + esdsink->channels = 2; + esdsink->frequency = 44100; + esdsink->host = NULL; +} + +static gboolean +gst_esdsink_sync_parms (GstEsdsink *esdsink) +{ + g_return_val_if_fail (esdsink != NULL, FALSE); + g_return_val_if_fail (GST_IS_ESDSINK (esdsink), FALSE); + + if (esdsink->fd == -1) return TRUE; + + // Need to set fd to use new parameters: only way to do this is to reopen. + gst_esdsink_close_audio (esdsink); + return gst_esdsink_open_audio (esdsink); +} + +static void +gst_esdsink_newcaps (GstPad *pad, GstCaps *caps) +{ + GstEsdsink *esdsink; + + esdsink = GST_ESDSINK (gst_pad_get_parent (pad)); + + esdsink->depth = gst_caps_get_int (caps, "depth"); + esdsink->channels = gst_caps_get_int (caps, "channels"); + esdsink->frequency = gst_caps_get_int (caps, "rate"); + + gst_esdsink_sync_parms (esdsink); +} + +static void +gst_esdsink_chain (GstPad *pad, GstBuffer *buf) +{ + GstEsdsink *esdsink; + + g_return_if_fail(pad != NULL); + g_return_if_fail(GST_IS_PAD(pad)); + g_return_if_fail(buf != NULL); + + esdsink = GST_ESDSINK (gst_pad_get_parent (pad)); + + if (GST_BUFFER_DATA (buf) != NULL) { + if (!esdsink->mute && esdsink->fd >= 0) { + GST_DEBUG (0, "esdsink: fd=%d data=%p size=%d\n", + esdsink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + write (esdsink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + } + } + gst_buffer_unref (buf); +} + +static void +gst_esdsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GstEsdsink *esdsink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_ESDSINK(object)); + esdsink = GST_ESDSINK(object); + + switch (prop_id) { + case ARG_MUTE: + esdsink->mute = g_value_get_boolean (value); + break; + case ARG_DEPTH: + esdsink->depth = g_value_get_enum (value); + gst_esdsink_sync_parms (esdsink); + break; + case ARG_CHANNELS: + esdsink->channels = g_value_get_enum (value); + gst_esdsink_sync_parms (esdsink); + break; + case ARG_RATE: + esdsink->frequency = g_value_get_int (value); + gst_esdsink_sync_parms (esdsink); + break; + case ARG_HOST: + if (esdsink->host != NULL) g_free(esdsink->host); + if (g_value_get_string (value) == NULL) + esdsink->host = NULL; + else + esdsink->host = g_strdup (g_value_get_string (value)); + break; + default: + break; + } +} + +static void +gst_esdsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GstEsdsink *esdsink; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail(GST_IS_ESDSINK(object)); + esdsink = GST_ESDSINK(object); + + switch (prop_id) { + case ARG_MUTE: + g_value_set_boolean (value, esdsink->mute); + break; + case ARG_DEPTH: + g_value_set_enum (value, esdsink->depth); + break; + case ARG_CHANNELS: + g_value_set_enum (value, esdsink->channels); + break; + case ARG_RATE: + g_value_set_int (value, esdsink->frequency); + break; + case ARG_HOST: + g_value_set_string (value, esdsink->host); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +plugin_init (GModule *module, GstPlugin *plugin) +{ + GstElementFactory *factory; + + factory = gst_elementfactory_new("esdsink", GST_TYPE_ESDSINK, + &esdsink_details); + g_return_val_if_fail(factory != NULL, FALSE); + + gst_elementfactory_add_padtemplate(factory, GST_PADTEMPLATE_GET (sink_factory)); + + gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory)); + + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "esdsink", + plugin_init +}; + +static gboolean +gst_esdsink_open_audio (GstEsdsink *sink) +{ + // Name used by esound for this connection. + const char * connname = "GStreamer"; + + // Bitmap describing audio format. + esd_format_t esdformat = ESD_STREAM | ESD_PLAY; + + g_return_val_if_fail (sink->fd == -1, FALSE); + + if (sink->depth == 16) esdformat |= ESD_BITS16; + else if (sink->depth == 8) esdformat |= ESD_BITS8; + else { + GST_DEBUG (0, "esdsink: invalid bit depth (%d)\n", sink->depth); + return FALSE; + } + + if (sink->channels == 2) esdformat |= ESD_STEREO; + else if (sink->channels == 1) esdformat |= ESD_MONO; + else { + GST_DEBUG (0, "esdsink: invalid number of channels (%d)\n", sink->channels); + return FALSE; + } + + GST_DEBUG (0, "esdsink: attempting to open connection to esound server\n"); + sink->fd = esd_play_stream_fallback(esdformat, sink->frequency, sink->host, connname); + if ( sink->fd < 0 ) { + GST_DEBUG (0, "esdsink: can't open connection to esound server\n"); + return FALSE; + } + + GST_FLAG_SET (sink, GST_ESDSINK_OPEN); + + return TRUE; +} + +static void +gst_esdsink_close_audio (GstEsdsink *sink) +{ + if (sink->fd < 0) return; + + close(sink->fd); + sink->fd = -1; + + GST_FLAG_UNSET (sink, GST_ESDSINK_OPEN); + + GST_DEBUG (0, "esdsink: closed sound device\n"); +} + +static GstElementStateReturn +gst_esdsink_change_state (GstElement *element) +{ + g_return_val_if_fail (GST_IS_ESDSINK (element), FALSE); + + /* if going down into NULL state, close the fd if it's open */ + if (GST_STATE_PENDING (element) == GST_STATE_NULL) { + if (GST_FLAG_IS_SET (element, GST_ESDSINK_OPEN)) + gst_esdsink_close_audio (GST_ESDSINK (element)); + /* otherwise (READY or higher) we need to open the fd */ + } else { + if (!GST_FLAG_IS_SET (element, GST_ESDSINK_OPEN)) { + if (!gst_esdsink_open_audio (GST_ESDSINK (element))) + return GST_STATE_FAILURE; + } + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + return GST_STATE_SUCCESS; +} + diff --git a/ext/esd/esdsink.h b/ext/esd/esdsink.h new file mode 100644 index 0000000000..c3957d72b2 --- /dev/null +++ b/ext/esd/esdsink.h @@ -0,0 +1,76 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * 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_ESDSINK_H__ +#define __GST_ESDSINK_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_ESDSINK \ + (gst_esdsink_get_type()) +#define GST_ESDSINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ESDSINK,GstEsdsink)) +#define GST_ESDSINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ESDSINK,GstEsdsink)) +#define GST_IS_ESDSINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ESDSINK)) +#define GST_IS_ESDSINK_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ESDSINK)) + +typedef enum { + GST_ESDSINK_OPEN = GST_ELEMENT_FLAG_LAST, + GST_ESDSINK_FLAG_LAST = GST_ELEMENT_FLAG_LAST+2, +} GstEsdSinkFlags; + +typedef struct _GstEsdsink GstEsdsink; +typedef struct _GstEsdsinkClass GstEsdsinkClass; + +struct _GstEsdsink { + GstElement element; + + GstPad *sinkpad; + + gboolean mute; + int fd; + gint format; + gint depth; + gint channels; + gint frequency; + gchar* host; +}; + +struct _GstEsdsinkClass { + GstElementClass parent_class; +}; + +GType gst_esdsink_get_type(void); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_ESDSINK_H__ */