summaryrefslogtreecommitdiffstats
path: root/sys/oss
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2005-08-23 09:46:29 +0000
committerAndy Wingo <wingo@pobox.com>2005-08-23 09:46:29 +0000
commitffaaa7528a2348853c1a89963646012f2edba310 (patch)
treebe82a4e040013dcfef1596c87acdf13423c5d621 /sys/oss
parent86eb113de104057812506e7b694e9f0eda1cbef7 (diff)
sys/oss/gstosssrc.*: Totally ported, dude.
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.
Diffstat (limited to 'sys/oss')
-rw-r--r--sys/oss/Makefile.am3
-rw-r--r--sys/oss/gstossaudio.c6
-rw-r--r--sys/oss/gstosssink.c6
-rw-r--r--sys/oss/gstosssrc.c721
-rw-r--r--sys/oss/gstosssrc.h48
5 files changed, 311 insertions, 473 deletions
diff --git a/sys/oss/Makefile.am b/sys/oss/Makefile.am
index 3d6f6e79..d298b7ce 100644
--- a/sys/oss/Makefile.am
+++ b/sys/oss/Makefile.am
@@ -4,7 +4,8 @@ libgstossaudio_la_SOURCES = gstossaudio.c \
gstosselement.c \
gstosshelper.c \
gstossmixer.c \
- gstosssink.c
+ gstosssink.c \
+ gstosssrc.c
# gstossdmabuffer.c
diff --git a/sys/oss/gstossaudio.c b/sys/oss/gstossaudio.c
index 4b30faf6..65cf7037 100644
--- a/sys/oss/gstossaudio.c
+++ b/sys/oss/gstossaudio.c
@@ -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;
diff --git a/sys/oss/gstosssink.c b/sys/oss/gstosssink.c
index e26a8e79..efef1ba0 100644
--- a/sys/oss/gstosssink.c
+++ b/sys/oss/gstosssink.c
@@ -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 ]; "
diff --git a/sys/oss/gstosssrc.c b/sys/oss/gstosssrc.c
index 78e506ed..e7a5cda1 100644
--- a/sys/oss/gstosssrc.c
+++ b/sys/oss/gstosssrc.c
@@ -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:
*
@@ -23,62 +23,66 @@
#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);
}
diff --git a/sys/oss/gstosssrc.h b/sys/oss/gstosssrc.h
index a2b69164..f787524f 100644
--- a/sys/oss/gstosssrc.h
+++ b/sys/oss/gstosssrc.h
@@ -21,58 +21,44 @@
*/
-#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__ */