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);  | 
