diff options
Diffstat (limited to 'sys/oss/gstosssrc.c')
-rw-r--r-- | sys/oss/gstosssrc.c | 322 |
1 files changed, 165 insertions, 157 deletions
diff --git a/sys/oss/gstosssrc.c b/sys/oss/gstosssrc.c index 93c048b1..b3f51693 100644 --- a/sys/oss/gstosssrc.c +++ b/sys/oss/gstosssrc.c @@ -51,7 +51,8 @@ enum { enum { ARG_0, ARG_DEVICE, - ARG_BYTESPERREAD, + ARG_BUFFERSIZE, + ARG_FRAGMENT, }; GST_PAD_TEMPLATE_FACTORY (osssrc_src_factory, @@ -85,16 +86,23 @@ static void gst_osssrc_class_init (GstOssSrcClass *klass); static void gst_osssrc_init (GstOssSrc *osssrc); static GstPadConnectReturn gst_osssrc_srcconnect (GstPad *pad, GstCaps *caps); +static const GstFormat* gst_osssrc_get_formats (GstPad *pad); +static gboolean gst_osssrc_convert (GstPad *pad, + GstFormat src_format, gint64 src_value, + GstFormat *dest_format, gint64 *dest_value); + static void gst_osssrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gst_osssrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static GstElementStateReturn gst_osssrc_change_state (GstElement *element); -static gboolean gst_osssrc_send_event (GstElement *element, GstEvent *event); -static void gst_osssrc_close_audio (GstOssSrc *src); -static gboolean gst_osssrc_open_audio (GstOssSrc *src); -static gboolean gst_osssrc_sync_parms (GstOssSrc *osssrc); +static const GstEventMask* gst_osssrc_get_event_masks (GstPad *pad); +static gboolean gst_osssrc_src_event (GstPad *pad, GstEvent *event); +static gboolean gst_osssrc_send_event (GstElement *element, GstEvent *event); +static const GstPadQueryType* gst_osssrc_get_query_types (GstPad *pad); +static gboolean gst_osssrc_src_query (GstPad *pad, GstPadQueryType type, + GstFormat *format, gint64 *value); static GstBuffer * gst_osssrc_get (GstPad *pad); @@ -134,12 +142,16 @@ gst_osssrc_class_init (GstOssSrcClass *klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BYTESPERREAD, - g_param_spec_ulong("bytes_per_read","bytes_per_read","bytes_per_read", - 0,G_MAXULONG,0,G_PARAM_READWRITE)); /* CHECKME */ + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFFERSIZE, + g_param_spec_ulong ("buffersize","Buffer Size","The size of the buffers with samples", + 0, G_MAXULONG, 0, G_PARAM_READWRITE)); g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE, - g_param_spec_string("device","device","oss device (/dev/dspN usually)", - "default",G_PARAM_READWRITE)); + g_param_spec_string ("device", "device", "oss device (/dev/dspN usually)", + "default", G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FRAGMENT, + g_param_spec_int ("fragment", "Fragment", + "The fragment as 0xMMMMSSSS (MMMM = total fragments, 2^SSSS = fragment size)", + 0, G_MAXINT, 6, G_PARAM_READWRITE)); gobject_class->set_property = gst_osssrc_set_property; gobject_class->get_property = gst_osssrc_get_property; @@ -155,25 +167,20 @@ gst_osssrc_init (GstOssSrc *osssrc) GST_PAD_TEMPLATE_GET (osssrc_src_factory), "src"); gst_pad_set_get_function (osssrc->srcpad, gst_osssrc_get); gst_pad_set_connect_function (osssrc->srcpad, gst_osssrc_srcconnect); + 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); + gst_pad_set_event_mask_function (osssrc->srcpad, gst_osssrc_get_event_masks); + gst_pad_set_query_function (osssrc->srcpad, gst_osssrc_src_query); + gst_pad_set_query_type_function (osssrc->srcpad, gst_osssrc_get_query_types); + + gst_element_add_pad (GST_ELEMENT (osssrc), osssrc->srcpad); - osssrc->device = g_strdup ("/dev/dsp"); - osssrc->fd = -1; - - /* adding some default values */ - osssrc->law = 0; - osssrc->endianness = G_BYTE_ORDER; - osssrc->sign = TRUE; - osssrc->depth = 16; - osssrc->width = 16; - osssrc->channels = 2; - osssrc->rate = 44100; - osssrc->need_eos = FALSE; - - osssrc->bytes_per_read = 4096; + gst_osscommon_init (&osssrc->common); + + osssrc->buffersize = 4096; osssrc->curoffset = 0; - osssrc->basetime = 0; - osssrc->samples_since_basetime = 0; } static GstPadConnectReturn @@ -186,29 +193,14 @@ gst_osssrc_srcconnect (GstPad *pad, GstCaps *caps) if (!GST_CAPS_IS_FIXED (caps)) return GST_PAD_CONNECT_DELAYED; - gst_caps_get_int (caps, "law", &src->law); - gst_caps_get_int (caps, "endianness", &src->endianness); - gst_caps_get_boolean (caps, "signed", &src->sign); - gst_caps_get_int (caps, "width", &src->width); - gst_caps_get_int (caps, "depth", &src->depth); - gst_caps_get_int (caps, "rate", &src->rate); - gst_caps_get_int (caps, "channels", &src->channels); + if (!gst_osscommon_parse_caps (&src->common, caps)) + return GST_PAD_CONNECT_REFUSED; - if (!gst_osssrc_sync_parms (src)) + if (!gst_osscommon_sync_parms (&src->common)) return GST_PAD_CONNECT_REFUSED; return GST_PAD_CONNECT_OK; } -#define GET_FIXED_INT(caps, name, dest) \ -G_STMT_START { \ - if (gst_caps_has_fixed_property (caps, name)) \ - gst_caps_get_int (caps, name, dest); \ -} G_STMT_END -#define GET_FIXED_BOOLEAN(caps, name, dest) \ -G_STMT_START { \ - if (gst_caps_has_fixed_property (caps, name)) \ - gst_caps_get_boolean (caps, name, dest); \ -} G_STMT_END static gboolean gst_osssrc_negotiate (GstPad *pad) @@ -220,16 +212,10 @@ gst_osssrc_negotiate (GstPad *pad) allowed = gst_pad_get_allowed_caps (pad); - /* peel off fixed stuff from the allowed caps */ - GET_FIXED_INT (allowed, "law", &src->law); - GET_FIXED_INT (allowed, "endianness", &src->endianness); - GET_FIXED_BOOLEAN (allowed, "signed", &src->sign); - GET_FIXED_INT (allowed, "width", &src->width); - GET_FIXED_INT (allowed, "depth", &src->depth); - GET_FIXED_INT (allowed, "rate", &src->rate); - GET_FIXED_INT (allowed, "channels", &src->channels); + if (!gst_osscommon_merge_fixed_caps (&src->common, allowed)) + return FALSE; - if (!gst_osssrc_sync_parms (src)) + if (!gst_osscommon_sync_parms (&src->common)) return FALSE; /* set caps on src pad */ @@ -238,13 +224,13 @@ gst_osssrc_negotiate (GstPad *pad) "oss_src", "audio/raw", "format", GST_PROPS_STRING ("int"), - "law", GST_PROPS_INT (src->law), - "endianness", GST_PROPS_INT (src->endianness), - "signed", GST_PROPS_BOOLEAN (src->sign), - "width", GST_PROPS_INT (src->width), - "depth", GST_PROPS_INT (src->depth), - "rate", GST_PROPS_INT (src->rate), - "channels", GST_PROPS_INT (src->channels) + "law", GST_PROPS_INT (src->common.law), + "endianness", GST_PROPS_INT (src->common.endianness), + "signed", GST_PROPS_BOOLEAN (src->common.sign), + "width", GST_PROPS_INT (src->common.width), + "depth", GST_PROPS_INT (src->common.depth), + "rate", GST_PROPS_INT (src->common.rate), + "channels", GST_PROPS_INT (src->common.channels) )) <= 0) { return FALSE; @@ -258,7 +244,6 @@ gst_osssrc_get (GstPad *pad) GstOssSrc *src; GstBuffer *buf; glong readbytes; - glong readsamples; src = GST_OSSSRC(gst_pad_get_parent (pad)); @@ -269,10 +254,10 @@ gst_osssrc_get (GstPad *pad) return GST_BUFFER (gst_event_new (GST_EVENT_EOS)); } - buf = gst_buffer_new_and_alloc (src->bytes_per_read); + buf = gst_buffer_new_and_alloc (src->buffersize); - readbytes = read (src->fd,GST_BUFFER_DATA (buf), - src->bytes_per_read); + readbytes = read (src->common.fd,GST_BUFFER_DATA (buf), + src->buffersize); if (readbytes == 0) { gst_element_set_eos (GST_ELEMENT (src)); @@ -286,16 +271,16 @@ gst_osssrc_get (GstPad *pad) return NULL; } } + if (src->common.bps == 0) { + gst_element_error (GST_ELEMENT (src), "no format negotiated"); + return NULL; + } GST_BUFFER_SIZE (buf) = readbytes; GST_BUFFER_OFFSET (buf) = src->curoffset; - GST_BUFFER_TIMESTAMP (buf) = src->basetime + - src->samples_since_basetime * GST_SECOND / src->rate; + GST_BUFFER_TIMESTAMP (buf) = src->curoffset * GST_SECOND / src->common.bps; src->curoffset += readbytes; - readsamples = readbytes / src->channels; - if (src->width == 16) readsamples /= 2; - src->samples_since_basetime += readsamples; GST_DEBUG (GST_CAT_PLUGIN_INFO, "pushed buffer from soundcard of %ld bytes, timestamp %lld", readbytes, GST_BUFFER_TIMESTAMP (buf)); @@ -308,19 +293,20 @@ gst_osssrc_set_property (GObject *object, guint prop_id, const GValue *value, GP { GstOssSrc *src; - /* it's not null if we got it, but it might not be ours */ - g_return_if_fail (GST_IS_OSSSRC (object)); - src = GST_OSSSRC (object); switch (prop_id) { - case ARG_BYTESPERREAD: - src->bytes_per_read = g_value_get_ulong (value); + case ARG_BUFFERSIZE: + src->buffersize = g_value_get_ulong (value); break; case ARG_DEVICE: - g_free(src->device); - src->device = g_strdup (g_value_get_string (value)); + g_free(src->common.device); + src->common.device = g_strdup (g_value_get_string (value)); break; + case ARG_FRAGMENT: + src->common.fragment = g_value_get_int (value); + gst_osscommon_sync_parms (&src->common); + break; default: break; } @@ -331,17 +317,17 @@ gst_osssrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSp { GstOssSrc *src; - /* it's not null if we got it, but it might not be ours */ - g_return_if_fail (GST_IS_OSSSRC (object)); - src = GST_OSSSRC (object); switch (prop_id) { - case ARG_BYTESPERREAD: - g_value_set_ulong (value, src->bytes_per_read); + case ARG_BUFFERSIZE: + g_value_set_ulong (value, src->buffersize); break; case ARG_DEVICE: - g_value_set_string (value, src->device); + g_value_set_string (value, src->common.device); + break; + case ARG_FRAGMENT: + g_value_set_int (value, src->common.fragment); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -361,8 +347,13 @@ gst_osssrc_change_state (GstElement *element) break; case GST_STATE_READY_TO_PAUSED: if (!GST_FLAG_IS_SET (element, GST_OSSSRC_OPEN)) { - if (!gst_osssrc_open_audio (osssrc)) + gchar *error; + if (!gst_osscommon_open_audio (&osssrc->common, GST_OSSCOMMON_READ, &error)) { + gst_element_error (GST_ELEMENT (osssrc), error); + g_free (error); return GST_STATE_FAILURE; + } + GST_FLAG_SET (osssrc, GST_OSSSRC_OPEN); } break; case GST_STATE_PAUSED_TO_PLAYING: @@ -370,8 +361,11 @@ gst_osssrc_change_state (GstElement *element) case GST_STATE_PLAYING_TO_PAUSED: break; case GST_STATE_PAUSED_TO_READY: - if (GST_FLAG_IS_SET (element, GST_OSSSRC_OPEN)) - gst_osssrc_close_audio (osssrc); + if (GST_FLAG_IS_SET (element, GST_OSSSRC_OPEN)) { + gst_osscommon_close_audio (&osssrc->common); + GST_FLAG_UNSET (osssrc, GST_OSSSRC_OPEN); + } + gst_osscommon_init (&osssrc->common); break; case GST_STATE_READY_TO_NULL: break; @@ -383,103 +377,117 @@ gst_osssrc_change_state (GstElement *element) return GST_STATE_SUCCESS; } +static const GstFormat* +gst_osssrc_get_formats (GstPad *pad) +{ + static const GstFormat formats[] = { + GST_FORMAT_TIME, + GST_FORMAT_UNITS, + GST_FORMAT_BYTES, + 0 + }; + return formats; +} + static gboolean -gst_osssrc_send_event (GstElement *element, - GstEvent *event) +gst_osssrc_convert (GstPad *pad, GstFormat src_format, gint64 src_value, + GstFormat *dest_format, gint64 *dest_value) +{ + GstOssSrc *osssrc; + + osssrc = GST_OSSSRC (gst_pad_get_parent (pad)); + + return gst_osscommon_convert (&osssrc->common, src_format, src_value, + dest_format, dest_value); +} + +static const GstEventMask* +gst_osssrc_get_event_masks (GstPad *pad) +{ + static const GstEventMask gst_osssrc_src_event_masks[] = { + { GST_EVENT_EOS, 0 }, + { GST_EVENT_SIZE, 0 }, + { 0, } + }; + return gst_osssrc_src_event_masks; +} + +static gboolean +gst_osssrc_src_event (GstPad *pad, GstEvent *event) { - gboolean retval = FALSE; GstOssSrc *osssrc; + gboolean retval = FALSE; - osssrc = GST_OSSSRC (element); + osssrc = GST_OSSSRC (gst_pad_get_parent (pad)); 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_osscommon_convert (&osssrc->common, + 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; } - gst_event_unref (event); return retval; } -static gboolean -gst_osssrc_open_audio (GstOssSrc *src) +static gboolean +gst_osssrc_send_event (GstElement *element, + GstEvent *event) { - g_return_val_if_fail (!GST_FLAG_IS_SET (src, GST_OSSSRC_OPEN), FALSE); - - /* first try to open the sound card */ - src->fd = open(src->device, O_RDONLY); - - /* if we have it, set the default parameters and go have fun */ - if (src->fd > 0) { - - /* set card state */ - GST_DEBUG (GST_CAT_PLUGIN_INFO,"opened audio: %s",src->device); - - GST_FLAG_SET (src, GST_OSSSRC_OPEN); - return TRUE; - } + GstOssSrc *osssrc = GST_OSSSRC (element); - return FALSE; + return gst_osssrc_src_event (osssrc->srcpad, event); } -static void -gst_osssrc_close_audio (GstOssSrc *src) +static const GstPadQueryType* +gst_osssrc_get_query_types (GstPad *pad) { - g_return_if_fail (GST_FLAG_IS_SET (src, GST_OSSSRC_OPEN)); + static const GstPadQueryType query_types[] = { + GST_PAD_QUERY_POSITION, + 0, + }; + return query_types; +} - close(src->fd); - src->fd = -1; - - GST_FLAG_UNSET (src, GST_OSSSRC_OPEN); -} - -static gboolean -gst_osssrc_sync_parms (GstOssSrc *osssrc) +static gboolean +gst_osssrc_src_query (GstPad *pad, GstPadQueryType type, GstFormat *format, gint64 *value) { - audio_buf_info ispace; - gint frag; - /* remember : ioctl on samplerate returns the sample rate the card - * is actually set to ! Setting it to 44101 Hz could cause it to - * be set to 44101, for example - */ - guint rate; - gint format; - gint bps; - - g_return_val_if_fail (osssrc->fd > 0, FALSE); - - /* get rate, we don't modify the original rate as the audio device - * might not exactly give us the requested value */ - rate = osssrc->rate; - - /* transform format parameters to oss format */ - if (!gst_ossformat_get (osssrc->law, osssrc->endianness, osssrc->sign, - osssrc->width, osssrc->depth, &format, &bps)) - { - return FALSE; + gboolean res = FALSE; + GstOssSrc *osssrc; + + osssrc = GST_OSSSRC (gst_pad_get_parent (pad)); + + switch (type) { + case GST_PAD_QUERY_POSITION: + res = gst_osscommon_convert (&osssrc->common, + GST_FORMAT_BYTES, osssrc->curoffset, + format, value); + break; + default: + break; } - - frag = 0x7fff0006; - - ioctl(osssrc->fd, SNDCTL_DSP_SETFRAGMENT, &frag); - ioctl(osssrc->fd, SNDCTL_DSP_RESET, 0); - - ioctl(osssrc->fd, SNDCTL_DSP_SETFMT, &format); - ioctl(osssrc->fd, SNDCTL_DSP_CHANNELS, &osssrc->channels); - ioctl(osssrc->fd, SNDCTL_DSP_SPEED, &rate); - ioctl(osssrc->fd, SNDCTL_DSP_GETISPACE, &ispace); - ioctl(osssrc->fd, SNDCTL_DSP_GETBLKSIZE, &frag); - - g_print("setting sound card to %dHz %d bit %s (%d bytes buffer, %d fragment)\n", - rate, osssrc->width, - (osssrc->channels == 2) ? "stereo" : "mono", ispace.bytes, frag); - - return TRUE; -} + return res; +} gboolean gst_osssrc_factory_init (GstPlugin *plugin) |