5ae22ae191d4556d2a27f080d8c3e497b376028b
[platform/upstream/gst-plugins-good.git] / ext / pulse / pulsesink.c
1 /*-*- Mode: C; c-basic-offset: 2 -*-*/
2
3 /*  GStreamer pulseaudio plugin
4  *
5  *  Copyright (c) 2004-2008 Lennart Poettering
6  *            (c) 2009      Wim Taymans
7  *
8  *  gst-pulse is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU Lesser General Public License as
10  *  published by the Free Software Foundation; either version 2.1 of the
11  *  License, or (at your option) any later version.
12  *
13  *  gst-pulse is distributed in the hope that it will be useful, but
14  *  WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with gst-pulse; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21  *  USA.
22  */
23
24 /**
25  * SECTION:element-pulsesink
26  * @see_also: pulsesrc, pulsemixer
27  *
28  * This element outputs audio to a
29  * <ulink href="http://www.pulseaudio.org">PulseAudio sound server</ulink>.
30  *
31  * <refsect2>
32  * <title>Example pipelines</title>
33  * |[
34  * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! pulsesink
35  * ]| Play an Ogg/Vorbis file.
36  * |[
37  * gst-launch -v audiotestsrc ! audioconvert ! volume volume=0.4 ! pulsesink
38  * ]| Play a 440Hz sine wave.
39  * </refsect2>
40  */
41
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45
46 #include <string.h>
47 #include <stdio.h>
48
49 #include <gst/base/gstbasesink.h>
50 #include <gst/gsttaglist.h>
51 #include <gst/interfaces/streamvolume.h>
52 #include <gst/gst-i18n-plugin.h>
53
54 #include <gst/pbutils/pbutils.h>        /* only used for GST_PLUGINS_BASE_VERSION_* */
55
56 #include "pulsesink.h"
57 #include "pulseutil.h"
58
59 GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
60 #define GST_CAT_DEFAULT pulse_debug
61
62 /* according to
63  * http://www.pulseaudio.org/ticket/314
64  * we need pulse-0.9.12 to use sink volume properties
65  */
66
67 #define DEFAULT_SERVER          NULL
68 #define DEFAULT_DEVICE          NULL
69 #define DEFAULT_DEVICE_NAME     NULL
70 #define DEFAULT_VOLUME          1.0
71 #define DEFAULT_MUTE            FALSE
72 #define MAX_VOLUME              10.0
73
74 enum
75 {
76   PROP_0,
77   PROP_SERVER,
78   PROP_DEVICE,
79   PROP_DEVICE_NAME,
80   PROP_VOLUME,
81   PROP_MUTE,
82   PROP_LAST
83 };
84
85 #define GST_TYPE_PULSERING_BUFFER        \
86         (gst_pulseringbuffer_get_type())
87 #define GST_PULSERING_BUFFER(obj)        \
88         (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PULSERING_BUFFER,GstPulseRingBuffer))
89 #define GST_PULSERING_BUFFER_CLASS(klass) \
90         (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PULSERING_BUFFER,GstPulseRingBufferClass))
91 #define GST_PULSERING_BUFFER_GET_CLASS(obj) \
92         (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PULSERING_BUFFER, GstPulseRingBufferClass))
93 #define GST_PULSERING_BUFFER_CAST(obj)        \
94         ((GstPulseRingBuffer *)obj)
95 #define GST_IS_PULSERING_BUFFER(obj)     \
96         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PULSERING_BUFFER))
97 #define GST_IS_PULSERING_BUFFER_CLASS(klass)\
98         (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PULSERING_BUFFER))
99
100 typedef struct _GstPulseRingBuffer GstPulseRingBuffer;
101 typedef struct _GstPulseRingBufferClass GstPulseRingBufferClass;
102
103 /* We keep a custom ringbuffer that is backed up by data allocated by
104  * pulseaudio. We must also overide the commit function to write into
105  * pulseaudio memory instead. */
106 struct _GstPulseRingBuffer
107 {
108   GstRingBuffer object;
109
110   gchar *stream_name;
111
112   pa_context *context;
113   pa_stream *stream;
114
115   pa_sample_spec sample_spec;
116
117 #ifdef HAVE_PULSE_0_9_16
118   void *m_data;
119   size_t m_towrite;
120   size_t m_writable;
121   gint64 m_offset;
122   gint64 m_lastoffset;
123 #endif
124
125   gboolean corked:1;
126   gboolean in_commit:1;
127   gboolean paused:1;
128 };
129 struct _GstPulseRingBufferClass
130 {
131   GstRingBufferClass parent_class;
132 };
133
134 static GType gst_pulseringbuffer_get_type (void);
135 static void gst_pulseringbuffer_finalize (GObject * object);
136
137 static GstRingBufferClass *ring_parent_class = NULL;
138
139 static gboolean gst_pulseringbuffer_open_device (GstRingBuffer * buf);
140 static gboolean gst_pulseringbuffer_close_device (GstRingBuffer * buf);
141 static gboolean gst_pulseringbuffer_acquire (GstRingBuffer * buf,
142     GstRingBufferSpec * spec);
143 static gboolean gst_pulseringbuffer_release (GstRingBuffer * buf);
144 static gboolean gst_pulseringbuffer_start (GstRingBuffer * buf);
145 static gboolean gst_pulseringbuffer_pause (GstRingBuffer * buf);
146 static gboolean gst_pulseringbuffer_stop (GstRingBuffer * buf);
147 static void gst_pulseringbuffer_clear (GstRingBuffer * buf);
148 static guint gst_pulseringbuffer_commit (GstRingBuffer * buf,
149     guint64 * sample, guchar * data, gint in_samples, gint out_samples,
150     gint * accum);
151
152 G_DEFINE_TYPE (GstPulseRingBuffer, gst_pulseringbuffer, GST_TYPE_RING_BUFFER);
153
154 static void
155 gst_pulseringbuffer_class_init (GstPulseRingBufferClass * klass)
156 {
157   GObjectClass *gobject_class;
158   GstRingBufferClass *gstringbuffer_class;
159
160   gobject_class = (GObjectClass *) klass;
161   gstringbuffer_class = (GstRingBufferClass *) klass;
162
163   ring_parent_class = g_type_class_peek_parent (klass);
164
165   gobject_class->finalize = gst_pulseringbuffer_finalize;
166
167   gstringbuffer_class->open_device =
168       GST_DEBUG_FUNCPTR (gst_pulseringbuffer_open_device);
169   gstringbuffer_class->close_device =
170       GST_DEBUG_FUNCPTR (gst_pulseringbuffer_close_device);
171   gstringbuffer_class->acquire =
172       GST_DEBUG_FUNCPTR (gst_pulseringbuffer_acquire);
173   gstringbuffer_class->release =
174       GST_DEBUG_FUNCPTR (gst_pulseringbuffer_release);
175   gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_pulseringbuffer_start);
176   gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_pulseringbuffer_pause);
177   gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_pulseringbuffer_start);
178   gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_pulseringbuffer_stop);
179   gstringbuffer_class->clear_all =
180       GST_DEBUG_FUNCPTR (gst_pulseringbuffer_clear);
181
182   gstringbuffer_class->commit = GST_DEBUG_FUNCPTR (gst_pulseringbuffer_commit);
183 }
184
185 static void
186 gst_pulseringbuffer_init (GstPulseRingBuffer * pbuf)
187 {
188   pbuf->stream_name = NULL;
189   pbuf->context = NULL;
190   pbuf->stream = NULL;
191
192 #ifdef HAVE_PULSE_0_9_13
193   pa_sample_spec_init (&pbuf->sample_spec);
194 #else
195   pbuf->sample_spec.format = PA_SAMPLE_INVALID;
196   pbuf->sample_spec.rate = 0;
197   pbuf->sample_spec.channels = 0;
198 #endif
199
200 #ifdef HAVE_PULSE_0_9_16
201   pbuf->m_data = NULL;
202   pbuf->m_towrite = 0;
203   pbuf->m_writable = 0;
204   pbuf->m_offset = 0;
205   pbuf->m_lastoffset = 0;
206 #endif
207
208   pbuf->corked = TRUE;
209   pbuf->in_commit = FALSE;
210   pbuf->paused = FALSE;
211 }
212
213 static void
214 gst_pulsering_destroy_stream (GstPulseRingBuffer * pbuf)
215 {
216   if (pbuf->stream) {
217
218 #ifdef HAVE_PULSE_0_9_16
219     if (pbuf->m_data) {
220       /* drop shm memory buffer */
221       pa_stream_cancel_write (pbuf->stream);
222
223       /* reset internal variables */
224       pbuf->m_data = NULL;
225       pbuf->m_towrite = 0;
226       pbuf->m_writable = 0;
227       pbuf->m_offset = 0;
228       pbuf->m_lastoffset = 0;
229     }
230 #endif
231
232     pa_stream_disconnect (pbuf->stream);
233
234     /* Make sure we don't get any further callbacks */
235     pa_stream_set_state_callback (pbuf->stream, NULL, NULL);
236     pa_stream_set_write_callback (pbuf->stream, NULL, NULL);
237     pa_stream_set_underflow_callback (pbuf->stream, NULL, NULL);
238     pa_stream_set_overflow_callback (pbuf->stream, NULL, NULL);
239
240     pa_stream_unref (pbuf->stream);
241     pbuf->stream = NULL;
242   }
243
244   g_free (pbuf->stream_name);
245   pbuf->stream_name = NULL;
246 }
247
248 static void
249 gst_pulsering_destroy_context (GstPulseRingBuffer * pbuf)
250 {
251   gst_pulsering_destroy_stream (pbuf);
252
253   if (pbuf->context) {
254     pa_context_disconnect (pbuf->context);
255
256     /* Make sure we don't get any further callbacks */
257     pa_context_set_state_callback (pbuf->context, NULL, NULL);
258 #ifdef HAVE_PULSE_0_9_12
259     pa_context_set_subscribe_callback (pbuf->context, NULL, NULL);
260 #endif
261
262     pa_context_unref (pbuf->context);
263     pbuf->context = NULL;
264   }
265 }
266
267 static void
268 gst_pulseringbuffer_finalize (GObject * object)
269 {
270   GstPulseRingBuffer *ringbuffer;
271
272   ringbuffer = GST_PULSERING_BUFFER_CAST (object);
273
274   gst_pulsering_destroy_context (ringbuffer);
275
276   G_OBJECT_CLASS (ring_parent_class)->finalize (object);
277 }
278
279 static gboolean
280 gst_pulsering_is_dead (GstPulseSink * psink, GstPulseRingBuffer * pbuf)
281 {
282   if (!pbuf->context
283       || !PA_CONTEXT_IS_GOOD (pa_context_get_state (pbuf->context))
284       || !pbuf->stream
285       || !PA_STREAM_IS_GOOD (pa_stream_get_state (pbuf->stream))) {
286     const gchar *err_str = pbuf->context ?
287         pa_strerror (pa_context_errno (pbuf->context)) : NULL;
288
289     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED, ("Disconnected: %s",
290             err_str), (NULL));
291     return TRUE;
292   }
293   return FALSE;
294 }
295
296 static void
297 gst_pulsering_context_state_cb (pa_context * c, void *userdata)
298 {
299   GstPulseSink *psink;
300   GstPulseRingBuffer *pbuf;
301   pa_context_state_t state;
302
303   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
304   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
305
306   state = pa_context_get_state (c);
307   GST_LOG_OBJECT (psink, "got new context state %d", state);
308
309   /* psink can be null when we are shutting down and the ringbuffer is already
310    * unparented */
311   if (psink == NULL)
312     return;
313
314   switch (state) {
315     case PA_CONTEXT_READY:
316     case PA_CONTEXT_TERMINATED:
317     case PA_CONTEXT_FAILED:
318       GST_LOG_OBJECT (psink, "signaling");
319       pa_threaded_mainloop_signal (psink->mainloop, 0);
320       break;
321
322     case PA_CONTEXT_UNCONNECTED:
323     case PA_CONTEXT_CONNECTING:
324     case PA_CONTEXT_AUTHORIZING:
325     case PA_CONTEXT_SETTING_NAME:
326       break;
327   }
328 }
329
330 #ifdef HAVE_PULSE_0_9_12
331 static void
332 gst_pulsering_context_subscribe_cb (pa_context * c,
333     pa_subscription_event_type_t t, uint32_t idx, void *userdata)
334 {
335   GstPulseSink *psink;
336   GstPulseRingBuffer *pbuf;
337
338   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
339   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
340
341   GST_LOG_OBJECT (psink, "type %d, idx %u", t, idx);
342
343   if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE) &&
344       t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_NEW))
345     return;
346
347   if (!pbuf->stream)
348     return;
349
350   if (idx != pa_stream_get_index (pbuf->stream))
351     return;
352
353   /* Actually this event is also triggered when other properties of
354    * the stream change that are unrelated to the volume. However it is
355    * probably cheaper to signal the change here and check for the
356    * volume when the GObject property is read instead of querying it always. */
357
358   /* inform streaming thread to notify */
359   g_atomic_int_compare_and_exchange (&psink->notify, 0, 1);
360 }
361 #endif
362
363 /* will be called when the device should be opened. In this case we will connect
364  * to the server. We should not try to open any streams in this state. */
365 static gboolean
366 gst_pulseringbuffer_open_device (GstRingBuffer * buf)
367 {
368   GstPulseSink *psink;
369   GstPulseRingBuffer *pbuf;
370   gchar *name;
371   pa_mainloop_api *api;
372
373   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
374   pbuf = GST_PULSERING_BUFFER_CAST (buf);
375
376   g_assert (!pbuf->context);
377   g_assert (!pbuf->stream);
378
379   name = gst_pulse_client_name ();
380
381   pa_threaded_mainloop_lock (psink->mainloop);
382
383   /* get the mainloop api and create a context */
384   GST_LOG_OBJECT (psink, "new context with name %s", GST_STR_NULL (name));
385   api = pa_threaded_mainloop_get_api (psink->mainloop);
386   if (!(pbuf->context = pa_context_new (api, name)))
387     goto create_failed;
388
389   /* register some essential callbacks */
390   pa_context_set_state_callback (pbuf->context,
391       gst_pulsering_context_state_cb, pbuf);
392 #ifdef HAVE_PULSE_0_9_12
393   pa_context_set_subscribe_callback (pbuf->context,
394       gst_pulsering_context_subscribe_cb, pbuf);
395 #endif
396
397   /* try to connect to the server and wait for completioni, we don't want to
398    * autospawn a deamon */
399   GST_LOG_OBJECT (psink, "connect to server %s", GST_STR_NULL (psink->server));
400   if (pa_context_connect (pbuf->context, psink->server, PA_CONTEXT_NOAUTOSPAWN,
401           NULL) < 0)
402     goto connect_failed;
403
404   for (;;) {
405     pa_context_state_t state;
406
407     state = pa_context_get_state (pbuf->context);
408
409     GST_LOG_OBJECT (psink, "context state is now %d", state);
410
411     if (!PA_CONTEXT_IS_GOOD (state))
412       goto connect_failed;
413
414     if (state == PA_CONTEXT_READY)
415       break;
416
417     /* Wait until the context is ready */
418     GST_LOG_OBJECT (psink, "waiting..");
419     pa_threaded_mainloop_wait (psink->mainloop);
420   }
421
422   GST_LOG_OBJECT (psink, "opened the device");
423
424   pa_threaded_mainloop_unlock (psink->mainloop);
425   g_free (name);
426
427   return TRUE;
428
429   /* ERRORS */
430 unlock_and_fail:
431   {
432     gst_pulsering_destroy_context (pbuf);
433
434     pa_threaded_mainloop_unlock (psink->mainloop);
435     g_free (name);
436     return FALSE;
437   }
438 create_failed:
439   {
440     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
441         ("Failed to create context"), (NULL));
442     goto unlock_and_fail;
443   }
444 connect_failed:
445   {
446     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED, ("Failed to connect: %s",
447             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
448     goto unlock_and_fail;
449   }
450 }
451
452 /* close the device */
453 static gboolean
454 gst_pulseringbuffer_close_device (GstRingBuffer * buf)
455 {
456   GstPulseSink *psink;
457   GstPulseRingBuffer *pbuf;
458
459   pbuf = GST_PULSERING_BUFFER_CAST (buf);
460   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
461
462   GST_LOG_OBJECT (psink, "closing device");
463
464   pa_threaded_mainloop_lock (psink->mainloop);
465   gst_pulsering_destroy_context (pbuf);
466   pa_threaded_mainloop_unlock (psink->mainloop);
467
468   GST_LOG_OBJECT (psink, "closed device");
469
470   return TRUE;
471 }
472
473 static void
474 gst_pulsering_stream_state_cb (pa_stream * s, void *userdata)
475 {
476   GstPulseSink *psink;
477   GstPulseRingBuffer *pbuf;
478   pa_stream_state_t state;
479
480   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
481   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
482
483   state = pa_stream_get_state (s);
484   GST_LOG_OBJECT (psink, "got new stream state %d", state);
485
486   switch (state) {
487     case PA_STREAM_READY:
488     case PA_STREAM_FAILED:
489     case PA_STREAM_TERMINATED:
490       GST_LOG_OBJECT (psink, "signaling");
491       pa_threaded_mainloop_signal (psink->mainloop, 0);
492       break;
493     case PA_STREAM_UNCONNECTED:
494     case PA_STREAM_CREATING:
495       break;
496   }
497 }
498
499 static void
500 gst_pulsering_stream_request_cb (pa_stream * s, size_t length, void *userdata)
501 {
502   GstPulseSink *psink;
503   GstRingBuffer *rbuf;
504   GstPulseRingBuffer *pbuf;
505
506   rbuf = GST_RING_BUFFER_CAST (userdata);
507   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
508   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
509
510   GST_LOG_OBJECT (psink, "got request for length %" G_GSIZE_FORMAT, length);
511
512   if (pbuf->in_commit && (length >= rbuf->spec.segsize)) {
513     /* only signal when we are waiting in the commit thread
514      * and got request for atleast a segment */
515     pa_threaded_mainloop_signal (psink->mainloop, 0);
516   }
517 }
518
519 static void
520 gst_pulsering_stream_underflow_cb (pa_stream * s, void *userdata)
521 {
522   GstPulseSink *psink;
523   GstPulseRingBuffer *pbuf;
524
525   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
526   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
527
528   GST_WARNING_OBJECT (psink, "Got underflow");
529 }
530
531 static void
532 gst_pulsering_stream_overflow_cb (pa_stream * s, void *userdata)
533 {
534   GstPulseSink *psink;
535   GstPulseRingBuffer *pbuf;
536
537   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
538   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
539
540   GST_WARNING_OBJECT (psink, "Got overflow");
541 }
542
543 static void
544 gst_pulsering_stream_latency_cb (pa_stream * s, void *userdata)
545 {
546   GstPulseSink *psink;
547   GstPulseRingBuffer *pbuf;
548   const pa_timing_info *info;
549   pa_usec_t sink_usec;
550
551   info = pa_stream_get_timing_info (s);
552
553   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
554   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
555
556   if (!info) {
557     GST_LOG_OBJECT (psink, "latency update (information unknown)");
558     return;
559   }
560 #ifdef HAVE_PULSE_0_9_11
561   sink_usec = info->configured_sink_usec;
562 #else
563   sink_usec = 0;
564 #endif
565
566   GST_LOG_OBJECT (psink,
567       "latency_update, %" G_GUINT64_FORMAT ", %d:%" G_GINT64_FORMAT ", %d:%"
568       G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT,
569       GST_TIMEVAL_TO_TIME (info->timestamp), info->write_index_corrupt,
570       info->write_index, info->read_index_corrupt, info->read_index,
571       info->sink_usec, sink_usec);
572 }
573
574 static void
575 gst_pulsering_stream_suspended_cb (pa_stream * p, void *userdata)
576 {
577   GstPulseSink *psink;
578   GstPulseRingBuffer *pbuf;
579
580   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
581   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
582
583   if (pa_stream_is_suspended (p))
584     GST_DEBUG_OBJECT (psink, "stream suspended");
585   else
586     GST_DEBUG_OBJECT (psink, "stream resumed");
587 }
588
589 #ifdef HAVE_PULSE_0_9_11
590 static void
591 gst_pulsering_stream_started_cb (pa_stream * p, void *userdata)
592 {
593   GstPulseSink *psink;
594   GstPulseRingBuffer *pbuf;
595
596   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
597   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
598
599   GST_DEBUG_OBJECT (psink, "stream started");
600 }
601 #endif
602
603 #ifdef HAVE_PULSE_0_9_15
604 static void
605 gst_pulsering_stream_event_cb (pa_stream * p, const char *name,
606     pa_proplist * pl, void *userdata)
607 {
608   GstPulseSink *psink;
609   GstPulseRingBuffer *pbuf;
610
611   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
612   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
613
614   if (!strcmp (name, PA_STREAM_EVENT_REQUEST_CORK)) {
615     /* the stream wants to PAUSE, post a message for the application. */
616     GST_DEBUG_OBJECT (psink, "got request for CORK");
617     gst_element_post_message (GST_ELEMENT_CAST (psink),
618         gst_message_new_request_state (GST_OBJECT_CAST (psink),
619             GST_STATE_PAUSED));
620
621   } else if (!strcmp (name, PA_STREAM_EVENT_REQUEST_UNCORK)) {
622     GST_DEBUG_OBJECT (psink, "got request for UNCORK");
623     gst_element_post_message (GST_ELEMENT_CAST (psink),
624         gst_message_new_request_state (GST_OBJECT_CAST (psink),
625             GST_STATE_PLAYING));
626   } else {
627     GST_DEBUG_OBJECT (psink, "got unknown event %s", name);
628   }
629 }
630 #endif
631
632 /* This method should create a new stream of the given @spec. No playback should
633  * start yet so we start in the corked state. */
634 static gboolean
635 gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
636 {
637   GstPulseSink *psink;
638   GstPulseRingBuffer *pbuf;
639   pa_buffer_attr wanted;
640   const pa_buffer_attr *actual;
641   pa_channel_map channel_map;
642   pa_operation *o = NULL;
643 #ifdef HAVE_PULSE_0_9_20
644   pa_cvolume v;
645 #endif
646   pa_cvolume *pv = NULL;
647   pa_stream_flags_t flags;
648   const gchar *name;
649   GstAudioClock *clock;
650
651   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
652   pbuf = GST_PULSERING_BUFFER_CAST (buf);
653
654   GST_LOG_OBJECT (psink, "creating sample spec");
655   /* convert the gstreamer sample spec to the pulseaudio format */
656   if (!gst_pulse_fill_sample_spec (spec, &pbuf->sample_spec))
657     goto invalid_spec;
658
659   pa_threaded_mainloop_lock (psink->mainloop);
660
661   /* we need a context and a no stream */
662   g_assert (pbuf->context);
663   g_assert (!pbuf->stream);
664
665   /* enable event notifications */
666   GST_LOG_OBJECT (psink, "subscribing to context events");
667   if (!(o = pa_context_subscribe (pbuf->context,
668               PA_SUBSCRIPTION_MASK_SINK_INPUT, NULL, NULL)))
669     goto subscribe_failed;
670
671   pa_operation_unref (o);
672
673   /* initialize the channel map */
674   gst_pulse_gst_to_channel_map (&channel_map, spec);
675
676   /* find a good name for the stream */
677   if (psink->stream_name)
678     name = psink->stream_name;
679   else
680     name = "Playback Stream";
681
682   /* create a stream */
683   GST_LOG_OBJECT (psink, "creating stream with name %s", name);
684   if (!(pbuf->stream = pa_stream_new (pbuf->context,
685               name, &pbuf->sample_spec, &channel_map)))
686     goto stream_failed;
687
688   /* install essential callbacks */
689   pa_stream_set_state_callback (pbuf->stream,
690       gst_pulsering_stream_state_cb, pbuf);
691   pa_stream_set_write_callback (pbuf->stream,
692       gst_pulsering_stream_request_cb, pbuf);
693   pa_stream_set_underflow_callback (pbuf->stream,
694       gst_pulsering_stream_underflow_cb, pbuf);
695   pa_stream_set_overflow_callback (pbuf->stream,
696       gst_pulsering_stream_overflow_cb, pbuf);
697   pa_stream_set_latency_update_callback (pbuf->stream,
698       gst_pulsering_stream_latency_cb, pbuf);
699   pa_stream_set_suspended_callback (pbuf->stream,
700       gst_pulsering_stream_suspended_cb, pbuf);
701 #ifdef HAVE_PULSE_0_9_11
702   pa_stream_set_started_callback (pbuf->stream,
703       gst_pulsering_stream_started_cb, pbuf);
704 #endif
705 #ifdef HAVE_PULSE_0_9_15
706   pa_stream_set_event_callback (pbuf->stream,
707       gst_pulsering_stream_event_cb, pbuf);
708 #endif
709
710   /* buffering requirements. When setting prebuf to 0, the stream will not pause
711    * when we cause an underrun, which causes time to continue. */
712   memset (&wanted, 0, sizeof (wanted));
713   wanted.tlength = spec->segtotal * spec->segsize;
714   wanted.maxlength = -1;
715   wanted.prebuf = 0;
716   wanted.minreq = spec->segsize;
717
718   GST_INFO_OBJECT (psink, "tlength:   %d", wanted.tlength);
719   GST_INFO_OBJECT (psink, "maxlength: %d", wanted.maxlength);
720   GST_INFO_OBJECT (psink, "prebuf:    %d", wanted.prebuf);
721   GST_INFO_OBJECT (psink, "minreq:    %d", wanted.minreq);
722
723 #ifdef HAVE_PULSE_0_9_20
724   /* configure volume when we changed it, else we leave the default */
725   if (psink->volume_set) {
726     GST_LOG_OBJECT (psink, "have volume of %f", psink->volume);
727     pv = &v;
728     gst_pulse_cvolume_from_linear (pv, pbuf->sample_spec.channels,
729         psink->volume);
730   } else {
731     pv = NULL;
732   }
733 #endif
734
735   /* construct the flags */
736   flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE |
737 #ifdef HAVE_PULSE_0_9_11
738       PA_STREAM_ADJUST_LATENCY |
739 #endif
740       PA_STREAM_START_CORKED;
741
742 #ifdef HAVE_PULSE_0_9_12
743   if (psink->mute_set && psink->mute)
744     flags |= PA_STREAM_START_MUTED;
745 #endif
746
747   /* we always start corked (see flags above) */
748   pbuf->corked = TRUE;
749
750   /* try to connect now */
751   GST_LOG_OBJECT (psink, "connect for playback to device %s",
752       GST_STR_NULL (psink->device));
753   if (pa_stream_connect_playback (pbuf->stream, psink->device,
754           &wanted, flags, pv, NULL) < 0)
755     goto connect_failed;
756
757   /* our clock will now start from 0 again */
758   clock = GST_AUDIO_CLOCK (GST_BASE_AUDIO_SINK (psink)->provided_clock);
759   gst_audio_clock_reset (clock, 0);
760
761   for (;;) {
762     pa_stream_state_t state;
763
764     state = pa_stream_get_state (pbuf->stream);
765
766     GST_LOG_OBJECT (psink, "stream state is now %d", state);
767
768     if (!PA_STREAM_IS_GOOD (state))
769       goto connect_failed;
770
771     if (state == PA_STREAM_READY)
772       break;
773
774     /* Wait until the stream is ready */
775     pa_threaded_mainloop_wait (psink->mainloop);
776   }
777
778   /* After we passed the volume off of to PA we never want to set it
779      again, since it is PA's job to save/restore volumes.  */
780   psink->volume_set = psink->mute_set = FALSE;
781
782   GST_LOG_OBJECT (psink, "stream is acquired now");
783
784   /* get the actual buffering properties now */
785   actual = pa_stream_get_buffer_attr (pbuf->stream);
786
787   GST_INFO_OBJECT (psink, "tlength:   %d (wanted: %d)", actual->tlength,
788       wanted.tlength);
789   GST_INFO_OBJECT (psink, "maxlength: %d", actual->maxlength);
790   GST_INFO_OBJECT (psink, "prebuf:    %d", actual->prebuf);
791   GST_INFO_OBJECT (psink, "minreq:    %d (wanted %d)", actual->minreq,
792       wanted.minreq);
793
794   spec->segsize = actual->minreq;
795   spec->segtotal = actual->tlength / spec->segsize;
796
797   pa_threaded_mainloop_unlock (psink->mainloop);
798
799   return TRUE;
800
801   /* ERRORS */
802 unlock_and_fail:
803   {
804     gst_pulsering_destroy_stream (pbuf);
805     pa_threaded_mainloop_unlock (psink->mainloop);
806
807     return FALSE;
808   }
809 invalid_spec:
810   {
811     GST_ELEMENT_ERROR (psink, RESOURCE, SETTINGS,
812         ("Invalid sample specification."), (NULL));
813     return FALSE;
814   }
815 subscribe_failed:
816   {
817     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
818         ("pa_context_subscribe() failed: %s",
819             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
820     goto unlock_and_fail;
821   }
822 stream_failed:
823   {
824     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
825         ("Failed to create stream: %s",
826             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
827     goto unlock_and_fail;
828   }
829 connect_failed:
830   {
831     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
832         ("Failed to connect stream: %s",
833             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
834     goto unlock_and_fail;
835   }
836 }
837
838 /* free the stream that we acquired before */
839 static gboolean
840 gst_pulseringbuffer_release (GstRingBuffer * buf)
841 {
842   GstPulseSink *psink;
843   GstPulseRingBuffer *pbuf;
844
845   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
846   pbuf = GST_PULSERING_BUFFER_CAST (buf);
847
848   pa_threaded_mainloop_lock (psink->mainloop);
849   gst_pulsering_destroy_stream (pbuf);
850   pa_threaded_mainloop_unlock (psink->mainloop);
851
852   return TRUE;
853 }
854
855 static void
856 gst_pulsering_success_cb (pa_stream * s, int success, void *userdata)
857 {
858   GstPulseRingBuffer *pbuf;
859   GstPulseSink *psink;
860
861   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
862   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
863
864   pa_threaded_mainloop_signal (psink->mainloop, 0);
865 }
866
867 /* update the corked state of a stream, must be called with the mainloop
868  * lock */
869 static gboolean
870 gst_pulsering_set_corked (GstPulseRingBuffer * pbuf, gboolean corked,
871     gboolean wait)
872 {
873   pa_operation *o = NULL;
874   GstPulseSink *psink;
875   gboolean res = FALSE;
876
877   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
878
879   GST_DEBUG_OBJECT (psink, "setting corked state to %d", corked);
880   if (pbuf->corked != corked) {
881     if (!(o = pa_stream_cork (pbuf->stream, corked,
882                 gst_pulsering_success_cb, pbuf)))
883       goto cork_failed;
884
885     while (wait && pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
886       pa_threaded_mainloop_wait (psink->mainloop);
887       if (gst_pulsering_is_dead (psink, pbuf))
888         goto server_dead;
889     }
890     pbuf->corked = corked;
891   } else {
892     GST_DEBUG_OBJECT (psink, "skipping, already in requested state");
893   }
894   res = TRUE;
895
896 cleanup:
897   if (o)
898     pa_operation_unref (o);
899
900   return res;
901
902   /* ERRORS */
903 server_dead:
904   {
905     GST_DEBUG_OBJECT (psink, "the server is dead");
906     goto cleanup;
907   }
908 cork_failed:
909   {
910     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
911         ("pa_stream_cork() failed: %s",
912             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
913     goto cleanup;
914   }
915 }
916
917 static void
918 gst_pulseringbuffer_clear (GstRingBuffer * buf)
919 {
920   GstPulseSink *psink;
921   GstPulseRingBuffer *pbuf;
922   pa_operation *o = NULL;
923
924   pbuf = GST_PULSERING_BUFFER_CAST (buf);
925   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
926
927   pa_threaded_mainloop_lock (psink->mainloop);
928   GST_DEBUG_OBJECT (psink, "clearing");
929   if (pbuf->stream) {
930     /* don't wait for the flush to complete */
931     if ((o = pa_stream_flush (pbuf->stream, NULL, pbuf)))
932       pa_operation_unref (o);
933   }
934   pa_threaded_mainloop_unlock (psink->mainloop);
935 }
936
937 static void
938 mainloop_enter_defer_cb (pa_mainloop_api * api, void *userdata)
939 {
940   GstPulseSink *pulsesink = GST_PULSESINK (userdata);
941   GstMessage *message;
942   GValue val = { 0 };
943
944   g_value_init (&val, G_TYPE_POINTER);
945   g_value_set_pointer (&val, g_thread_self ());
946
947   GST_DEBUG_OBJECT (pulsesink, "posting ENTER stream status");
948   message = gst_message_new_stream_status (GST_OBJECT (pulsesink),
949       GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT (pulsesink));
950   gst_message_set_stream_status_object (message, &val);
951
952   gst_element_post_message (GST_ELEMENT (pulsesink), message);
953
954   /* signal the waiter */
955   pulsesink->pa_defer_ran = TRUE;
956   pa_threaded_mainloop_signal (pulsesink->mainloop, 0);
957 }
958
959 /* start/resume playback ASAP, we don't uncork here but in the commit method */
960 static gboolean
961 gst_pulseringbuffer_start (GstRingBuffer * buf)
962 {
963   GstPulseSink *psink;
964   GstPulseRingBuffer *pbuf;
965
966   pbuf = GST_PULSERING_BUFFER_CAST (buf);
967   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
968
969   pa_threaded_mainloop_lock (psink->mainloop);
970
971   GST_DEBUG_OBJECT (psink, "scheduling stream status");
972   psink->pa_defer_ran = FALSE;
973   pa_mainloop_api_once (pa_threaded_mainloop_get_api (psink->mainloop),
974       mainloop_enter_defer_cb, psink);
975
976   GST_DEBUG_OBJECT (psink, "starting");
977   pbuf->paused = FALSE;
978   gst_pulsering_set_corked (pbuf, FALSE, FALSE);
979   pa_threaded_mainloop_unlock (psink->mainloop);
980
981   return TRUE;
982 }
983
984 /* pause/stop playback ASAP */
985 static gboolean
986 gst_pulseringbuffer_pause (GstRingBuffer * buf)
987 {
988   GstPulseSink *psink;
989   GstPulseRingBuffer *pbuf;
990   gboolean res;
991
992   pbuf = GST_PULSERING_BUFFER_CAST (buf);
993   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
994
995   pa_threaded_mainloop_lock (psink->mainloop);
996   GST_DEBUG_OBJECT (psink, "pausing and corking");
997   /* make sure the commit method stops writing */
998   pbuf->paused = TRUE;
999   res = gst_pulsering_set_corked (pbuf, TRUE, FALSE);
1000   if (pbuf->in_commit) {
1001     /* we are waiting in a commit, signal */
1002     GST_DEBUG_OBJECT (psink, "signal commit");
1003     pa_threaded_mainloop_signal (psink->mainloop, 0);
1004   }
1005   pa_threaded_mainloop_unlock (psink->mainloop);
1006
1007   return res;
1008 }
1009
1010 static void
1011 mainloop_leave_defer_cb (pa_mainloop_api * api, void *userdata)
1012 {
1013   GstPulseSink *pulsesink = GST_PULSESINK (userdata);
1014   GstMessage *message;
1015   GValue val = { 0 };
1016
1017   g_value_init (&val, G_TYPE_POINTER);
1018   g_value_set_pointer (&val, g_thread_self ());
1019
1020   GST_DEBUG_OBJECT (pulsesink, "posting LEAVE stream status");
1021   message = gst_message_new_stream_status (GST_OBJECT (pulsesink),
1022       GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT (pulsesink));
1023   gst_message_set_stream_status_object (message, &val);
1024   gst_element_post_message (GST_ELEMENT (pulsesink), message);
1025
1026   pulsesink->pa_defer_ran = TRUE;
1027   pa_threaded_mainloop_signal (pulsesink->mainloop, 0);
1028   gst_object_unref (pulsesink);
1029 }
1030
1031 /* stop playback, we flush everything. */
1032 static gboolean
1033 gst_pulseringbuffer_stop (GstRingBuffer * buf)
1034 {
1035   GstPulseSink *psink;
1036   GstPulseRingBuffer *pbuf;
1037   gboolean res = FALSE;
1038   pa_operation *o = NULL;
1039
1040   pbuf = GST_PULSERING_BUFFER_CAST (buf);
1041   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
1042
1043   pa_threaded_mainloop_lock (psink->mainloop);
1044   pbuf->paused = TRUE;
1045   res = gst_pulsering_set_corked (pbuf, TRUE, TRUE);
1046   /* Inform anyone waiting in _commit() call that it shall wakeup */
1047   if (pbuf->in_commit) {
1048     GST_DEBUG_OBJECT (psink, "signal commit thread");
1049     pa_threaded_mainloop_signal (psink->mainloop, 0);
1050   }
1051
1052   if (strcmp (psink->pa_version, "0.9.12")) {
1053     /* then try to flush, it's not fatal when this fails */
1054     GST_DEBUG_OBJECT (psink, "flushing");
1055     if ((o = pa_stream_flush (pbuf->stream, gst_pulsering_success_cb, pbuf))) {
1056       while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
1057         GST_DEBUG_OBJECT (psink, "wait for completion");
1058         pa_threaded_mainloop_wait (psink->mainloop);
1059         if (gst_pulsering_is_dead (psink, pbuf))
1060           goto server_dead;
1061       }
1062       GST_DEBUG_OBJECT (psink, "flush completed");
1063     }
1064   }
1065   res = TRUE;
1066
1067 cleanup:
1068   if (o) {
1069     pa_operation_cancel (o);
1070     pa_operation_unref (o);
1071   }
1072
1073   GST_DEBUG_OBJECT (psink, "scheduling stream status");
1074   psink->pa_defer_ran = FALSE;
1075   gst_object_ref (psink);
1076   pa_mainloop_api_once (pa_threaded_mainloop_get_api (psink->mainloop),
1077       mainloop_leave_defer_cb, psink);
1078
1079   GST_DEBUG_OBJECT (psink, "waiting for stream status");
1080   pa_threaded_mainloop_unlock (psink->mainloop);
1081
1082   return res;
1083
1084   /* ERRORS */
1085 server_dead:
1086   {
1087     GST_DEBUG_OBJECT (psink, "the server is dead");
1088     goto cleanup;
1089   }
1090 }
1091
1092 /* in_samples >= out_samples, rate > 1.0 */
1093 #define FWD_UP_SAMPLES(s,se,d,de)               \
1094 G_STMT_START {                                  \
1095   guint8 *sb = s, *db = d;                      \
1096   while (s <= se && d < de) {                   \
1097     memcpy (d, s, bps);                         \
1098     s += bps;                                   \
1099     *accum += outr;                             \
1100     if ((*accum << 1) >= inr) {                 \
1101       *accum -= inr;                            \
1102       d += bps;                                 \
1103     }                                           \
1104   }                                             \
1105   in_samples -= (s - sb)/bps;                   \
1106   out_samples -= (d - db)/bps;                  \
1107   GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess);     \
1108 } G_STMT_END
1109
1110 /* out_samples > in_samples, for rates smaller than 1.0 */
1111 #define FWD_DOWN_SAMPLES(s,se,d,de)             \
1112 G_STMT_START {                                  \
1113   guint8 *sb = s, *db = d;                      \
1114   while (s <= se && d < de) {                   \
1115     memcpy (d, s, bps);                         \
1116     d += bps;                                   \
1117     *accum += inr;                              \
1118     if ((*accum << 1) >= outr) {                \
1119       *accum -= outr;                           \
1120       s += bps;                                 \
1121     }                                           \
1122   }                                             \
1123   in_samples -= (s - sb)/bps;                   \
1124   out_samples -= (d - db)/bps;                  \
1125   GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess);   \
1126 } G_STMT_END
1127
1128 #define REV_UP_SAMPLES(s,se,d,de)               \
1129 G_STMT_START {                                  \
1130   guint8 *sb = se, *db = d;                     \
1131   while (s <= se && d < de) {                   \
1132     memcpy (d, se, bps);                        \
1133     se -= bps;                                  \
1134     *accum += outr;                             \
1135     while (d < de && (*accum << 1) >= inr) {    \
1136       *accum -= inr;                            \
1137       d += bps;                                 \
1138     }                                           \
1139   }                                             \
1140   in_samples -= (sb - se)/bps;                  \
1141   out_samples -= (d - db)/bps;                  \
1142   GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess);     \
1143 } G_STMT_END
1144
1145 #define REV_DOWN_SAMPLES(s,se,d,de)             \
1146 G_STMT_START {                                  \
1147   guint8 *sb = se, *db = d;                     \
1148   while (s <= se && d < de) {                   \
1149     memcpy (d, se, bps);                        \
1150     d += bps;                                   \
1151     *accum += inr;                              \
1152     while (s <= se && (*accum << 1) >= outr) {  \
1153       *accum -= outr;                           \
1154       se -= bps;                                \
1155     }                                           \
1156   }                                             \
1157   in_samples -= (sb - se)/bps;                  \
1158   out_samples -= (d - db)/bps;                  \
1159   GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess);   \
1160 } G_STMT_END
1161
1162
1163 /* our custom commit function because we write into the buffer of pulseaudio
1164  * instead of keeping our own buffer */
1165 static guint
1166 gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample,
1167     guchar * data, gint in_samples, gint out_samples, gint * accum)
1168 {
1169   GstPulseSink *psink;
1170   GstPulseRingBuffer *pbuf;
1171   guint result;
1172   guint8 *data_end;
1173   gboolean reverse;
1174   gint *toprocess;
1175   gint inr, outr, bps;
1176   gint64 offset;
1177   guint bufsize;
1178
1179   pbuf = GST_PULSERING_BUFFER_CAST (buf);
1180   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
1181
1182   /* FIXME post message rather than using a signal (as mixer interface) */
1183   if (g_atomic_int_compare_and_exchange (&psink->notify, 1, 0)) {
1184     g_object_notify (G_OBJECT (psink), "volume");
1185     g_object_notify (G_OBJECT (psink), "mute");
1186   }
1187
1188   /* make sure the ringbuffer is started */
1189   if (G_UNLIKELY (g_atomic_int_get (&buf->state) !=
1190           GST_RING_BUFFER_STATE_STARTED)) {
1191     /* see if we are allowed to start it */
1192     if (G_UNLIKELY (g_atomic_int_get (&buf->abidata.ABI.may_start) == FALSE))
1193       goto no_start;
1194
1195     GST_DEBUG_OBJECT (buf, "start!");
1196     if (!gst_ring_buffer_start (buf))
1197       goto start_failed;
1198   }
1199
1200   pa_threaded_mainloop_lock (psink->mainloop);
1201   GST_DEBUG_OBJECT (psink, "entering commit");
1202   pbuf->in_commit = TRUE;
1203
1204   bps = buf->spec.bytes_per_sample;
1205   bufsize = buf->spec.segsize * buf->spec.segtotal;
1206
1207   /* our toy resampler for trick modes */
1208   reverse = out_samples < 0;
1209   out_samples = ABS (out_samples);
1210
1211   if (in_samples >= out_samples)
1212     toprocess = &in_samples;
1213   else
1214     toprocess = &out_samples;
1215
1216   inr = in_samples - 1;
1217   outr = out_samples - 1;
1218
1219   GST_DEBUG_OBJECT (psink, "in %d, out %d", inr, outr);
1220
1221   /* data_end points to the last sample we have to write, not past it. This is
1222    * needed to properly handle reverse playback: it points to the last sample. */
1223   data_end = data + (bps * inr);
1224
1225   if (pbuf->paused)
1226     goto was_paused;
1227
1228   /* offset is in bytes */
1229   offset = *sample * bps;
1230
1231   while (*toprocess > 0) {
1232     size_t avail;
1233     guint towrite;
1234
1235     GST_LOG_OBJECT (psink,
1236         "need to write %d samples at offset %" G_GINT64_FORMAT, *toprocess,
1237         offset);
1238
1239 #ifdef HAVE_PULSE_0_9_16
1240     if (offset != pbuf->m_lastoffset)
1241       GST_LOG_OBJECT (psink, "discontinuity, offset is %" G_GINT64_FORMAT ", "
1242           "last offset was %" G_GINT64_FORMAT, offset, pbuf->m_lastoffset);
1243
1244     towrite = out_samples * bps;
1245
1246     /* Only ever write segsize bytes at once. This will
1247      * also limit the PA shm buffer to segsize
1248      */
1249     if (towrite > buf->spec.segsize)
1250       towrite = buf->spec.segsize;
1251
1252     if ((pbuf->m_writable < towrite) || (offset != pbuf->m_lastoffset)) {
1253       /* if no room left or discontinuity in offset,
1254          we need to flush data and get a new buffer */
1255
1256       /* flush the buffer if possible */
1257       if ((pbuf->m_data != NULL) && (pbuf->m_towrite > 0)) {
1258
1259         GST_LOG_OBJECT (psink,
1260             "flushing %u samples at offset %" G_GINT64_FORMAT,
1261             (guint) pbuf->m_towrite / bps, pbuf->m_offset);
1262
1263         if (pa_stream_write (pbuf->stream, (uint8_t *) pbuf->m_data,
1264                 pbuf->m_towrite, NULL, pbuf->m_offset, PA_SEEK_ABSOLUTE) < 0) {
1265           goto write_failed;
1266         }
1267       }
1268       pbuf->m_towrite = 0;
1269       pbuf->m_offset = offset;  /* keep track of current offset */
1270
1271       /* get a buffer to write in for now on */
1272       for (;;) {
1273         pbuf->m_writable = pa_stream_writable_size (pbuf->stream);
1274
1275         if (pbuf->m_writable == (size_t) - 1)
1276           goto writable_size_failed;
1277
1278         pbuf->m_writable /= bps;
1279         pbuf->m_writable *= bps;        /* handle only complete samples */
1280
1281         if (pbuf->m_writable >= towrite)
1282           break;
1283
1284         /* see if we need to uncork because we have no free space */
1285         if (pbuf->corked) {
1286           if (!gst_pulsering_set_corked (pbuf, FALSE, FALSE))
1287             goto uncork_failed;
1288         }
1289
1290         /* we can't write a single byte, wait a bit */
1291         GST_LOG_OBJECT (psink, "waiting for free space");
1292         pa_threaded_mainloop_wait (psink->mainloop);
1293
1294         if (pbuf->paused)
1295           goto was_paused;
1296       }
1297
1298       /* make sure we only buffer up latency-time samples */
1299       if (pbuf->m_writable > buf->spec.segsize) {
1300         /* limit buffering to latency-time value */
1301         pbuf->m_writable = buf->spec.segsize;
1302
1303         GST_LOG_OBJECT (psink, "Limiting buffering to %" G_GSIZE_FORMAT,
1304             pbuf->m_writable);
1305       }
1306
1307       GST_LOG_OBJECT (psink, "requesting %" G_GSIZE_FORMAT " bytes of "
1308           "shared memory", pbuf->m_writable);
1309
1310       if (pa_stream_begin_write (pbuf->stream, &pbuf->m_data,
1311               &pbuf->m_writable) < 0) {
1312         GST_LOG_OBJECT (psink, "pa_stream_begin_write() failed");
1313         goto writable_size_failed;
1314       }
1315
1316       GST_LOG_OBJECT (psink, "got %" G_GSIZE_FORMAT " bytes of shared memory",
1317           pbuf->m_writable);
1318
1319       /* Just to make sure that we didn't get more than requested */
1320       if (pbuf->m_writable > buf->spec.segsize) {
1321         /* limit buffering to latency-time value */
1322         pbuf->m_writable = buf->spec.segsize;
1323       }
1324     }
1325
1326     if (pbuf->m_writable < towrite)
1327       towrite = pbuf->m_writable;
1328     avail = towrite / bps;
1329
1330     GST_LOG_OBJECT (psink, "writing %u samples at offset %" G_GUINT64_FORMAT,
1331         (guint) avail, offset);
1332
1333     if (G_LIKELY (inr == outr && !reverse)) {
1334       /* no rate conversion, simply write out the samples */
1335       /* copy the data into internal buffer */
1336
1337       memcpy ((guint8 *) pbuf->m_data + pbuf->m_towrite, data, towrite);
1338       pbuf->m_towrite += towrite;
1339       pbuf->m_writable -= towrite;
1340
1341       data += towrite;
1342       in_samples -= avail;
1343       out_samples -= avail;
1344     } else {
1345       guint8 *dest, *d, *d_end;
1346
1347       /* write into the PulseAudio shm buffer */
1348       dest = d = (guint8 *) pbuf->m_data + pbuf->m_towrite;
1349       d_end = d + towrite;
1350
1351       if (!reverse) {
1352         if (inr >= outr)
1353           /* forward speed up */
1354           FWD_UP_SAMPLES (data, data_end, d, d_end);
1355         else
1356           /* forward slow down */
1357           FWD_DOWN_SAMPLES (data, data_end, d, d_end);
1358       } else {
1359         if (inr >= outr)
1360           /* reverse speed up */
1361           REV_UP_SAMPLES (data, data_end, d, d_end);
1362         else
1363           /* reverse slow down */
1364           REV_DOWN_SAMPLES (data, data_end, d, d_end);
1365       }
1366       /* see what we have left to write */
1367       towrite = (d - dest);
1368       pbuf->m_towrite += towrite;
1369       pbuf->m_writable -= towrite;
1370
1371       avail = towrite / bps;
1372     }
1373
1374     /* flush the buffer if it's full */
1375     if ((pbuf->m_data != NULL) && (pbuf->m_towrite > 0)
1376         && (pbuf->m_writable == 0)) {
1377       GST_LOG_OBJECT (psink, "flushing %u samples at offset %" G_GINT64_FORMAT,
1378           (guint) pbuf->m_towrite / bps, pbuf->m_offset);
1379
1380       if (pa_stream_write (pbuf->stream, (uint8_t *) pbuf->m_data,
1381               pbuf->m_towrite, NULL, pbuf->m_offset, PA_SEEK_ABSOLUTE) < 0) {
1382         goto write_failed;
1383       }
1384       pbuf->m_towrite = 0;
1385       pbuf->m_offset = offset + towrite;        /* keep track of current offset */
1386     }
1387 #else
1388
1389     for (;;) {
1390       /* FIXME, this is not quite right */
1391       if ((avail = pa_stream_writable_size (pbuf->stream)) == (size_t) - 1)
1392         goto writable_size_failed;
1393
1394       /* We always try to satisfy a request for data */
1395       GST_LOG_OBJECT (psink, "writable bytes %" G_GSIZE_FORMAT, avail);
1396
1397       /* convert to samples, we can only deal with multiples of the
1398        * sample size */
1399       avail /= bps;
1400
1401       if (avail > 0)
1402         break;
1403
1404       /* see if we need to uncork because we have no free space */
1405       if (pbuf->corked) {
1406         if (!gst_pulsering_set_corked (pbuf, FALSE, FALSE))
1407           goto uncork_failed;
1408       }
1409
1410       /* we can't write a single byte, wait a bit */
1411       GST_LOG_OBJECT (psink, "waiting for free space");
1412       pa_threaded_mainloop_wait (psink->mainloop);
1413
1414       if (pbuf->paused)
1415         goto was_paused;
1416     }
1417
1418     if (avail > out_samples)
1419       avail = out_samples;
1420
1421     towrite = avail * bps;
1422
1423     GST_LOG_OBJECT (psink, "writing %u samples at offset %" G_GUINT64_FORMAT,
1424         (guint) avail, offset);
1425
1426     if (G_LIKELY (inr == outr && !reverse)) {
1427       /* no rate conversion, simply write out the samples */
1428       if (pa_stream_write (pbuf->stream, data, towrite, NULL, offset,
1429               PA_SEEK_ABSOLUTE) < 0)
1430         goto write_failed;
1431
1432       data += towrite;
1433       in_samples -= avail;
1434       out_samples -= avail;
1435     } else {
1436       guint8 *dest, *d, *d_end;
1437
1438       /* we need to allocate a temporary buffer to resample the data into,
1439        * FIXME, we should have a pulseaudio API to allocate this buffer for us
1440        * from the shared memory. */
1441       dest = d = g_malloc (towrite);
1442       d_end = d + towrite;
1443
1444       if (!reverse) {
1445         if (inr >= outr)
1446           /* forward speed up */
1447           FWD_UP_SAMPLES (data, data_end, d, d_end);
1448         else
1449           /* forward slow down */
1450           FWD_DOWN_SAMPLES (data, data_end, d, d_end);
1451       } else {
1452         if (inr >= outr)
1453           /* reverse speed up */
1454           REV_UP_SAMPLES (data, data_end, d, d_end);
1455         else
1456           /* reverse slow down */
1457           REV_DOWN_SAMPLES (data, data_end, d, d_end);
1458       }
1459       /* see what we have left to write */
1460       towrite = (d - dest);
1461       if (pa_stream_write (pbuf->stream, dest, towrite,
1462               g_free, offset, PA_SEEK_ABSOLUTE) < 0)
1463         goto write_failed;
1464
1465       avail = towrite / bps;
1466     }
1467 #endif /* HAVE_PULSE_0_9_16 */
1468
1469     *sample += avail;
1470     offset += avail * bps;
1471
1472 #ifdef HAVE_PULSE_0_9_16
1473     pbuf->m_lastoffset = offset;
1474 #endif
1475
1476     /* check if we need to uncork after writing the samples */
1477     if (pbuf->corked) {
1478       const pa_timing_info *info;
1479
1480       if ((info = pa_stream_get_timing_info (pbuf->stream))) {
1481         GST_LOG_OBJECT (psink,
1482             "read_index at %" G_GUINT64_FORMAT ", offset %" G_GINT64_FORMAT,
1483             info->read_index, offset);
1484
1485         /* we uncork when the read_index is too far behind the offset we need
1486          * to write to. */
1487         if (info->read_index + bufsize <= offset) {
1488           if (!gst_pulsering_set_corked (pbuf, FALSE, FALSE))
1489             goto uncork_failed;
1490         }
1491       } else {
1492         GST_LOG_OBJECT (psink, "no timing info available yet");
1493       }
1494     }
1495   }
1496   /* we consumed all samples here */
1497   data = data_end + bps;
1498
1499   pbuf->in_commit = FALSE;
1500   pa_threaded_mainloop_unlock (psink->mainloop);
1501
1502 done:
1503   result = inr - ((data_end - data) / bps);
1504   GST_LOG_OBJECT (psink, "wrote %d samples", result);
1505
1506   return result;
1507
1508   /* ERRORS */
1509 unlock_and_fail:
1510   {
1511     pbuf->in_commit = FALSE;
1512     GST_LOG_OBJECT (psink, "we are reset");
1513     pa_threaded_mainloop_unlock (psink->mainloop);
1514     goto done;
1515   }
1516 no_start:
1517   {
1518     GST_LOG_OBJECT (psink, "we can not start");
1519     return 0;
1520   }
1521 start_failed:
1522   {
1523     GST_LOG_OBJECT (psink, "failed to start the ringbuffer");
1524     return 0;
1525   }
1526 uncork_failed:
1527   {
1528     pbuf->in_commit = FALSE;
1529     GST_ERROR_OBJECT (psink, "uncork failed");
1530     pa_threaded_mainloop_unlock (psink->mainloop);
1531     goto done;
1532   }
1533 was_paused:
1534   {
1535     pbuf->in_commit = FALSE;
1536     GST_LOG_OBJECT (psink, "we are paused");
1537     pa_threaded_mainloop_unlock (psink->mainloop);
1538     goto done;
1539   }
1540 writable_size_failed:
1541   {
1542     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
1543         ("pa_stream_writable_size() failed: %s",
1544             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
1545     goto unlock_and_fail;
1546   }
1547 write_failed:
1548   {
1549     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
1550         ("pa_stream_write() failed: %s",
1551             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
1552     goto unlock_and_fail;
1553   }
1554 }
1555
1556 static void gst_pulsesink_set_property (GObject * object, guint prop_id,
1557     const GValue * value, GParamSpec * pspec);
1558 static void gst_pulsesink_get_property (GObject * object, guint prop_id,
1559     GValue * value, GParamSpec * pspec);
1560 static void gst_pulsesink_finalize (GObject * object);
1561
1562 static gboolean gst_pulsesink_event (GstBaseSink * sink, GstEvent * event);
1563
1564 static GstStateChangeReturn gst_pulsesink_change_state (GstElement * element,
1565     GstStateChange transition);
1566
1567 static void gst_pulsesink_init_interfaces (GType type);
1568
1569 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
1570 # define ENDIANNESS   "LITTLE_ENDIAN, BIG_ENDIAN"
1571 #else
1572 # define ENDIANNESS   "BIG_ENDIAN, LITTLE_ENDIAN"
1573 #endif
1574
1575 GST_IMPLEMENT_PULSEPROBE_METHODS (GstPulseSink, gst_pulsesink);
1576 GST_BOILERPLATE_FULL (GstPulseSink, gst_pulsesink, GstBaseAudioSink,
1577     GST_TYPE_BASE_AUDIO_SINK, gst_pulsesink_init_interfaces);
1578
1579 static gboolean
1580 gst_pulsesink_interface_supported (GstImplementsInterface *
1581     iface, GType interface_type)
1582 {
1583   GstPulseSink *this = GST_PULSESINK_CAST (iface);
1584
1585   if (interface_type == GST_TYPE_PROPERTY_PROBE && this->probe)
1586     return TRUE;
1587   if (interface_type == GST_TYPE_STREAM_VOLUME)
1588     return TRUE;
1589
1590   return FALSE;
1591 }
1592
1593 static void
1594 gst_pulsesink_implements_interface_init (GstImplementsInterfaceClass * klass)
1595 {
1596   klass->supported = gst_pulsesink_interface_supported;
1597 }
1598
1599 static void
1600 gst_pulsesink_init_interfaces (GType type)
1601 {
1602   static const GInterfaceInfo implements_iface_info = {
1603     (GInterfaceInitFunc) gst_pulsesink_implements_interface_init,
1604     NULL,
1605     NULL,
1606   };
1607   static const GInterfaceInfo probe_iface_info = {
1608     (GInterfaceInitFunc) gst_pulsesink_property_probe_interface_init,
1609     NULL,
1610     NULL,
1611   };
1612 #ifdef HAVE_PULSE_0_9_12
1613   static const GInterfaceInfo svol_iface_info = {
1614     NULL, NULL, NULL
1615   };
1616
1617   g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_iface_info);
1618 #endif
1619
1620   g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
1621       &implements_iface_info);
1622   g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
1623       &probe_iface_info);
1624 }
1625
1626 static void
1627 gst_pulsesink_base_init (gpointer g_class)
1628 {
1629   static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
1630       GST_PAD_SINK,
1631       GST_PAD_ALWAYS,
1632       GST_STATIC_CAPS ("audio/x-raw-int, "
1633           "endianness = (int) { " ENDIANNESS " }, "
1634           "signed = (boolean) TRUE, "
1635           "width = (int) 16, "
1636           "depth = (int) 16, "
1637           "rate = (int) [ 1, MAX ], "
1638           "channels = (int) [ 1, 32 ];"
1639           "audio/x-raw-float, "
1640           "endianness = (int) { " ENDIANNESS " }, "
1641           "width = (int) 32, "
1642           "rate = (int) [ 1, MAX ], "
1643           "channels = (int) [ 1, 32 ];"
1644           "audio/x-raw-int, "
1645           "endianness = (int) { " ENDIANNESS " }, "
1646           "signed = (boolean) TRUE, "
1647           "width = (int) 32, "
1648           "depth = (int) 32, "
1649           "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
1650 #ifdef HAVE_PULSE_0_9_15
1651           "audio/x-raw-int, "
1652           "endianness = (int) { " ENDIANNESS " }, "
1653           "signed = (boolean) TRUE, "
1654           "width = (int) 24, "
1655           "depth = (int) 24, "
1656           "rate = (int) [ 1, MAX ], "
1657           "channels = (int) [ 1, 32 ];"
1658           "audio/x-raw-int, "
1659           "endianness = (int) { " ENDIANNESS " }, "
1660           "signed = (boolean) TRUE, "
1661           "width = (int) 32, "
1662           "depth = (int) 24, "
1663           "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
1664 #endif
1665           "audio/x-raw-int, "
1666           "signed = (boolean) FALSE, "
1667           "width = (int) 8, "
1668           "depth = (int) 8, "
1669           "rate = (int) [ 1, MAX ], "
1670           "channels = (int) [ 1, 32 ];"
1671           "audio/x-alaw, "
1672           "rate = (int) [ 1, MAX], "
1673           "channels = (int) [ 1, 32 ];"
1674           "audio/x-mulaw, "
1675           "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ]")
1676       );
1677
1678   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1679
1680   gst_element_class_set_details_simple (element_class,
1681       "PulseAudio Audio Sink",
1682       "Sink/Audio", "Plays audio to a PulseAudio server", "Lennart Poettering");
1683   gst_element_class_add_pad_template (element_class,
1684       gst_static_pad_template_get (&pad_template));
1685 }
1686
1687 static GstRingBuffer *
1688 gst_pulsesink_create_ringbuffer (GstBaseAudioSink * sink)
1689 {
1690   GstRingBuffer *buffer;
1691
1692   GST_DEBUG_OBJECT (sink, "creating ringbuffer");
1693   buffer = g_object_new (GST_TYPE_PULSERING_BUFFER, NULL);
1694   GST_DEBUG_OBJECT (sink, "created ringbuffer @%p", buffer);
1695
1696   return buffer;
1697 }
1698
1699 static void
1700 gst_pulsesink_class_init (GstPulseSinkClass * klass)
1701 {
1702   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1703   GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass);
1704   GstBaseSinkClass *bc;
1705   GstBaseAudioSinkClass *gstaudiosink_class = GST_BASE_AUDIO_SINK_CLASS (klass);
1706   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
1707
1708   gobject_class->finalize = gst_pulsesink_finalize;
1709   gobject_class->set_property = gst_pulsesink_set_property;
1710   gobject_class->get_property = gst_pulsesink_get_property;
1711
1712   gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_pulsesink_event);
1713
1714   /* restore the original basesink pull methods */
1715   bc = g_type_class_peek (GST_TYPE_BASE_SINK);
1716   gstbasesink_class->activate_pull = GST_DEBUG_FUNCPTR (bc->activate_pull);
1717
1718   gstelement_class->change_state =
1719       GST_DEBUG_FUNCPTR (gst_pulsesink_change_state);
1720
1721   gstaudiosink_class->create_ringbuffer =
1722       GST_DEBUG_FUNCPTR (gst_pulsesink_create_ringbuffer);
1723
1724   /* Overwrite GObject fields */
1725   g_object_class_install_property (gobject_class,
1726       PROP_SERVER,
1727       g_param_spec_string ("server", "Server",
1728           "The PulseAudio server to connect to", DEFAULT_SERVER,
1729           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1730
1731   g_object_class_install_property (gobject_class, PROP_DEVICE,
1732       g_param_spec_string ("device", "Device",
1733           "The PulseAudio sink device to connect to", DEFAULT_DEVICE,
1734           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1735
1736   g_object_class_install_property (gobject_class,
1737       PROP_DEVICE_NAME,
1738       g_param_spec_string ("device-name", "Device name",
1739           "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
1740           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
1741
1742 #ifdef HAVE_PULSE_0_9_12
1743   g_object_class_install_property (gobject_class,
1744       PROP_VOLUME,
1745       g_param_spec_double ("volume", "Volume",
1746           "Linear volume of this stream, 1.0=100%", 0.0, MAX_VOLUME,
1747           DEFAULT_VOLUME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1748   g_object_class_install_property (gobject_class,
1749       PROP_MUTE,
1750       g_param_spec_boolean ("mute", "Mute",
1751           "Mute state of this stream", DEFAULT_MUTE,
1752           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1753 #endif
1754 }
1755
1756 /* returns the current time of the sink ringbuffer */
1757 static GstClockTime
1758 gst_pulsesink_get_time (GstClock * clock, GstBaseAudioSink * sink)
1759 {
1760   GstPulseSink *psink;
1761   GstPulseRingBuffer *pbuf;
1762   pa_usec_t time;
1763
1764   if (!sink->ringbuffer || !sink->ringbuffer->acquired)
1765     return GST_CLOCK_TIME_NONE;
1766
1767   pbuf = GST_PULSERING_BUFFER_CAST (sink->ringbuffer);
1768   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
1769
1770   pa_threaded_mainloop_lock (psink->mainloop);
1771   if (gst_pulsering_is_dead (psink, pbuf))
1772     goto server_dead;
1773
1774   /* if we don't have enough data to get a timestamp, just return NONE, which
1775    * will return the last reported time */
1776   if (pa_stream_get_time (pbuf->stream, &time) < 0) {
1777     GST_DEBUG_OBJECT (psink, "could not get time");
1778     time = GST_CLOCK_TIME_NONE;
1779   } else
1780     time *= 1000;
1781   pa_threaded_mainloop_unlock (psink->mainloop);
1782
1783   GST_LOG_OBJECT (psink, "current time is %" GST_TIME_FORMAT,
1784       GST_TIME_ARGS (time));
1785
1786   return time;
1787
1788   /* ERRORS */
1789 server_dead:
1790   {
1791     GST_DEBUG_OBJECT (psink, "the server is dead");
1792     pa_threaded_mainloop_unlock (psink->mainloop);
1793
1794     return GST_CLOCK_TIME_NONE;
1795   }
1796 }
1797
1798 static void
1799 gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass)
1800 {
1801   pulsesink->server = NULL;
1802   pulsesink->device = NULL;
1803   pulsesink->device_description = NULL;
1804
1805   pulsesink->volume = DEFAULT_VOLUME;
1806   pulsesink->volume_set = FALSE;
1807
1808   pulsesink->mute = DEFAULT_MUTE;
1809   pulsesink->mute_set = FALSE;
1810
1811   pulsesink->notify = 0;
1812
1813   /* needed for conditional execution */
1814   pulsesink->pa_version = pa_get_library_version ();
1815
1816   GST_DEBUG_OBJECT (pulsesink, "using pulseaudio version %s",
1817       pulsesink->pa_version);
1818
1819   /* TRUE for sinks, FALSE for sources */
1820   pulsesink->probe = gst_pulseprobe_new (G_OBJECT (pulsesink),
1821       G_OBJECT_GET_CLASS (pulsesink), PROP_DEVICE, pulsesink->device,
1822       TRUE, FALSE);
1823 }
1824
1825 static void
1826 gst_pulsesink_finalize (GObject * object)
1827 {
1828   GstPulseSink *pulsesink = GST_PULSESINK_CAST (object);
1829
1830   g_free (pulsesink->server);
1831   g_free (pulsesink->device);
1832   g_free (pulsesink->device_description);
1833
1834   if (pulsesink->probe) {
1835     gst_pulseprobe_free (pulsesink->probe);
1836     pulsesink->probe = NULL;
1837   }
1838
1839   G_OBJECT_CLASS (parent_class)->finalize (object);
1840 }
1841
1842 #ifdef HAVE_PULSE_0_9_12
1843 static void
1844 gst_pulsesink_set_volume (GstPulseSink * psink, gdouble volume)
1845 {
1846   pa_cvolume v;
1847   pa_operation *o = NULL;
1848   GstPulseRingBuffer *pbuf;
1849   uint32_t idx;
1850
1851   if (!psink->mainloop)
1852     goto no_mainloop;
1853
1854   pa_threaded_mainloop_lock (psink->mainloop);
1855
1856   GST_DEBUG_OBJECT (psink, "setting volume to %f", volume);
1857
1858   pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
1859   if (pbuf == NULL || pbuf->stream == NULL)
1860     goto no_buffer;
1861
1862   if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
1863     goto no_index;
1864
1865   gst_pulse_cvolume_from_linear (&v, pbuf->sample_spec.channels, volume);
1866
1867   if (!(o = pa_context_set_sink_input_volume (pbuf->context, idx,
1868               &v, NULL, NULL)))
1869     goto volume_failed;
1870
1871   /* We don't really care about the result of this call */
1872 unlock:
1873
1874   if (o)
1875     pa_operation_unref (o);
1876
1877   pa_threaded_mainloop_unlock (psink->mainloop);
1878
1879   return;
1880
1881   /* ERRORS */
1882 no_mainloop:
1883   {
1884     psink->volume = volume;
1885     psink->volume_set = TRUE;
1886
1887     GST_DEBUG_OBJECT (psink, "we have no mainloop");
1888     return;
1889   }
1890 no_buffer:
1891   {
1892     psink->volume = volume;
1893     psink->volume_set = TRUE;
1894
1895     GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
1896     goto unlock;
1897   }
1898 no_index:
1899   {
1900     GST_DEBUG_OBJECT (psink, "we don't have a stream index");
1901     goto unlock;
1902   }
1903 volume_failed:
1904   {
1905     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
1906         ("pa_stream_set_sink_input_volume() failed: %s",
1907             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
1908     goto unlock;
1909   }
1910 }
1911
1912 static void
1913 gst_pulsesink_set_mute (GstPulseSink * psink, gboolean mute)
1914 {
1915   pa_operation *o = NULL;
1916   GstPulseRingBuffer *pbuf;
1917   uint32_t idx;
1918
1919   if (!psink->mainloop)
1920     goto no_mainloop;
1921
1922   pa_threaded_mainloop_lock (psink->mainloop);
1923
1924   GST_DEBUG_OBJECT (psink, "setting mute state to %d", mute);
1925
1926   pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
1927   if (pbuf == NULL || pbuf->stream == NULL)
1928     goto no_buffer;
1929
1930   if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
1931     goto no_index;
1932
1933   if (!(o = pa_context_set_sink_input_mute (pbuf->context, idx,
1934               mute, NULL, NULL)))
1935     goto mute_failed;
1936
1937   /* We don't really care about the result of this call */
1938 unlock:
1939
1940   if (o)
1941     pa_operation_unref (o);
1942
1943   pa_threaded_mainloop_unlock (psink->mainloop);
1944
1945   return;
1946
1947   /* ERRORS */
1948 no_mainloop:
1949   {
1950     psink->mute = mute;
1951     psink->mute_set = TRUE;
1952
1953     GST_DEBUG_OBJECT (psink, "we have no mainloop");
1954     return;
1955   }
1956 no_buffer:
1957   {
1958     psink->mute = mute;
1959     psink->mute_set = TRUE;
1960
1961     GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
1962     goto unlock;
1963   }
1964 no_index:
1965   {
1966     GST_DEBUG_OBJECT (psink, "we don't have a stream index");
1967     goto unlock;
1968   }
1969 mute_failed:
1970   {
1971     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
1972         ("pa_stream_set_sink_input_mute() failed: %s",
1973             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
1974     goto unlock;
1975   }
1976 }
1977
1978 static void
1979 gst_pulsesink_sink_input_info_cb (pa_context * c, const pa_sink_input_info * i,
1980     int eol, void *userdata)
1981 {
1982   GstPulseRingBuffer *pbuf;
1983   GstPulseSink *psink;
1984
1985   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
1986   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
1987
1988   if (!i)
1989     goto done;
1990
1991   if (!pbuf->stream)
1992     goto done;
1993
1994   /* If the index doesn't match our current stream,
1995    * it implies we just recreated the stream (caps change)
1996    */
1997   if (i->index == pa_stream_get_index (pbuf->stream)) {
1998     psink->volume = pa_sw_volume_to_linear (pa_cvolume_max (&i->volume));
1999     psink->mute = i->mute;
2000   }
2001
2002 done:
2003   pa_threaded_mainloop_signal (psink->mainloop, 0);
2004 }
2005
2006 static gdouble
2007 gst_pulsesink_get_volume (GstPulseSink * psink)
2008 {
2009   GstPulseRingBuffer *pbuf;
2010   pa_operation *o = NULL;
2011   gdouble v = DEFAULT_VOLUME;
2012   uint32_t idx;
2013
2014   if (!psink->mainloop)
2015     goto no_mainloop;
2016
2017   pa_threaded_mainloop_lock (psink->mainloop);
2018
2019   pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
2020   if (pbuf == NULL || pbuf->stream == NULL)
2021     goto no_buffer;
2022
2023   if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
2024     goto no_index;
2025
2026   if (!(o = pa_context_get_sink_input_info (pbuf->context, idx,
2027               gst_pulsesink_sink_input_info_cb, pbuf)))
2028     goto info_failed;
2029
2030   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
2031     pa_threaded_mainloop_wait (psink->mainloop);
2032     if (gst_pulsering_is_dead (psink, pbuf))
2033       goto unlock;
2034   }
2035
2036 unlock:
2037   v = psink->volume;
2038
2039   if (o)
2040     pa_operation_unref (o);
2041
2042   pa_threaded_mainloop_unlock (psink->mainloop);
2043
2044   if (v > MAX_VOLUME) {
2045     GST_WARNING_OBJECT (psink, "Clipped volume from %f to %f", v, MAX_VOLUME);
2046     v = MAX_VOLUME;
2047   }
2048
2049   return v;
2050
2051   /* ERRORS */
2052 no_mainloop:
2053   {
2054     v = psink->volume;
2055     GST_DEBUG_OBJECT (psink, "we have no mainloop");
2056     return v;
2057   }
2058 no_buffer:
2059   {
2060     GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
2061     goto unlock;
2062   }
2063 no_index:
2064   {
2065     GST_DEBUG_OBJECT (psink, "we don't have a stream index");
2066     goto unlock;
2067   }
2068 info_failed:
2069   {
2070     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
2071         ("pa_context_get_sink_input_info() failed: %s",
2072             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
2073     goto unlock;
2074   }
2075 }
2076
2077 static gboolean
2078 gst_pulsesink_get_mute (GstPulseSink * psink)
2079 {
2080   GstPulseRingBuffer *pbuf;
2081   pa_operation *o = NULL;
2082   uint32_t idx;
2083   gboolean mute = FALSE;
2084
2085   if (!psink->mainloop)
2086     goto no_mainloop;
2087
2088   pa_threaded_mainloop_lock (psink->mainloop);
2089   mute = psink->mute;
2090
2091   pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
2092   if (pbuf == NULL || pbuf->stream == NULL)
2093     goto no_buffer;
2094
2095   if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
2096     goto no_index;
2097
2098   if (!(o = pa_context_get_sink_input_info (pbuf->context, idx,
2099               gst_pulsesink_sink_input_info_cb, pbuf)))
2100     goto info_failed;
2101
2102   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
2103     pa_threaded_mainloop_wait (psink->mainloop);
2104     if (gst_pulsering_is_dead (psink, pbuf))
2105       goto unlock;
2106   }
2107
2108 unlock:
2109   if (o)
2110     pa_operation_unref (o);
2111
2112   pa_threaded_mainloop_unlock (psink->mainloop);
2113
2114   return mute;
2115
2116   /* ERRORS */
2117 no_mainloop:
2118   {
2119     mute = psink->mute;
2120     GST_DEBUG_OBJECT (psink, "we have no mainloop");
2121     return mute;
2122   }
2123 no_buffer:
2124   {
2125     GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
2126     goto unlock;
2127   }
2128 no_index:
2129   {
2130     GST_DEBUG_OBJECT (psink, "we don't have a stream index");
2131     goto unlock;
2132   }
2133 info_failed:
2134   {
2135     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
2136         ("pa_context_get_sink_input_info() failed: %s",
2137             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
2138     goto unlock;
2139   }
2140 }
2141 #endif
2142
2143 static void
2144 gst_pulsesink_sink_info_cb (pa_context * c, const pa_sink_info * i, int eol,
2145     void *userdata)
2146 {
2147   GstPulseRingBuffer *pbuf;
2148   GstPulseSink *psink;
2149
2150   pbuf = GST_PULSERING_BUFFER_CAST (userdata);
2151   psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
2152
2153   if (!i)
2154     goto done;
2155
2156   if (!pbuf->stream)
2157     goto done;
2158
2159   g_assert (i->index == pa_stream_get_device_index (pbuf->stream));
2160
2161   g_free (psink->device_description);
2162   psink->device_description = g_strdup (i->description);
2163
2164 done:
2165   pa_threaded_mainloop_signal (psink->mainloop, 0);
2166 }
2167
2168 static gchar *
2169 gst_pulsesink_device_description (GstPulseSink * psink)
2170 {
2171   GstPulseRingBuffer *pbuf;
2172   pa_operation *o = NULL;
2173   gchar *t;
2174
2175   if (!psink->mainloop)
2176     goto no_mainloop;
2177
2178   pa_threaded_mainloop_lock (psink->mainloop);
2179   pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
2180   if (pbuf == NULL || pbuf->stream == NULL)
2181     goto no_buffer;
2182
2183   if (!(o = pa_context_get_sink_info_by_index (pbuf->context,
2184               pa_stream_get_device_index (pbuf->stream),
2185               gst_pulsesink_sink_info_cb, pbuf)))
2186     goto info_failed;
2187
2188   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
2189     pa_threaded_mainloop_wait (psink->mainloop);
2190     if (gst_pulsering_is_dead (psink, pbuf))
2191       goto unlock;
2192   }
2193
2194 unlock:
2195   if (o)
2196     pa_operation_unref (o);
2197
2198   t = g_strdup (psink->device_description);
2199   pa_threaded_mainloop_unlock (psink->mainloop);
2200
2201   return t;
2202
2203   /* ERRORS */
2204 no_mainloop:
2205   {
2206     GST_DEBUG_OBJECT (psink, "we have no mainloop");
2207     return NULL;
2208   }
2209 no_buffer:
2210   {
2211     GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
2212     goto unlock;
2213   }
2214 info_failed:
2215   {
2216     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
2217         ("pa_context_get_sink_info_by_index() failed: %s",
2218             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
2219     goto unlock;
2220   }
2221 }
2222
2223 static void
2224 gst_pulsesink_set_property (GObject * object,
2225     guint prop_id, const GValue * value, GParamSpec * pspec)
2226 {
2227   GstPulseSink *pulsesink = GST_PULSESINK_CAST (object);
2228
2229   switch (prop_id) {
2230     case PROP_SERVER:
2231       g_free (pulsesink->server);
2232       pulsesink->server = g_value_dup_string (value);
2233       if (pulsesink->probe)
2234         gst_pulseprobe_set_server (pulsesink->probe, pulsesink->server);
2235       break;
2236     case PROP_DEVICE:
2237       g_free (pulsesink->device);
2238       pulsesink->device = g_value_dup_string (value);
2239       break;
2240 #ifdef HAVE_PULSE_0_9_12
2241     case PROP_VOLUME:
2242       gst_pulsesink_set_volume (pulsesink, g_value_get_double (value));
2243       break;
2244     case PROP_MUTE:
2245       gst_pulsesink_set_mute (pulsesink, g_value_get_boolean (value));
2246       break;
2247 #endif
2248     default:
2249       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2250       break;
2251   }
2252 }
2253
2254 static void
2255 gst_pulsesink_get_property (GObject * object,
2256     guint prop_id, GValue * value, GParamSpec * pspec)
2257 {
2258
2259   GstPulseSink *pulsesink = GST_PULSESINK_CAST (object);
2260
2261   switch (prop_id) {
2262     case PROP_SERVER:
2263       g_value_set_string (value, pulsesink->server);
2264       break;
2265     case PROP_DEVICE:
2266       g_value_set_string (value, pulsesink->device);
2267       break;
2268     case PROP_DEVICE_NAME:
2269       g_value_take_string (value, gst_pulsesink_device_description (pulsesink));
2270       break;
2271 #ifdef HAVE_PULSE_0_9_12
2272     case PROP_VOLUME:
2273       g_value_set_double (value, gst_pulsesink_get_volume (pulsesink));
2274       break;
2275     case PROP_MUTE:
2276       g_value_set_boolean (value, gst_pulsesink_get_mute (pulsesink));
2277       break;
2278 #endif
2279     default:
2280       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2281       break;
2282   }
2283 }
2284
2285 static void
2286 gst_pulsesink_change_title (GstPulseSink * psink, const gchar * t)
2287 {
2288   pa_operation *o = NULL;
2289   GstPulseRingBuffer *pbuf;
2290
2291   pa_threaded_mainloop_lock (psink->mainloop);
2292
2293   pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
2294
2295   if (pbuf == NULL || pbuf->stream == NULL)
2296     goto no_buffer;
2297
2298   g_free (pbuf->stream_name);
2299   pbuf->stream_name = g_strdup (t);
2300
2301   if (!(o = pa_stream_set_name (pbuf->stream, pbuf->stream_name, NULL, NULL)))
2302     goto name_failed;
2303
2304   /* We're not interested if this operation failed or not */
2305 unlock:
2306   if (o)
2307     pa_operation_unref (o);
2308   pa_threaded_mainloop_unlock (psink->mainloop);
2309
2310   return;
2311
2312   /* ERRORS */
2313 no_buffer:
2314   {
2315     GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
2316     goto unlock;
2317   }
2318 name_failed:
2319   {
2320     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
2321         ("pa_stream_set_name() failed: %s",
2322             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
2323     goto unlock;
2324   }
2325 }
2326
2327 #ifdef HAVE_PULSE_0_9_11
2328 static void
2329 gst_pulsesink_change_props (GstPulseSink * psink, GstTagList * l)
2330 {
2331   static const gchar *const map[] = {
2332     GST_TAG_TITLE, PA_PROP_MEDIA_TITLE,
2333
2334     /* might get overriden in the next iteration by GST_TAG_ARTIST */
2335     GST_TAG_PERFORMER, PA_PROP_MEDIA_ARTIST,
2336
2337     GST_TAG_ARTIST, PA_PROP_MEDIA_ARTIST,
2338     GST_TAG_LANGUAGE_CODE, PA_PROP_MEDIA_LANGUAGE,
2339     GST_TAG_LOCATION, PA_PROP_MEDIA_FILENAME,
2340     /* We might add more here later on ... */
2341     NULL
2342   };
2343   pa_proplist *pl = NULL;
2344   const gchar *const *t;
2345   gboolean empty = TRUE;
2346   pa_operation *o = NULL;
2347   GstPulseRingBuffer *pbuf;
2348
2349   pl = pa_proplist_new ();
2350
2351   for (t = map; *t; t += 2) {
2352     gchar *n = NULL;
2353
2354     if (gst_tag_list_get_string (l, *t, &n)) {
2355
2356       if (n && *n) {
2357         pa_proplist_sets (pl, *(t + 1), n);
2358         empty = FALSE;
2359       }
2360
2361       g_free (n);
2362     }
2363   }
2364   if (empty)
2365     goto finish;
2366
2367   pa_threaded_mainloop_lock (psink->mainloop);
2368   pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
2369   if (pbuf == NULL || pbuf->stream == NULL)
2370     goto no_buffer;
2371
2372   if (!(o = pa_stream_proplist_update (pbuf->stream, PA_UPDATE_REPLACE,
2373               pl, NULL, NULL)))
2374     goto update_failed;
2375
2376   /* We're not interested if this operation failed or not */
2377 unlock:
2378
2379   if (o)
2380     pa_operation_unref (o);
2381
2382   pa_threaded_mainloop_unlock (psink->mainloop);
2383
2384 finish:
2385
2386   if (pl)
2387     pa_proplist_free (pl);
2388
2389   return;
2390
2391   /* ERRORS */
2392 no_buffer:
2393   {
2394     GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
2395     goto unlock;
2396   }
2397 update_failed:
2398   {
2399     GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
2400         ("pa_stream_proplist_update() failed: %s",
2401             pa_strerror (pa_context_errno (pbuf->context))), (NULL));
2402     goto unlock;
2403   }
2404 }
2405 #endif
2406
2407 static gboolean
2408 gst_pulsesink_event (GstBaseSink * sink, GstEvent * event)
2409 {
2410   GstPulseSink *pulsesink = GST_PULSESINK_CAST (sink);
2411
2412   switch (GST_EVENT_TYPE (event)) {
2413     case GST_EVENT_TAG:{
2414       gchar *title = NULL, *artist = NULL, *location = NULL, *description =
2415           NULL, *t = NULL, *buf = NULL;
2416       GstTagList *l;
2417
2418       gst_event_parse_tag (event, &l);
2419
2420       gst_tag_list_get_string (l, GST_TAG_TITLE, &title);
2421       gst_tag_list_get_string (l, GST_TAG_ARTIST, &artist);
2422       gst_tag_list_get_string (l, GST_TAG_LOCATION, &location);
2423       gst_tag_list_get_string (l, GST_TAG_DESCRIPTION, &description);
2424
2425       if (!artist)
2426         gst_tag_list_get_string (l, GST_TAG_PERFORMER, &artist);
2427
2428       if (title && artist)
2429         /* TRANSLATORS: 'song title' by 'artist name' */
2430         t = buf = g_strdup_printf (_("'%s' by '%s'"), g_strstrip (title),
2431             g_strstrip (artist));
2432       else if (title)
2433         t = g_strstrip (title);
2434       else if (description)
2435         t = g_strstrip (description);
2436       else if (location)
2437         t = g_strstrip (location);
2438
2439       if (t)
2440         gst_pulsesink_change_title (pulsesink, t);
2441
2442       g_free (title);
2443       g_free (artist);
2444       g_free (location);
2445       g_free (description);
2446       g_free (buf);
2447
2448 #ifdef HAVE_PULSE_0_9_11
2449       gst_pulsesink_change_props (pulsesink, l);
2450 #endif
2451
2452       break;
2453     }
2454     default:
2455       ;
2456   }
2457
2458   return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
2459 }
2460
2461 static GstStateChangeReturn
2462 gst_pulsesink_change_state (GstElement * element, GstStateChange transition)
2463 {
2464   GstPulseSink *pulsesink = GST_PULSESINK (element);
2465   GstStateChangeReturn ret;
2466   guint res;
2467
2468   switch (transition) {
2469     case GST_STATE_CHANGE_NULL_TO_READY:
2470       g_assert (pulsesink->mainloop == NULL);
2471       pulsesink->mainloop = pa_threaded_mainloop_new ();
2472       g_assert (pulsesink->mainloop != NULL);
2473       res = pa_threaded_mainloop_start (pulsesink->mainloop);
2474       g_assert (res == 0);
2475
2476       /* override with a custom clock */
2477       if (GST_BASE_AUDIO_SINK (pulsesink)->provided_clock)
2478         gst_object_unref (GST_BASE_AUDIO_SINK (pulsesink)->provided_clock);
2479
2480 /* FIXME: get rid once we can depend on core/base git again (>= 0.10.30.1)
2481  * (and the pbutils include above as well) */
2482 #if defined(GST_PLUGINS_BASE_VERSION_MAJOR)
2483       GST_BASE_AUDIO_SINK (pulsesink)->provided_clock =
2484           gst_audio_clock_new_full ("GstPulseSinkClock",
2485           (GstAudioClockGetTimeFunc) gst_pulsesink_get_time,
2486           gst_object_ref (pulsesink), (GDestroyNotify) gst_object_unref);
2487 #else
2488       GST_BASE_AUDIO_SINK (pulsesink)->provided_clock =
2489           gst_audio_clock_new ("GstPulseSinkClock",
2490           (GstAudioClockGetTimeFunc) gst_pulsesink_get_time, pulsesink);
2491 #endif
2492       break;
2493     case GST_STATE_CHANGE_READY_TO_PAUSED:
2494       gst_element_post_message (element,
2495           gst_message_new_clock_provide (GST_OBJECT_CAST (element),
2496               GST_BASE_AUDIO_SINK (pulsesink)->provided_clock, TRUE));
2497       break;
2498     default:
2499       break;
2500   }
2501
2502   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2503
2504   /* Clear the PA mainloop if baseaudiosink failed to open the ring_buffer */
2505   if (ret == GST_STATE_CHANGE_FAILURE
2506       && transition == GST_STATE_CHANGE_NULL_TO_READY) {
2507     g_assert (pulsesink->mainloop);
2508     pa_threaded_mainloop_stop (pulsesink->mainloop);
2509     pa_threaded_mainloop_free (pulsesink->mainloop);
2510     pulsesink->mainloop = NULL;
2511   }
2512
2513   switch (transition) {
2514     case GST_STATE_CHANGE_PAUSED_TO_READY:
2515       gst_element_post_message (element,
2516           gst_message_new_clock_lost (GST_OBJECT_CAST (element),
2517               GST_BASE_AUDIO_SINK (pulsesink)->provided_clock));
2518       break;
2519     case GST_STATE_CHANGE_READY_TO_NULL:
2520       if (GST_BASE_AUDIO_SINK (pulsesink)->provided_clock)
2521         gst_object_unref (GST_BASE_AUDIO_SINK (pulsesink)->provided_clock);
2522       GST_BASE_AUDIO_SINK (pulsesink)->provided_clock = NULL;
2523       if (pulsesink->mainloop) {
2524         pa_threaded_mainloop_stop (pulsesink->mainloop);
2525         pa_threaded_mainloop_free (pulsesink->mainloop);
2526         pulsesink->mainloop = NULL;
2527       }
2528       break;
2529     default:
2530       break;
2531   }
2532
2533   return ret;
2534 }