sys/oss/gstosssrc.*: Totally ported, dude.
authorAndy Wingo <wingo@pobox.com>
Tue, 23 Aug 2005 09:46:29 +0000 (09:46 +0000)
committerAndy Wingo <wingo@pobox.com>
Tue, 23 Aug 2005 09:46:29 +0000 (09:46 +0000)
Original commit message from CVS:
2005-08-23  Andy Wingo  <wingo@pobox.com>

* sys/oss/gstosssrc.h:
* sys/oss/gstosssrc.c: Totally ported, dude.

* sys/oss/Makefile.am:
* sys/oss/gstossaudio.c: Add osssrc.

* sys/oss/gstosssink.c: We do native byte order.

ChangeLog
sys/oss/Makefile.am
sys/oss/gstossaudio.c
sys/oss/gstosssink.c
sys/oss/gstosssrc.c
sys/oss/gstosssrc.h

index 87ed50a..d295cfa 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2005-08-23  Andy Wingo  <wingo@pobox.com>
+
+       * sys/oss/gstosssrc.h: 
+       * sys/oss/gstosssrc.c: Totally ported, dude.
+
+       * sys/oss/Makefile.am:
+       * sys/oss/gstossaudio.c: Add osssrc.
+       
+       * sys/oss/gstosssink.c: We do native byte order.
+
 2005-08-23  Owen Fraser-Green  <owen@discobabe.net>
 
        * gst/realmedia/rmdemux.c (gst_rmdemux_src_event): Fixed bug
index 3d6f6e7..d298b7c 100644 (file)
@@ -4,7 +4,8 @@ libgstossaudio_la_SOURCES = gstossaudio.c       \
                            gstosselement.c     \
                            gstosshelper.c      \
                            gstossmixer.c       \
-                           gstosssink.c
+                           gstosssink.c        \
+                           gstosssrc.c
 
 #                          gstossdmabuffer.c
 
index 4b30faf..65cf703 100644 (file)
@@ -35,9 +35,9 @@ static gboolean
 plugin_init (GstPlugin * plugin)
 {
   if (                          /*!gst_element_register (plugin, "ossmixer", GST_RANK_PRIMARY,
-                                   GST_TYPE_OSSELEMENT) ||
-                                   !gst_element_register (plugin, "osssrc", GST_RANK_PRIMARY,
-                                   GST_TYPE_OSSSRC) || */
+                                   GST_TYPE_OSSELEMENT) || */
+      !gst_element_register (plugin, "osssrc", GST_RANK_PRIMARY,
+          GST_TYPE_OSS_SRC) ||
       !gst_element_register (plugin, "osssink", GST_RANK_SECONDARY,
           GST_TYPE_OSSSINK)) {
     return FALSE;
index e26a8e7..efef1ba 100644 (file)
@@ -69,10 +69,8 @@ static GstStaticPadTemplate osssink_sink_factory =
     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, "
-        "signed = (boolean) TRUE, "
+        "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
+        "signed = (boolean) { TRUE, FALSE }, "
         "width = (int) 16, "
         "depth = (int) 16, "
         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]; "
index 78e506e..e7a5cda 100644 (file)
@@ -1,6 +1,6 @@
 /* GStreamer
  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- *                    2000 Wim Taymans <wtay@chello.be>
+ *               2000,2005 Wim Taymans <wim@fluendo.com>
  *
  * gstosssrc.c: 
  *
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #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>
+#include "gstosssrc.h"
 
-#endif /* HAVE_OSS_INCLUDE_IN_ROOT */
 
-#endif /* HAVE_OSS_INCLUDE_IN_SYS */
-
-#include <gstosssrc.h>
-#include <gstosselement.h>
-#include <gst/audio/audioclock.h>
-
-/* elementfactory information */
 static GstElementDetails gst_oss_src_details =
 GST_ELEMENT_DETAILS ("Audio Source (OSS)",
     "Source/Audio",
-    "Read from the sound card",
-    "Erik Walthinsen <omega@cse.ogi.edu>");
+    "Capture from a sound card via OSS",
+    "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
 
 
-/* OssSrc signals and args */
 enum
 {
-  /* FILL ME */
-  LAST_SIGNAL
+  PROP_0,
+  PROP_DEVICE,
+  PROP_DEVICE_NAME,
 };
 
-enum
-{
-  ARG_0,
-  ARG_BUFFERSIZE,
-  ARG_FRAGMENT
-};
+GST_BOILERPLATE (GstOssSrc, gst_oss_src, GstAudioSrc, GST_TYPE_AUDIO_SRC);
+
+/*
+GST_BOILERPLATE_WITH_INTERFACE (GstOssSrc, gst_oss_src, GstAudioSrc, GST_TYPE_AUDIO_SRC,
+ GstMixer, GST_TYPE_MIXER, gst_oss_src_mixer);
+GST_IMPLEMENT_OSS_MIXER_METHODS (GstOssSrc, gst_oss_src_mixer);
+*/
+
+static void gst_oss_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_oss_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+
+static void gst_oss_src_dispose (GObject * object);
+
+static GstCaps *gst_oss_src_getcaps (GstBaseSrc * bsrc);
+
+static gboolean gst_oss_src_open (GstAudioSrc * asrc);
+static gboolean gst_oss_src_close (GstAudioSrc * asrc);
+static gboolean gst_oss_src_prepare (GstAudioSrc * asrc,
+    GstRingBufferSpec * spec);
+static gboolean gst_oss_src_unprepare (GstAudioSrc * asrc);
+static guint gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length);
+static guint gst_oss_src_delay (GstAudioSrc * asrc);
+static void gst_oss_src_reset (GstAudioSrc * asrc);
+
+
 
 static GstStaticPadTemplate osssrc_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("audio/x-raw-int, "
-        "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
+        "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, "
         "signed = (boolean) { TRUE, FALSE }, "
         "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 }, "
@@ -87,64 +91,11 @@ static GstStaticPadTemplate osssrc_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]")
     );
 
-static void gst_oss_src_base_init (gpointer g_class);
-static void gst_oss_src_class_init (GstOssSrcClass * klass);
-static void gst_oss_src_init (GstOssSrc * osssrc);
-static void gst_oss_src_dispose (GObject * object);
-
-static GstPadLinkReturn gst_oss_src_src_link (GstPad * pad, GstPad * peer);
-static GstCaps *gst_oss_src_getcaps (GstPad * pad);
-static const GstFormat *gst_oss_src_get_formats (GstPad * pad);
-static gboolean gst_oss_src_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value);
-
-static void gst_oss_src_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
-static void gst_oss_src_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static GstElementStateReturn gst_oss_src_change_state (GstElement * element);
-
-static void gst_oss_src_set_clock (GstElement * element, GstClock * clock);
-static GstClock *gst_oss_src_get_clock (GstElement * element);
-static GstClockTime gst_oss_src_get_time (GstClock * clock, gpointer data);
-
-static const GstEventMask *gst_oss_src_get_event_masks (GstPad * pad);
-static gboolean gst_oss_src_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_oss_src_send_event (GstElement * element, GstEvent * event);
-static const GstQueryType *gst_oss_src_get_query_types (GstPad * pad);
-static gboolean gst_oss_src_src_query (GstPad * pad, GstQueryType type,
-    GstFormat * format, gint64 * value);
-
-static void gst_oss_src_loop (GstPad * pad);
 
-static GstElementClass *parent_class = NULL;
-
-/*static guint gst_oss_src_signals[LAST_SIGNAL] = { 0 }; */
-
-GType
-gst_oss_src_get_type (void)
+static void
+gst_oss_src_dispose (GObject * object)
 {
-  static GType osssrc_type = 0;
-
-  if (!osssrc_type) {
-    static const GTypeInfo osssrc_info = {
-      sizeof (GstOssSrcClass),
-      gst_oss_src_base_init,
-      NULL,
-      (GClassInitFunc) gst_oss_src_class_init,
-      NULL,
-      NULL,
-      sizeof (GstOssSrc),
-      0,
-      (GInstanceInitFunc) gst_oss_src_init,
-    };
-
-    osssrc_type =
-        g_type_register_static (GST_TYPE_OSSELEMENT, "GstOssSrc", &osssrc_info,
-        0);
-  }
-  return osssrc_type;
+  G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
@@ -153,6 +104,7 @@ gst_oss_src_base_init (gpointer g_class)
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
   gst_element_class_set_details (element_class, &gst_oss_src_details);
+
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&osssrc_src_factory));
 }
@@ -161,435 +113,336 @@ gst_oss_src_class_init (GstOssSrcClass * klass)
 {
   GObjectClass *gobject_class;
   GstElementClass *gstelement_class;
+  GstBaseSrcClass *gstbasesrc_class;
+  GstBaseAudioSrcClass *gstbaseaudiosrc_class;
+  GstAudioSrcClass *gstaudiosrc_class;
 
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
+  gstbasesrc_class = (GstBaseSrcClass *) klass;
+  gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
+  gstaudiosrc_class = (GstAudioSrcClass *) klass;
+
+  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_oss_src_dispose);
+  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_oss_src_get_property);
+  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_oss_src_set_property);
+
+  gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss_src_getcaps);
+
+  gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_oss_src_open);
+  gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_oss_src_prepare);
+  gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss_src_unprepare);
+  gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_oss_src_close);
+  gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_oss_src_read);
+  gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_oss_src_delay);
+  gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_oss_src_reset);
+
+  g_object_class_install_property (gobject_class, PROP_DEVICE,
+      g_param_spec_string ("device", "Device",
+          "OSS device (usually /dev/dspN)", "/dev/dsp", G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+      g_param_spec_string ("device-name", "Device name",
+          "Human-readable name of the sound device", "", G_PARAM_READABLE));
+}
 
-  parent_class = g_type_class_ref (GST_TYPE_OSSELEMENT);
-
-  gobject_class->set_property = gst_oss_src_set_property;
-  gobject_class->get_property = gst_oss_src_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,
-          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));
-
-  gobject_class->dispose = gst_oss_src_dispose;
+static void
+gst_oss_src_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstOssSrc *src;
 
-  gstelement_class->change_state = gst_oss_src_change_state;
-  gstelement_class->send_event = gst_oss_src_send_event;
+  src = GST_OSS_SRC (object);
 
-  gstelement_class->set_clock = gst_oss_src_set_clock;
-  gstelement_class->get_clock = gst_oss_src_get_clock;
+  switch (prop_id) {
+    case PROP_DEVICE:
+      if (src->device)
+        g_free (src->device);
+      src->device = g_strdup (g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }
 
 static void
-gst_oss_src_init (GstOssSrc * osssrc)
+gst_oss_src_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
 {
-  osssrc->srcpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&osssrc_src_factory), "src");
-  gst_pad_set_loop_function (osssrc->srcpad, gst_oss_src_loop);
-  gst_pad_set_getcaps_function (osssrc->srcpad, gst_oss_src_getcaps);
-  gst_pad_set_link_function (osssrc->srcpad, gst_oss_src_src_link);
-  gst_pad_set_convert_function (osssrc->srcpad, gst_oss_src_convert);
-  gst_pad_set_formats_function (osssrc->srcpad, gst_oss_src_get_formats);
-  gst_pad_set_event_function (osssrc->srcpad, gst_oss_src_src_event);
-  gst_pad_set_event_mask_function (osssrc->srcpad, gst_oss_src_get_event_masks);
-  gst_pad_set_query_function (osssrc->srcpad, gst_oss_src_src_query);
-  gst_pad_set_query_type_function (osssrc->srcpad, gst_oss_src_get_query_types);
-
-  gst_element_add_pad (GST_ELEMENT (osssrc), osssrc->srcpad);
-
-  osssrc->buffersize = 4096;
-  osssrc->curoffset = 0;
-
-  osssrc->provided_clock =
-      gst_audio_clock_new ("ossclock", gst_oss_src_get_time, osssrc);
-  gst_object_set_parent (GST_OBJECT (osssrc->provided_clock),
-      GST_OBJECT (osssrc));
-
-  osssrc->clock = NULL;
+  GstOssSrc *src;
+
+  src = GST_OSS_SRC (object);
+
+  switch (prop_id) {
+    case PROP_DEVICE:
+      g_value_set_string (value, src->device);
+      break;
+    case PROP_DEVICE_NAME:
+      g_value_set_string (value, src->device_name);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }
 
 static void
-gst_oss_src_dispose (GObject * object)
+gst_oss_src_init (GstOssSrc * osssrc)
 {
-  GstOssSrc *osssrc = (GstOssSrc *) object;
+  GST_DEBUG ("initializing osssrc");
 
-  if (osssrc->provided_clock != NULL) {
-    gst_object_unparent (GST_OBJECT (osssrc->provided_clock));
-    osssrc->provided_clock = NULL;
-  }
-
-  G_OBJECT_CLASS (parent_class)->dispose (object);
+  osssrc->device = g_strdup ("/dev/dsp");
+  osssrc->element = g_object_new (GST_TYPE_OSSELEMENT, NULL);
 }
 
 static GstCaps *
-gst_oss_src_getcaps (GstPad * pad)
+gst_oss_src_getcaps (GstBaseSrc * bsrc)
 {
-  GstOssSrc *src;
+  GstOssSrc *osssrc;
+  GstOssElement *element;
   GstCaps *caps;
 
-  src = GST_OSSSRC (GST_PAD_PARENT (pad));
+  osssrc = GST_OSS_SRC (bsrc);
+  element = osssrc->element;
 
-  gst_osselement_probe_caps (GST_OSSELEMENT (src));
+  gst_osselement_probe_caps (element);
 
-  if (GST_OSSELEMENT (src)->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_BASE_SRC_PAD (bsrc)));
   } else {
-    caps = gst_caps_copy (GST_OSSELEMENT (src)->probed_caps);
+    caps = gst_caps_ref (element->probed_caps);
   }
 
   return caps;
 }
 
-static GstPadLinkReturn
-gst_oss_src_src_link (GstPad * pad, GstPad * peer)
+static gint
+ilog2 (gint x)
 {
-  return GST_RPAD_LINKFUNC (peer) (peer, pad);
+  /* 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 gboolean
-gst_oss_src_negotiate (GstPad * pad)
+#define SET_PARAM(_oss, _label, _name, _val)   \
+G_STMT_START {                                 \
+  int _tmp = _val;                             \
+  if (ioctl(_oss->fd, _name, &_tmp) == -1) {   \
+    perror(_label);                            \
+    return FALSE;                              \
+  }                                            \
+  GST_DEBUG_OBJECT (_oss, _label " %d", _tmp); \
+} G_STMT_END
+
+#define GET_PARAM(oss, label, name, val)       \
+G_STMT_START {                                 \
+  if (ioctl(oss->fd, name, val) == -1) {       \
+    perror(label);                             \
+    return FALSE;                              \
+  }                                            \
+} G_STMT_END
+
+static gint
+gst_oss_src_get_format (GstBufferFormat fmt)
 {
-  GstOssSrc *src;
-  GstCaps *allowed;
-
-  src = GST_OSSSRC (GST_PAD_PARENT (pad));
-
-  //allowed = gst_pad_get_allowed_caps (pad);
-  allowed = NULL;
-
-  if (!gst_osselement_merge_fixed_caps (GST_OSSELEMENT (src), allowed))
-    return FALSE;
-
-  if (!gst_osselement_sync_parms (GST_OSSELEMENT (src)))
-    return FALSE;
-
-  /* set caps on src pad */
-  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);
+  gint result;
 
-  return TRUE;
+  switch (fmt) {
+    case GST_MU_LAW:
+      result = AFMT_MU_LAW;
+      break;
+    case GST_A_LAW:
+      result = AFMT_A_LAW;
+      break;
+    case GST_IMA_ADPCM:
+      result = AFMT_IMA_ADPCM;
+      break;
+    case GST_U8:
+      result = AFMT_U8;
+      break;
+    case GST_S16_LE:
+      result = AFMT_S16_LE;
+      break;
+    case GST_S16_BE:
+      result = AFMT_S16_BE;
+      break;
+    case GST_S8:
+      result = AFMT_S8;
+      break;
+    case GST_U16_LE:
+      result = AFMT_U16_LE;
+      break;
+    case GST_U16_BE:
+      result = AFMT_U16_BE;
+      break;
+    case GST_MPEG:
+      result = AFMT_MPEG;
+      break;
+    default:
+      result = 0;
+      break;
+  }
+  return result;
 }
 
-static GstClockTime
-gst_oss_src_get_time (GstClock * clock, gpointer data)
+static gboolean
+gst_oss_src_open (GstAudioSrc * asrc)
 {
-  GstOssSrc *osssrc = GST_OSSSRC (data);
-  audio_buf_info info;
+  GstOssSrc *oss;
+  int mode;
 
-  if (!GST_OSSELEMENT (osssrc)->bps)
-    return 0;
+  oss = GST_OSS_SRC (asrc);
 
-  if (ioctl (GST_OSSELEMENT (osssrc)->fd, SNDCTL_DSP_GETISPACE, &info) < 0)
-    return 0;
+  mode = O_RDONLY;
+  mode |= O_NONBLOCK;
 
-  return (osssrc->curoffset * GST_OSSELEMENT (osssrc)->sample_width +
-      info.bytes) * GST_SECOND / GST_OSSELEMENT (osssrc)->bps;
-}
-
-static GstClock *
-gst_oss_src_get_clock (GstElement * element)
-{
-  GstOssSrc *osssrc;
-
-  osssrc = GST_OSSSRC (element);
+  oss->fd = open (oss->device, mode, 0);
+  if (oss->fd == -1) {
+    perror (oss->device);
+    return FALSE;
+  }
 
-  return GST_CLOCK (osssrc->provided_clock);
+  return TRUE;
 }
 
-static void
-gst_oss_src_set_clock (GstElement * element, GstClock * clock)
+static gboolean
+gst_oss_src_close (GstAudioSrc * asrc)
 {
-  GstOssSrc *osssrc;
-
-  osssrc = GST_OSSSRC (element);
-
-  osssrc->clock = clock;
+  close (GST_OSS_SRC (asrc)->fd);
+  return TRUE;
 }
 
-static void
-gst_oss_src_loop (GstPad * pad)
+static gboolean
+gst_oss_src_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
 {
-  GstOssSrc *src;
-  GstBuffer *buf;
-  glong readbytes;
-  glong readsamples;
-
-  src = GST_OSSSRC (GST_PAD_PARENT (pad));
+  GstOssSrc *oss;
+  struct audio_buf_info info;
+  int mode;
+  int tmp;
 
-  GST_DEBUG ("attempting to read something from the soundcard");
+  oss = GST_OSS_SRC (asrc);
 
-  if (src->need_eos) {
-    src->need_eos = FALSE;
-    gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
-    return;
+  mode = fcntl (oss->fd, F_GETFL);
+  mode &= ~O_NONBLOCK;
+  if (fcntl (oss->fd, F_SETFL, mode) == -1) {
+    perror (oss->device);
+    return FALSE;
   }
 
-  buf = gst_buffer_new_and_alloc (src->buffersize);
+  tmp = gst_oss_src_get_format (spec->format);
+  if (tmp == 0)
+    goto wrong_format;
 
-  if (!GST_PAD_CAPS (pad)) {
-    /* nothing was negotiated, we can decide on a format */
-    if (!gst_oss_src_negotiate (pad)) {
-      gst_buffer_unref (buf);
-      GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), (NULL));
-      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;
-  }
+  tmp = ilog2 (spec->segsize);
+  tmp = ((spec->segtotal & 0x7fff) << 16) | tmp;
+  GST_DEBUG ("set segsize: %d, segtotal: %d, value: %08x", spec->segsize,
+      spec->segtotal, tmp);
 
-  readbytes = read (GST_OSSELEMENT (src)->fd, GST_BUFFER_DATA (buf),
-      src->buffersize);
-  if (readbytes < 0) {
-    gst_buffer_unref (buf);
-    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
-    return;
-  }
+  SET_PARAM (oss, "SETFRAGMENT", SNDCTL_DSP_SETFRAGMENT, tmp);
 
-  if (readbytes == 0) {
-    gst_buffer_unref (buf);
-    gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
-    return;
-  }
+  SET_PARAM (oss, "RESET", SNDCTL_DSP_RESET, 0);
 
-  readsamples = readbytes * GST_OSSELEMENT (src)->rate /
-      GST_OSSELEMENT (src)->bps;
-
-  GST_BUFFER_SIZE (buf) = readbytes;
-  GST_BUFFER_OFFSET (buf) = src->curoffset;
-  GST_BUFFER_OFFSET_END (buf) = src->curoffset + readsamples;
-  GST_BUFFER_DURATION (buf) =
-      readsamples * GST_SECOND / GST_OSSELEMENT (src)->rate;
-
-  /* if we have a clock */
-  if (src->clock) {
-    if (src->clock == src->provided_clock) {
-      /* if it's our own clock, we can be very accurate */
-      GST_BUFFER_TIMESTAMP (buf) =
-          src->curoffset * GST_SECOND / GST_OSSELEMENT (src)->rate;
-    } else {
-      /* somebody elses clock, timestamp with that clock, no discontinuity in
-       * the stream since the OFFSET is updated correctly. Elements can stretch
-       * to match timestamps */
-      GST_BUFFER_TIMESTAMP (buf) =
-          gst_element_get_time (GST_ELEMENT (src)) - GST_BUFFER_DURATION (buf);
-    }
-  } else {
-    /* no clock, no timestamp */
-    GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
-  }
-
-  src->curoffset += readsamples;
-
-  GST_DEBUG ("pushed buffer from soundcard of %ld bytes, timestamp %"
-      G_GINT64_FORMAT, readbytes, GST_BUFFER_TIMESTAMP (buf));
+  SET_PARAM (oss, "SETFMT", SNDCTL_DSP_SETFMT, tmp);
+  if (spec->channels == 2)
+    SET_PARAM (oss, "STEREO", SNDCTL_DSP_STEREO, 1);
+  SET_PARAM (oss, "CHANNELS", SNDCTL_DSP_CHANNELS, spec->channels);
+  SET_PARAM (oss, "SPEED", SNDCTL_DSP_SPEED, spec->rate);
 
-  gst_pad_push (pad, buf);
+  GET_PARAM (oss, "GETISPACE", SNDCTL_DSP_GETISPACE, &info);
 
-  return;
-}
+  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);
 
-static void
-gst_oss_src_set_property (GObject * object, guint prop_id, const GValue * value,
-    GParamSpec * pspec)
-{
-  GstOssSrc *src;
+  GST_DEBUG ("got segsize: %d, segtotal: %d, value: %08x", spec->segsize,
+      spec->segtotal, tmp);
 
-  src = GST_OSSSRC (object);
+  return TRUE;
 
-  switch (prop_id) {
-    case ARG_BUFFERSIZE:
-      src->buffersize = g_value_get_ulong (value);
-      break;
-    case ARG_FRAGMENT:
-      GST_OSSELEMENT (src)->fragment = g_value_get_int (value);
-      gst_osselement_sync_parms (GST_OSSELEMENT (src));
-      break;
-    default:
-      break;
+wrong_format:
+  {
+    GST_DEBUG ("wrong format %d\n", spec->format);
+    return FALSE;
   }
 }
 
-static void
-gst_oss_src_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
+static gboolean
+gst_oss_src_unprepare (GstAudioSrc * asrc)
 {
-  GstOssSrc *src;
-
-  src = GST_OSSSRC (object);
+  /* could do a SNDCTL_DSP_RESET, but the OSS manual recommends a close/open */
 
-  switch (prop_id) {
-    case ARG_BUFFERSIZE:
-      g_value_set_ulong (value, src->buffersize);
-      break;
-    case ARG_FRAGMENT:
-      g_value_set_int (value, GST_OSSELEMENT (src)->fragment);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
+  if (!gst_oss_src_close (asrc))
+    goto couldnt_close;
 
-static GstElementStateReturn
-gst_oss_src_change_state (GstElement * element)
-{
-  GstOssSrc *osssrc = GST_OSSSRC (element);
+  if (!gst_oss_src_open (asrc))
+    goto couldnt_reopen;
 
-  GST_DEBUG ("osssrc: state change");
+  return TRUE;
 
-  switch (GST_STATE_TRANSITION (element)) {
-    case GST_STATE_READY_TO_PAUSED:
-      osssrc->curoffset = 0;
-      break;
-    case GST_STATE_PAUSED_TO_PLAYING:
-      gst_audio_clock_set_active (GST_AUDIO_CLOCK (osssrc->provided_clock),
-          TRUE);
-      break;
-    case GST_STATE_PLAYING_TO_PAUSED:
-      gst_audio_clock_set_active (GST_AUDIO_CLOCK (osssrc->provided_clock),
-          FALSE);
-      break;
-    case GST_STATE_PAUSED_TO_READY:
-      if (GST_FLAG_IS_SET (element, GST_OSSSRC_OPEN))
-        ioctl (GST_OSSELEMENT (osssrc)->fd, SNDCTL_DSP_RESET, 0);
-      break;
-    default:
-      break;
+couldnt_close:
+  {
+    GST_DEBUG ("Could not close the audio device");
+    return FALSE;
+  }
+couldnt_reopen:
+  {
+    GST_DEBUG ("Could not reopen the audio device");
+    return FALSE;
   }
-
-  if (GST_ELEMENT_CLASS (parent_class)->change_state)
-    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
-
-  return GST_STATE_SUCCESS;
-}
-
-static const GstFormat *
-gst_oss_src_get_formats (GstPad * pad)
-{
-  static const GstFormat formats[] = {
-    GST_FORMAT_TIME,
-    GST_FORMAT_DEFAULT,
-    GST_FORMAT_BYTES,
-    0
-  };
-
-  return formats;
 }
 
-static gboolean
-gst_oss_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
+static guint
+gst_oss_src_read (GstAudioSrc * asrc, gpointer data, guint length)
 {
-  GstOssSrc *osssrc;
-
-  osssrc = GST_OSSSRC (GST_PAD_PARENT (pad));
-
-  return gst_osselement_convert (GST_OSSELEMENT (osssrc), src_format, src_value,
-      dest_format, dest_value);
+  return read (GST_OSS_SRC (asrc)->fd, data, length);
 }
 
-static const GstEventMask *
-gst_oss_src_get_event_masks (GstPad * pad)
+static guint
+gst_oss_src_delay (GstAudioSrc * asrc)
 {
-  static const GstEventMask gst_oss_src_src_event_masks[] = {
-    {GST_EVENT_EOS, 0},
-    {GST_EVENT_SIZE, 0},
-    {0,}
-  };
+  GstOssSrc *oss;
+  gint delay = 0;
+  gint ret;
 
-  return gst_oss_src_src_event_masks;
-}
+  oss = GST_OSS_SRC (asrc);
 
-static gboolean
-gst_oss_src_src_event (GstPad * pad, GstEvent * event)
-{
-  GstOssSrc *osssrc;
-  gboolean retval = FALSE;
+#ifdef SNDCTL_DSP_GETODELAY
+  ret = ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay);
+#else
+  ret = -1;
+#endif
+  if (ret < 0) {
+    audio_buf_info info;
 
-  osssrc = GST_OSSSRC (GST_PAD_PARENT (pad));
+    ret = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &info);
 
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_EOS:
-      osssrc->need_eos = TRUE;
-      retval = TRUE;
-      break;
-    case GST_EVENT_SIZE:
-    {
-      GstFormat format;
-      gint64 value;
-
-      format = GST_FORMAT_BYTES;
-
-      /* convert to bytes */
-      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");
-        retval = TRUE;
-      }
-    }
-    default:
-      break;
+    delay = (ret < 0 ? 0 : (info.fragstotal * info.fragsize) - info.bytes);
   }
-  gst_event_unref (event);
-  return retval;
+  return delay / oss->bytes_per_sample;
 }
 
-static gboolean
-gst_oss_src_send_event (GstElement * element, GstEvent * event)
-{
-  GstOssSrc *osssrc = GST_OSSSRC (element);
-
-  return gst_oss_src_src_event (osssrc->srcpad, event);
-}
-
-static const GstQueryType *
-gst_oss_src_get_query_types (GstPad * pad)
+static void
+gst_oss_src_reset (GstAudioSrc * asrc)
 {
-  static const GstQueryType query_types[] = {
-    GST_QUERY_POSITION,
-    0,
-  };
+  GstOssSrc *oss;
 
-  return query_types;
-}
+  //gint ret;
 
-static gboolean
-gst_oss_src_src_query (GstPad * pad, GstQueryType type, GstFormat * format,
-    gint64 * value)
-{
-  gboolean res = FALSE;
-  GstOssSrc *osssrc;
+  oss = GST_OSS_SRC (asrc);
 
-  osssrc = GST_OSSSRC (GST_PAD_PARENT (pad));
-
-  switch (type) {
-    case GST_QUERY_POSITION:
-      res = gst_osselement_convert (GST_OSSELEMENT (osssrc),
-          GST_FORMAT_DEFAULT, osssrc->curoffset, format, value);
-      break;
-    default:
-      break;
-  }
-  return res;
+  /* deadlocks on my machine... */
+  //ret = ioctl (oss->fd, SNDCTL_DSP_RESET, 0);
 }
index a2b6916..f787524 100644 (file)
  */
 
 
-#ifndef __GST_OSSSRC_H__
-#define __GST_OSSSRC_H__
+#ifndef __GST_OSS_SRC_H__
+#define __GST_OSS_SRC_H__
 
 
 #include <gst/gst.h>
+#include <gst/audio/gstaudiosrc.h>
+
 #include "gstosselement.h"
 
 G_BEGIN_DECLS
 
-#define GST_TYPE_OSSSRC \
-  (gst_oss_src_get_type())
-#define GST_OSSSRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSSSRC,GstOssSrc))
-#define GST_OSSSRC_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSSSRC,GstOssSrcClass))
-#define GST_IS_OSSSRC(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSSSRC))
-#define GST_IS_OSSSRC_CLASS(obj) \
-  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSSSRC))
-
-typedef enum {
-  GST_OSSSRC_OPEN              = GST_ELEMENT_FLAG_LAST,
-
-  GST_OSSSRC_FLAG_LAST = GST_ELEMENT_FLAG_LAST+2,
-} GstOssSrcFlags;
+#define GST_TYPE_OSS_SRC          (gst_oss_src_get_type())
+#define GST_OSS_SRC(obj)          (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OSS_SRC,GstOssSrc))
+#define GST_OSS_SRC_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OSS_SRC,GstOssSrcClass))
+#define GST_IS_OSS_SRC(obj)       (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSS_SRC))
+#define GST_IS_OSS_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OSS_SRC))
 
 typedef struct _GstOssSrc GstOssSrc;
 typedef struct _GstOssSrcClass GstOssSrcClass;
 
 struct _GstOssSrc {
-  GstOssElement  element;
+  GstAudioSrc    src;
 
-  /* pads */
-  GstPad       *srcpad;
+  GstOssElement *element;
 
-  gboolean      need_eos; /* Do we need to emit an EOS? */
-  
-  /* blocking.
-   * curoffset is in *samples*. */
-  gulong        curoffset;
-  gulong        buffersize;
+  gint fd;
+  gint          bytes_per_sample;
 
-  /* clocks */
-  GstClock *provided_clock, *clock;
+  gchar *device;
+  gchar *device_name;
 };
 
 struct _GstOssSrcClass {
-  GstOssElementClass parent_class;
+  GstAudioSrcClass parent_class;
 };
 
 GType gst_oss_src_get_type(void);
 
 G_END_DECLS
 
-#endif /* __GST_OSSSRC_H__ */
+#endif /* __GST_OSS_SRC_H__ */