summaryrefslogtreecommitdiffstats
path: root/sys/oss
diff options
context:
space:
mode:
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>2003-09-13 01:22:59 +0000
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>2003-09-13 01:22:59 +0000
commit96fc83aeacef995433db8ee4794227d9b3d2ca6b (patch)
treebba38e3589d56522ac6ab4b9edc37d20837f76d2 /sys/oss
parentadda650f237852748a9f1070b7923f0df194c3d6 (diff)
Interface implementation example: OSS mixer. Also osscommon->osselement so it can be loaded without being a source/si...
Original commit message from CVS: Interface implementation example: OSS mixer. Also osscommon->osselement so it can be loaded without being a source/sink (for a stand-alone mixer)
Diffstat (limited to 'sys/oss')
-rw-r--r--sys/oss/Makefile.am16
-rw-r--r--sys/oss/gstossaudio.c21
-rw-r--r--sys/oss/gstosselement.c681
-rw-r--r--sys/oss/gstosselement.h113
-rw-r--r--sys/oss/gstossmixer.c323
-rw-r--r--sys/oss/gstossmixer.h45
-rw-r--r--sys/oss/gstosssink.c102
-rw-r--r--sys/oss/gstosssink.h7
-rw-r--r--sys/oss/gstosssrc.c108
-rw-r--r--sys/oss/gstosssrc.h6
10 files changed, 1249 insertions, 173 deletions
diff --git a/sys/oss/Makefile.am b/sys/oss/Makefile.am
index 37b0f8fe..21d957b5 100644
--- a/sys/oss/Makefile.am
+++ b/sys/oss/Makefile.am
@@ -3,11 +3,12 @@ plugin_LTLIBRARIES = libgstossaudio.la
EXTRA_LTLIBRARIES = libgstosshelper.la
-libgstossaudio_la_SOURCES = gstosssink.c \
+libgstossaudio_la_SOURCES = gstossaudio.c \
+ gstosselement.c \
+ gstossmixer.c \
+ gstosssink.c \
gstosssrc.c \
- gstossaudio.c \
- gstossgst.c \
- gstosscommon.c
+ gstossgst.c
libgstossaudio_la_CFLAGS = $(GST_CFLAGS)
libgstossaudio_la_LIBADD =
@@ -16,4 +17,9 @@ libgstossaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstosshelper_la_SOURCES = gstosshelper.c
libgstosshelper_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-noinst_HEADERS = gstosssink.h gstosssrc.h gstossgst.h gstosshelper.h gstosscommon.h
+noinst_HEADERS = gstosssink.h \
+ gstosssrc.h \
+ gstossgst.h \
+ gstosshelper.h \
+ gstosselement.h \
+ gstossmixer.c
diff --git a/sys/oss/gstossaudio.c b/sys/oss/gstossaudio.c
index e1d54c3a..8c9421a7 100644
--- a/sys/oss/gstossaudio.c
+++ b/sys/oss/gstossaudio.c
@@ -17,7 +17,11 @@
* Boston, MA 02111-1307, USA.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "gstosselement.h"
#include "gstosssink.h"
#include "gstosssrc.h"
#include "gstossgst.h"
@@ -25,19 +29,16 @@
static gboolean
plugin_init (GModule *module, GstPlugin *plugin)
{
- gboolean ret;
-
if (!gst_library_load ("gstaudio"))
return FALSE;
- ret = gst_osssink_factory_init (plugin);
- g_return_val_if_fail (ret == TRUE, FALSE);
-
- ret = gst_osssrc_factory_init (plugin);
- g_return_val_if_fail (ret == TRUE, FALSE);
-
- ret = gst_ossgst_factory_init (plugin);
- g_return_val_if_fail (ret == TRUE, FALSE);
+ if (!gst_osselement_factory_init (plugin) ||
+ !gst_osssrc_factory_init (plugin) ||
+ !gst_osssink_factory_init (plugin) ||
+ !gst_ossgst_factory_init (plugin)) {
+ g_warning ("Failed to register OSS elements!");
+ return FALSE;
+ }
return TRUE;
}
diff --git a/sys/oss/gstosselement.c b/sys/oss/gstosselement.c
new file mode 100644
index 00000000..f4379986
--- /dev/null
+++ b/sys/oss/gstosselement.c
@@ -0,0 +1,681 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstosssink.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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/soundcard.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "gstosselement.h"
+#include "gstossmixer.h"
+
+enum {
+ ARG_0,
+ ARG_DEVICE,
+ ARG_MIXERDEV,
+};
+
+/* elementfactory information */
+static GstElementDetails gst_osselement_details = {
+ "Audio Element (OSS)",
+ "Generic/Audio",
+ "LGPL",
+ "Generic OSS element",
+ VERSION,
+ "Erik Walthinsen <omega@cse.ogi.edu>",
+ "(C) 1999",
+};
+
+static void gst_osselement_class_init (GstOssElementClass *klass);
+static void gst_osselement_init (GstOssElement *oss);
+static void gst_osselement_dispose (GObject *object);
+
+static void gst_osselement_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gst_osselement_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static GstElementStateReturn gst_osselement_change_state (GstElement *element);
+
+static GstElementClass *parent_class = NULL;
+/*static guint gst_osssrc_signals[LAST_SIGNAL] = { 0 }; */
+
+GType
+gst_osselement_get_type (void)
+{
+ static GType osselement_type = 0;
+
+ if (!osselement_type) {
+ static const GTypeInfo osselement_info = {
+ sizeof(GstOssElementClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)gst_osselement_class_init,
+ NULL,
+ NULL,
+ sizeof(GstOssElement),
+ 0,
+ (GInstanceInitFunc)gst_osselement_init,
+ };
+ static const GInterfaceInfo ossiface_info = {
+ (GInterfaceInitFunc) gst_oss_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo ossmixer_info = {
+ (GInterfaceInitFunc) gst_ossmixer_interface_init,
+ NULL,
+ NULL,
+ };
+
+ osselement_type = g_type_register_static (GST_TYPE_ELEMENT,
+ "GstOssElement",
+ &osselement_info, 0);
+ g_type_add_interface_static (osselement_type,
+ GST_TYPE_INTERFACE,
+ &ossiface_info);
+ g_type_add_interface_static (osselement_type,
+ GST_TYPE_MIXER,
+ &ossmixer_info);
+ }
+
+ return osselement_type;
+}
+
+static void
+gst_osselement_class_init (GstOssElementClass *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_DEVICE,
+ g_param_spec_string ("device", "device", "oss device (/dev/dspN usually)",
+ "default", G_PARAM_READWRITE));
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MIXERDEV,
+ g_param_spec_string ("mixerdev", "mixer device",
+ "oss mixer device (/dev/mixerN usually)",
+ "default", G_PARAM_READWRITE));
+
+ gobject_class->set_property = gst_osselement_set_property;
+ gobject_class->get_property = gst_osselement_get_property;
+ gobject_class->dispose = gst_osselement_dispose;
+
+ gstelement_class->change_state = gst_osselement_change_state;
+}
+
+static void
+gst_osselement_init (GstOssElement *oss)
+{
+ oss->device = g_strdup ("/dev/dsp");
+ oss->mixer_dev = g_strdup ("/dev/mixer");
+ oss->fd = -1;
+ oss->mixer_fd = -1;
+ oss->channellist = NULL;
+
+ gst_osselement_reset (oss);
+}
+
+static void
+gst_osselement_dispose (GObject *object)
+{
+ GstOssElement *oss = (GstOssElement *) object;
+
+ g_free (oss->device);
+ g_free (oss->mixer_dev);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+void
+gst_osselement_reset (GstOssElement *oss)
+{
+ oss->law = 0;
+ oss->endianness = G_BYTE_ORDER;
+ oss->sign = TRUE;
+ oss->width = 16;
+ oss->depth = 16;
+ oss->channels = 2;
+ oss->rate = 44100;
+ oss->fragment = 6;
+ oss->bps = 0;
+
+/* AFMT_*_BE not available on all OSS includes (e.g. FBSD) */
+#ifdef WORDS_BIGENDIAN
+ oss->format = AFMT_S16_BE;
+#else
+ oss->format = AFMT_S16_LE;
+#endif /* WORDS_BIGENDIAN */
+}
+
+static gboolean
+gst_ossformat_get (gint law, gint endianness, gboolean sign, gint width, gint depth,
+ gint *format, gint *bps)
+{
+ if (width != depth)
+ return FALSE;
+
+ *bps = 1;
+
+ if (law == 0) {
+ if (width == 16) {
+ if (sign == TRUE) {
+ if (endianness == G_LITTLE_ENDIAN) {
+ *format = AFMT_S16_LE;
+ GST_DEBUG (
+ "16 bit signed LE, no law (%d)", *format);
+ }
+ else if (endianness == G_BIG_ENDIAN) {
+ *format = AFMT_S16_BE;
+ GST_DEBUG (
+ "16 bit signed BE, no law (%d)", *format);
+ }
+ }
+ else {
+ if (endianness == G_LITTLE_ENDIAN) {
+ *format = AFMT_U16_LE;
+ GST_DEBUG (
+ "16 bit unsigned LE, no law (%d)", *format);
+ }
+ else if (endianness == G_BIG_ENDIAN) {
+ *format = AFMT_U16_BE;
+ GST_DEBUG (
+ "16 bit unsigned BE, no law (%d)", *format);
+ }
+ }
+ *bps = 2;
+ }
+ else if (width == 8) {
+ if (sign == TRUE) {
+ *format = AFMT_S8;
+ GST_DEBUG (
+ "8 bit signed, no law (%d)", *format);
+ }
+ else {
+ *format = AFMT_U8;
+ GST_DEBUG (
+ "8 bit unsigned, no law (%d)", *format);
+ }
+ *bps = 1;
+ }
+ } else if (law == 1) {
+ *format = AFMT_MU_LAW;
+ GST_DEBUG (
+ "mu law (%d)", *format);
+ } else if (law == 2) {
+ *format = AFMT_A_LAW;
+ GST_DEBUG (
+ "a law (%d)", *format);
+ } else {
+ g_critical ("unknown law");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+gst_osselement_parse_caps (GstOssElement *oss, GstCaps *caps)
+{
+ gint bps, format;
+
+ gst_caps_get_int (caps, "width", &oss->width);
+ gst_caps_get_int (caps, "depth", &oss->depth);
+
+ if (oss->width != oss->depth)
+ return FALSE;
+
+ gst_caps_get_int (caps, "law", &oss->law);
+ gst_caps_get_int (caps, "endianness", &oss->endianness);
+ gst_caps_get_boolean (caps, "signed", &oss->sign);
+
+ if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign,
+ oss->width, oss->depth, &format, &bps))
+ {
+ GST_DEBUG ("could not get format");
+ return FALSE;
+ }
+
+ gst_caps_get_int (caps, "channels", &oss->channels);
+ gst_caps_get_int (caps, "rate", &oss->rate);
+
+ oss->bps = bps * oss->channels * oss->rate;
+ oss->format = format;
+
+ return TRUE;
+}
+
+#define GET_FIXED_INT(caps, name, dest) \
+G_STMT_START { \
+ if (gst_caps_has_fixed_property (caps, name)) \
+ gst_caps_get_int (caps, name, dest); \
+} G_STMT_END
+#define GET_FIXED_BOOLEAN(caps, name, dest) \
+G_STMT_START { \
+ if (gst_caps_has_fixed_property (caps, name)) \
+ gst_caps_get_boolean (caps, name, dest); \
+} G_STMT_END
+
+gboolean
+gst_osselement_merge_fixed_caps (GstOssElement *oss, GstCaps *caps)
+{
+ gint bps, format;
+
+ /* peel off fixed stuff from the caps */
+ GET_FIXED_INT (caps, "law", &oss->law);
+ GET_FIXED_INT (caps, "endianness", &oss->endianness);
+ GET_FIXED_BOOLEAN (caps, "signed", &oss->sign);
+ GET_FIXED_INT (caps, "width", &oss->width);
+ GET_FIXED_INT (caps, "depth", &oss->depth);
+
+ if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign,
+ oss->width, oss->depth, &format, &bps))
+ {
+ return FALSE;
+ }
+
+ GET_FIXED_INT (caps, "rate", &oss->rate);
+ GET_FIXED_INT (caps, "channels", &oss->channels);
+
+ oss->bps = bps * oss->channels * oss->rate;
+ oss->format = format;
+
+ return TRUE;
+}
+
+gboolean
+gst_osselement_sync_parms (GstOssElement *oss)
+{
+ audio_buf_info space;
+ int frag;
+ gint target_format;
+ gint target_channels;
+ gint target_rate;
+ gint fragscale, frag_ln;
+
+ if (oss->fd == -1)
+ return FALSE;
+
+ if (oss->fragment >> 16)
+ frag = oss->fragment;
+ else
+ frag = 0x7FFF0000 | oss->fragment;
+
+ GST_INFO ("osselement: setting sound card to %dHz %d format %s (%08x fragment)",
+ oss->rate, oss->format,
+ (oss->channels == 2) ? "stereo" : "mono", frag);
+
+ ioctl (oss->fd, SNDCTL_DSP_SETFRAGMENT, &frag);
+ ioctl (oss->fd, SNDCTL_DSP_RESET, 0);
+
+ target_format = oss->format;
+ target_channels = oss->channels;
+ target_rate = oss->rate;
+
+ ioctl (oss->fd, SNDCTL_DSP_SETFMT, &oss->format);
+ ioctl (oss->fd, SNDCTL_DSP_CHANNELS, &oss->channels);
+ ioctl (oss->fd, SNDCTL_DSP_SPEED, &oss->rate);
+
+ ioctl (oss->fd, SNDCTL_DSP_GETBLKSIZE, &oss->fragment_size);
+
+ if (oss->mode == GST_OSSELEMENT_WRITE) {
+ ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &space);
+ }
+ else {
+ ioctl (oss->fd, SNDCTL_DSP_GETISPACE, &space);
+ }
+
+ /* calculate new fragment using a poor man's logarithm function */
+ fragscale = 1;
+ frag_ln = 0;
+ while (fragscale < space.fragsize) {
+ fragscale <<= 1;
+ frag_ln++;
+ }
+ oss->fragment = space.fragstotal << 16 | frag_ln;
+
+ GST_INFO ("osselement: set sound card to %dHz, %d format, %s "
+ "(%d bytes buffer, %08x fragment)",
+ oss->rate, oss->format,
+ (oss->channels == 2) ? "stereo" : "mono",
+ space.bytes, oss->fragment);
+
+ oss->fragment_time = (GST_SECOND * oss->fragment_size) / oss->bps;
+ GST_INFO ("fragment time %u %" G_GUINT64_FORMAT "\n",
+ oss->bps, oss->fragment_time);
+
+ if (target_format != oss->format ||
+ target_channels != oss->channels ||
+ target_rate != oss->rate)
+ {
+ g_warning ("couldn't set requested OSS parameters, enjoy the noise :)");
+ /* we could eventually return FALSE here, or just do some additional tests
+ * to see that the frequencies don't differ too much etc.. */
+ }
+ return TRUE;
+}
+
+static gboolean
+gst_osselement_open_audio (GstOssElement *oss)
+{
+ gint caps;
+ GstOssOpenMode mode = GST_OSSELEMENT_READ;
+ const GList *padlist;
+
+ g_return_val_if_fail (oss->fd == -1, FALSE);
+ GST_INFO ("osselement: attempting to open sound device");
+
+ /* Ok, so how do we open the device? We assume that we have (max.) one
+ * pad, and if this is a sinkpad, we're osssink (w). else, we're osssrc (r) */
+ padlist = gst_element_get_pad_list (GST_ELEMENT (oss));
+ if (padlist != NULL) {
+ GstPad *firstpad = padlist->data;
+ if (GST_PAD_IS_SINK (firstpad)) {
+ mode = GST_OSSELEMENT_WRITE;
+ }
+ }
+
+ /* first try to open the sound card */
+ if (mode == GST_OSSELEMENT_WRITE) {
+ /* open non blocking first so that it returns immediatly with an error
+ * when we cannot get to the device */
+ oss->fd = open (oss->device, O_WRONLY | O_NONBLOCK);
+
+ if (oss->fd >= 0) {
+ close (oss->fd);
+
+ /* re-open the sound device in blocking mode */
+ oss->fd = open (oss->device, O_WRONLY);
+ }
+ }
+ else {
+ oss->fd = open (oss->device, O_RDONLY);
+ }
+
+ if (oss->fd < 0) {
+ switch (errno) {
+ case EBUSY:
+ gst_element_error (GST_ELEMENT (oss),
+ "osselement: Unable to open %s (in use ?)",
+ oss->device);
+ break;
+ case EISDIR:
+ gst_element_error (GST_ELEMENT (oss),
+ "osselement: Device %s is a directory",
+ oss->device);
+ break;
+ case EACCES:
+ case ETXTBSY:
+ gst_element_error (GST_ELEMENT (oss),
+ "osselement: Cannot access %s, check permissions",
+ oss->device);
+ break;
+ case ENXIO:
+ case ENODEV:
+ case ENOENT:
+ gst_element_error (GST_ELEMENT (oss),
+ "osselement: Cannot access %s, does it exist ?",
+ oss->device);
+ break;
+ case EROFS:
+ gst_element_error (GST_ELEMENT (oss),
+ "osselement: Cannot access %s, read-only filesystem ?",
+ oss->device);
+ default:
+ /* FIXME: strerror is not threadsafe */
+ gst_element_error (GST_ELEMENT (oss),
+ "osselement: Cannot open %s, generic error: %s",
+ oss->device, strerror (errno));
+ break;
+ }
+ return FALSE;
+ }
+
+ oss->mode = mode;
+
+ /* we have it, set the default parameters and go have fun */
+ /* set card state */
+ ioctl (oss->fd, SNDCTL_DSP_GETCAPS, &caps);
+
+ GST_INFO ("osselement: Capabilities %08x", caps);
+
+ if (caps & DSP_CAP_DUPLEX) GST_INFO ( "osselement: Full duplex");
+ if (caps & DSP_CAP_REALTIME) GST_INFO ( "osselement: Realtime");
+ if (caps & DSP_CAP_BATCH) GST_INFO ( "osselement: Batch");
+ if (caps & DSP_CAP_COPROC) GST_INFO ( "osselement: Has coprocessor");
+ if (caps & DSP_CAP_TRIGGER) GST_INFO ( "osselement: Trigger");
+ if (caps & DSP_CAP_MMAP) GST_INFO ( "osselement: Direct access");
+
+#ifdef DSP_CAP_MULTI
+ if (caps & DSP_CAP_MULTI) GST_INFO ( "osselement: Multiple open");
+#endif /* DSP_CAP_MULTI */
+
+#ifdef DSP_CAP_BIND
+ if (caps & DSP_CAP_BIND) GST_INFO ( "osselement: Channel binding");
+#endif /* DSP_CAP_BIND */
+
+ ioctl(oss->fd, SNDCTL_DSP_GETFMTS, &caps);
+
+ GST_INFO ( "osselement: Formats %08x", caps);
+ if (caps & AFMT_MU_LAW) GST_INFO ( "osselement: MU_LAW");
+ if (caps & AFMT_A_LAW) GST_INFO ( "osselement: A_LAW");
+ if (caps & AFMT_IMA_ADPCM) GST_INFO ( "osselement: IMA_ADPCM");
+ if (caps & AFMT_U8) GST_INFO ( "osselement: U8");
+ if (caps & AFMT_S16_LE) GST_INFO ( "osselement: S16_LE");
+ if (caps & AFMT_S16_BE) GST_INFO ( "osselement: S16_BE");
+ if (caps & AFMT_S8) GST_INFO ( "osselement: S8");
+ if (caps & AFMT_U16_LE) GST_INFO ( "osselement: U16_LE");
+ if (caps & AFMT_U16_BE) GST_INFO ( "osselement: U16_BE");
+ if (caps & AFMT_MPEG) GST_INFO ( "osselement: MPEG");
+#ifdef AFMT_AC3
+ if (caps & AFMT_AC3) GST_INFO ( "osselement: AC3");
+#endif
+
+ GST_INFO ("osselement: opened audio (%s) with fd=%d",
+ oss->device, oss->fd);
+
+ oss->caps = caps;
+
+ gst_ossmixer_build_list (oss);
+
+ return TRUE;
+}
+
+static void
+gst_osselement_close_audio (GstOssElement *oss)
+{
+ if (oss->fd < 0)
+ return;
+
+ gst_ossmixer_free_list (oss);
+ close(oss->fd);
+ oss->fd = -1;
+}
+
+gboolean
+gst_osselement_convert (GstOssElement *oss,
+ GstFormat src_format,
+ gint64 src_value,
+ GstFormat *dest_format,
+ gint64 *dest_value)
+{
+ gboolean res = TRUE;
+
+ if (src_format == *dest_format) {
+ *dest_value = src_value;
+ return TRUE;
+ }
+
+ if (oss->bps == 0 || oss->channels == 0 || oss->width == 0)
+ return FALSE;
+
+ switch (src_format) {
+ case GST_FORMAT_BYTES:
+ switch (*dest_format) {
+ case GST_FORMAT_TIME:
+ *dest_value = src_value * GST_SECOND / oss->bps;
+ break;
+ case GST_FORMAT_DEFAULT:
+ *dest_value = src_value / (oss->channels * oss->width);
+ break;
+ default:
+ res = FALSE;
+ }
+ break;
+ case GST_FORMAT_TIME:
+ switch (*dest_format) {
+ case GST_FORMAT_BYTES:
+ *dest_value = src_value * oss->bps / GST_SECOND;
+ break;
+ case GST_FORMAT_DEFAULT:
+ *dest_value = src_value * oss->rate / GST_SECOND;
+ break;
+ default:
+ res = FALSE;
+ }
+ break;
+ case GST_FORMAT_DEFAULT:
+ switch (*dest_format) {
+ case GST_FORMAT_TIME:
+ *dest_value = src_value * GST_SECOND / oss->rate;
+ break;
+ case GST_FORMAT_BYTES:
+ *dest_value = src_value * oss->channels * oss->width;
+ break;
+ default:
+ res = FALSE;
+ }
+ break;
+ default:
+ res = FALSE;
+ }
+
+ return res;
+}
+
+static void
+gst_osselement_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GstOssElement *oss = GST_OSSELEMENT (object);
+
+ switch (prop_id) {
+ case ARG_DEVICE:
+ /* disallow changing the device while it is opened
+ get_property("device") should return the right one */
+ if (gst_element_get_state (GST_ELEMENT (oss)) != GST_STATE_NULL) {
+ g_free (oss->device);
+ oss->device = g_strdup (g_value_get_string (value));
+ }
+ break;
+ case ARG_MIXERDEV:
+ /* disallow changing the device while it is opened
+ get_property("mixerdev") should return the right one */
+ if (gst_element_get_state (GST_ELEMENT (oss)) != GST_STATE_NULL) {
+ g_free (oss->mixer_dev);
+ oss->mixer_dev = g_strdup (g_value_get_string (value));
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gst_osselement_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GstOssElement *oss = GST_OSSELEMENT (object);
+
+ switch (prop_id) {
+ case ARG_DEVICE:
+ g_value_set_string (value, oss->device);
+ break;
+ case ARG_MIXERDEV:
+ g_value_set_string (value, oss->mixer_dev);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstElementStateReturn
+gst_osselement_change_state (GstElement *element)
+{
+ GstOssElement *oss = GST_OSSELEMENT (element);
+
+ switch (GST_STATE_TRANSITION (element)) {
+ case GST_STATE_NULL_TO_READY:
+ if (!gst_osselement_open_audio (oss)) {
+ return GST_STATE_FAILURE;
+ }
+ GST_INFO ("osselement: opened sound device");
+ break;
+ case GST_STATE_READY_TO_NULL:
+ gst_osselement_close_audio (oss);
+ gst_osselement_reset (oss);
+ GST_INFO ("osselement: closed sound device");
+ break;
+ default:
+ break;
+ }
+
+ if (GST_ELEMENT_CLASS (parent_class)->change_state)
+ return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+ return GST_STATE_SUCCESS;
+}
+
+gboolean
+gst_osselement_factory_init (GstPlugin *plugin)
+{
+ GstElementFactory *factory;
+
+ factory = gst_element_factory_new ("osselement",
+ GST_TYPE_OSSELEMENT,
+ &gst_osselement_details);
+ g_return_val_if_fail (factory != NULL, FALSE);
+
+ gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+ return TRUE;
+}
diff --git a/sys/oss/gstosselement.h b/sys/oss/gstosselement.h
new file mode 100644
index 00000000..eeae84b0
--- /dev/null
+++ b/sys/oss/gstosselement.h
@@ -0,0 +1,113 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstosselement.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_OSS_ELEMENT_H__
+#define __GST_OSS_ELEMENT_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSSELEMENT \
+ (gst_osselement_get_type())
+#define GST_OSSELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSSELEMENT,GstOssElement))
+#define GST_OSSELEMENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSSELEMENT,GstOssElementClass))
+#define GST_IS_OSSELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSSELEMENT))
+#define GST_IS_OSSELEMENT_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSSELEMENT))
+
+typedef struct _GstOssElement GstOssElement;
+typedef struct _GstOssElementClass GstOssElementClass;
+
+typedef enum {
+ GST_OSSELEMENT_READ,
+ GST_OSSELEMENT_WRITE,
+} GstOssOpenMode;
+
+struct _GstOssElement
+{
+ /* yes, we're a gstelement too */
+ GstElement parent;
+
+ gchar *device,
+ *mixer_dev;
+
+ /* device state */
+ int fd;
+ int caps; /* the capabilities */
+ gint format;
+ gint fragment;
+ guint64 fragment_time;
+ gint fragment_size;
+ GstOssOpenMode mode;
+
+ /* stats */
+ guint bps;
+
+ /* parameters */
+ gint law;
+ gint endianness;
+ gboolean sign;
+ gint width;
+ gint depth;
+ gint channels;
+ gint rate;
+
+ /* mixer stuff */
+ GList *channellist;
+ guint32 stereomask,
+ recdevs,
+ recmask,
+ mixcaps;
+ gint mixer_fd;
+};
+
+struct _GstOssElementClass {
+ GstElementClass klass;
+};
+
+GType gst_osselement_get_type (void);
+
+/* factory register function */
+gboolean gst_osselement_factory_init (GstPlugin *plugin);
+
+/* some useful functions */
+gboolean gst_osselement_parse_caps (GstOssElement *oss,
+ GstCaps *caps);
+gboolean gst_osselement_merge_fixed_caps (GstOssElement *oss,
+ GstCaps *caps);
+
+gboolean gst_osselement_sync_parms (GstOssElement *oss);
+void gst_osselement_reset (GstOssElement *oss);
+
+gboolean gst_osselement_convert (GstOssElement *oss,
+ GstFormat src_format,
+ gint64 src_value,
+ GstFormat *dest_format,
+ gint64 *dest_value);
+
+G_END_DECLS
+
+#endif /* __GST_OSS_ELEMENT_H__ */
diff --git a/sys/oss/gstossmixer.c b/sys/oss/gstossmixer.c
new file mode 100644
index 00000000..50efc2f4
--- /dev/null
+++ b/sys/oss/gstossmixer.c
@@ -0,0 +1,323 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstossmixer.h: mixer interface implementation for OSS
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+
+#include "gstossmixer.h"
+
+#define MASK_BIT_IS_SET(mask, bit) \
+ (mask & (1 << bit))
+
+static gboolean gst_ossmixer_supported (GstInterface *iface);
+
+static const GList * gst_ossmixer_list_channels (GstMixer *ossmixer);
+
+static void gst_ossmixer_set_volume (GstMixer *ossmixer,
+ GstMixerChannel *channel,
+ gint *volumes);
+static void gst_ossmixer_get_volume (GstMixer *ossmixer,
+ GstMixerChannel *channel,
+ gint *volumes);
+
+static void gst_ossmixer_set_record (GstMixer *ossmixer,
+ GstMixerChannel *channel,
+ gboolean record);
+static void gst_ossmixer_set_mute (GstMixer *ossmixer,
+ GstMixerChannel *channel,
+ gboolean mute);
+
+static const gchar *labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
+
+GstMixerChannel *
+gst_ossmixer_channel_new (GstOssElement *oss,
+ gint channel_num,
+ gint max_chans,
+ gint flags)
+{
+ GstMixerChannel *channel = (GstMixerChannel *) g_new (GstOssMixerChannel, 1);
+ gint volumes[2];
+
+ channel->label = g_strdup (labels[channel_num]);
+ channel->num_channels = max_chans;
+ channel->flags = flags;
+ channel->min_volume = 0;
+ channel->max_volume = 100;
+ ((GstOssMixerChannel *) channel)->channel_num = channel_num;
+
+ /* volume */
+ gst_ossmixer_get_volume (GST_MIXER (oss),
+ channel, volumes);
+ if (max_chans == 1) {
+ volumes[1] = 0;
+ }
+ ((GstOssMixerChannel *) channel)->lvol = volumes[0];
+ ((GstOssMixerChannel *) channel)->rvol = volumes[1];
+
+ return channel;
+}
+
+void
+gst_ossmixer_channel_free (GstMixerChannel *channel)
+{
+ g_free (channel->label);
+ g_free (channel);
+}
+
+void
+gst_oss_interface_init (GstInterfaceClass *klass)
+{
+ /* default virtual functions */
+ klass->supported = gst_ossmixer_supported;
+}
+
+void
+gst_ossmixer_interface_init (GstMixerClass *klass)
+{
+ /* default virtual functions */
+ klass->list_channels = gst_ossmixer_list_channels;
+ klass->set_volume = gst_ossmixer_set_volume;
+ klass->get_volume = gst_ossmixer_get_volume;
+ klass->set_mute = gst_ossmixer_set_mute;
+ klass->set_record = gst_ossmixer_set_record;
+}
+
+static gboolean
+gst_ossmixer_supported (GstInterface *iface)
+{
+ return (GST_OSSELEMENT (iface)->mixer_fd != -1);
+}
+
+static const GList *
+gst_ossmixer_list_channels (GstMixer *mixer)
+{
+ GstOssElement *oss = GST_OSSELEMENT (mixer);
+
+ g_return_val_if_fail (oss->mixer_fd != -1, NULL);
+
+ return (const GList *) GST_OSSELEMENT (mixer)->channellist;
+}
+
+static void
+gst_ossmixer_get_volume (GstMixer *mixer,
+ GstMixerChannel *channel,
+ gint *volumes)
+{
+ gint volume;
+ GstOssElement *oss = GST_OSSELEMENT (mixer);
+ GstOssMixerChannel *osschannel = (GstOssMixerChannel *) channel;
+
+ g_return_if_fail (oss->mixer_fd != -1);
+
+ if (channel->flags & GST_MIXER_CHANNEL_MUTE) {
+ volumes[0] = osschannel->lvol;
+ if (channel->num_channels == 2) {
+ volumes[1] = osschannel->rvol;
+ }
+ } else {
+ /* get */
+ if (ioctl(oss->mixer_fd, MIXER_READ (osschannel->channel_num), &volume) < 0) {
+ g_warning("Error getting recording device (%d) volume (0x%x): %s\n",
+ osschannel->channel_num, volume, strerror(errno));
+ volume = 0;
+ }
+
+ osschannel->lvol = volumes[0] = (volume & 0xff);
+ if (channel->num_channels == 2) {
+ osschannel->rvol = volumes[1] = ((volume >> 8) & 0xff);
+ }
+ }
+}
+
+static void
+gst_ossmixer_set_volume (GstMixer *mixer,
+ GstMixerChannel *channel,
+ gint *volumes)
+{
+ gint volume;
+ GstOssElement *oss = GST_OSSELEMENT (mixer);
+ GstOssMixerChannel *osschannel = (GstOssMixerChannel *) channel;
+
+ g_return_if_fail (oss->mixer_fd != -1);
+
+ /* prepare the value for ioctl() */
+ if (!(channel->flags & GST_MIXER_CHANNEL_MUTE)) {
+ volume = (volumes[0] & 0xff);
+ if (channel->num_channels == 2) {
+ volume |= ((volumes[1] & 0xff) << 8);
+ }
+
+ /* set */
+ if (ioctl(oss->mixer_fd, MIXER_WRITE (osschannel->channel_num), &volume) < 0) {
+ g_warning("Error setting recording device (%d) volume (0x%x): %s\n",
+ osschannel->channel_num, volume, strerror(errno));
+ return;
+ }
+ }
+
+ osschannel->lvol = volumes[0];
+ if (channel->num_channels == 2) {
+ osschannel->rvol = volumes[1];
+ }
+}
+
+static void
+gst_ossmixer_set_mute (GstMixer *mixer,
+ GstMixerChannel *channel,
+ gboolean mute)
+{
+ int volume;
+ GstOssElement *oss = GST_OSSELEMENT (mixer);
+ GstOssMixerChannel *osschannel = (GstOssMixerChannel *) channel;
+
+ g_return_if_fail (oss->mixer_fd != -1);
+
+ if (mute) {
+ volume = 0;
+ } else {
+ volume = (osschannel->lvol & 0xff);
+ if (MASK_BIT_IS_SET (oss->stereomask, osschannel->channel_num)) {
+ volume |= ((osschannel->rvol & 0xff) << 8);
+ }
+ }
+
+ if (ioctl(oss->mixer_fd, MIXER_WRITE(osschannel->channel_num), &volume) < 0) {
+ g_warning("Error setting mixer recording device volume (0x%x): %s",
+ volume, strerror(errno));
+ return;
+ }
+
+ if (mute) {
+ channel->flags |= GST_MIXER_CHANNEL_MUTE;
+ } else {
+ channel->flags &= ~GST_MIXER_CHANNEL_MUTE;
+ }
+}
+
+static void
+gst_ossmixer_set_record (GstMixer *mixer,
+ GstMixerChannel *channel,
+ gboolean record)
+{
+ GstOssElement *oss = GST_OSSELEMENT (mixer);
+ GstOssMixerChannel *osschannel = (GstOssMixerChannel *) channel;
+
+ g_return_if_fail (oss->mixer_fd != -1);
+
+ /* if we're exclusive, then we need to unset the current one(s) */
+ if (oss->mixcaps & SOUND_CAP_EXCL_INPUT) {
+ GList *channel;
+ for (channel = oss->channellist; channel != NULL; channel = channel->next) {
+ GstMixerChannel *turn = (GstMixerChannel *) channel->data;
+ turn->flags &= ~GST_MIXER_CHANNEL_RECORD;
+ }
+ oss->recdevs = 0;
+ }
+
+ /* set new record bit, if needed */
+ if (record) {
+ oss->recdevs |= (1 << osschannel->channel_num);
+ } else {
+ oss->recdevs &= ~(1 << osschannel->channel_num);
+ }
+
+ /* set it to the device */
+ if (ioctl(oss->mixer_fd, SOUND_MIXER_WRITE_RECSRC, &oss->recdevs) < 0) {
+ g_warning("Error setting mixer recording devices (0x%x): %s",
+ oss->recdevs, strerror(errno));
+ return;
+ }
+
+ if (record) {
+ channel->flags |= GST_MIXER_CHANNEL_RECORD;
+ } else {
+ channel->flags &= ~GST_MIXER_CHANNEL_RECORD;
+ }
+}
+
+void
+gst_ossmixer_build_list (GstOssElement *oss)
+{
+ gint i, devmask;
+
+ g_return_if_fail (oss->mixer_fd == -1);
+
+ oss->mixer_fd = open (oss->mixer_dev, O_RDWR);
+ if (oss->mixer_fd == -1) {
+ g_warning ("Failed to open mixer device %s, mixing disabled: %s",
+ oss->mixer_dev, strerror (errno));
+ return;
+ }
+
+ /* get masks */
+ ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECMASK, &oss->recmask);
+ ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECSRC, &oss->recdevs);
+ ioctl (oss->mixer_fd, SOUND_MIXER_READ_STEREODEVS, &oss->stereomask);
+ ioctl (oss->mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask);
+ ioctl (oss->mixer_fd, SOUND_MIXER_READ_CAPS, &oss->mixcaps);
+
+ /* build channel list */
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (devmask & (1 << i)) {
+ GstMixerChannel *channel;
+ gboolean input = FALSE, stereo = FALSE, record = FALSE;
+
+ /* channel exists, make up capabilities */
+ if (MASK_BIT_IS_SET (oss->stereomask, i))
+ stereo = TRUE;
+ if (MASK_BIT_IS_SET (oss->recmask, i))
+ input = TRUE;
+ if (MASK_BIT_IS_SET (oss->recdevs, i))
+ record = TRUE;
+
+ /* add channel to list */
+ channel = gst_ossmixer_channel_new (oss, i, stereo ? 2 : 1,
+ (record ? GST_MIXER_CHANNEL_RECORD : 0) |
+ (input ? GST_MIXER_CHANNEL_INPUT :
+ GST_MIXER_CHANNEL_OUTPUT));
+ oss->channellist = g_list_append (oss->channellist, channel);
+ }
+ }
+}
+
+void
+gst_ossmixer_free_list (GstOssElement *oss)
+{
+ g_return_if_fail (oss->mixer_fd != -1);
+
+ g_list_foreach (oss->channellist, (GFunc) gst_ossmixer_channel_free, NULL);
+ g_list_free (oss->channellist);
+ oss->channellist = NULL;
+
+ close (oss->mixer_fd);
+ oss->mixer_fd = -1;
+}
diff --git a/sys/oss/gstossmixer.h b/sys/oss/gstossmixer.h
new file mode 100644
index 00000000..eddb40ac
--- /dev/null
+++ b/sys/oss/gstossmixer.h
@@ -0,0 +1,45 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstossmixer.h: mixer interface implementation for OSS
+ *
+ * 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_OSS_MIXER_H__
+#define __GST_OSS_MIXER_H__
+
+#include <gst/gst.h>
+#include <gst/mixer/mixer.h>
+#include "gstosselement.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GstOssMixerChannel {
+ GstMixerChannel parent;
+ gint lvol, rvol;
+ gint channel_num;
+} GstOssMixerChannel;
+
+void gst_ossmixer_interface_init (GstMixerClass *klass);
+void gst_oss_interface_init (GstInterfaceClass *klass);
+void gst_ossmixer_build_list (GstOssElement *oss);
+void gst_ossmixer_free_list (GstOssElement *oss);
+
+G_END_DECLS
+
+#endif /* __GST_OSS_MIXER_H__ */
diff --git a/sys/oss/gstosssink.c b/sys/oss/gstosssink.c
index 05a0419d..067f69ce 100644
--- a/sys/oss/gstosssink.c
+++ b/sys/oss/gstosssink.c
@@ -45,7 +45,6 @@ static GstElementDetails gst_osssink_details = {
static void gst_osssink_class_init (GstOssSinkClass *klass);
static void gst_osssink_init (GstOssSink *osssink);
static void gst_osssink_dispose (GObject *object);
-static void gst_osssink_finalize (GObject *object);
static GstElementStateReturn gst_osssink_change_state (GstElement *element);
static void gst_osssink_set_clock (GstElement *element, GstClock *clock);
@@ -78,7 +77,6 @@ enum {
enum {
ARG_0,
- ARG_DEVICE,
ARG_MUTE,
ARG_FRAGMENT,
ARG_BUFFER_SIZE,
@@ -132,7 +130,7 @@ gst_osssink_get_type (void)
0,
(GInstanceInitFunc)gst_osssink_init,
};
- osssink_type = g_type_register_static (GST_TYPE_ELEMENT, "GstOssSink", &osssink_info, 0);
+ osssink_type = g_type_register_static (GST_TYPE_OSSELEMENT, "GstOssSink", &osssink_info, 0);
}
return osssink_type;
@@ -163,16 +161,6 @@ gst_osssink_dispose (GObject *object)
}
static void
-gst_osssink_finalize (GObject *object)
-{
- GstOssSink *osssink = (GstOssSink *) object;
-
- g_free (osssink->common.device);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
gst_osssink_class_init (GstOssSinkClass *klass)
{
GObjectClass *gobject_class;
@@ -181,11 +169,8 @@ gst_osssink_class_init (GstOssSinkClass *klass)
gobject_class = (GObjectClass*)klass;
gstelement_class = (GstElementClass*)klass;
- parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+ parent_class = g_type_class_ref(GST_TYPE_OSSELEMENT);
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE,
- g_param_spec_string ("device", "Device", "The device to use for output",
- "/dev/dsp", G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MUTE,
g_param_spec_boolean ("mute", "Mute", "Mute the audio",
FALSE, G_PARAM_READWRITE));
@@ -211,7 +196,6 @@ gst_osssink_class_init (GstOssSinkClass *klass)
gobject_class->set_property = gst_osssink_set_property;
gobject_class->get_property = gst_osssink_get_property;
gobject_class->dispose = gst_osssink_dispose;
- gobject_class->finalize = gst_osssink_finalize;
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_osssink_change_state);
gstelement_class->query = GST_DEBUG_FUNCPTR (gst_osssink_query);
@@ -235,8 +219,6 @@ gst_osssink_init (GstOssSink *osssink)
gst_pad_set_chain_function (osssink->sinkpad, gst_osssink_chain);
- gst_osscommon_init (&osssink->common);
-
osssink->bufsize = 4096;
osssink->chunk_size = 4096;
osssink->resync = FALSE;
@@ -260,10 +242,10 @@ gst_osssink_sinkconnect (GstPad *pad, GstCaps *caps)
if (!GST_CAPS_IS_FIXED (caps))
return GST_PAD_LINK_DELAYED;
- if (!gst_osscommon_parse_caps (&osssink->common, caps))
+ if (!gst_osselement_parse_caps (GST_OSSELEMENT (osssink), caps))
return GST_PAD_LINK_REFUSED;
- if (!gst_osscommon_sync_parms (&osssink->common)) {
+ if (!gst_osselement_sync_parms (GST_OSSELEMENT (osssink))) {
return GST_PAD_LINK_REFUSED;
}
@@ -275,12 +257,12 @@ gst_osssink_get_delay (GstOssSink *osssink)
{
gint delay = 0;
- if (osssink->common.fd == -1)
+ if (GST_OSSELEMENT (osssink)->fd == -1)
return 0;
- if (ioctl (osssink->common.fd, SNDCTL_DSP_GETODELAY, &delay) < 0) {
+ if (ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_GETODELAY, &delay) < 0) {
audio_buf_info info;
- if (ioctl (osssink->common.fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
+ if (ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
delay = 0;
}
else {
@@ -297,7 +279,7 @@ gst_osssink_get_time (GstClock *clock, gpointer data)
gint delay;
GstClockTime res;
- if (!osssink->common.bps)
+ if (!GST_OSSELEMENT (osssink)->bps)
return 0;
delay = gst_osssink_get_delay (osssink);
@@ -308,7 +290,7 @@ gst_osssink_get_time (GstClock *clock, gpointer data)
if (((guint64)delay) > osssink->handled) {
delay = osssink->handled;
}
- res = (osssink->handled - delay) * GST_SECOND / osssink->common.bps;
+ res = (osssink->handled - delay) * GST_SECOND / GST_OSSELEMENT (osssink)->bps;
return res;
}
@@ -347,7 +329,7 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
- ioctl (osssink->common.fd, SNDCTL_DSP_SYNC);
+ ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_SYNC);
gst_audio_clock_set_active (GST_AUDIO_CLOCK (osssink->provided_clock), FALSE);
gst_pad_event_default (pad, event);
return;
@@ -355,7 +337,7 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
{
gint64 value;
- ioctl (osssink->common.fd, SNDCTL_DSP_RESET);
+ ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_RESET);
if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) {
if (!gst_clock_handle_discont (osssink->clock, value))
gst_audio_clock_set_active (GST_AUDIO_CLOCK (osssink->provided_clock), FALSE);
@@ -372,7 +354,7 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
return;
}
- if (!osssink->common.bps) {
+ if (!GST_OSSELEMENT (osssink)->bps) {
gst_buffer_unref (buf);
gst_element_error (GST_ELEMENT (osssink), "capsnego was never performed, unknown data type");
return;
@@ -380,7 +362,7 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
buftime = GST_BUFFER_TIMESTAMP (buf);
- if (osssink->common.fd >= 0) {
+ if (GST_OSSELEMENT (osssink)->fd >= 0) {
if (!osssink->mute) {
guchar *data = GST_BUFFER_DATA (buf);
gint size = GST_BUFFER_SIZE (buf);
@@ -392,7 +374,7 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
GstClockTimeDiff jitter;
delay = gst_osssink_get_delay (osssink);
- queued = delay * GST_SECOND / osssink->common.bps;
+ queued = delay * GST_SECOND / GST_OSSELEMENT (osssink)->bps;
if (osssink->resync && osssink->sync) {
GstClockID id = gst_clock_new_single_shot_id (osssink->clock, buftime - queued);
@@ -415,7 +397,7 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
else {
audio_buf_info ospace;
- ioctl (osssink->common.fd, SNDCTL_DSP_GETOSPACE, &ospace);
+ ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_GETOSPACE, &ospace);
if (ospace.bytes >= size) {
to_write = size;
@@ -423,7 +405,7 @@ gst_osssink_chain (GstPad *pad, GstBuffer *buf)
}
while (to_write > 0) {
- gint done = write (osssink->common.fd, data,
+ gint done = write (GST_OSSELEMENT (osssink)->fd, data,
MIN (to_write, osssink->chunk_size));
if (done == -1) {
@@ -464,8 +446,9 @@ gst_osssink_convert (GstPad *pad, GstFormat src_format, gint64 src_value,
osssink = GST_OSSSINK (gst_pad_get_parent (pad));
- return gst_osscommon_convert (&osssink->common, src_format, src_value,
- dest_format, dest_value);
+ return gst_osselement_convert (GST_OSSELEMENT (osssink),
+ src_format, src_value,
+ dest_format, dest_value);
}
static const GstQueryType*
@@ -528,23 +511,13 @@ gst_osssink_set_property (GObject *object, guint prop_id, const GValue *value, G
osssink = GST_OSSSINK (object);
switch (prop_id) {
- case ARG_DEVICE:
- /* disallow changing the device while it is opened
- get_property("device") should return the right one */
- if (!GST_FLAG_IS_SET (osssink, GST_OSSSINK_OPEN))
- {
- g_free (osssink->common.device);
- osssink->common.device = g_strdup (g_value_get_string (value));
- g_object_notify (object, "device");
- }
- break;
case ARG_MUTE:
osssink->mute = g_value_get_boolean (value);
g_object_notify (G_OBJECT (osssink), "mute");
break;
case ARG_FRAGMENT:
- osssink->common.fragment = g_value_get_int (value);
- gst_osscommon_sync_parms (&osssink->common);
+ GST_OSSELEMENT (osssink)->fragment = g_value_get_int (value);
+ gst_osselement_sync_parms (GST_OSSELEMENT (osssink));
break;
case ARG_BUFFER_SIZE:
osssink->bufsize = g_value_get_uint (value);
@@ -572,14 +545,11 @@ gst_osssink_get_property (GObject *object, guint prop_id, GValue *value, GParamS
osssink = GST_OSSSINK (object);
switch (prop_id) {
- case ARG_DEVICE:
- g_value_set_string (value, osssink->common.device);
- break;
case ARG_MUTE:
g_value_set_boolean (value, osssink->mute);
break;
case ARG_FRAGMENT:
- g_value_set_int (value, osssink->common.fragment);
+ g_value_set_int (value, GST_OSSELEMENT (osssink)->fragment);
break;
case ARG_BUFFER_SIZE:
g_value_set_uint (value, osssink->bufsize);
@@ -604,43 +574,23 @@ gst_osssink_change_state (GstElement *element)
osssink = GST_OSSSINK (element);
switch (GST_STATE_TRANSITION (element)) {
- case GST_STATE_NULL_TO_READY:
- if (!GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) {
- gchar *error;
-
- if (!gst_osscommon_open_audio (&osssink->common, GST_OSSCOMMON_WRITE, &error)) {
- gst_element_error (GST_ELEMENT (osssink), error);
- g_free (error);
- return GST_STATE_FAILURE;
- }
- GST_FLAG_SET (element, GST_OSSSINK_OPEN);
- }
- break;
case GST_STATE_READY_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_PLAYING:
osssink->resync = TRUE;
break;
case GST_STATE_PLAYING_TO_PAUSED:
- {
if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN))
- ioctl (osssink->common.fd, SNDCTL_DSP_RESET, 0);
+ ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_RESET, 0);
gst_audio_clock_set_active (GST_AUDIO_CLOCK (osssink->provided_clock), FALSE);
osssink->resync = TRUE;
break;
- }
case GST_STATE_PAUSED_TO_READY:
if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN))
- ioctl (osssink->common.fd, SNDCTL_DSP_RESET, 0);
- gst_osscommon_reset (&osssink->common);
+ ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_RESET, 0);
+ gst_osselement_reset (GST_OSSELEMENT (osssink));
break;
- case GST_STATE_READY_TO_NULL:
- if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN)) {
- gst_osscommon_close_audio (&osssink->common);
- GST_FLAG_UNSET (osssink, GST_OSSSINK_OPEN);
-
- GST_INFO ( "osssink: closed sound device");
- }
+ default:
break;
}
diff --git a/sys/oss/gstosssink.h b/sys/oss/gstosssink.h
index 7427769d..590ce7f2 100644
--- a/sys/oss/gstosssink.h
+++ b/sys/oss/gstosssink.h
@@ -27,7 +27,7 @@
#include <gst/gst.h>
-#include "gstosscommon.h"
+#include "gstosselement.h"
#include <gst/audio/audioclock.h>
G_BEGIN_DECLS
@@ -53,7 +53,7 @@ typedef struct _GstOssSink GstOssSink;
typedef struct _GstOssSinkClass GstOssSinkClass;
struct _GstOssSink {
- GstElement element;
+ GstOssElement element;
GstPad *sinkpad;
GstBufferPool *sinkpool;
@@ -64,12 +64,9 @@ struct _GstOssSink {
gboolean sync;
guint64 handled;
- GstOssCommon common;
-
gboolean mute;
guint bufsize;
guint chunk_size;
-
};
struct _GstOssSinkClass {
diff --git a/sys/oss/gstosssrc.c b/sys/oss/gstosssrc.c
index 0e41d247..c2ff0025 100644
--- a/sys/oss/gstosssrc.c
+++ b/sys/oss/gstosssrc.c
@@ -33,7 +33,7 @@
#include <string.h>
#include <gstosssrc.h>
-#include <gstosscommon.h>
+#include <gstosselement.h>
#include <gst/audio/audioclock.h>
/* elementfactory information */
@@ -56,7 +56,6 @@ enum {
enum {
ARG_0,
- ARG_DEVICE,
ARG_BUFFERSIZE,
ARG_FRAGMENT,
};
@@ -89,7 +88,6 @@ GST_PAD_TEMPLATE_FACTORY (osssrc_src_factory,
static void gst_osssrc_class_init (GstOssSrcClass *klass);
static void gst_osssrc_init (GstOssSrc *osssrc);
static void gst_osssrc_dispose (GObject *object);
-static void gst_osssrc_finalize (GObject *object);
static GstPadLinkReturn gst_osssrc_srcconnect (GstPad *pad, GstCaps *caps);
static const GstFormat* gst_osssrc_get_formats (GstPad *pad);
@@ -136,7 +134,7 @@ gst_osssrc_get_type (void)
0,
(GInstanceInitFunc)gst_osssrc_init,
};
- osssrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstOssSrc", &osssrc_info, 0);
+ osssrc_type = g_type_register_static (GST_TYPE_OSSELEMENT, "GstOssSrc", &osssrc_info, 0);
}
return osssrc_type;
}
@@ -150,14 +148,11 @@ gst_osssrc_class_init (GstOssSrcClass *klass)
gobject_class = (GObjectClass*)klass;
gstelement_class = (GstElementClass*)klass;
- parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+ parent_class = g_type_class_ref (GST_TYPE_OSSELEMENT);
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFFERSIZE,
g_param_spec_ulong ("buffersize","Buffer Size","The size of the buffers with samples",
0, G_MAXULONG, 0, G_PARAM_READWRITE));
- g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE,
- g_param_spec_string ("device", "device", "oss device (/dev/dspN usually)",
- "default", G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FRAGMENT,
g_param_spec_int ("fragment", "Fragment",
"The fragment as 0xMMMMSSSS (MMMM = total fragments, 2^SSSS = fragment size)",
@@ -166,7 +161,6 @@ gst_osssrc_class_init (GstOssSrcClass *klass)
gobject_class->set_property = gst_osssrc_set_property;
gobject_class->get_property = gst_osssrc_get_property;
gobject_class->dispose = gst_osssrc_dispose;
- gobject_class->finalize = gst_osssrc_finalize;
gstelement_class->change_state = gst_osssrc_change_state;
gstelement_class->send_event = gst_osssrc_send_event;
@@ -192,8 +186,6 @@ gst_osssrc_init (GstOssSrc *osssrc)
gst_element_add_pad (GST_ELEMENT (osssrc), osssrc->srcpad);
- gst_osscommon_init (&osssrc->common);
-
osssrc->buffersize = 4096;
osssrc->curoffset = 0;
@@ -202,6 +194,7 @@ gst_osssrc_init (GstOssSrc *osssrc)
osssrc->clock = NULL;
}
+
static void
gst_osssrc_dispose (GObject *object)
{
@@ -211,16 +204,6 @@ gst_osssrc_dispose (GObject *object)
G_OBJECT_CLASS (parent_class)->dispose (object);
}
-static void
-gst_osssrc_finalize (GObject *object)
-{
- GstOssSrc *osssrc = (GstOssSrc *) object;
-
- g_free (osssrc->common.device);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
static GstPadLinkReturn
gst_osssrc_srcconnect (GstPad *pad, GstCaps *caps)
@@ -232,10 +215,10 @@ gst_osssrc_srcconnect (GstPad *pad, GstCaps *caps)
if (!GST_CAPS_IS_FIXED (caps))
return GST_PAD_LINK_DELAYED;
- if (!gst_osscommon_parse_caps (&src->common, caps))
+ if (!gst_osselement_parse_caps (GST_OSSELEMENT (src), caps))
return GST_PAD_LINK_REFUSED;
- if (!gst_osscommon_sync_parms (&src->common))
+ if (!gst_osselement_sync_parms (GST_OSSELEMENT (src)))
return GST_PAD_LINK_REFUSED;
return GST_PAD_LINK_OK;
@@ -251,10 +234,10 @@ gst_osssrc_negotiate (GstPad *pad)
allowed = gst_pad_get_allowed_caps (pad);
- if (!gst_osscommon_merge_fixed_caps (&src->common, allowed))
+ if (!gst_osselement_merge_fixed_caps (GST_OSSELEMENT (src), allowed))
return FALSE;
- if (!gst_osscommon_sync_parms (&src->common))
+ if (!gst_osselement_sync_parms (GST_OSSELEMENT (src)))
return FALSE;
/* set caps on src pad */
@@ -262,12 +245,12 @@ gst_osssrc_negotiate (GstPad *pad)
GST_CAPS_NEW (
"oss_src",
"audio/x-raw-int",
- "endianness", GST_PROPS_INT (src->common.endianness),
- "signed", GST_PROPS_BOOLEAN (src->common.sign),
- "width", GST_PROPS_INT (src->common.width),
- "depth", GST_PROPS_INT (src->common.depth),
- "rate", GST_PROPS_INT (src->common.rate),
- "channels", GST_PROPS_INT (src->common.channels)
+ "endianness", GST_PROPS_INT (GST_OSSELEMENT (src)->endianness),
+ "signed", GST_PROPS_BOOLEAN (GST_OSSELEMENT (src)->sign),
+ "width", GST_PROPS_INT (GST_OSSELEMENT (src)->width),
+ "depth", GST_PROPS_INT (GST_OSSELEMENT (src)->depth),
+ "rate", GST_PROPS_INT (GST_OSSELEMENT (src)->rate),
+ "channels", GST_PROPS_INT (GST_OSSELEMENT (src)->channels)
)) <= 0)
{
return FALSE;
@@ -281,13 +264,13 @@ gst_osssrc_get_time (GstClock *clock, gpointer data)
GstOssSrc *osssrc = GST_OSSSRC (data);
audio_buf_info info;
- if (!osssrc->common.bps)
+ if (!GST_OSSELEMENT (osssrc)->bps)
return 0;
- if (ioctl(osssrc->common.fd, SNDCTL_DSP_GETISPACE, &info) < 0)
+ if (ioctl(GST_OSSELEMENT (osssrc)->fd, SNDCTL_DSP_GETISPACE, &info) < 0)
return 0;
- return (osssrc->curoffset + info.bytes) * GST_SECOND / osssrc->common.bps;
+ return (osssrc->curoffset + info.bytes) * GST_SECOND / GST_OSSELEMENT (osssrc)->bps;
}
static GstClock*
@@ -336,13 +319,13 @@ gst_osssrc_get (GstPad *pad)
return GST_BUFFER (gst_event_new (GST_EVENT_INTERRUPT));
}
}
- if (src->common.bps == 0) {
+ if (GST_OSSELEMENT (src)->bps == 0) {
gst_buffer_unref (buf);
gst_element_error (GST_ELEMENT (src), "no format negotiated");
return GST_BUFFER (gst_event_new (GST_EVENT_INTERRUPT));
}
- readbytes = read (src->common.fd,GST_BUFFER_DATA (buf),
+ readbytes = read (GST_OSSELEMENT (src)->fd,GST_BUFFER_DATA (buf),
src->buffersize);
if (readbytes < 0) {
gst_buffer_unref (buf);
@@ -361,7 +344,9 @@ gst_osssrc_get (GstPad *pad)
GST_BUFFER_OFFSET (buf) = src->curoffset;
/* FIXME: we are falsely assuming that we are the master clock here */
- GST_BUFFER_TIMESTAMP (buf) = src->curoffset * GST_SECOND / src->common.bps;
+ GST_BUFFER_TIMESTAMP (buf) = src->curoffset * GST_SECOND / GST_OSSELEMENT (src)->bps;
+ GST_BUFFER_DURATION (buf) = (GST_SECOND * GST_BUFFER_SIZE (buf)) /
+ (GST_OSSELEMENT (src)->bps * GST_OSSELEMENT (src)->rate);
src->curoffset += readbytes;
@@ -382,13 +367,9 @@ gst_osssrc_set_property (GObject *object, guint prop_id, const GValue *value, GP
case ARG_BUFFERSIZE:
src->buffersize = g_value_get_ulong (value);
break;
- case ARG_DEVICE:
- g_free(src->common.device);
- src->common.device = g_strdup (g_value_get_string (value));
- break;
case ARG_FRAGMENT:
- src->common.fragment = g_value_get_int (value);
- gst_osscommon_sync_parms (&src->common);
+ GST_OSSELEMENT (src)->fragment = g_value_get_int (value);
+ gst_osselement_sync_parms (GST_OSSELEMENT (src));
break;
default:
break;
@@ -406,11 +387,8 @@ gst_osssrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSp
case ARG_BUFFERSIZE:
g_value_set_ulong (value, src->buffersize);
break;
- case ARG_DEVICE:
- g_value_set_string (value, src->common.device);
- break;
case ARG_FRAGMENT:
- g_value_set_int (value, src->common.fragment);
+ g_value_set_int (value, GST_OSSELEMENT (src)->fragment);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -426,17 +404,6 @@ gst_osssrc_change_state (GstElement *element)
GST_DEBUG ("osssrc: state change");
switch (GST_STATE_TRANSITION (element)) {
- case GST_STATE_NULL_TO_READY:
- if (!GST_FLAG_IS_SET (element, GST_OSSSRC_OPEN)) {
- gchar *error;
- if (!gst_osscommon_open_audio (&osssrc->common, GST_OSSCOMMON_READ, &error)) {
- gst_element_error (GST_ELEMENT (osssrc), error);
- g_free (error);
- return GST_STATE_FAILURE;
- }
- GST_FLAG_SET (osssrc, GST_OSSSRC_OPEN);
- }
- break;
case GST_STATE_READY_TO_PAUSED:
osssrc->curoffset = 0;
break;
@@ -448,14 +415,9 @@ gst_osssrc_change_state (GstElement *element)
break;
case GST_STATE_PAUSED_TO_READY:
if (GST_FLAG_IS_SET (element, GST_OSSSRC_OPEN))
- ioctl (osssrc->common.fd, SNDCTL_DSP_RESET, 0);
+ ioctl (GST_OSSELEMENT (osssrc)->fd, SNDCTL_DSP_RESET, 0);
break;
- case GST_STATE_READY_TO_NULL:
- if (GST_FLAG_IS_SET (element, GST_OSSSRC_OPEN)) {
- gst_osscommon_close_audio (&osssrc->common);
- GST_FLAG_UNSET (osssrc, GST_OSSSRC_OPEN);
- }
- gst_osscommon_init (&osssrc->common);
+ default:
break;
}
@@ -485,7 +447,7 @@ gst_osssrc_convert (GstPad *pad, GstFormat src_format, gint64 src_value,
osssrc = GST_OSSSRC (gst_pad_get_parent (pad));
- return gst_osscommon_convert (&osssrc->common, src_format, src_value,
+ return gst_osselement_convert (GST_OSSELEMENT (osssrc), src_format, src_value,
dest_format, dest_value);
}
@@ -521,10 +483,10 @@ gst_osssrc_src_event (GstPad *pad, GstEvent *event)
format = GST_FORMAT_BYTES;
/* convert to bytes */
- if (gst_osscommon_convert (&osssrc->common,
- GST_EVENT_SIZE_FORMAT (event),
- GST_EVENT_SIZE_VALUE (event),
- &format, &value))
+ if (gst_osselement_convert (GST_OSSELEMENT (osssrc),
+ GST_EVENT_SIZE_FORMAT (event),
+ GST_EVENT_SIZE_VALUE (event),
+ &format, &value))
{
osssrc->buffersize = GST_EVENT_SIZE_VALUE (event);
g_object_notify (G_OBJECT (osssrc), "buffersize");
@@ -567,9 +529,9 @@ gst_osssrc_src_query (GstPad *pad, GstQueryType type, GstFormat *format, gint64
switch (type) {
case GST_QUERY_POSITION:
- res = gst_osscommon_convert (&osssrc->common,
- GST_FORMAT_BYTES, osssrc->curoffset,
- format, value);
+ res = gst_osselement_convert (GST_OSSELEMENT (osssrc),
+ GST_FORMAT_BYTES, osssrc->curoffset,
+ format, value);
break;
default:
break;
diff --git a/sys/oss/gstosssrc.h b/sys/oss/gstosssrc.h
index befbaf93..dff5aef5 100644
--- a/sys/oss/gstosssrc.h
+++ b/sys/oss/gstosssrc.h
@@ -26,7 +26,7 @@
#include <gst/gst.h>
-#include "gstosscommon.h"
+#include "gstosselement.h"
G_BEGIN_DECLS
@@ -51,13 +51,11 @@ typedef struct _GstOssSrc GstOssSrc;
typedef struct _GstOssSrcClass GstOssSrcClass;
struct _GstOssSrc {
- GstElement element;
+ GstOssElement element;
/* pads */
GstPad *srcpad;
- GstOssCommon common;
-
gboolean need_eos; /* Do we need to emit an EOS? */
/* blocking */