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.