From ffaaa7528a2348853c1a89963646012f2edba310 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Tue, 23 Aug 2005 09:46:29 +0000 Subject: sys/oss/gstosssrc.*: Totally ported, dude. Original commit message from CVS: 2005-08-23 Andy Wingo * 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. --- sys/oss/Makefile.am | 3 +- sys/oss/gstossaudio.c | 6 +- sys/oss/gstosssink.c | 6 +- sys/oss/gstosssrc.c | 721 ++++++++++++++++++++------------------------------ sys/oss/gstosssrc.h | 48 ++-- 5 files changed, 311 insertions(+), 473 deletions(-) (limited to 'sys/oss') 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 - * 2000 Wim Taymans + * 2000,2005 Wim Taymans * * gstosssrc.c: * @@ -23,62 +23,66 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include -#include -#include #include +#include #include #include #include - -#ifdef HAVE_OSS_INCLUDE_IN_SYS #include -#else - -#ifdef HAVE_OSS_INCLUDE_IN_ROOT -#include -#else -#include +#include "gstosssrc.h" -#endif /* HAVE_OSS_INCLUDE_IN_ROOT */ -#endif /* HAVE_OSS_INCLUDE_IN_SYS */ - -#include -#include -#include - -/* elementfactory information */ static GstElementDetails gst_oss_src_details = GST_ELEMENT_DETAILS ("Audio Source (OSS)", "Source/Audio", - "Read from the sound card", - "Erik Walthinsen "); + "Capture from a sound card via OSS", + "Erik Walthinsen , " "Wim Taymans "); -/* 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 +#include + #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__ */ -- cgit