Oh, I also should have mentioned that this patch fixes the
SunRay mixer problem, so the mixer should now work on SunRay's.

Brian Cameron wrote:
> 
> The attached patch updates gst-plugins-good to CVS head, and
> includes what was previously in 3 separate patches.  This
> patch also includes the work that Jan Schmidt has done to
> improve the performance of changing volume in programs like
> rhythmbox and totem.
> 
> You can refer to bugzilla bug #360673 for more information
> that Padraig, Jan and myself did to resolve these issues.
> Much thanks to Padraig for getting some momentum behind
> resolving these issues.  Now media performance on Solaris
> is much better than it was before.
> 
> Brian
> 
> 
> ------------------------------------------------------------------------
> 
> Index: ChangeLog
> ===================================================================
> --- ChangeLog (revision 9997)
> +++ ChangeLog (working copy)
> @@ -1,3 +1,14 @@
> +2006-12-11  Brian Cameron  <brian.cameron at sun.com>
> +
> +     * patches/gst-plugins-good-03-srcopen.diff, 
> +       patches/gst-plugins-good-04-master.diff,
> +       patches/gst-plugins-good-05-reset.diff:  Remove patches that are
> +       now contained in the single gst-plugins-03-cvshead.diff patch.
> +     * gst.spec, gst-plugins-good.spec, patches/gst-plugins-03-cvshead.diff:
> +       Updated patch to replace 3 older patches and update to CVS head
> +       which has these fixes and also fixes the performance issues with
> +       change volume in GStreamer applications.
> +
>  2006-12-11  Damien Carbery <damien.carbery at sun.com>
>  
>       * metacity.spec: Bump to 2.17.3.
> Index: patches/gst-plugins-good-03-srcopen.diff
> ===================================================================
> --- patches/gst-plugins-good-03-srcopen.diff  (revision 9997)
> +++ patches/gst-plugins-good-03-srcopen.diff  (working copy)
> @@ -1,26 +0,0 @@
> ---- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosrc.c-orig       
> 2006-08-28 15:50:15.105741000 -0500
> -+++ gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosrc.c    2006-08-28 
> 15:50:18.220367000 -0500
> -@@ -46,6 +46,7 @@
> - #include <string.h>
> - #include <unistd.h>
> - #include <stropts.h>
> -+#include <sys/mixer.h>
> - 
> - #include "gstsunaudiosrc.h"
> - 
> -@@ -241,11 +242,12 @@ static gboolean
> - gst_sunaudiosrc_open (GstAudioSrc * asrc)
> - {
> -   GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
> --  int fd, ret;
> -+  int fd, ret, err;
> - 
> --  fd = open (sunaudiosrc->device, O_RDWR | O_NONBLOCK);
> -+  fd = open (sunaudiosrc->device, O_RDONLY);
> -+  err = ioctl(fd, AUDIO_MIXER_MULTIPLE_OPEN);
> - 
> --  if (fd == -1) {
> -+  if (fd == -1 || err == -1) {
> -     GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, OPEN_READ, (NULL),
> -         ("can't open connection to Sun Audio device %s", 
> sunaudiosrc->device));
> - 
> Index: patches/gst-plugins-good-04-master.diff
> ===================================================================
> --- patches/gst-plugins-good-04-master.diff   (revision 9997)
> +++ patches/gst-plugins-good-04-master.diff   (working copy)
> @@ -1,16 +0,0 @@
> -diff -u gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixerctrl.c-orig 
> gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixerctrl.c
> ---- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixerctrl.c-orig 
> 2006-09-15 15:04:48.217088000 +0100
> -+++ gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixerctrl.c      
> 2006-09-15 15:05:18.769401000 +0100
> -@@ -74,9 +74,9 @@
> -   if (mixer->tracklist == NULL) {
> -     g_return_if_fail (mixer->mixer_fd != -1);
> - 
> --    /* Output */
> -+    /* Output & should be MASTER when it's the only one. */
> -     track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_OUTPUT,
> --        2, GST_MIXER_TRACK_OUTPUT);
> -+        2, GST_MIXER_TRACK_OUTPUT|GST_MIXER_TRACK_MASTER);
> -     mixer->tracklist = g_list_append (mixer->tracklist, track);
> - 
> -     /* Input */
> -
> Index: patches/gst-plugins-good-05-reset.diff
> ===================================================================
> --- patches/gst-plugins-good-05-reset.diff    (revision 9997)
> +++ patches/gst-plugins-good-05-reset.diff    (working copy)
> @@ -1,105 +0,0 @@
> ---- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosink.c-orig      
> 2006-11-27 15:31:20.547804000 -0600
> -+++ gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosink.c   2006-11-27 
> 15:31:31.945555000 -0600
> -@@ -42,6 +42,7 @@
> - 
> - #include <fcntl.h>
> - #include <string.h>
> -+#include <stropts.h>
> - #include <unistd.h>
> - #include <sys/mman.h>
> - 
> -@@ -390,4 +391,45 @@ gst_sunaudiosink_delay (GstAudioSink * a
> - static void
> - gst_sunaudiosink_reset (GstAudioSink * asink)
> - {
> -+  /* Get current values */
> -+  GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink);
> -+  audio_info_t ainfo;
> -+  int ret;
> -+
> -+  ret = ioctl (sunaudiosink->fd, AUDIO_GETINFO, &ainfo);
> -+  if (ret == -1) {
> -+    /*
> -+     * Should never happen, but if we couldn't getinfo, then no point
> -+     * trying to setinfo
> -+     */
> -+    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> -+            strerror (errno)));
> -+    return;
> -+  }
> -+
> -+  /*
> -+   * Pause the audio - so audio stops playing immediately rather than
> -+   * waiting for the ringbuffer to empty.
> -+   */
> -+  ainfo.play.pause = !NULL;
> -+  ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo);
> -+  if (ret == -1) {
> -+    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> -+            strerror (errno)));
> -+  }
> -+
> -+  /* Flush the audio */
> -+  ret = ioctl(sunaudiosink->fd, I_FLUSH, FLUSHW);
> -+  if (ret == -1) {
> -+    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> -+            strerror (errno)));
> -+  }
> -+
> -+  /* unpause the audio */
> -+  ainfo.play.pause = NULL;
> -+  ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo);
> -+  if (ret == -1) {
> -+    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> -+            strerror (errno)));
> -+  }
> - }
> ---- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosrc.c-orig       
> 2006-11-27 15:33:27.137164000 -0600
> -+++ gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosrc.c    2006-11-27 
> 15:35:11.133518000 -0600
> -@@ -398,5 +398,45 @@ gst_sunaudiosrc_delay (GstAudioSrc * asr
> - static void
> - gst_sunaudiosrc_reset (GstAudioSrc * asrc)
> - {
> --  return;
> -+  /* Get current values */
> -+  GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
> -+  audio_info_t ainfo;
> -+  int ret;
> -+
> -+  ret = ioctl (sunaudiosrc->fd, AUDIO_GETINFO, &ainfo);
> -+  if (ret == -1) {
> -+    /*
> -+     * Should never happen, but if we couldn't getinfo, then no point
> -+     * trying to setinfo
> -+     */
> -+    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
> -+            strerror (errno)));
> -+    return;
> -+  }
> -+
> -+  /*
> -+   * Pause the audio - so audio stops playing immediately rather than
> -+   * waiting for the ringbuffer to empty.
> -+   */
> -+  ainfo.record.pause = !NULL;
> -+  ret = ioctl (sunaudiosrc->fd, AUDIO_SETINFO, &ainfo);
> -+  if (ret == -1) {
> -+    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
> -+            strerror (errno)));
> -+  }
> -+
> -+  /* Flush the audio */
> -+  ret = ioctl(sunaudiosrc->fd, I_FLUSH, FLUSHR);
> -+  if (ret == -1) {
> -+    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
> -+            strerror (errno)));
> -+  }
> -+
> -+  /* unpause the audio */
> -+  ainfo.record.pause = NULL;
> -+  ret = ioctl (sunaudiosrc->fd, AUDIO_SETINFO, &ainfo);
> -+  if (ret == -1) {
> -+    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
> -+            strerror (errno)));
> -+  }
> - }
> Index: patches/gst-plugins-good-03-cvshead.diff
> ===================================================================
> --- patches/gst-plugins-good-03-cvshead.diff  (revision 0)
> +++ patches/gst-plugins-good-03-cvshead.diff  (revision 0)
> @@ -0,0 +1,646 @@
> +diff -urp gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixer.c 
> gst-plugins-good/sys/sunaudio/gstsunaudiomixer.c
> +--- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixer.c  2006-05-03 
> 04:26:52.000000000 -0500
> ++++ gst-plugins-good/sys/sunaudio/gstsunaudiomixer.c 2006-12-08 
> 08:42:42.000000000 -0600
> +@@ -86,7 +86,7 @@ gst_sunaudiomixer_change_state (GstEleme
> +         if (audiodev == NULL) {
> +           this->mixer = gst_sunaudiomixer_ctrl_new ("/dev/audioctl");
> +         } else {
> +-          gchar *device = g_strdup_printf ("/dev/%sctl", audiodev);
> ++          gchar *device = g_strdup_printf ("%sctl", audiodev);
> + 
> +           this->mixer = gst_sunaudiomixer_ctrl_new (device);
> +           g_free (device);
> +diff -urp gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixerctrl.c 
> gst-plugins-good/sys/sunaudio/gstsunaudiomixerctrl.c
> +--- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixerctrl.c      
> 2006-08-08 05:27:29.000000000 -0500
> ++++ gst-plugins-good/sys/sunaudio/gstsunaudiomixerctrl.c     2006-12-09 
> 10:17:33.000000000 -0600
> +@@ -35,6 +35,9 @@
> + #include "gstsunaudiomixerctrl.h"
> + #include "gstsunaudiomixertrack.h"
> + 
> ++GST_DEBUG_CATEGORY_EXTERN (sunaudio_debug);
> ++#define GST_CAT_DEFAULT sunaudio_debug
> ++
> + #define SCALE_FACTOR 2.55       /* 255/100 */
> + 
> + static gboolean
> +@@ -74,9 +77,9 @@ gst_sunaudiomixer_ctrl_build_list (GstSu
> +   if (mixer->tracklist == NULL) {
> +     g_return_if_fail (mixer->mixer_fd != -1);
> + 
> +-    /* Output */
> ++    /* Output & should be MASTER when it's the only one. */
> +     track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_OUTPUT,
> +-        2, GST_MIXER_TRACK_OUTPUT);
> ++        2, GST_MIXER_TRACK_OUTPUT | GST_MIXER_TRACK_MASTER);
> +     mixer->tracklist = g_list_append (mixer->tracklist, track);
> + 
> +     /* Input */
> +diff -urp gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixertrack.h 
> gst-plugins-good/sys/sunaudio/gstsunaudiomixertrack.h
> +--- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiomixertrack.h     
> 2006-08-08 05:27:29.000000000 -0500
> ++++ gst-plugins-good/sys/sunaudio/gstsunaudiomixertrack.h    2006-10-16 
> 13:22:47.000000000 -0500
> +@@ -62,7 +62,7 @@ typedef struct _GstSunAudioMixerTrackCla
> + } GstSunAudioMixerTrackClass;
> + 
> + GType               gst_sunaudiomixer_track_get_type        (void);
> +-GstMixerTrack*      gst_sunaudiomixer_track_new             (gint 
> track_num, gint max_chans, gint flags);
> ++GstMixerTrack*      gst_sunaudiomixer_track_new             
> (GstSunAudioTrackType track_num, gint max_chans, gint flags);
> + 
> + G_END_DECLS
> + 
> +diff -urp gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosink.c 
> gst-plugins-good/sys/sunaudio/gstsunaudiosink.c
> +--- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosink.c   2006-08-08 
> 05:27:29.000000000 -0500
> ++++ gst-plugins-good/sys/sunaudio/gstsunaudiosink.c  2006-12-11 
> 15:21:16.000000000 -0600
> +@@ -42,11 +42,15 @@
> + 
> + #include <fcntl.h>
> + #include <string.h>
> ++#include <stropts.h>
> + #include <unistd.h>
> + #include <sys/mman.h>
> + 
> + #include "gstsunaudiosink.h"
> + 
> ++GST_DEBUG_CATEGORY_EXTERN (sunaudio_debug);
> ++#define GST_CAT_DEFAULT sunaudio_debug
> ++
> + /* elementfactory information */
> + static const GstElementDetails plugin_details =
> + GST_ELEMENT_DETAILS ("Sun Audio Sink",
> +@@ -59,6 +63,7 @@ static void gst_sunaudiosink_base_init (
> + static void gst_sunaudiosink_class_init (GstSunAudioSinkClass * klass);
> + static void gst_sunaudiosink_init (GstSunAudioSink * filter);
> + static void gst_sunaudiosink_dispose (GObject * object);
> ++static void gst_sunaudiosink_finalize (GObject * object);
> + 
> + static void gst_sunaudiosink_set_property (GObject * object, guint prop_id,
> +     const GValue * value, GParamSpec * pspec);
> +@@ -128,6 +133,24 @@ gst_sunaudiosink_dispose (GObject * obje
> + }
> + 
> + static void
> ++gst_sunaudiosink_finalize (GObject * object)
> ++{
> ++  GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (object);
> ++
> ++  g_mutex_free (sunaudiosink->write_mutex);
> ++  g_cond_free (sunaudiosink->sleep_cond);
> ++
> ++  g_free (sunaudiosink->device);
> ++
> ++  if (sunaudiosink->fd != -1) {
> ++    close (sunaudiosink->fd);
> ++    sunaudiosink->fd = -1;
> ++  }
> ++
> ++  G_OBJECT_CLASS (parent_class)->finalize (object);
> ++}
> ++
> ++static void
> + gst_sunaudiosink_base_init (gpointer g_class)
> + {
> +   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
> +@@ -155,6 +178,8 @@ gst_sunaudiosink_class_init (GstSunAudio
> +   parent_class = g_type_class_peek_parent (klass);
> + 
> +   gobject_class->dispose = gst_sunaudiosink_dispose;
> ++  gobject_class->finalize = gst_sunaudiosink_finalize;
> ++
> +   gobject_class->set_property =
> +       GST_DEBUG_FUNCPTR (gst_sunaudiosink_set_property);
> +   gobject_class->get_property =
> +@@ -174,12 +199,12 @@ gst_sunaudiosink_class_init (GstSunAudio
> +   g_object_class_install_property (gobject_class, PROP_DEVICE,
> +       g_param_spec_string ("device", "Device", "Audio Device (/dev/audio)",
> +           DEFAULT_DEVICE, G_PARAM_READWRITE));
> +-
> + }
> + 
> + static void
> + gst_sunaudiosink_init (GstSunAudioSink * sunaudiosink)
> + {
> ++  GstBaseAudioSink *ba_sink = GST_BASE_AUDIO_SINK (sunaudiosink);
> +   const char *audiodev;
> + 
> +   GST_DEBUG_OBJECT (sunaudiosink, "initializing sunaudiosink");
> +@@ -190,6 +215,10 @@ gst_sunaudiosink_init (GstSunAudioSink *
> +   if (audiodev == NULL)
> +     audiodev = DEFAULT_DEVICE;
> +   sunaudiosink->device = g_strdup (audiodev);
> ++
> ++  /* mutex and gconf used to control the write method */
> ++  sunaudiosink->write_mutex = g_mutex_new ();
> ++  sunaudiosink->sleep_cond = g_cond_new ();
> + }
> + 
> + static void
> +@@ -202,8 +231,10 @@ gst_sunaudiosink_set_property (GObject *
> + 
> +   switch (prop_id) {
> +     case PROP_DEVICE:
> ++      GST_OBJECT_LOCK (sunaudiosink);
> +       g_free (sunaudiosink->device);
> +       sunaudiosink->device = g_strdup (g_value_get_string (value));
> ++      GST_OBJECT_UNLOCK (sunaudiosink);
> +       break;
> +     default:
> +       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
> +@@ -221,7 +252,9 @@ gst_sunaudiosink_get_property (GObject *
> + 
> +   switch (prop_id) {
> +     case PROP_DEVICE:
> ++      GST_OBJECT_LOCK (sunaudiosink);
> +       g_value_set_string (value, sunaudiosink->device);
> ++      GST_OBJECT_UNLOCK (sunaudiosink);
> +       break;
> +     default:
> +       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
> +@@ -253,6 +286,7 @@ gst_sunaudiosink_open (GstAudioSink * as
> +   int fd, ret;
> + 
> +   /* First try to open non-blocking */
> ++  GST_OBJECT_LOCK (sunaudiosink);
> +   fd = open (sunaudiosink->device, O_WRONLY | O_NONBLOCK);
> + 
> +   if (fd >= 0) {
> +@@ -261,31 +295,24 @@ gst_sunaudiosink_open (GstAudioSink * as
> +   }
> + 
> +   if (fd == -1) {
> +-    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, OPEN_WRITE, (NULL),
> +-        ("can't open connection to Sun Audio device %s", 
> sunaudiosink->device));
> +-
> +-    return FALSE;
> ++    GST_OBJECT_UNLOCK (sunaudiosink);
> ++    goto open_failed;
> +   }
> + 
> +   sunaudiosink->fd = fd;
> ++  GST_OBJECT_UNLOCK (sunaudiosink);
> + 
> +   ret = ioctl (fd, AUDIO_GETDEV, &sunaudiosink->dev);
> +-  if (ret == -1) {
> +-    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> +-            strerror (errno)));
> +-    return FALSE;
> +-  }
> ++  if (ret == -1)
> ++    goto ioctl_error;
> + 
> +   GST_DEBUG_OBJECT (sunaudiosink, "name %s", sunaudiosink->dev.name);
> +   GST_DEBUG_OBJECT (sunaudiosink, "version %s", sunaudiosink->dev.version);
> +   GST_DEBUG_OBJECT (sunaudiosink, "config %s", sunaudiosink->dev.config);
> + 
> +   ret = ioctl (fd, AUDIO_GETINFO, &sunaudiosink->info);
> +-  if (ret == -1) {
> +-    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> +-            strerror (errno)));
> +-    return FALSE;
> +-  }
> ++  if (ret == -1)
> ++    goto ioctl_error;
> + 
> +   GST_DEBUG_OBJECT (sunaudiosink, "monitor_gain %d",
> +       sunaudiosink->info.monitor_gain);
> +@@ -299,6 +326,16 @@ gst_sunaudiosink_open (GstAudioSink * as
> +       sunaudiosink->info.sw_features_enabled);
> + 
> +   return TRUE;
> ++
> ++open_failed:
> ++  GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, OPEN_WRITE, (NULL),
> ++      ("can't open connection to Sun Audio device %s", 
> sunaudiosink->device));
> ++  return FALSE;
> ++ioctl_error:
> ++  close (sunaudiosink->fd);
> ++  GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> ++          strerror (errno)));
> ++  return FALSE;
> + }
> + 
> + static gboolean
> +@@ -306,8 +343,10 @@ gst_sunaudiosink_close (GstAudioSink * a
> + {
> +   GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink);
> + 
> +-  close (sunaudiosink->fd);
> +-  sunaudiosink->fd = -1;
> ++  if (sunaudiosink->fd != -1) {
> ++    close (sunaudiosink->fd);
> ++    sunaudiosink->fd = -1;
> ++  }
> +   return TRUE;
> + }
> + 
> +@@ -339,16 +378,12 @@ gst_sunaudiosink_prepare (GstAudioSink *
> +   ainfo.play.encoding = AUDIO_ENCODING_LINEAR;
> +   ainfo.play.port = ports;
> + 
> +-  /*
> +-   * SunAudio doesn't really give access to buffer size, these values work. 
>  Setting
> +-   * the buffer so large (512K) is a bit annoying because this causes the 
> volume
> +-   * control in audio players to be slow in responding since the audio 
> volume won't
> +-   * change until the buffer empties.  SunAudio doesn't seem to allow 
> changing the
> +-   * audio output buffer size to anything smaller, though.  I notice 
> setting the
> +-   * values smaller causes the audio to stutter, which is worse.
> +-   */
> +-  spec->segsize = 4096;
> +-  spec->segtotal = 128;
> ++  /* buffer_time for playback is not implemented in Solaris at the moment,
> ++     but at some point in the future, it might be */
> ++  ainfo.play.buffer_size =
> ++      gst_util_uint64_scale (spec->rate * spec->bytes_per_sample,
> ++      spec->buffer_time, GST_SECOND / GST_USECOND);
> ++
> +   spec->silence_sample[0] = 0;
> +   spec->silence_sample[1] = 0;
> +   spec->silence_sample[2] = 0;
> +@@ -361,6 +396,34 @@ gst_sunaudiosink_prepare (GstAudioSink *
> +     return FALSE;
> +   }
> + 
> ++  /* Now read back the info to find out the actual buffer size and set 
> ++     segtotal */
> ++  AUDIO_INITINFO (&ainfo);
> ++
> ++  ret = ioctl (sunaudiosink->fd, AUDIO_GETINFO, &ainfo);
> ++  if (ret == -1) {
> ++    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++    return FALSE;
> ++  }
> ++#if 0
> ++  /* We don't actually use the buffer_size from the sound device, because
> ++   * it seems it's just bogus sometimes */
> ++  sunaudiosink->segtotal = spec->segtotal =
> ++      ainfo.play.buffer_size / spec->segsize;
> ++#else
> ++  sunaudiosink->segtotal = spec->segtotal;
> ++#endif
> ++  sunaudiosink->segtotal_samples =
> ++      spec->segtotal * spec->segsize / spec->bytes_per_sample;
> ++
> ++  sunaudiosink->segs_written = (gint) ainfo.play.eof;
> ++  sunaudiosink->samples_written = ainfo.play.samples;
> ++  sunaudiosink->bytes_per_sample = spec->bytes_per_sample;
> ++
> ++  GST_DEBUG_OBJECT (sunaudiosink, "Got device buffer_size of %u",
> ++      ainfo.play.buffer_size);
> ++
> +   return TRUE;
> + }
> + 
> +@@ -370,24 +433,231 @@ gst_sunaudiosink_unprepare (GstAudioSink
> +   return TRUE;
> + }
> + 
> ++#define LOOP_WHILE_EINTR(v,func) do { (v) = (func); } \
> ++            while ((v) == -1 && errno == EINTR);
> ++
> ++/* Called with the write_mutex held */
> ++static void
> ++gst_sunaudio_sink_do_delay (GstSunAudioSink * sink)
> ++{
> ++  GstBaseAudioSink *ba_sink = GST_BASE_AUDIO_SINK (sink);
> ++  GstClockTime total_sleep;
> ++  GstClockTime max_sleep;
> ++  gint sleep_usecs;
> ++  GTimeVal sleep_end;
> ++  gint err;
> ++  audio_info_t ainfo;
> ++  guint diff;
> ++
> ++  /* This code below ensures that we don't race any further than 
> buffer_time 
> ++   * ahead of the audio output, by sleeping if the next write call would 
> cause
> ++   * us to advance too far in the ring-buffer */
> ++  LOOP_WHILE_EINTR (err, ioctl (sink->fd, AUDIO_GETINFO, &ainfo));
> ++  if (err < 0)
> ++    goto write_error;
> ++
> ++  /* Compute our offset from the output (copes with overflow) */
> ++  diff = (guint) (sink->segs_written) - ainfo.play.eof;
> ++  if (diff > sink->segtotal) {
> ++    /* This implies that reset did a flush just as the sound device aquired
> ++     * some buffers internally, and it causes us to be out of sync with the
> ++     * eof measure. This corrects it */
> ++    sink->segs_written = ainfo.play.eof;
> ++    diff = 0;
> ++  }
> ++
> ++  if (diff + 1 < sink->segtotal)
> ++    return;                     /* no need to sleep at all */
> ++
> ++  /* Never sleep longer than the initial number of undrained segments in 
> the 
> ++     device plus one */
> ++  total_sleep = 0;
> ++  max_sleep = (diff + 1) * (ba_sink->latency_time * GST_USECOND);
> ++  /* sleep for a segment period between .eof polls */
> ++  sleep_usecs = ba_sink->latency_time;
> ++
> ++  /* Current time is our reference point */
> ++  g_get_current_time (&sleep_end);
> ++
> ++  /* If the next segment would take us too far along the ring buffer,
> ++   * sleep for a bit to free up a slot. If there were a way to find out
> ++   * when the eof field actually increments, we could use, but the only
> ++   * notification mechanism seems to be SIGPOLL, which we can't use from
> ++   * a support library */
> ++  while (diff + 1 >= sink->segtotal && total_sleep < max_sleep) {
> ++    GST_LOG_OBJECT (sink, "need to block to drain segment(s). "
> ++        "Sleeping for %d us", sleep_usecs);
> ++
> ++    g_time_val_add (&sleep_end, sleep_usecs);
> ++
> ++    if (g_cond_timed_wait (sink->sleep_cond, sink->write_mutex, 
> &sleep_end)) {
> ++      GST_LOG_OBJECT (sink, "Waking up early due to reset");
> ++      return;                   /* Got told to wake up */
> ++    }
> ++    total_sleep += (sleep_usecs * GST_USECOND);
> ++
> ++    LOOP_WHILE_EINTR (err, ioctl (sink->fd, AUDIO_GETINFO, &ainfo));
> ++    if (err < 0)
> ++      goto write_error;
> ++
> ++    /* Compute our (new) offset from the output (copes with overflow) */
> ++    diff = (guint) g_atomic_int_get (&sink->segs_written) - ainfo.play.eof;
> ++  }
> ++
> ++  return;
> ++
> ++write_error:
> ++  GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
> ++      ("Playback error on device '%s': %s", sink->device, strerror 
> (errno)));
> ++  return;
> ++poll_failed:
> ++  GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
> ++      ("Playback error on device '%s': %s", sink->device, strerror 
> (errno)));
> ++  return;
> ++}
> ++
> + static guint
> + gst_sunaudiosink_write (GstAudioSink * asink, gpointer data, guint length)
> + {
> +-  return write (GST_SUNAUDIO_SINK (asink)->fd, data, length);
> ++  GstSunAudioSink *sink = GST_SUNAUDIO_SINK (asink);
> ++
> ++  gint bytes_written, err;
> ++
> ++  g_mutex_lock (sink->write_mutex);
> ++  if (sink->flushing) {
> ++    /* Exit immediately if reset tells us to */
> ++    g_mutex_unlock (sink->write_mutex);
> ++    return length;
> ++  }
> ++
> ++  LOOP_WHILE_EINTR (bytes_written, write (sink->fd, data, length));
> ++  if (bytes_written < 0) {
> ++    err = bytes_written;
> ++    goto write_error;
> ++  }
> ++
> ++  /* Increment our sample counter, for delay calcs */
> ++  g_atomic_int_add (&sink->samples_written, length / 
> sink->bytes_per_sample);
> ++
> ++  /* Don't consider the segment written if we didn't output the whole lot 
> yet */
> ++  if (bytes_written < length) {
> ++    g_mutex_unlock (sink->write_mutex);
> ++    return (guint) bytes_written;
> ++  }
> ++
> ++  /* Write a zero length output to trigger increment of the eof field */
> ++  LOOP_WHILE_EINTR (err, write (sink->fd, NULL, 0));
> ++  if (err < 0)
> ++    goto write_error;
> ++
> ++  /* Count this extra segment we've written */
> ++  sink->segs_written += 1;
> ++
> ++  /* Now delay so we don't overrun the ring buffer */
> ++  gst_sunaudio_sink_do_delay (sink);
> ++
> ++  g_mutex_unlock (sink->write_mutex);
> ++  return length;
> ++
> ++write_error:
> ++  g_mutex_unlock (sink->write_mutex);
> ++
> ++  GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
> ++      ("Playback error on device '%s': %s", sink->device, strerror 
> (errno)));
> ++  return length;                /* Say we wrote the segment to let the 
> ringbuffer exit */
> + }
> + 
> + /*
> +- * Should provide the current delay between writing a sample to the
> +- * audio device and that sample being actually played.  Returning 0 for
> +- * now, but this isn't good for synchronization
> +- */
> ++ * Provide the current number of unplayed samples that have been written
> ++ * to the device */
> + static guint
> + gst_sunaudiosink_delay (GstAudioSink * asink)
> + {
> +-  return 0;
> ++  GstSunAudioSink *sink = GST_SUNAUDIO_SINK (asink);
> ++  audio_info_t ainfo;
> ++  gint ret;
> ++  guint offset;
> ++
> ++  ret = ioctl (sink->fd, AUDIO_GETINFO, &ainfo);
> ++  if (G_UNLIKELY (ret == -1))
> ++    return 0;
> ++
> ++  offset = (g_atomic_int_get (&sink->samples_written) - ainfo.play.samples);
> ++
> ++  /* If the offset is larger than the total ringbuffer size, then we asked
> ++     between the write call and when samples_written is updated */
> ++  if (G_UNLIKELY (offset > sink->segtotal_samples))
> ++    return 0;
> ++
> ++  return offset;
> + }
> + 
> + static void
> + gst_sunaudiosink_reset (GstAudioSink * asink)
> + {
> ++  /* Get current values */
> ++  GstSunAudioSink *sunaudiosink = GST_SUNAUDIO_SINK (asink);
> ++  audio_info_t ainfo;
> ++  int ret;
> ++
> ++  ret = ioctl (sunaudiosink->fd, AUDIO_GETINFO, &ainfo);
> ++  if (ret == -1) {
> ++    /*
> ++     * Should never happen, but if we couldn't getinfo, then no point
> ++     * trying to setinfo
> ++     */
> ++    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++    return;
> ++  }
> ++
> ++  /*
> ++   * Pause the audio - so audio stops playing immediately rather than
> ++   * waiting for the ringbuffer to empty.
> ++   */
> ++  ainfo.play.pause = !NULL;
> ++  ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo);
> ++  if (ret == -1) {
> ++    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++  }
> ++
> ++  /* Flush the audio */
> ++  ret = ioctl (sunaudiosink->fd, I_FLUSH, FLUSHW);
> ++  if (ret == -1) {
> ++    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++  }
> ++
> ++  /* Now, we take the write_mutex and signal to ensure the write thread
> ++   * is not busy, and we signal the condition to wake up any sleeper,
> ++   * then we flush again in case the write wrote something after we flushed,
> ++   * and finally release the lock and unpause */
> ++  g_mutex_lock (sunaudiosink->write_mutex);
> ++  sunaudiosink->flushing = TRUE;
> ++
> ++  g_cond_signal (sunaudiosink->sleep_cond);
> ++
> ++  ret = ioctl (sunaudiosink->fd, I_FLUSH, FLUSHW);
> ++  if (ret == -1) {
> ++    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++  }
> ++
> ++  /* unpause the audio */
> ++  ainfo.play.pause = NULL;
> ++  ret = ioctl (sunaudiosink->fd, AUDIO_SETINFO, &ainfo);
> ++  if (ret == -1) {
> ++    GST_ELEMENT_ERROR (sunaudiosink, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++  }
> ++
> ++  /* After flushing the audio device, we need to remeasure the sample count
> ++   * and segments written count so we're in sync with the device */
> ++
> ++  sunaudiosink->segs_written = ainfo.play.eof;
> ++  g_atomic_int_set (&sunaudiosink->samples_written, ainfo.play.samples);
> ++
> ++  sunaudiosink->flushing = FALSE;
> ++  g_mutex_unlock (sunaudiosink->write_mutex);
> + }
> +diff -urp gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosink.h 
> gst-plugins-good/sys/sunaudio/gstsunaudiosink.h
> +--- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosink.h   2006-08-08 
> 05:27:29.000000000 -0500
> ++++ gst-plugins-good/sys/sunaudio/gstsunaudiosink.h  2006-12-09 
> 10:17:33.000000000 -0600
> +@@ -47,7 +47,20 @@ struct _GstSunAudioSink {
> +   audio_device_t dev;
> +   audio_info_t info;
> + 
> +-  gint   bytes_per_sample;
> ++  /* Number of segments the ringbuffer is configured for */
> ++  guint segtotal;
> ++  guint segtotal_samples;
> ++
> ++  /* Number of segments written to the device */
> ++  gint segs_written;
> ++  /* Number of samples written to the device */
> ++  gint samples_written;
> ++  guint bytes_per_sample;
> ++
> ++  /* mutex and gconf used to control the write method */
> ++  GMutex *write_mutex;
> ++  GCond *sleep_cond;
> ++  gboolean flushing;
> + };
> + 
> + struct _GstSunAudioSinkClass {
> +diff -urp gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosrc.c 
> gst-plugins-good/sys/sunaudio/gstsunaudiosrc.c
> +--- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosrc.c    2006-07-28 
> 03:32:47.000000000 -0500
> ++++ gst-plugins-good/sys/sunaudio/gstsunaudiosrc.c   2006-12-09 
> 10:17:33.000000000 -0600
> +@@ -46,9 +46,13 @@
> + #include <string.h>
> + #include <unistd.h>
> + #include <stropts.h>
> ++#include <sys/mixer.h>
> + 
> + #include "gstsunaudiosrc.h"
> + 
> ++GST_DEBUG_CATEGORY_EXTERN (sunaudio_debug);
> ++#define GST_CAT_DEFAULT sunaudio_debug
> ++
> + static GstElementDetails plugin_details =
> + GST_ELEMENT_DETAILS ("Sun Audio Source",
> +     "Source/Audio",
> +@@ -241,11 +245,12 @@ static gboolean
> + gst_sunaudiosrc_open (GstAudioSrc * asrc)
> + {
> +   GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
> +-  int fd, ret;
> ++  int fd, ret, err;
> + 
> +-  fd = open (sunaudiosrc->device, O_RDWR | O_NONBLOCK);
> ++  fd = open (sunaudiosrc->device, O_RDONLY);
> ++  err = ioctl (fd, AUDIO_MIXER_MULTIPLE_OPEN);
> + 
> +-  if (fd == -1) {
> ++  if (fd == -1 || err == -1) {
> +     GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, OPEN_READ, (NULL),
> +         ("can't open connection to Sun Audio device %s", 
> sunaudiosrc->device));
> + 
> +@@ -396,5 +401,45 @@ gst_sunaudiosrc_delay (GstAudioSrc * asr
> + static void
> + gst_sunaudiosrc_reset (GstAudioSrc * asrc)
> + {
> +-  return;
> ++  /* Get current values */
> ++  GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
> ++  audio_info_t ainfo;
> ++  int ret;
> ++
> ++  ret = ioctl (sunaudiosrc->fd, AUDIO_GETINFO, &ainfo);
> ++  if (ret == -1) {
> ++    /*
> ++     * Should never happen, but if we couldn't getinfo, then no point
> ++     * trying to setinfo
> ++     */
> ++    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++    return;
> ++  }
> ++
> ++  /*
> ++   * Pause the audio - so audio stops playing immediately rather than
> ++   * waiting for the ringbuffer to empty.
> ++   */
> ++  ainfo.record.pause = !NULL;
> ++  ret = ioctl (sunaudiosrc->fd, AUDIO_SETINFO, &ainfo);
> ++  if (ret == -1) {
> ++    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++  }
> ++
> ++  /* Flush the audio */
> ++  ret = ioctl (sunaudiosrc->fd, I_FLUSH, FLUSHR);
> ++  if (ret == -1) {
> ++    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++  }
> ++
> ++  /* unpause the audio */
> ++  ainfo.record.pause = NULL;
> ++  ret = ioctl (sunaudiosrc->fd, AUDIO_SETINFO, &ainfo);
> ++  if (ret == -1) {
> ++    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
> ++            strerror (errno)));
> ++  }
> + }
> +diff -urp gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosrc.h 
> gst-plugins-good/sys/sunaudio/gstsunaudiosrc.h
> +--- gst-plugins-good-0.10.4/sys/sunaudio/gstsunaudiosrc.h    2006-06-20 
> 05:35:48.000000000 -0500
> ++++ gst-plugins-good/sys/sunaudio/gstsunaudiosrc.h   2006-09-16 
> 16:57:29.000000000 -0500
> +@@ -35,7 +35,7 @@ G_BEGIN_DECLS
> + #define GST_SUNAUDIO_SRC(obj)     
> (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SUNAUDIO_SRC,GstSunAudioSrc))
> + #define GST_SUNAUDIO_SRC_CLASS(klass)  
> (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SUNAUDIO_SRC,GstSunAudioSrcClass))
> + #define GST_IS_SUNAUDIO_SRC(obj)       
> (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SUNAUDIO_SRC))
> +-#define GST_IS_SUNAUDIO_SRC_CLASS(obj) 
> (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SUNAUDIO_SRC))
> ++#define GST_IS_SUNAUDIO_SRC_CLASS(klass) 
> (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SUNAUDIO_SRC))
> + 
> + typedef struct _GstSunAudioSrc GstSunAudioSrc;
> + typedef struct _GstSunAudioSrcClass GstSunAudioSrcClass;
> Index: gst.spec
> ===================================================================
> --- gst.spec  (revision 9997)
> +++ gst.spec  (working copy)
> @@ -39,13 +39,6 @@
>  Patch1:       gst-01-gettext.diff
>  #owner:yippi date:2006-01-22 type:bug
>  Patch2:       gst-02-solaris-resolv.diff
> -# Patch note: The gst-03-nofork.diff patch is a nasty hack.
> -# Comments are in the patch.  The resolv patch would probably
> -# be better fixed by checking in configure and getting patch
> -# upstream.
> -#
> -#owner:yippi date:2006-06-14 type:bug
> -Patch3:       gst-03-nofork.diff
>  URL:          http://gstreamer.net/
>  BuildRoot:    %{_tmppath}/%{name}-%{version}-build
>  Docdir:       %{_defaultdocdir}/doc
> @@ -114,7 +107,6 @@
>  %setup -q 
>  %patch1 -p1
>  %patch2 -p1
> -%patch3 -p1
>  
>  bash -x %SOURCE18
>  
> @@ -213,6 +205,8 @@
>  %{_mandir}/man1/gst-*
>  
>  %changelog
> +* Mon Dec 11 2006 - brian.cameron at sun.com
> +- Remove nofork patch since this is now fixed upstream.
>  * Thu Dec  7 2006 - brian.cameron at sun.com
>  - Bump to 0.10.11
>  * Fri Nov  3 2006 - laca at sun.com
> Index: gst-plugins-good.spec
> ===================================================================
> --- gst-plugins-good.spec     (revision 9997)
> +++ gst-plugins-good.spec     (working copy)
> @@ -28,12 +28,8 @@
>  # compiler optimization that the function gets inlined.
>  #owner:yippi date:2006-06-22 type:branding
>  Patch2:         gst-plugins-good-02-fixgoom.diff
> -#owner:yippi date:2006-07-27 type:bug bugzilla:349015
> -Patch3:         gst-plugins-good-03-srcopen.diff
> -#owner:yippi date:2006-09-15 type:bug bugzilla:356142
> -Patch4:         gst-plugins-good-04-master.diff
> -#owner:yippi date:2006-11-28 type:bug bugzilla:360673
> -Patch5:         gst-plugins-good-05-reset.diff
> +#owner:yippi date:2006-07-27 type:bug bugzilla:349015,356142,360673
> +Patch3:         gst-plugins-good-03-cvshead.diff
>  BuildRoot:      %{_tmppath}/%{name}-%{version}-root
>  Docdir:         %{_defaultdocdir}/doc
>  Autoreqprov:    on
> @@ -81,8 +77,6 @@
>  %patch1 -p1
>  %patch2 -p1
>  %patch3 -p1
> -%patch4 -p1
> -%patch5 -p1
>  
>  bash -x %SOURCE1
>  
> @@ -158,6 +152,10 @@
>  %{_datadir}/gtk-doc
>  
>  %changelog
> +* Mon Dec 11 2006 - brian.cameron at sun.com
> +- Remove patches 4, 5, 6 and replace with a patch that updates to 
> +  CVS head.  This fixes all these issues and the performance issues
> +  we have been seeing with GStreamer on Solaris.
>  * Mon Nov 27 2006 - brian.cameron at sun.com
>  - Patch to rest function so that on close we flush the input/output
>    buffer.  This makes pause/stopping a file much more responsive.


Reply via email to