sys/oss/: Port from THREADED+wim's fixes.
authorAndy Wingo <wingo@pobox.com>
Fri, 8 Jul 2005 11:19:19 +0000 (11:19 +0000)
committerAndy Wingo <wingo@pobox.com>
Fri, 8 Jul 2005 11:19:19 +0000 (11:19 +0000)
Original commit message from CVS:
2005-07-08  Andy Wingo  <wingo@pobox.com>

* sys/oss/: Port from THREADED+wim's fixes.

14 files changed:
ChangeLog
sys/Makefile.am
sys/oss/Makefile.am
sys/oss/gstossaudio.c
sys/oss/gstossdmabuffer.c [new file with mode: 0644]
sys/oss/gstossdmabuffer.h [new file with mode: 0644]
sys/oss/gstosselement.c
sys/oss/gstosselement.h
sys/oss/gstossmixer.c
sys/oss/gstossmixer.h
sys/oss/gstosssink.c
sys/oss/gstosssink.h
sys/oss/gstosssrc.c
sys/oss/oss_probe.c

index 3280377b1df947fdb87ad5188384c88341562078..8ec71251b162dd0e9049acc52b1be5f5f71a7f04 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 2005-07-08  Andy Wingo  <wingo@pobox.com>
 
+       * sys/oss/: Port from THREADED+wim's fixes.
+
        * gst/avi/Makefile.am (libgstavi_la_CFLAGS): No gettext hacks, the
        defines come from config.h.
 
index 3b0016035646662c60625d1224ca21285e55dae1..5406c3130a0fe466c68b6fad8504dad501c401fc 100644 (file)
@@ -4,11 +4,11 @@
 # DXR3_DIR=
 # endif
 
-if USE_OSS
-OSS_DIR=oss
-else
+if USE_OSS
+OSS_DIR=oss
+else
 OSS_DIR=
-endif
+endif
 
 # if USE_OSX_AUDIO
 # OSX_AUDIO_DIR=osxaudio
@@ -34,12 +34,6 @@ OSS_DIR=
 # SUNAUDIO_DIR=
 # endif
 
-# if USE_GST_V4L
-# V4L_DIR=v4l
-# else
-# V4L_DIR=
-# endif
-
 # if USE_GST_V4L2
 # V4L2_DIR=v4l2
 # else
index 69e0144f335835c51b31d8c84aa889123be2451d..3d6f6e7953cd9b0c8fbd3ee08a7ee36e114fc61f 100644 (file)
@@ -1,25 +1,29 @@
 plugin_LTLIBRARIES = libgstossaudio.la
 
 libgstossaudio_la_SOURCES = gstossaudio.c      \
-                           gstosselement.c     \
+                           gstosselement.c     \
+                           gstosshelper.c      \
                            gstossmixer.c       \
-                           gstosssink.c        \
-                           gstosssrc.c
+                           gstosssink.c
 
-libgstossaudio_la_CFLAGS = $(GST_CFLAGS)
-libgstossaudio_la_LIBADD = $(top_builddir)/gst-libs/gst/libgstinterfaces-@GST_MAJORMINOR@.la
-libgstossaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_PLUGINS_BASE_LIBS)
+#                          gstossdmabuffer.c
 
-noinst_HEADERS = gstosssink.h  \
-               gstosssrc.h     \
-               gstosselement.h\
-               gstossmixer.h \
-               gst-i18n-plugin.h \
-               gettext.h
+libgstossaudio_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
+libgstossaudio_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
+                -lgstinterfaces-@GST_MAJORMINOR@ \
+               -lgstaudio-@GST_MAJORMINOR@
+libgstossaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) 
 
-noinst_PROGRAMS = oss_probe
+noinst_HEADERS = gstosssink.h    \
+               gstosssrc.h       \
+               gstosselement.h   \
+                gstosshelper.h   \
+               gstossdmabuffer.h \
+               gstossmixer.h
 
-oss_probe_SOURCES = oss_probe.c
-oss_probe_CFLAGS = $(GST_CFLAGS)
-oss_probe_LDADD = $(GLIB_LIBS)
+# noinst_PROGRAMS = #oss_probe
+
+# oss_probe_SOURCES = oss_probe.c
+# oss_probe_CFLAGS = $(GST_CFLAGS)
+# oss_probe_LDADD = $(GLIB_LIBS)
 
index e5f8ee493f33fe4bf5d2b1957fee8e4cab372a8c..4b5866dfe80abe70e1e85173fea63abd4a325ca1 100644 (file)
@@ -21,7 +21,7 @@
 #include "config.h"
 #endif
 
-#include "gst-i18n-plugin.h"
+#include "gst/gst-i18n-plugin.h"
 
 #include "gstosselement.h"
 #include "gstosssink.h"
@@ -34,13 +34,10 @@ GST_DEBUG_CATEGORY (oss_debug);
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-  if (!gst_library_load ("gstaudio"))
-    return FALSE;
-
-  if (!gst_element_register (plugin, "ossmixer", GST_RANK_PRIMARY,
-          GST_TYPE_OSSELEMENT) ||
-      !gst_element_register (plugin, "osssrc", GST_RANK_PRIMARY,
-          GST_TYPE_OSSSRC) ||
+  if (                          /*!gst_element_register (plugin, "ossmixer", GST_RANK_PRIMARY,
+                                   GST_TYPE_OSSELEMENT) ||
+                                   !gst_element_register (plugin, "osssrc", GST_RANK_PRIMARY,
+                                   GST_TYPE_OSSSRC) || */
       !gst_element_register (plugin, "osssink", GST_RANK_PRIMARY,
           GST_TYPE_OSSSINK)) {
     return FALSE;
diff --git a/sys/oss/gstossdmabuffer.c b/sys/oss/gstossdmabuffer.c
new file mode 100644 (file)
index 0000000..47e06d1
--- /dev/null
@@ -0,0 +1,316 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstossdmabuffer.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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/soundcard.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+
+#include "gstossdmabuffer.h"
+
+static void gst_ossdmabuffer_class_init (GstOssDMABufferClass * klass);
+static void gst_ossdmabuffer_init (GstOssDMABuffer * ossdmabuffer);
+static void gst_ossdmabuffer_dispose (GObject * object);
+static void gst_ossdmabuffer_finalize (GObject * object);
+
+static gboolean gst_ossdmabuffer_acquire (GstRingBuffer * buf,
+    GstRingBufferSpec * spec);
+static gboolean gst_ossdmabuffer_release (GstRingBuffer * buf);
+static gboolean gst_ossdmabuffer_play (GstRingBuffer * buf);
+static gboolean gst_ossdmabuffer_stop (GstRingBuffer * buf);
+
+static GstRingBufferClass *parent_class = NULL;
+
+GType
+gst_ossdmabuffer_get_type (void)
+{
+  static GType ossdmabuffer_type = 0;
+
+  if (!ossdmabuffer_type) {
+    static const GTypeInfo ossdmabuffer_info = {
+      sizeof (GstOssDMABufferClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gst_ossdmabuffer_class_init,
+      NULL,
+      NULL,
+      sizeof (GstOssDMABuffer),
+      0,
+      (GInstanceInitFunc) gst_ossdmabuffer_init,
+      NULL
+    };
+
+    ossdmabuffer_type =
+        g_type_register_static (GST_TYPE_RINGBUFFER, "GstOssDMABuffer",
+        &ossdmabuffer_info, 0);
+  }
+  return ossdmabuffer_type;
+}
+
+static void
+gst_ossdmabuffer_class_init (GstOssDMABufferClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstObjectClass *gstobject_class;
+  GstRingBufferClass *gstringbuffer_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstobject_class = (GstObjectClass *) klass;
+  gstringbuffer_class = (GstRingBufferClass *) klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_RINGBUFFER);
+
+  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ossdmabuffer_dispose);
+  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ossdmabuffer_finalize);
+
+  gstringbuffer_class->acquire = gst_ossdmabuffer_acquire;
+  gstringbuffer_class->release = gst_ossdmabuffer_release;
+  gstringbuffer_class->play = gst_ossdmabuffer_play;
+  gstringbuffer_class->stop = gst_ossdmabuffer_stop;
+}
+
+static void
+gst_ossdmabuffer_init (GstOssDMABuffer * ossdmabuffer)
+{
+  ossdmabuffer->cond = g_cond_new ();
+  ossdmabuffer->element = g_object_new (GST_TYPE_OSSELEMENT, NULL);
+}
+
+static void
+gst_ossdmabuffer_dispose (GObject * object)
+{
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_ossdmabuffer_finalize (GObject * object)
+{
+  GstOssDMABuffer *obuf = (GstOssDMABuffer *) object;
+
+  g_cond_free (obuf->cond);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_ossdmabuffer_func (GstRingBuffer * buf)
+{
+  fd_set writeset;
+  struct count_info count;
+  GstOssDMABuffer *obuf = (GstOssDMABuffer *) buf;
+
+  GST_LOCK (buf);
+  while (obuf->running) {
+    if (buf->state == GST_RINGBUFFER_STATE_PLAYING) {
+      int segsize;
+
+      GST_UNLOCK (buf);
+
+      segsize = buf->spec.segsize;
+
+      FD_ZERO (&writeset);
+      FD_SET (obuf->fd, &writeset);
+
+      select (obuf->fd + 1, NULL, &writeset, NULL, NULL);
+
+      if (ioctl (obuf->fd, SNDCTL_DSP_GETOPTR, &count) == -1) {
+        perror ("GETOPTR");
+        continue;
+      }
+
+      if (count.blocks > buf->spec.segtotal)
+        count.blocks = buf->spec.segtotal;
+
+      gst_ringbuffer_callback (buf, count.blocks);
+
+      GST_LOCK (buf);
+    } else {
+      GST_OSSDMABUFFER_SIGNAL (obuf);
+      GST_OSSDMABUFFER_WAIT (obuf);
+    }
+  }
+  GST_UNLOCK (buf);
+}
+
+static gboolean
+gst_ossdmabuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
+{
+  int tmp;
+  struct audio_buf_info info;
+  GstOssDMABuffer *obuf = (GstOssDMABuffer *) buf;;
+  caddr_t mmap_buf;
+  int mode;
+  gint size;
+  gboolean parsed;
+
+  parsed = gst_osselement_parse_caps (obuf->element, spec->caps);
+  if (!parsed)
+    return FALSE;
+
+  mode = O_RDWR;
+  mode |= O_NONBLOCK;
+
+  obuf->fd = open ("/dev/dsp", mode, 0);
+  if (obuf->fd == -1) {
+    perror ("OPEN");
+    return FALSE;
+  }
+  //obuf->frag = 0x00040008;
+  obuf->frag = 0xffff000a;
+
+  tmp = obuf->element->format;
+  if (ioctl (obuf->fd, SNDCTL_DSP_SETFMT, &tmp) == -1) {
+    perror ("SETFMT");
+    return FALSE;
+  }
+
+  tmp = obuf->element->channels;
+  if (ioctl (obuf->fd, SNDCTL_DSP_STEREO, &tmp) == -1) {
+    perror ("STEREO");
+    return FALSE;
+  }
+
+  tmp = obuf->element->channels;
+  if (ioctl (obuf->fd, SNDCTL_DSP_CHANNELS, &tmp) == -1) {
+    perror ("CHANNELS");
+    return FALSE;
+  }
+
+  tmp = obuf->element->rate;
+  if (ioctl (obuf->fd, SNDCTL_DSP_SPEED, &tmp) == -1) {
+    perror ("SPEED");
+    return FALSE;
+  }
+
+  if (ioctl (obuf->fd, SNDCTL_DSP_GETCAPS, &obuf->caps) == -1) {
+    perror ("/dev/dsp");
+    fprintf (stderr, "Sorry but your sound driver is too old\n");
+    return FALSE;
+  }
+
+  if (!(obuf->caps & DSP_CAP_TRIGGER) || !(obuf->caps & DSP_CAP_MMAP)) {
+    fprintf (stderr, "Sorry but your soundcard can't do this\n");
+    return FALSE;
+  }
+
+  if (ioctl (obuf->fd, SNDCTL_DSP_SETFRAGMENT, &obuf->frag) == -1) {
+    perror ("SETFRAGMENT");
+    return FALSE;
+  }
+
+  if (ioctl (obuf->fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
+    perror ("GETOSPACE");
+    return FALSE;
+  }
+
+  buf->spec.segsize = info.fragsize;
+  buf->spec.segtotal = info.fragstotal;
+  size = info.fragsize * info.fragstotal;
+  g_print ("segsize %d, segtotal %d\n", info.fragsize, info.fragstotal);
+
+  mmap_buf = (caddr_t) mmap (NULL, size, PROT_WRITE,
+      MAP_FILE | MAP_SHARED, obuf->fd, 0);
+
+  if ((caddr_t) mmap_buf == (caddr_t) - 1) {
+    perror ("mmap (write)");
+    return FALSE;
+  }
+
+  buf->data = gst_buffer_new ();
+  GST_BUFFER_DATA (buf->data) = mmap_buf;
+  GST_BUFFER_SIZE (buf->data) = size;
+  GST_BUFFER_FLAG_SET (buf->data, GST_BUFFER_DONTFREE);
+
+  tmp = 0;
+  if (ioctl (obuf->fd, SNDCTL_DSP_SETTRIGGER, &tmp) == -1) {
+    perror ("SETTRIGGER");
+    return FALSE;
+  }
+
+  GST_LOCK (obuf);
+  obuf->running = TRUE;
+  obuf->thread = g_thread_create ((GThreadFunc) gst_ossdmabuffer_func,
+      buf, TRUE, NULL);
+  GST_OSSDMABUFFER_WAIT (obuf);
+  GST_UNLOCK (obuf);
+
+  return TRUE;
+}
+
+static gboolean
+gst_ossdmabuffer_release (GstRingBuffer * buf)
+{
+  GstOssDMABuffer *obuf = (GstOssDMABuffer *) buf;;
+
+  gst_buffer_unref (buf->data);
+
+  GST_LOCK (obuf);
+  obuf->running = FALSE;
+  GST_OSSDMABUFFER_SIGNAL (obuf);
+  GST_UNLOCK (obuf);
+
+  g_thread_join (obuf->thread);
+
+  return TRUE;
+}
+
+static gboolean
+gst_ossdmabuffer_play (GstRingBuffer * buf)
+{
+  int tmp;
+  GstOssDMABuffer *obuf;
+
+  obuf = (GstOssDMABuffer *) buf;
+
+  tmp = PCM_ENABLE_OUTPUT;
+  if (ioctl (obuf->fd, SNDCTL_DSP_SETTRIGGER, &tmp) == -1) {
+    perror ("SETTRIGGER");
+  }
+  GST_OSSDMABUFFER_SIGNAL (obuf);
+
+  return TRUE;
+}
+
+static gboolean
+gst_ossdmabuffer_stop (GstRingBuffer * buf)
+{
+  int tmp;
+  GstOssDMABuffer *obuf;
+
+  obuf = (GstOssDMABuffer *) buf;
+
+  tmp = 0;
+  if (ioctl (obuf->fd, SNDCTL_DSP_SETTRIGGER, &tmp) == -1) {
+    perror ("SETTRIGGER");
+  }
+  GST_OSSDMABUFFER_WAIT (obuf);
+  buf->playseg = 0;
+
+  return TRUE;
+}
diff --git a/sys/oss/gstossdmabuffer.h b/sys/oss/gstossdmabuffer.h
new file mode 100644 (file)
index 0000000..3a2c6ea
--- /dev/null
@@ -0,0 +1,77 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstossdmabuffer.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_OSSDMABUFFER_H__
+#define __GST_OSSDMABUFFER_H__
+
+#include <gst/gst.h>
+
+#include "gstosselement.h"
+#include <gst/audio/gstringbuffer.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OSSDMABUFFER          (gst_ossdmabuffer_get_type())
+#define GST_OSSDMABUFFER(obj)          (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSSDMABUFFER,GstOssDMABuffer))
+#define GST_OSSDMABUFFER_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSSDMABUFFER,GstOssDMABufferClass))
+#define GST_IS_OSSDMABUFFER(obj)       (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSSDMABUFFER))
+#define GST_IS_OSSDMABUFFER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSSDMABUFFER))
+
+#define GST_OSSELEMENT_GET(obj)  GST_OSSELEMENT (obj->element)
+
+typedef enum {
+  GST_OSSDMABUFFER_OPEN                = (1 << 0),
+} GstOssDMABufferFlags;
+
+typedef struct _GstOssDMABuffer GstOssDMABuffer;
+typedef struct _GstOssDMABufferClass GstOssDMABufferClass;
+
+#define GST_OSSDMABUFFER_THREAD(buf)   (GST_OSSDMABUFFER(buf)->thread)
+#define GST_OSSDMABUFFER_LOCK         GST_LOCK
+#define GST_OSSDMABUFFER_UNLOCK               GST_UNLOCK
+#define GST_OSSDMABUFFER_COND(buf)     (GST_OSSDMABUFFER(buf)->cond)
+#define GST_OSSDMABUFFER_SIGNAL(buf)   (g_cond_signal (GST_OSSDMABUFFER_COND (buf)))
+#define GST_OSSDMABUFFER_WAIT(buf)     (g_cond_wait (GST_OSSDMABUFFER_COND (buf), GST_GET_LOCK (buf)))
+
+struct _GstOssDMABuffer {
+  GstRingBuffer  buffer;
+
+  GstOssElement        *element;
+
+  int            fd;
+  int            caps;
+  int            frag;
+
+  GThread       *thread;
+  GCond         *cond;
+  gboolean       running;
+};
+
+struct _GstOssDMABufferClass {
+  GstRingBufferClass parent_class;
+};
+
+GType gst_ossdmabuffer_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_OSSDMABUFFER_H__ */
index ae1cf3a825afed4361e534432bd0cfe6c7c8cd6b..d967480ee14076f98ee9bbf6bbc7efe4ebbbab8a 100644 (file)
@@ -1,9 +1,8 @@
 /* GStreamer
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
  *                    2000 Wim Taymans <wim.taymans@chello.be>
- *                    2004 Toni Willberg <toniw@iki.fi>
  *
- * gstosselement.c:
+ * gstosssink.c: 
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -25,7 +24,7 @@
 #include "config.h"
 #endif
 
-#include "gst-i18n-plugin.h"
+#include "gst/gst-i18n-plugin.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <errno.h>
 #include <string.h>
 
-#ifdef HAVE_OSS_INCLUDE_IN_SYS
 #include <sys/soundcard.h>
-#else
-
-#ifdef HAVE_OSS_INCLUDE_IN_ROOT
-#include <soundcard.h>
-#else
 
-#include <machine/soundcard.h>
-
-#endif /* HAVE_OSS_INCLUDE_IN_ROOT */
-
-#endif /* HAVE_OSS_INCLUDE_IN_SYS */
-
-#include <gst/propertyprobe/propertyprobe.h>
+#include <gst/interfaces/propertyprobe.h>
 
 #include "gstosselement.h"
 #include "gstossmixer.h"
 
 enum
 {
-  ARG_0,
+  ARG_ZERO,
   ARG_DEVICE,
   ARG_MIXERDEV,
   ARG_DEVICE_NAME
@@ -79,7 +66,6 @@ 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;
 
@@ -152,6 +138,9 @@ gst_osselement_class_init (GstOssElementClass * klass)
 
   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
 
+  gobject_class->set_property = gst_osselement_set_property;
+  gobject_class->get_property = gst_osselement_get_property;
+
   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));
@@ -163,11 +152,7 @@ gst_osselement_class_init (GstOssElementClass * klass)
       g_param_spec_string ("device_name", "Device name", "Name of the device",
           NULL, G_PARAM_READABLE));
 
-  gobject_class->set_property = gst_osselement_set_property;
-  gobject_class->get_property = gst_osselement_get_property;
   gobject_class->finalize = gst_osselement_finalize;
-
-  gstelement_class->change_state = gst_osselement_change_state;
 }
 
 static const GList *
@@ -245,7 +230,7 @@ gst_osselement_class_probe_devices (GstOssElementClass * klass, gboolean check)
   static GList *device_combinations;
   GList *padtempllist;
   gint openmode = O_RDONLY;
-  gboolean is_mixer = FALSE;
+  gboolean mixer = FALSE;
 
   /* 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
@@ -257,7 +242,7 @@ gst_osselement_class_probe_devices (GstOssElementClass * klass, gboolean check)
     if (GST_PAD_TEMPLATE_DIRECTION (firstpadtempl) == GST_PAD_SINK) {
       openmode = O_WRONLY;
     }
-    is_mixer = TRUE;
+    mixer = TRUE;
   }
 
   if (!init && !check) {
@@ -303,7 +288,7 @@ gst_osselement_class_probe_devices (GstOssElementClass * klass, gboolean check)
         /* we just check the dsp. we assume the mixer always works.
          * we don't need a mixer anyway (says OSS)... If we are a
          * mixer element, we use the mixer anyway. */
-        if ((fd = open (is_mixer ? mixer :
+        if ((fd = open (mixer ? mixer :
                     dsp, openmode | O_NONBLOCK)) > 0 || errno == EBUSY) {
           GstOssDeviceCombination *combi;
 
@@ -314,7 +299,7 @@ gst_osselement_class_probe_devices (GstOssElementClass * klass, gboolean check)
           combi = g_new0 (GstOssDeviceCombination, 1);
           combi->dsp = dsp;
           combi->mixer = mixer;
-          combi->dev = is_mixer ? mixer_dev : dsp_dev;
+          combi->dev = mixer ? mixer_dev : dsp_dev;
           device_combinations = device_combination_append (device_combinations,
               combi);
         } else {
@@ -525,18 +510,19 @@ gst_osselement_parse_caps (GstOssElement * oss, const GstCaps * caps)
 {
   gint bps, format;
   GstStructure *structure;
+  gboolean res;
 
   structure = gst_caps_get_structure (caps, 0);
 
-  gst_structure_get_int (structure, "width", &oss->width);
-  gst_structure_get_int (structure, "depth", &oss->depth);
+  res = gst_structure_get_int (structure, "width", &oss->width);
+  res &= gst_structure_get_int (structure, "depth", &oss->depth);
 
-  if (oss->width != oss->depth)
+  if (!res || oss->width != oss->depth)
     return FALSE;
 
-  gst_structure_get_int (structure, "law", &oss->law);
-  gst_structure_get_int (structure, "endianness", &oss->endianness);
-  gst_structure_get_boolean (structure, "signed", &oss->sign);
+  res = gst_structure_get_int (structure, "law", &oss->law);
+  res &= gst_structure_get_int (structure, "endianness", &oss->endianness);
+  res &= gst_structure_get_boolean (structure, "signed", &oss->sign);
 
   if (!gst_ossformat_get (oss->law, oss->endianness, oss->sign,
           oss->width, oss->depth, &format, &bps)) {
@@ -605,8 +591,10 @@ gst_osselement_sync_parms (GstOssElement * oss)
 
   /* gint fragscale, frag_ln; */
 
-  if (oss->fd == -1)
+  if (oss->fd == -1) {
+    GST_INFO ("osselement: no fd");
     return FALSE;
+  }
 
   if ((oss->fragment & 0xFFFF) == 0) {
     frag = 0;
@@ -634,7 +622,7 @@ gst_osselement_sync_parms (GstOssElement * oss)
 
   ioctl (oss->fd, SNDCTL_DSP_GETBLKSIZE, &oss->fragment_size);
 
-  if (oss->mode == GST_OSSELEMENT_WRITE) {
+  if (oss->mode == 1) {
     ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &space);
   } else {
     ioctl (oss->fd, SNDCTL_DSP_GETISPACE, &space);
@@ -680,31 +668,19 @@ gst_osselement_sync_parms (GstOssElement * oss)
   return TRUE;
 }
 
-static gboolean
-gst_osselement_open_audio (GstOssElement * oss)
+gboolean
+gst_osselement_open_audio (GstOssElement * oss, GstOssOpenMode mode)
 {
   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;
-    }
-  } else {
+  if (mode == GST_OSS_MODE_MIXER)
     goto do_mixer;
-  }
 
   /* first try to open the sound card */
-  if (mode == GST_OSSELEMENT_WRITE) {
+  if (mode == 1) {
     /* 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);
@@ -728,7 +704,7 @@ gst_osselement_open_audio (GstOssElement * oss)
         break;
       case EACCES:
       case ETXTBSY:
-        if (mode == GST_OSSELEMENT_WRITE)
+        if (mode == 1)
           GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
               (_("Could not access device \"%s\", check its permissions."),
                   oss->device), GST_ERROR_SYSTEM);
@@ -745,8 +721,7 @@ gst_osselement_open_audio (GstOssElement * oss)
             GST_ERROR_SYSTEM);
         break;
       default:
-        /* FIXME: strerror is not threadsafe */
-        if (mode == GST_OSSELEMENT_WRITE)
+        if (mode == 1)
           GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
               (_("Could not open device \"%s\" for writing."), oss->device),
               GST_ERROR_SYSTEM);
@@ -823,17 +798,17 @@ gst_osselement_open_audio (GstOssElement * oss)
   oss->caps = caps;
 
 do_mixer:
-  gst_ossmixer_build_list (oss);
+  gst_ossmixer_build_list (NULL, NULL);
 
   return TRUE;
 }
 
-static void
+void
 gst_osselement_close_audio (GstOssElement * oss)
 {
-  gst_ossmixer_free_list (oss);
+  gst_ossmixer_free_list (NULL);
   if (oss->probed_caps) {
-    gst_caps_free (oss->probed_caps);
+    gst_caps_unref (oss->probed_caps);
     oss->probed_caps = NULL;
   }
 
@@ -913,7 +888,7 @@ gst_osselement_set_property (GObject * object,
     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) {
+      if (oss->fd == -1) {
         g_free (oss->device);
         oss->device = g_strdup (g_value_get_string (value));
 
@@ -939,7 +914,7 @@ gst_osselement_set_property (GObject * object,
     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) {
+      if (oss->fd == -1) {
         g_free (oss->mixer_dev);
         oss->mixer_dev = g_strdup (g_value_get_string (value));
       }
@@ -971,34 +946,6 @@ gst_osselement_get_property (GObject * object,
   }
 }
 
-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;
-}
-
-
 /* rate probing code */
 
 
@@ -1061,31 +1008,15 @@ gst_osselement_probe_caps (GstOssElement * oss)
   GstStructure *structure;
   unsigned int format_bit;
   unsigned int format_mask;
-
   GstCaps *caps;
 
-  gboolean mono_supported = FALSE;
-  gboolean stereo_supported = FALSE;
-  int n_channels;
-
   if (oss->probed_caps != NULL)
     return;
   if (oss->fd == -1)
     return;
 
-
   /* FIXME test make sure we're not currently playing */
-
-  /* check if the device supports mono, stereo or both */
-  n_channels = 1;
-  ret = ioctl (oss->fd, SNDCTL_DSP_CHANNELS, &n_channels);
-  if (n_channels == 1)
-    mono_supported = TRUE;
-
-  n_channels = 2;
-  ret = ioctl (oss->fd, SNDCTL_DSP_CHANNELS, &n_channels);
-  if (n_channels == 2)
-    stereo_supported = TRUE;
+  /* FIXME test both mono and stereo */
 
   format_mask = AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_S8 |
       AFMT_U16_LE | AFMT_U16_BE;
@@ -1101,12 +1032,7 @@ gst_osselement_probe_caps (GstOssElement * oss)
       probe = g_new0 (GstOssProbe, 1);
       probe->fd = oss->fd;
       probe->format = format_bit;
-
-      if (stereo_supported) {
-        probe->n_channels = 2;
-      } else {
-        probe->n_channels = 1;
-      }
+      probe->n_channels = 2;
 
       ret = gst_osselement_rate_probe_check (probe);
       if (probe->min == -1 || probe->max == -1) {
@@ -1140,21 +1066,7 @@ gst_osselement_probe_caps (GstOssElement * oss)
       g_free (probe);
 
       structure = gst_osselement_get_format_structure (format_bit);
-
-      if (mono_supported && stereo_supported) {
-        gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2,
-            NULL);
-      } else if (mono_supported) {
-        gst_structure_set (structure, "channels", G_TYPE_INT, 1, NULL);
-      } else if (stereo_supported) {
-        gst_structure_set (structure, "channels", G_TYPE_INT, 2, NULL);
-      } else {
-        /* falling back to [1,2] because we don't know what breaks if we abort here */
-        GST_ERROR (_("Your OSS device doesn't support mono or stereo."));
-        gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2,
-            NULL);
-      }
-
+      gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
       gst_structure_set_value (structure, "rate", &rate_value);
       g_value_unset (&rate_value);
 
index fb161ad63b78d31f13c32f158b3ced955727aa19..b895d42b9d76d8b346d6c9b4e21af1b8fe1e301d 100644 (file)
@@ -26,9 +26,7 @@
 #include <gst/gst.h>
 #include <sys/types.h>
 
-/* debugging category */
-GST_DEBUG_CATEGORY_EXTERN (oss_debug);
-#define GST_CAT_DEFAULT oss_debug
+#include "gstosshelper.h"
 
 G_BEGIN_DECLS
 
@@ -48,16 +46,6 @@ G_BEGIN_DECLS
 typedef struct _GstOssElement GstOssElement;
 typedef struct _GstOssElementClass GstOssElementClass;
 
-typedef enum {
-  GST_OSSELEMENT_READ,
-  GST_OSSELEMENT_WRITE,
-} GstOssOpenMode;
-
-typedef struct _GstOssDeviceCombination {
-  gchar *dsp, *mixer;
-  dev_t dev;
-} GstOssDeviceCombination;
-
 struct _GstOssElement
 {
   /* yes, we're a gstelement too */
@@ -73,7 +61,6 @@ struct _GstOssElement
   gint          fragment;
   guint64       fragment_time;
   gint          fragment_size;
-  GstOssOpenMode mode;
   GstCaps       *probed_caps;
 
   /* stats bytes per *second* */
@@ -90,6 +77,7 @@ struct _GstOssElement
   gint          depth;
   gint          channels;
   gint          rate;
+  gint mode;
 
   /* mixer stuff */
   GList                *tracklist;
@@ -115,8 +103,12 @@ gboolean   gst_osselement_parse_caps       (GstOssElement *oss,
 gboolean       gst_osselement_merge_fixed_caps (GstOssElement *oss,
                                                 GstCaps      *caps);
        
+gboolean       gst_osselement_open_audio       (GstOssElement *oss, GstOssOpenMode mode);
 gboolean       gst_osselement_sync_parms       (GstOssElement *oss);
 void           gst_osselement_reset            (GstOssElement *oss);
+void           gst_osselement_close_audio      (GstOssElement *oss);
+
+       
 
 gboolean       gst_osselement_convert          (GstOssElement *oss, 
                                                 GstFormat      src_format,
index dc75294bb08307b1cc65c01dcc55365e42e92394..1d462908ee603826036762de4d228207875ff9c7 100644 (file)
 #include <string.h>
 #include <errno.h>
 #include <sys/ioctl.h>
-
-#ifdef HAVE_OSS_INCLUDE_IN_SYS
 #include <sys/soundcard.h>
-#else
-
-#ifdef HAVE_OSS_INCLUDE_IN_ROOT
-#include <soundcard.h>
-#else
-
-#include <machine/soundcard.h>
 
-#endif /* HAVE_OSS_INCLUDE_IN_ROOT */
-
-#endif /* HAVE_OSS_INCLUDE_IN_SYS */
-
-#include <gst-i18n-plugin.h>
+#include <gst/gst-i18n-plugin.h>
 
 #include "gstossmixer.h"
 
@@ -202,7 +189,7 @@ gst_ossmixer_track_init (GstOssMixerTrack * track)
 }
 
 GstMixerTrack *
-gst_ossmixer_track_new (GstOssElement * oss,
+gst_ossmixer_track_new (GstOssDevice * oss,
     gint track_num, gint max_chans, gint flags)
 {
   GstOssMixerTrack *osstrack;
@@ -258,14 +245,17 @@ gst_ossmixer_interface_init (GstMixerClass * klass)
 static gboolean
 gst_ossmixer_supported (GstImplementsInterface * iface, GType iface_type)
 {
+  GstOssDevice *oss = g_object_get_data (G_OBJECT (iface), "oss-data");
+
+  g_return_val_if_fail (oss != NULL, FALSE);
   g_assert (iface_type == GST_TYPE_MIXER);
 
-  return (GST_OSSELEMENT (iface)->mixer_fd != -1);
+  return (oss->mixer_fd != -1);
 }
 
 /* unused with G_DISABLE_* */
 static G_GNUC_UNUSED gboolean
-gst_ossmixer_contains_track (GstOssElement * oss, GstOssMixerTrack * osstrack)
+gst_ossmixer_contains_track (GstOssDevice * oss, GstOssMixerTrack * osstrack)
 {
   const GList *item;
 
@@ -279,7 +269,9 @@ gst_ossmixer_contains_track (GstOssElement * oss, GstOssMixerTrack * osstrack)
 static const GList *
 gst_ossmixer_list_tracks (GstMixer * mixer)
 {
-  return (const GList *) GST_OSSELEMENT (mixer)->tracklist;
+  GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
+
+  return (const GList *) oss->tracklist;
 }
 
 static void
@@ -287,10 +279,11 @@ gst_ossmixer_get_volume (GstMixer * mixer,
     GstMixerTrack * track, gint * volumes)
 {
   gint volume;
-  GstOssElement *oss = GST_OSSELEMENT (mixer);
+  GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
   GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
 
   /* assert that we're opened and that we're using a known item */
+  g_return_if_fail (oss != NULL);
   g_return_if_fail (oss->mixer_fd != -1);
   g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
 
@@ -319,10 +312,11 @@ gst_ossmixer_set_volume (GstMixer * mixer,
     GstMixerTrack * track, gint * volumes)
 {
   gint volume;
-  GstOssElement *oss = GST_OSSELEMENT (mixer);
+  GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
   GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
 
   /* assert that we're opened and that we're using a known item */
+  g_return_if_fail (oss != NULL);
   g_return_if_fail (oss->mixer_fd != -1);
   g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
 
@@ -351,10 +345,11 @@ static void
 gst_ossmixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute)
 {
   int volume;
-  GstOssElement *oss = GST_OSSELEMENT (mixer);
+  GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
   GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
 
   /* assert that we're opened and that we're using a known item */
+  g_return_if_fail (oss != NULL);
   g_return_if_fail (oss->mixer_fd != -1);
   g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
 
@@ -384,10 +379,11 @@ static void
 gst_ossmixer_set_record (GstMixer * mixer,
     GstMixerTrack * track, gboolean record)
 {
-  GstOssElement *oss = GST_OSSELEMENT (mixer);
+  GstOssDevice *oss = g_object_get_data (G_OBJECT (mixer), "oss-data");
   GstOssMixerTrack *osstrack = GST_OSSMIXER_TRACK (track);
 
   /* assert that we're opened and that we're using a known item */
+  g_return_if_fail (oss != NULL);
   g_return_if_fail (oss->mixer_fd != -1);
   g_return_if_fail (gst_ossmixer_contains_track (oss, osstrack));
 
@@ -430,11 +426,9 @@ gst_ossmixer_set_record (GstMixer * mixer,
 }
 
 void
-gst_ossmixer_build_list (GstOssElement * oss)
+gst_ossmixer_build_list (GstOssDeviceCombination * c, GstOssDevice * oss)
 {
   gint i, devmask, master = -1;
-  const GList *pads = gst_element_get_pad_list (GST_ELEMENT (oss));
-  GstPadDirection dir = GST_PAD_UNKNOWN;
 
 #ifdef SOUND_MIXER_INFO
   struct mixer_info minfo;
@@ -442,18 +436,14 @@ gst_ossmixer_build_list (GstOssElement * oss)
 
   g_return_if_fail (oss->mixer_fd == -1);
 
-  oss->mixer_fd = open (oss->mixer_dev, O_RDWR);
+  oss->mixer_fd = open (c->mixer, O_RDWR);
   if (oss->mixer_fd == -1) {
     /* this is valid. OSS devices don't need to expose a mixer */
     GST_DEBUG ("Failed to open mixer device %s, mixing disabled: %s",
-        oss->mixer_dev, strerror (errno));
+        c->mixer, strerror (errno));
     return;
   }
 
-  /* get direction */
-  if (pads && g_list_length ((GList *) pads) == 1)
-    dir = GST_PAD_DIRECTION (GST_PAD (pads->data));
-
   /* get masks */
   if (ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECMASK, &oss->recmask) < 0 ||
       ioctl (oss->mixer_fd, SOUND_MIXER_READ_RECSRC, &oss->recdevs) < 0 ||
@@ -499,8 +489,8 @@ gst_ossmixer_build_list (GstOssElement * oss)
         record = TRUE;
 
       /* do we want this in our list? */
-      if ((dir == GST_PAD_SRC && input == FALSE) ||
-          (dir == GST_PAD_SINK && i != SOUND_MIXER_PCM))
+      if ((oss->mode == GST_OSS_MODE_READ && input == FALSE) ||
+          (oss->mode == GST_OSS_MODE_WRITE && i != SOUND_MIXER_PCM))
         continue;
 
       /* add track to list */
@@ -515,7 +505,7 @@ gst_ossmixer_build_list (GstOssElement * oss)
 }
 
 void
-gst_ossmixer_free_list (GstOssElement * oss)
+gst_ossmixer_free_list (GstOssDevice * oss)
 {
   if (oss->mixer_fd == -1)
     return;
index dd2fb4fcbb3aacb3c323e5f06e4dc1ebe77e0f55..2eede0ed717cfa2808c16c4fad2f4eda2575446a 100644 (file)
@@ -23,8 +23,9 @@
 #define __GST_OSS_MIXER_H__
 
 #include <gst/gst.h>
-#include <gst/mixer/mixer.h>
-#include "gstosselement.h"
+#include <gst/interfaces/mixer.h>
+
+#include "gstosshelper.h"
 
 G_BEGIN_DECLS
 
@@ -56,8 +57,9 @@ GType gst_ossmixer_track_get_type     (void);
 
 void   gst_ossmixer_interface_init     (GstMixerClass *klass);
 void   gst_oss_interface_init          (GstImplementsInterfaceClass *klass);
-void   gst_ossmixer_build_list         (GstOssElement *oss);
-void   gst_ossmixer_free_list          (GstOssElement *oss);
+void   gst_ossmixer_build_list         (GstOssDeviceCombination * c,
+                                        GstOssDevice *oss);
+void   gst_ossmixer_free_list          (GstOssDevice *oss);
 
 G_END_DECLS
 
index e9c7438c429b9b757abe65f673d9e5c17431d54a..7d14feea8a17c54330c4e1d2bbbaae5f76dee213 100644 (file)
@@ -1,6 +1,6 @@
 /* GStreamer
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wim.taymans@chello.be>
+ *               2000,2005 Wim Taymans <wim@fluendo.com>
  *
  * gstosssink.c: 
  *
 #include "config.h"
 #endif
 #include <sys/ioctl.h>
+#include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
 #include <string.h>
-
-#ifdef HAVE_OSS_INCLUDE_IN_SYS
 #include <sys/soundcard.h>
-#else
-
-#ifdef HAVE_OSS_INCLUDE_IN_ROOT
-#include <soundcard.h>
-#else
 
-#include <machine/soundcard.h>
-
-#endif /* HAVE_OSS_INCLUDE_IN_ROOT */
-
-#endif /* HAVE_OSS_INCLUDE_IN_SYS */
 
 #include "gstosssink.h"
 
@@ -57,59 +46,33 @@ static void gst_osssink_class_init (GstOssSinkClass * klass);
 static void gst_osssink_init (GstOssSink * osssink);
 static void gst_osssink_dispose (GObject * object);
 
-static GstElementStateReturn gst_osssink_change_state (GstElement * element);
-static void gst_osssink_set_clock (GstElement * element, GstClock * clock);
-static GstClock *gst_osssink_get_clock (GstElement * element);
-static GstClockTime gst_osssink_get_time (GstClock * clock, gpointer data);
-
-static const GstFormat *gst_osssink_get_formats (GstPad * pad);
-static gboolean gst_osssink_convert (GstPad * pad, GstFormat src_format,
-    gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
-static const GstQueryType *gst_osssink_get_query_types (GstPad * pad);
-static gboolean gst_osssink_query (GstElement * element, GstQueryType type,
-    GstFormat * format, gint64 * value);
-static gboolean gst_osssink_sink_query (GstPad * pad, GstQueryType type,
-    GstFormat * format, gint64 * value);
+static GstCaps *gst_osssink_getcaps (GstBaseSink * bsink);
 
-static GstCaps *gst_osssink_sink_fixate (GstPad * pad, const GstCaps * caps);
-static GstCaps *gst_osssink_getcaps (GstPad * pad);
-static GstPadLinkReturn gst_osssink_sinkconnect (GstPad * pad,
-    const GstCaps * caps);
-
-static void gst_osssink_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_osssink_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-
-static void gst_osssink_chain (GstPad * pad, GstData * _data);
+static gboolean gst_osssink_open (GstAudioSink * asink,
+    GstRingBufferSpec * spec);
+static gboolean gst_osssink_close (GstAudioSink * asink);
+static guint gst_osssink_write (GstAudioSink * asink, gpointer data,
+    guint length);
+static guint gst_osssink_delay (GstAudioSink * asink);
+static void gst_osssink_reset (GstAudioSink * asink);
 
 /* OssSink signals and args */
 enum
 {
-  SIGNAL_HANDOFF,
   LAST_SIGNAL
 };
 
-enum
-{
-  ARG_0,
-  ARG_MUTE,
-  ARG_FRAGMENT,
-  ARG_BUFFER_SIZE,
-  ARG_SYNC,
-  ARG_CHUNK_SIZE
-      /* FILL ME */
-};
-
 static GstStaticPadTemplate osssink_sink_factory =
     GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("audio/x-raw-int, "
-        "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
-        "signed = (boolean) { TRUE, FALSE }, "
+        //"endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
+        //"signed = (boolean) { TRUE, FALSE }, "
+        "endianness = (int) LITTLE_ENDIAN, "
+        "signed = (boolean) TRUE, "
         "width = (int) 16, "
-        "depth = (int) { 8, 16 }, "
+        "depth = (int) 16, "
         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
         "audio/x-raw-int, "
         "signed = (boolean) { TRUE, FALSE }, "
@@ -119,7 +82,8 @@ static GstStaticPadTemplate osssink_sink_factory =
     );
 
 static GstElementClass *parent_class = NULL;
-static guint gst_osssink_signals[LAST_SIGNAL] = { 0 };
+
+/* static guint gst_osssink_signals[LAST_SIGNAL] = { 0 }; */
 
 GType
 gst_osssink_get_type (void)
@@ -140,7 +104,7 @@ gst_osssink_get_type (void)
     };
 
     osssink_type =
-        g_type_register_static (GST_TYPE_OSSELEMENT, "GstOssSink",
+        g_type_register_static (GST_TYPE_AUDIOSINK, "GstOssSink",
         &osssink_info, 0);
   }
 
@@ -150,13 +114,6 @@ gst_osssink_get_type (void)
 static void
 gst_osssink_dispose (GObject * object)
 {
-  GstOssSink *osssink = (GstOssSink *) object;
-
-  if (osssink->provided_clock) {
-    gst_object_unparent (GST_OBJECT (osssink->provided_clock));
-    osssink->provided_clock = NULL;
-  }
-
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
@@ -166,6 +123,7 @@ gst_osssink_base_init (gpointer g_class)
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
   gst_element_class_set_details (element_class, &gst_osssink_details);
+
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&osssink_sink_factory));
 }
@@ -174,515 +132,188 @@ gst_osssink_class_init (GstOssSinkClass * klass)
 {
   GObjectClass *gobject_class;
   GstElementClass *gstelement_class;
+  GstBaseSinkClass *gstbasesink_class;
+  GstBaseAudioSinkClass *gstbaseaudiosink_class;
+  GstAudioSinkClass *gstaudiosink_class;
 
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
+  gstbasesink_class = (GstBaseSinkClass *) klass;
+  gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
+  gstaudiosink_class = (GstAudioSinkClass *) klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_BASEAUDIOSINK);
 
-  parent_class = g_type_class_ref (GST_TYPE_OSSELEMENT);
-
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MUTE,
-      g_param_spec_boolean ("mute", "Mute", "Mute the audio",
-          FALSE, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
-      g_param_spec_boolean ("sync", "Sync",
-          "If syncing on timestamps should be enabled", TRUE,
-          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)",
-          0, G_MAXINT, 6, G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFFER_SIZE,
-      g_param_spec_uint ("buffer_size", "Buffer size",
-          "Size of buffers in osssink's bufferpool (bytes)", 0, G_MAXINT, 4096,
-          G_PARAM_READWRITE));
-  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CHUNK_SIZE,
-      g_param_spec_uint ("chunk_size", "Chunk size",
-          "Write data in chunk sized buffers", 0, G_MAXUINT, 4096,
-          G_PARAM_READWRITE));
-
-  gst_osssink_signals[SIGNAL_HANDOFF] =
-      g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstOssSinkClass, handoff), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
-  gobject_class->set_property = gst_osssink_set_property;
-  gobject_class->get_property = gst_osssink_get_property;
   gobject_class->dispose = gst_osssink_dispose;
 
-  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_osssink_change_state);
-  gstelement_class->query = GST_DEBUG_FUNCPTR (gst_osssink_query);
-  gstelement_class->set_clock = gst_osssink_set_clock;
-  gstelement_class->get_clock = gst_osssink_get_clock;
+  gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_osssink_getcaps);
 
+  gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_osssink_open);
+  gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_osssink_close);
+  gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_osssink_write);
+  gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_osssink_delay);
+  gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_osssink_reset);
 }
 
 static void
 gst_osssink_init (GstOssSink * osssink)
 {
-  osssink->sinkpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&osssink_sink_factory), "sink");
-  gst_element_add_pad (GST_ELEMENT (osssink), osssink->sinkpad);
-  gst_pad_set_link_function (osssink->sinkpad, gst_osssink_sinkconnect);
-  gst_pad_set_getcaps_function (osssink->sinkpad, gst_osssink_getcaps);
-  gst_pad_set_fixate_function (osssink->sinkpad, gst_osssink_sink_fixate);
-  gst_pad_set_convert_function (osssink->sinkpad, gst_osssink_convert);
-  gst_pad_set_query_function (osssink->sinkpad, gst_osssink_sink_query);
-  gst_pad_set_query_type_function (osssink->sinkpad,
-      gst_osssink_get_query_types);
-  gst_pad_set_formats_function (osssink->sinkpad, gst_osssink_get_formats);
-
-  gst_pad_set_chain_function (osssink->sinkpad, gst_osssink_chain);
-
   GST_DEBUG ("initializing osssink");
-  osssink->bufsize = 4096;
-  osssink->chunk_size = 4096;
-  osssink->mute = FALSE;
-  osssink->sync = TRUE;
-  osssink->provided_clock =
-      gst_audio_clock_new ("ossclock", gst_osssink_get_time, osssink);
-  gst_object_set_parent (GST_OBJECT (osssink->provided_clock),
-      GST_OBJECT (osssink));
-  osssink->handled = 0;
-
-  GST_FLAG_SET (osssink, GST_ELEMENT_THREAD_SUGGESTED);
-  GST_FLAG_SET (osssink, GST_ELEMENT_EVENT_AWARE);
-}
-
-static GstCaps *
-gst_osssink_sink_fixate (GstPad * pad, const GstCaps * caps)
-{
-  GstCaps *newcaps;
-  GstStructure *structure;
 
-  newcaps =
-      gst_caps_new_full (gst_structure_copy (gst_caps_get_structure (caps, 0)),
-      NULL);
-  structure = gst_caps_get_structure (newcaps, 0);
-
-  if (gst_caps_structure_fixate_field_nearest_int (structure, "rate", 44100)) {
-    return newcaps;
-  }
-  if (gst_caps_structure_fixate_field_nearest_int (structure, "depth", 16)) {
-    return newcaps;
-  }
-  if (gst_caps_structure_fixate_field_nearest_int (structure, "width", 16)) {
-    return newcaps;
-  }
-  if (gst_caps_structure_fixate_field_nearest_int (structure, "channels", 2)) {
-    return newcaps;
-  }
-
-  gst_caps_free (newcaps);
-
-  return NULL;
+  osssink->element = g_object_new (GST_TYPE_OSSELEMENT, NULL);
 }
 
 static GstCaps *
-gst_osssink_getcaps (GstPad * pad)
+gst_osssink_getcaps (GstBaseSink * bsink)
 {
-  GstOssSink *osssink = GST_OSSSINK (gst_pad_get_parent (pad));
+  GstOssSink *osssink;
+  GstOssElement *element;
   GstCaps *caps;
 
-  gst_osselement_probe_caps (GST_OSSELEMENT (osssink));
+  osssink = GST_OSSSINK (bsink);
+  element = osssink->element;
+
+  gst_osselement_probe_caps (element);
 
-  if (GST_OSSELEMENT (osssink)->probed_caps == NULL) {
-    caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+  if (element->probed_caps == NULL) {
+    caps =
+        gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASESINK_PAD
+            (bsink)));
   } else {
-    caps = gst_caps_copy (GST_OSSELEMENT (osssink)->probed_caps);
+    caps = gst_caps_ref (element->probed_caps);
   }
 
   return caps;
 }
 
-static GstPadLinkReturn
-gst_osssink_sinkconnect (GstPad * pad, const GstCaps * caps)
-{
-  GstOssSink *osssink = GST_OSSSINK (gst_pad_get_parent (pad));
-
-  if (!gst_osselement_parse_caps (GST_OSSELEMENT (osssink), caps))
-    return GST_PAD_LINK_REFUSED;
-
-  if (!gst_osselement_sync_parms (GST_OSSELEMENT (osssink))) {
-    return GST_PAD_LINK_REFUSED;
-  }
-
-  return GST_PAD_LINK_OK;
-}
-
-static inline gint
-gst_osssink_get_delay (GstOssSink * osssink)
-{
-  gint delay = 0;
-  gint ret;
-
-  if (GST_OSSELEMENT (osssink)->fd == -1)
-    return 0;
-
-#ifdef SNDCTL_DSP_GETODELAY
-  ret = ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_GETODELAY, &delay);
-#else
-  ret = -1;
-#endif
-  if (ret < 0) {
-    audio_buf_info info;
-
-    if (ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
-      delay = 0;
-    } else {
-      delay = (info.fragstotal * info.fragsize) - info.bytes;
-    }
-  }
-
-  return delay;
-}
-
-static GstClockTime
-gst_osssink_get_time (GstClock * clock, gpointer data)
+static gint
+ilog2 (gint x)
 {
-  GstOssSink *osssink = GST_OSSSINK (data);
-  gint delay;
-  GstClockTime res;
-
-  if (!GST_OSSELEMENT (osssink)->bps)
-    return 0;
-
-  delay = gst_osssink_get_delay (osssink);
-
-  /* sometimes delay is bigger than the number of bytes sent to the device,
-   * which screws up this calculation, we assume that everything is still
-   * in the device then
-   * thomas: with proper handling of the return value, this doesn't seem to
-   * happen anymore, so remove the second code path after april 2004 */
-  if (delay > (gint64) osssink->handled) {
-    /*g_warning ("Delay %d > osssink->handled %" G_GUINT64_FORMAT
-       ", setting to osssink->handled",
-       delay, osssink->handled); */
-    delay = osssink->handled;
-  }
-  res =
-      ((gint64) osssink->handled -
-      delay) * GST_SECOND / GST_OSSELEMENT (osssink)->bps;
-  if (res < 0)
-    res = 0;
-
-  return res;
+  /* well... hacker's delight explains... */
+  x = x | (x >> 1);
+  x = x | (x >> 2);
+  x = x | (x >> 4);
+  x = x | (x >> 8);
+  x = x | (x >> 16);
+  x = x - ((x >> 1) & 0x55555555);
+  x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+  x = (x + (x >> 4)) & 0x0f0f0f0f;
+  x = x + (x >> 8);
+  x = x + (x >> 16);
+  return (x & 0x0000003f) - 1;
 }
 
-static GstClock *
-gst_osssink_get_clock (GstElement * element)
-{
-  GstOssSink *osssink;
-
-  osssink = GST_OSSSINK (element);
+#define SET_PARAM(_oss, _name, _val)           \
+G_STMT_START {                                 \
+  int _tmp = _val;                             \
+  if (ioctl(_oss->fd, _name, &_tmp) == -1) {   \
+    perror(G_STRINGIFY (_name));               \
+    return FALSE;                              \
+  }                                            \
+  GST_DEBUG(G_STRINGIFY (name) " %d", _tmp);   \
+} G_STMT_END
+
+#define GET_PARAM(oss, name, val)              \
+G_STMT_START {                                 \
+  if (ioctl(oss->fd, name, val) == -1) {       \
+    perror(G_STRINGIFY (name));                        \
+    return FALSE;                              \
+  }                                            \
+} G_STMT_END
 
-  return GST_CLOCK (osssink->provided_clock);
-}
-
-static void
-gst_osssink_set_clock (GstElement * element, GstClock * clock)
+static gboolean
+gst_osssink_open (GstAudioSink * asink, GstRingBufferSpec * spec)
 {
-  GstOssSink *osssink;
+  struct audio_buf_info info;
+  int mode;
+  GstOssSink *oss;
+  int tmp;
 
-  osssink = GST_OSSSINK (element);
+  oss = GST_OSSSINK (asink);
 
-  osssink->clock = clock;
-}
+  mode = O_WRONLY;
+  mode |= O_NONBLOCK;
 
-static void
-gst_osssink_chain (GstPad * pad, GstData * _data)
-{
-  GstBuffer *buf = GST_BUFFER (_data);
-  GstOssSink *osssink;
-  GstClockTimeDiff buftime, soundtime, elementtime;
-  guchar *data;
-  guint to_write;
-  gint delay;
-
-  /* this has to be an audio buffer */
-  osssink = GST_OSSSINK (gst_pad_get_parent (pad));
-
-  if (GST_IS_EVENT (buf)) {
-    GstEvent *event = GST_EVENT (buf);
-
-    switch (GST_EVENT_TYPE (event)) {
-      case GST_EVENT_EOS:
-        ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_SYNC, 0);
-        gst_audio_clock_set_active (GST_AUDIO_CLOCK (osssink->provided_clock),
-            FALSE);
-        gst_pad_event_default (pad, event);
-        return;
-      default:
-        gst_pad_event_default (pad, event);
-        return;
-    }
-    g_assert_not_reached ();
+  oss->fd = open ("/dev/dsp", mode, 0);
+  if (oss->fd == -1) {
+    perror ("/dev/dsp");
+    return FALSE;
   }
+  mode = fcntl (oss->fd, F_GETFL);
+  mode &= ~O_NONBLOCK;
+  fcntl (oss->fd, F_SETFL, mode);
 
-  if (!GST_OSSELEMENT (osssink)->bps) {
-    gst_buffer_unref (buf);
-    GST_ELEMENT_ERROR (osssink, CORE, NEGOTIATION, (NULL),
-        ("format wasn't negotiated before chain function"));
-    return;
-  }
+  SET_PARAM (oss, SNDCTL_DSP_SETFMT, AFMT_S16_LE);
+  SET_PARAM (oss, SNDCTL_DSP_STEREO, 1);
+  SET_PARAM (oss, SNDCTL_DSP_CHANNELS, 2);
+  SET_PARAM (oss, SNDCTL_DSP_SPEED, 44100);
 
-  data = GST_BUFFER_DATA (buf);
-  to_write = GST_BUFFER_SIZE (buf);
-  /* sync audio with buffers timestamp. elementtime is the *current* time.
-   * soundtime is the time if the soundcard has processed all queued data. */
-  elementtime = gst_element_get_time (GST_ELEMENT (osssink));
-  delay = gst_osssink_get_delay (osssink);
-  if (delay < 0)
-    delay = 0;
-  soundtime = elementtime + delay * GST_SECOND / GST_OSSELEMENT (osssink)->bps;
-  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
-    buftime = GST_BUFFER_TIMESTAMP (buf);
-  } else {
-    buftime = soundtime;
-  }
-  GST_LOG_OBJECT (osssink,
-      "time: real %" GST_TIME_FORMAT ", buffer: %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (soundtime), GST_TIME_ARGS (buftime));
-  if (MAX (buftime, soundtime) - MIN (buftime, soundtime) > (GST_SECOND / 10)) {
-    /* we need to adjust to the buffers here */
-    GST_INFO_OBJECT (osssink,
-        "need sync: real %" GST_TIME_FORMAT ", buffer: %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (soundtime), GST_TIME_ARGS (buftime));
-    if (soundtime > buftime) {
-      /* do *not* throw frames out. It's useless. The next frame will come in
-       * too late. And the next one. And so on. We don't want to lose sound.
-       * This is a placeholder for what - some day - should become QoS, i.e.
-       * sending events upstream to drop buffers. */
-    } else {
-      guint64 to_handle =
-          (((buftime -
-                  soundtime) * GST_OSSELEMENT (osssink)->bps / GST_SECOND) /
-          ((GST_OSSELEMENT (osssink)->width / 8) *
-              GST_OSSELEMENT (osssink)->channels)) *
-          (GST_OSSELEMENT (osssink)->width / 8) *
-          GST_OSSELEMENT (osssink)->channels;
-      guint8 *sbuf = g_new (guint8, to_handle);
-
-      memset (sbuf, (GST_OSSELEMENT (osssink)->width == 8) ? 0 : 128,
-          to_handle);
-      while (to_handle > 0) {
-        gint done = write (GST_OSSELEMENT (osssink)->fd, sbuf,
-            MIN (to_handle, osssink->chunk_size));
-
-        if (done == -1 && errno != EINTR) {
-          break;
-        } else {
-          to_handle -= done;
-          osssink->handled += done;
-        }
-      }
-      g_free (sbuf);
-    }
-  }
+  tmp = ilog2 (spec->segsize);
+  tmp = ((spec->segtotal & 0x7fff) << 16) | tmp;
+  GST_DEBUG ("set segsize: %d, segtotal: %d, value: %08x", spec->segsize,
+      spec->segtotal, tmp);
 
-  if (GST_OSSELEMENT (osssink)->fd >= 0 && to_write > 0) {
-    if (!osssink->mute) {
-
-      while (to_write > 0) {
-        gint done = write (GST_OSSELEMENT (osssink)->fd, data,
-            MIN (to_write, osssink->chunk_size));
-
-        if (done == -1) {
-          if (errno != EINTR)
-            break;
-        } else {
-          to_write -= done;
-          data += done;
-          osssink->handled += done;
-        }
-      }
-    } else {
-      g_warning ("muting osssinks unimplemented wrt clocks!");
-    }
-  }
+  SET_PARAM (oss, SNDCTL_DSP_SETFRAGMENT, tmp);
+  GET_PARAM (oss, SNDCTL_DSP_GETOSPACE, &info);
 
-  gst_audio_clock_update_time ((GstAudioClock *) osssink->provided_clock,
-      gst_osssink_get_time (osssink->provided_clock, osssink));
+  spec->segsize = info.fragsize;
+  spec->segtotal = info.fragstotal;
+  spec->bytes_per_sample = 4;
+  oss->bytes_per_sample = 4;
+  memset (spec->silence_sample, 0, spec->bytes_per_sample);
 
-  gst_buffer_unref (buf);
-}
+  GST_DEBUG ("got segsize: %d, segtotal: %d, value: %08x", spec->segsize,
+      spec->segtotal, tmp);
 
-static const GstFormat *
-gst_osssink_get_formats (GstPad * pad)
-{
-  static const GstFormat formats[] = {
-    GST_FORMAT_TIME,
-    GST_FORMAT_DEFAULT,
-    GST_FORMAT_BYTES,
-    0
-  };
-
-  return formats;
+  return TRUE;
 }
 
 static gboolean
-gst_osssink_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
+gst_osssink_close (GstAudioSink * asink)
 {
-  GstOssSink *osssink;
-
-  osssink = GST_OSSSINK (gst_pad_get_parent (pad));
-
-  return gst_osselement_convert (GST_OSSELEMENT (osssink),
-      src_format, src_value, dest_format, dest_value);
+  close (GST_OSSSINK (asink)->fd);
+  return TRUE;
 }
 
-static const GstQueryType *
-gst_osssink_get_query_types (GstPad * pad)
+static guint
+gst_osssink_write (GstAudioSink * asink, gpointer data, guint length)
 {
-  static const GstQueryType query_types[] = {
-    GST_QUERY_LATENCY,
-    GST_QUERY_POSITION,
-    0,
-  };
-
-  return query_types;
+  return write (GST_OSSSINK (asink)->fd, data, length);
 }
 
-static gboolean
-gst_osssink_sink_query (GstPad * pad, GstQueryType type, GstFormat * format,
-    gint64 * value)
+static guint
+gst_osssink_delay (GstAudioSink * asink)
 {
-  gboolean res = TRUE;
-  GstOssSink *osssink;
-
-  osssink = GST_OSSSINK (gst_pad_get_parent (pad));
-
-  switch (type) {
-    case GST_QUERY_LATENCY:
-      if (!gst_osssink_convert (pad,
-              GST_FORMAT_BYTES, gst_osssink_get_delay (osssink),
-              format, value)) {
-        res = FALSE;
-      }
-      break;
-    case GST_QUERY_POSITION:
-      if (!gst_osssink_convert (pad,
-              GST_FORMAT_TIME, gst_element_get_time (GST_ELEMENT (osssink)),
-              format, value)) {
-        res = FALSE;
-      }
-      break;
-    default:
-      res =
-          gst_pad_query (gst_pad_get_peer (osssink->sinkpad), type, format,
-          value);
-      break;
-  }
-
-  return res;
-}
+  GstOssSink *oss;
+  gint delay = 0;
+  gint ret;
 
-static gboolean
-gst_osssink_query (GstElement * element, GstQueryType type, GstFormat * format,
-    gint64 * value)
-{
-  GstOssSink *osssink = GST_OSSSINK (element);
+  oss = GST_OSSSINK (asink);
 
-  return gst_osssink_sink_query (osssink->sinkpad, type, format, value);
-}
+#ifdef SNDCTL_DSP_GETODELAY
+  ret = ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay);
+#else
+  ret = -1;
+#endif
+  if (ret < 0) {
+    audio_buf_info info;
 
-static void
-gst_osssink_set_property (GObject * object, guint prop_id, const GValue * value,
-    GParamSpec * pspec)
-{
-  GstOssSink *osssink;
+    ret = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &info);
 
-  osssink = GST_OSSSINK (object);
-
-  switch (prop_id) {
-    case ARG_MUTE:
-      osssink->mute = g_value_get_boolean (value);
-      g_object_notify (G_OBJECT (osssink), "mute");
-      break;
-    case ARG_FRAGMENT:
-      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);
-      g_object_notify (object, "buffer_size");
-      break;
-    case ARG_SYNC:
-      osssink->sync = g_value_get_boolean (value);
-      g_object_notify (G_OBJECT (osssink), "sync");
-      break;
-    case ARG_CHUNK_SIZE:
-      osssink->chunk_size = g_value_get_uint (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
+    delay = (ret < 0 ? 0 : (info.fragstotal * info.fragsize) - info.bytes);
   }
+  return delay / oss->bytes_per_sample;
 }
 
 static void
-gst_osssink_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
+gst_osssink_reset (GstAudioSink * asink)
 {
-  GstOssSink *osssink;
+  GstOssSink *oss;
 
-  osssink = GST_OSSSINK (object);
-
-  switch (prop_id) {
-    case ARG_MUTE:
-      g_value_set_boolean (value, osssink->mute);
-      break;
-    case ARG_FRAGMENT:
-      g_value_set_int (value, GST_OSSELEMENT (osssink)->fragment);
-      break;
-    case ARG_BUFFER_SIZE:
-      g_value_set_uint (value, osssink->bufsize);
-      break;
-    case ARG_SYNC:
-      g_value_set_boolean (value, osssink->sync);
-      break;
-    case ARG_CHUNK_SIZE:
-      g_value_set_uint (value, osssink->chunk_size);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static GstElementStateReturn
-gst_osssink_change_state (GstElement * element)
-{
-  GstOssSink *osssink;
-
-  osssink = GST_OSSSINK (element);
-
-  switch (GST_STATE_TRANSITION (element)) {
-    case GST_STATE_READY_TO_PAUSED:
-      break;
-    case GST_STATE_PAUSED_TO_PLAYING:
-      gst_audio_clock_set_active (GST_AUDIO_CLOCK (osssink->provided_clock),
-          TRUE);
-      break;
-    case GST_STATE_PLAYING_TO_PAUSED:
-      if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN))
-        ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_RESET, 0);
-      gst_audio_clock_set_active (GST_AUDIO_CLOCK (osssink->provided_clock),
-          FALSE);
-      break;
-    case GST_STATE_PAUSED_TO_READY:
-      if (GST_FLAG_IS_SET (element, GST_OSSSINK_OPEN))
-        ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_RESET, 0);
-      gst_osselement_reset (GST_OSSELEMENT (osssink));
-      osssink->handled = 0;
-      break;
-    default:
-      break;
-  }
+  //gint ret;
 
-  if (GST_ELEMENT_CLASS (parent_class)->change_state)
-    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+  oss = GST_OSSSINK (asink);
 
-  return GST_STATE_SUCCESS;
+  /* deadlocks on my machine... */
+  //ret = ioctl (oss->fd, SNDCTL_DSP_RESET, 0);
 }
index 7542c8d1ad608d82dc85007213570899be35c536..964794c8ce9bbaf0ad18fdd332e4722547e00377 100644 (file)
 
 
 #include <gst/gst.h>
+#include <gst/audio/gstaudiosink.h>
 
 #include "gstosselement.h"
-#include <gst/audio/audioclock.h>
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_OSSSINK \
-  (gst_osssink_get_type())
-#define GST_OSSSINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSSSINK,GstOssSink))
-#define GST_OSSSINK_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSSSINK,GstOssSinkClass))
-#define GST_IS_OSSSINK(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSSSINK))
-#define GST_IS_OSSSINK_CLASS(obj) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSSSINK))
-
-typedef enum {
-  GST_OSSSINK_OPEN             = GST_ELEMENT_FLAG_LAST,
-
-  GST_OSSSINK_FLAG_LAST        = GST_ELEMENT_FLAG_LAST+2,
-} GstOssSinkFlags;
+#define GST_TYPE_OSSSINK          (gst_osssink_get_type())
+#define GST_OSSSINK(obj)          (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSSSINK,GstOssSink))
+#define GST_OSSSINK_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSSSINK,GstOssSinkClass))
+#define GST_IS_OSSSINK(obj)       (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSSSINK))
+#define GST_IS_OSSSINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSSSINK))
 
 typedef struct _GstOssSink GstOssSink;
 typedef struct _GstOssSinkClass GstOssSinkClass;
 
 struct _GstOssSink {
-  GstOssElement         element;
+  GstAudioSink    sink;
 
-  GstPad       *sinkpad;
+  GstOssElement *element;
 
-  GstClock     *provided_clock;
-  GstClock     *clock;
-  gboolean      sync;
-  guint64       handled;
-
-  gboolean      mute;
-  guint         bufsize;
-  guint         chunk_size;
+  gint fd;
+  gint          bytes_per_sample;
 };
 
 struct _GstOssSinkClass {
-  GstOssElementClass parent_class;
-
-  /* signals */
-  void (*handoff) (GstElement *element,GstPad *pad);
+  GstAudioSinkClass parent_class;
 };
 
 GType gst_osssink_get_type(void);
index 60edc3908185f889131c4d4e2c08fa8c2a7cf258..c88ba74741e423fec8a26273d9b6283aa1d9848e 100644 (file)
@@ -92,8 +92,7 @@ static void gst_osssrc_class_init (GstOssSrcClass * klass);
 static void gst_osssrc_init (GstOssSrc * osssrc);
 static void gst_osssrc_dispose (GObject * object);
 
-static GstPadLinkReturn gst_osssrc_srcconnect (GstPad * pad,
-    const GstCaps * caps);
+static GstPadLinkReturn gst_osssrc_src_link (GstPad * pad, GstPad * peer);
 static GstCaps *gst_osssrc_getcaps (GstPad * pad);
 static const GstFormat *gst_osssrc_get_formats (GstPad * pad);
 static gboolean gst_osssrc_convert (GstPad * pad,
@@ -117,7 +116,7 @@ static const GstQueryType *gst_osssrc_get_query_types (GstPad * pad);
 static gboolean gst_osssrc_src_query (GstPad * pad, GstQueryType type,
     GstFormat * format, gint64 * value);
 
-static GstData *gst_osssrc_get (GstPad * pad);
+static void gst_osssrc_loop (GstPad * pad);
 
 static GstElementClass *parent_class = NULL;
 
@@ -168,6 +167,9 @@ gst_osssrc_class_init (GstOssSrcClass * klass)
 
   parent_class = g_type_class_ref (GST_TYPE_OSSELEMENT);
 
+  gobject_class->set_property = gst_osssrc_set_property;
+  gobject_class->get_property = gst_osssrc_get_property;
+
   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,
@@ -177,8 +179,6 @@ gst_osssrc_class_init (GstOssSrcClass * klass)
           "The fragment as 0xMMMMSSSS (MMMM = total fragments, 2^SSSS = fragment size)",
           0, G_MAXINT, 6, G_PARAM_READWRITE));
 
-  gobject_class->set_property = gst_osssrc_set_property;
-  gobject_class->get_property = gst_osssrc_get_property;
   gobject_class->dispose = gst_osssrc_dispose;
 
   gstelement_class->change_state = gst_osssrc_change_state;
@@ -194,9 +194,9 @@ gst_osssrc_init (GstOssSrc * osssrc)
   osssrc->srcpad =
       gst_pad_new_from_template (gst_static_pad_template_get
       (&osssrc_src_factory), "src");
-  gst_pad_set_get_function (osssrc->srcpad, gst_osssrc_get);
+  gst_pad_set_loop_function (osssrc->srcpad, gst_osssrc_loop);
   gst_pad_set_getcaps_function (osssrc->srcpad, gst_osssrc_getcaps);
-  gst_pad_set_link_function (osssrc->srcpad, gst_osssrc_srcconnect);
+  gst_pad_set_link_function (osssrc->srcpad, gst_osssrc_src_link);
   gst_pad_set_convert_function (osssrc->srcpad, gst_osssrc_convert);
   gst_pad_set_formats_function (osssrc->srcpad, gst_osssrc_get_formats);
   gst_pad_set_event_function (osssrc->srcpad, gst_osssrc_src_event);
@@ -236,7 +236,7 @@ gst_osssrc_getcaps (GstPad * pad)
   GstOssSrc *src;
   GstCaps *caps;
 
-  src = GST_OSSSRC (gst_pad_get_parent (pad));
+  src = GST_OSSSRC (GST_PAD_PARENT (pad));
 
   gst_osselement_probe_caps (GST_OSSELEMENT (src));
 
@@ -250,19 +250,9 @@ gst_osssrc_getcaps (GstPad * pad)
 }
 
 static GstPadLinkReturn
-gst_osssrc_srcconnect (GstPad * pad, const GstCaps * caps)
+gst_osssrc_src_link (GstPad * pad, GstPad * peer)
 {
-  GstOssSrc *src;
-
-  src = GST_OSSSRC (gst_pad_get_parent (pad));
-
-  if (!gst_osselement_parse_caps (GST_OSSELEMENT (src), caps))
-    return GST_PAD_LINK_REFUSED;
-
-  if (!gst_osselement_sync_parms (GST_OSSELEMENT (src)))
-    return GST_PAD_LINK_REFUSED;
-
-  return GST_PAD_LINK_OK;
+  return GST_RPAD_LINKFUNC (peer) (peer, pad);
 }
 
 static gboolean
@@ -271,9 +261,10 @@ gst_osssrc_negotiate (GstPad * pad)
   GstOssSrc *src;
   GstCaps *allowed;
 
-  src = GST_OSSSRC (gst_pad_get_parent (pad));
+  src = GST_OSSSRC (GST_PAD_PARENT (pad));
 
-  allowed = gst_pad_get_allowed_caps (pad);
+  //allowed = gst_pad_get_allowed_caps (pad);
+  allowed = NULL;
 
   if (!gst_osselement_merge_fixed_caps (GST_OSSELEMENT (src), allowed))
     return FALSE;
@@ -282,17 +273,15 @@ gst_osssrc_negotiate (GstPad * pad)
     return FALSE;
 
   /* set caps on src pad */
-  if (gst_pad_try_set_caps (src->srcpad,
-          gst_caps_new_simple ("audio/x-raw-int",
-              "endianness", G_TYPE_INT, GST_OSSELEMENT (src)->endianness,
-              "signed", G_TYPE_BOOLEAN, GST_OSSELEMENT (src)->sign,
-              "width", G_TYPE_INT, GST_OSSELEMENT (src)->width,
-              "depth", G_TYPE_INT, GST_OSSELEMENT (src)->depth,
-              "rate", G_TYPE_INT, GST_OSSELEMENT (src)->rate,
-              "channels", G_TYPE_INT, GST_OSSELEMENT (src)->channels,
-              NULL)) <= 0) {
-    return FALSE;
-  }
+  GST_PAD_CAPS (src->srcpad) =
+      gst_caps_new_simple ("audio/x-raw-int",
+      "endianness", G_TYPE_INT, GST_OSSELEMENT (src)->endianness,
+      "signed", G_TYPE_BOOLEAN, GST_OSSELEMENT (src)->sign,
+      "width", G_TYPE_INT, GST_OSSELEMENT (src)->width,
+      "depth", G_TYPE_INT, GST_OSSELEMENT (src)->depth,
+      "rate", G_TYPE_INT, GST_OSSELEMENT (src)->rate,
+      "channels", G_TYPE_INT, GST_OSSELEMENT (src)->channels, NULL);
+
   return TRUE;
 }
 
@@ -332,21 +321,22 @@ gst_osssrc_set_clock (GstElement * element, GstClock * clock)
   osssrc->clock = clock;
 }
 
-static GstData *
-gst_osssrc_get (GstPad * pad)
+static void
+gst_osssrc_loop (GstPad * pad)
 {
   GstOssSrc *src;
   GstBuffer *buf;
   glong readbytes;
   glong readsamples;
 
-  src = GST_OSSSRC (gst_pad_get_parent (pad));
+  src = GST_OSSSRC (GST_PAD_PARENT (pad));
 
   GST_DEBUG ("attempting to read something from the soundcard");
 
   if (src->need_eos) {
     src->need_eos = FALSE;
-    return GST_DATA (gst_event_new (GST_EVENT_EOS));
+    gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
+    return;
   }
 
   buf = gst_buffer_new_and_alloc (src->buffersize);
@@ -356,14 +346,14 @@ gst_osssrc_get (GstPad * pad)
     if (!gst_osssrc_negotiate (pad)) {
       gst_buffer_unref (buf);
       GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), (NULL));
-      return GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
+      return;
     }
   }
   if (GST_OSSELEMENT (src)->bps == 0) {
     gst_buffer_unref (buf);
     GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL),
         ("format wasn't negotiated before chain function"));
-    return GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
+    return;
   }
 
   readbytes = read (GST_OSSELEMENT (src)->fd, GST_BUFFER_DATA (buf),
@@ -371,13 +361,13 @@ gst_osssrc_get (GstPad * pad)
   if (readbytes < 0) {
     gst_buffer_unref (buf);
     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
-    return GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
+    return;
   }
 
   if (readbytes == 0) {
     gst_buffer_unref (buf);
-    gst_element_set_eos (GST_ELEMENT (src));
-    return GST_DATA (gst_event_new (GST_EVENT_INTERRUPT));
+    gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
+    return;
   }
 
   readsamples = readbytes * GST_OSSELEMENT (src)->rate /
@@ -412,7 +402,9 @@ gst_osssrc_get (GstPad * pad)
   GST_DEBUG ("pushed buffer from soundcard of %ld bytes, timestamp %"
       G_GINT64_FORMAT, readbytes, GST_BUFFER_TIMESTAMP (buf));
 
-  return GST_DATA (buf);
+  gst_pad_push (pad, buf);
+
+  return;
 }
 
 static void
@@ -509,7 +501,7 @@ gst_osssrc_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
 {
   GstOssSrc *osssrc;
 
-  osssrc = GST_OSSSRC (gst_pad_get_parent (pad));
+  osssrc = GST_OSSSRC (GST_PAD_PARENT (pad));
 
   return gst_osselement_convert (GST_OSSELEMENT (osssrc), src_format, src_value,
       dest_format, dest_value);
@@ -533,7 +525,7 @@ gst_osssrc_src_event (GstPad * pad, GstEvent * event)
   GstOssSrc *osssrc;
   gboolean retval = FALSE;
 
-  osssrc = GST_OSSSRC (gst_pad_get_parent (pad));
+  osssrc = GST_OSSSRC (GST_PAD_PARENT (pad));
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_EOS:
@@ -589,7 +581,7 @@ gst_osssrc_src_query (GstPad * pad, GstQueryType type, GstFormat * format,
   gboolean res = FALSE;
   GstOssSrc *osssrc;
 
-  osssrc = GST_OSSSRC (gst_pad_get_parent (pad));
+  osssrc = GST_OSSSRC (GST_PAD_PARENT (pad));
 
   switch (type) {
     case GST_QUERY_POSITION:
index 1d54a6071c214c6eb082fa4860844c91065d0c46..5b0d12845bd6c75f2b2fea1260a0083aa00a843f 100644 (file)
@@ -1,24 +1,3 @@
-/* GStreamer
- * Copyright (C) 2004 David Schleef
- *               2004 Toni Willberg <toniw@iki.fi>
- *
- * oss_probe.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"
@@ -73,12 +52,9 @@ int
 main (int argc, char *argv[])
 {
   int fd;
-  int i, ret;
+  int i;
   Probe *probe;
 
-  gboolean mono_supported = FALSE;
-  gboolean stereo_supported = FALSE;
-
   fd = open ("/dev/dsp", O_RDWR);
   if (fd < 0) {
     perror ("/dev/dsp");
@@ -88,29 +64,7 @@ main (int argc, char *argv[])
   probe = g_new0 (Probe, 1);
   probe->fd = fd;
   probe->format = AFMT_S16_LE;
-
-  /* check if the device supports mono, stereo or both */
-  probe->n_channels = 1;
-  ret = ioctl (fd, SNDCTL_DSP_CHANNELS, &probe->n_channels);
-  if (probe->n_channels == 1)
-    mono_supported = TRUE;
-
   probe->n_channels = 2;
-  ret = ioctl (fd, SNDCTL_DSP_CHANNELS, &probe->n_channels);
-  if (probe->n_channels == 2)
-    stereo_supported = TRUE;
-
-  if (mono_supported && stereo_supported) {
-    g_print ("The device supports mono and stereo.\n");
-  } else if (mono_supported) {
-    g_print ("The device supports only mono.\n");
-  } else if (stereo_supported) {
-    g_print ("The device supports only stereo.\n");
-  } else {
-    /* exit with error */
-    g_error
-        ("The device doesn't support mono or stereo. This should not happen.\n");
-  }
 
   probe_check (probe);
   g_array_sort (probe->rates, int_compare);