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