update for ringbuffer change
[platform/upstream/gstreamer.git] / ext / pulse / pulseaudiosink.c
1 /*-*- Mode: C; c-basic-offset: 2 -*-*/
2
3 /*  GStreamer pulseaudio plugin
4  *
5  *  Copyright (c) 2011 Intel Corporation
6  *                2011 Collabora
7  *                2011 Arun Raghavan <arun.raghavan@collabora.co.uk>
8  *                2011 Sebastian Dröge <sebastian.droege@collabora.co.uk>
9  *
10  *  gst-pulse is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as
12  *  published by the Free Software Foundation; either version 2.1 of the
13  *  License, or (at your option) any later version.
14  *
15  *  gst-pulse is distributed in the hope that it will be useful, but
16  *  WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  *  Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with gst-pulse; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23  *  USA.
24  */
25
26 /**
27  * SECTION:element-pulseaudiosink
28  * @see_also: pulsesink, pulsesrc, pulsemixer
29  *
30  * This element outputs audio to a
31  * <ulink href="http://www.pulseaudio.org">PulseAudio sound server</ulink> via
32  * the @pulsesink element. It transparently takes care of passing compressed
33  * format as-is if the sink supports it, decoding if necessary, and changes
34  * to supported formats at runtime.
35  *
36  * <refsect2>
37  * <title>Example pipelines</title>
38  * |[
39  * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! pulseaudiosink
40  * ]| Decode and play an Ogg/Vorbis file.
41  * |[
42  * gst-launch -v filesrc location=test.mp3 ! mp3parse ! pulseaudiosink stream-properties="props,media.title=test"
43  * ]| Play an MP3 file on a sink that supports decoding directly, plug in a
44  * decoder if/when required.
45  * </refsect2>
46  */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51
52 #ifdef HAVE_PULSE_1_0
53
54 #include <gst/pbutils/pbutils.h>
55 #include <gst/gst-i18n-plugin.h>
56
57 #include <gst/audio/gstaudioiec61937.h>
58 #include "pulsesink.h"
59
60 GST_DEBUG_CATEGORY (pulseaudiosink_debug);
61 #define GST_CAT_DEFAULT (pulseaudiosink_debug)
62
63 #define GST_PULSE_AUDIO_SINK_LOCK(obj) G_STMT_START {                    \
64     GST_LOG_OBJECT (obj,                                              \
65                     "locking from thread %p",                         \
66                     g_thread_self ());                                \
67     g_mutex_lock (GST_PULSE_AUDIO_SINK_CAST(obj)->lock);                 \
68     GST_LOG_OBJECT (obj,                                              \
69                     "locked from thread %p",                          \
70                     g_thread_self ());                                \
71 } G_STMT_END
72
73 #define GST_PULSE_AUDIO_SINK_UNLOCK(obj) G_STMT_START {                  \
74     GST_LOG_OBJECT (obj,                                              \
75                     "unlocking from thread %p",                       \
76                     g_thread_self ());                                \
77     g_mutex_unlock (GST_PULSE_AUDIO_SINK_CAST(obj)->lock);               \
78 } G_STMT_END
79
80 typedef struct
81 {
82   GstBin parent;
83   GMutex *lock;
84
85   GstPad *sinkpad;
86   GstPad *sink_proxypad;
87   GstPadEventFunction sinkpad_old_eventfunc;
88   GstPadEventFunction proxypad_old_eventfunc;
89
90   GstPulseSink *psink;
91   GstElement *dbin;
92
93   GstSegment segment;
94
95   guint event_probe_id;
96   gulong pad_added_id;
97   guint block_probe_id;
98
99   gboolean format_lost;
100 } GstPulseAudioSink;
101
102 typedef struct
103 {
104   GstBinClass parent_class;
105   guint n_prop_own;
106   guint n_prop_total;
107 } GstPulseAudioSinkClass;
108
109 static void gst_pulse_audio_sink_get_property (GObject * object, guint prop_id,
110     GValue * value, GParamSpec * pspec);
111 static void gst_pulse_audio_sink_set_property (GObject * object, guint prop_id,
112     const GValue * value, GParamSpec * pspec);
113 static void gst_pulse_audio_sink_dispose (GObject * object);
114 static gboolean gst_pulse_audio_sink_src_event (GstPad * pad, GstEvent * event);
115 static gboolean gst_pulse_audio_sink_sink_event (GstPad * pad,
116     GstEvent * event);
117 static gboolean gst_pulse_audio_sink_sink_query (GstPad * pad,
118     GstQuery * query);
119 static gboolean gst_pulse_audio_sink_sink_acceptcaps (GstPulseAudioSink * pbin,
120     GstPad * pad, GstCaps * caps);
121 static GstStateChangeReturn
122 gst_pulse_audio_sink_change_state (GstElement * element,
123     GstStateChange transition);
124 static gboolean gst_pulse_audio_sink_set_caps (GstPulseAudioSink * pbin,
125     GstCaps * caps);
126
127 #define gst_pulse_audio_sink_parent_class parent_class
128 G_DEFINE_TYPE (GstPulseAudioSink, gst_pulse_audio_sink, GST_TYPE_BIN);
129
130 static GstStaticPadTemplate sink_template =
131 GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
132     GST_STATIC_CAPS (PULSE_SINK_TEMPLATE_CAPS));
133
134 static GParamSpec *
135 param_spec_copy (GParamSpec * spec)
136 {
137   const char *name, *nick, *blurb;
138   GParamFlags flags;
139
140   name = g_param_spec_get_name (spec);
141   nick = g_param_spec_get_nick (spec);
142   blurb = g_param_spec_get_blurb (spec);
143   flags = spec->flags;
144
145   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_BOOLEAN) {
146     return g_param_spec_boolean (name, nick, blurb,
147         G_PARAM_SPEC_BOOLEAN (spec)->default_value, flags);
148   }
149
150   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_BOXED) {
151     return g_param_spec_boxed (name, nick, blurb, spec->value_type, flags);
152   }
153
154   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_CHAR) {
155     GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (spec);
156     return g_param_spec_char (name, nick, blurb, cspec->minimum,
157         cspec->maximum, cspec->default_value, flags);
158   }
159
160   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_DOUBLE) {
161     GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (spec);
162     return g_param_spec_double (name, nick, blurb, dspec->minimum,
163         dspec->maximum, dspec->default_value, flags);
164   }
165
166   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_ENUM) {
167     return g_param_spec_enum (name, nick, blurb, spec->value_type,
168         G_PARAM_SPEC_ENUM (spec)->default_value, flags);
169   }
170
171   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_FLAGS) {
172     return g_param_spec_flags (name, nick, blurb, spec->value_type,
173         G_PARAM_SPEC_ENUM (spec)->default_value, flags);
174   }
175
176   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_FLOAT) {
177     GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (spec);
178     return g_param_spec_double (name, nick, blurb, fspec->minimum,
179         fspec->maximum, fspec->default_value, flags);
180   }
181
182   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_GTYPE) {
183     return g_param_spec_gtype (name, nick, blurb,
184         G_PARAM_SPEC_GTYPE (spec)->is_a_type, flags);
185   }
186
187   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_INT) {
188     GParamSpecInt *ispec = G_PARAM_SPEC_INT (spec);
189     return g_param_spec_int (name, nick, blurb, ispec->minimum,
190         ispec->maximum, ispec->default_value, flags);
191   }
192
193   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_INT64) {
194     GParamSpecInt64 *ispec = G_PARAM_SPEC_INT64 (spec);
195     return g_param_spec_int64 (name, nick, blurb, ispec->minimum,
196         ispec->maximum, ispec->default_value, flags);
197   }
198
199   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_LONG) {
200     GParamSpecLong *lspec = G_PARAM_SPEC_LONG (spec);
201     return g_param_spec_long (name, nick, blurb, lspec->minimum,
202         lspec->maximum, lspec->default_value, flags);
203   }
204
205   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_OBJECT) {
206     return g_param_spec_object (name, nick, blurb, spec->value_type, flags);
207   }
208
209   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_PARAM) {
210     return g_param_spec_param (name, nick, blurb, spec->value_type, flags);
211   }
212
213   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_POINTER) {
214     return g_param_spec_pointer (name, nick, blurb, flags);
215   }
216
217   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_STRING) {
218     return g_param_spec_string (name, nick, blurb,
219         G_PARAM_SPEC_STRING (spec)->default_value, flags);
220   }
221
222   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_UCHAR) {
223     GParamSpecUChar *cspec = G_PARAM_SPEC_UCHAR (spec);
224     return g_param_spec_uchar (name, nick, blurb, cspec->minimum,
225         cspec->maximum, cspec->default_value, flags);
226   }
227
228   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_UINT) {
229     GParamSpecUInt *ispec = G_PARAM_SPEC_UINT (spec);
230     return g_param_spec_uint (name, nick, blurb, ispec->minimum,
231         ispec->maximum, ispec->default_value, flags);
232   }
233
234   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_UINT64) {
235     GParamSpecUInt64 *ispec = G_PARAM_SPEC_UINT64 (spec);
236     return g_param_spec_uint64 (name, nick, blurb, ispec->minimum,
237         ispec->maximum, ispec->default_value, flags);
238   }
239
240   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_ULONG) {
241     GParamSpecULong *lspec = G_PARAM_SPEC_ULONG (spec);
242     return g_param_spec_ulong (name, nick, blurb, lspec->minimum,
243         lspec->maximum, lspec->default_value, flags);
244   }
245
246   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_UNICHAR) {
247     return g_param_spec_unichar (name, nick, blurb,
248         G_PARAM_SPEC_UNICHAR (spec)->default_value, flags);
249   }
250
251   if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_PARAM_VARIANT) {
252     GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (spec);
253     return g_param_spec_variant (name, nick, blurb, vspec->type,
254         vspec->default_value, flags);
255   }
256
257   g_warning ("Unknown param type %ld for '%s'",
258       (long) G_PARAM_SPEC_TYPE (spec), name);
259   g_assert_not_reached ();
260 }
261
262 static void
263 gst_pulse_audio_sink_class_init (GstPulseAudioSinkClass * klass)
264 {
265   GObjectClass *gobject_class = (GObjectClass *) klass;
266   GstElementClass *element_class = (GstElementClass *) klass;
267   GstPulseSinkClass *psink_class =
268       GST_PULSESINK_CLASS (g_type_class_ref (GST_TYPE_PULSESINK));
269   GParamSpec **specs;
270   guint n, i, j;
271
272   GST_DEBUG_CATEGORY_INIT (pulseaudiosink_debug, "pulseaudiosink", 0,
273       "Bin that wraps pulsesink for handling compressed formats");
274
275   gst_element_class_add_pad_template (element_class,
276       gst_static_pad_template_get (&sink_template));
277
278   gst_element_class_set_details_simple (element_class,
279       "Bin wrapping pulsesink", "Sink/Audio/Bin",
280       "Correctly handles sink changes when streaming compressed formats to "
281       "pulsesink", "Arun Raghavan <arun.raghavan@collabora.co.uk>");
282
283   gobject_class->get_property = gst_pulse_audio_sink_get_property;
284   gobject_class->set_property = gst_pulse_audio_sink_set_property;
285   gobject_class->dispose = gst_pulse_audio_sink_dispose;
286   element_class->change_state =
287       GST_DEBUG_FUNCPTR (gst_pulse_audio_sink_change_state);
288
289   /* Find out how many properties we already have */
290   specs = g_object_class_list_properties (gobject_class, &klass->n_prop_own);
291   g_free (specs);
292
293   /* Proxy pulsesink's properties */
294   specs = g_object_class_list_properties (G_OBJECT_CLASS (psink_class), &n);
295   for (i = 0, j = klass->n_prop_own; i < n; i++) {
296     if (g_object_class_find_property (gobject_class,
297             g_param_spec_get_name (specs[i]))) {
298       /* We already inherited this property from a parent, skip */
299       j--;
300     } else {
301       g_object_class_install_property (gobject_class, i + j + 1,
302           param_spec_copy (specs[i]));
303     }
304   }
305
306   klass->n_prop_total = i + j;
307
308   g_free (specs);
309   g_type_class_unref (psink_class);
310 }
311
312 static GstPad *
313 get_proxypad (GstPad * sinkpad)
314 {
315   GstIterator *iter = NULL;
316   GValue res = { 0 };
317   GstPad *proxypad = NULL;
318
319   iter = gst_pad_iterate_internal_links (sinkpad);
320   if (iter) {
321     if (gst_iterator_next (iter, &res) == GST_ITERATOR_OK) {
322       proxypad = g_value_dup_object (&res);
323       g_value_reset (&res);
324     }
325     gst_iterator_free (iter);
326   }
327
328   return proxypad;
329 }
330
331 static void
332 post_missing_element_message (GstPulseAudioSink * pbin, const gchar * name)
333 {
334   GstMessage *msg;
335
336   msg = gst_missing_element_message_new (GST_ELEMENT_CAST (pbin), name);
337   gst_element_post_message (GST_ELEMENT_CAST (pbin), msg);
338 }
339
340 static void
341 notify_cb (GObject * selector, GParamSpec * pspec, GstPulseAudioSink * pbin)
342 {
343   g_object_notify (G_OBJECT (pbin), g_param_spec_get_name (pspec));
344 }
345
346 static void
347 gst_pulse_audio_sink_init (GstPulseAudioSink * pbin)
348 {
349   GstPulseAudioSinkClass *klass =
350       GST_PULSE_AUDIO_SINK_CLASS (G_OBJECT_GET_CLASS (pbin));
351   GstPad *pad = NULL;
352   GParamSpec **specs;
353   GString *prop;
354   guint i;
355
356   pbin->lock = g_mutex_new ();
357
358   gst_segment_init (&pbin->segment, GST_FORMAT_UNDEFINED);
359
360   pbin->psink = GST_PULSESINK (gst_element_factory_make ("pulsesink",
361           "pulseaudiosink-sink"));
362   g_assert (pbin->psink != NULL);
363
364   if (!gst_bin_add (GST_BIN (pbin), GST_ELEMENT (pbin->psink))) {
365     GST_ERROR_OBJECT (pbin, "Failed to add pulsesink to bin");
366     goto error;
367   }
368
369   pad = gst_element_get_static_pad (GST_ELEMENT (pbin->psink), "sink");
370   pbin->sinkpad = gst_ghost_pad_new_from_template ("sink", pad,
371       gst_static_pad_template_get (&sink_template));
372
373   pbin->sinkpad_old_eventfunc = GST_PAD_EVENTFUNC (pbin->sinkpad);
374   gst_pad_set_event_function (pbin->sinkpad,
375       GST_DEBUG_FUNCPTR (gst_pulse_audio_sink_sink_event));
376   gst_pad_set_query_function (pbin->sinkpad,
377       GST_DEBUG_FUNCPTR (gst_pulse_audio_sink_sink_query));
378
379   gst_element_add_pad (GST_ELEMENT (pbin), pbin->sinkpad);
380
381   if (!(pbin->sink_proxypad = get_proxypad (pbin->sinkpad)))
382     GST_ERROR_OBJECT (pbin, "Failed to get proxypad of srcpad");
383   else {
384     pbin->proxypad_old_eventfunc = GST_PAD_EVENTFUNC (pbin->sink_proxypad);
385     gst_pad_set_event_function (pbin->sink_proxypad,
386         GST_DEBUG_FUNCPTR (gst_pulse_audio_sink_src_event));
387   }
388
389   /* Now proxy all the notify::* signals */
390   specs = g_object_class_list_properties (G_OBJECT_CLASS (klass), &i);
391   prop = g_string_sized_new (30);
392
393   for (i--; i >= klass->n_prop_own; i--) {
394     g_string_printf (prop, "notify::%s", g_param_spec_get_name (specs[i]));
395     g_signal_connect (pbin->psink, prop->str, G_CALLBACK (notify_cb), pbin);
396   }
397
398   g_string_free (prop, TRUE);
399   g_free (specs);
400
401   pbin->format_lost = FALSE;
402
403 out:
404   if (pad)
405     gst_object_unref (pad);
406
407   return;
408
409 error:
410   if (pbin->psink)
411     gst_object_unref (pbin->psink);
412   goto out;
413 }
414
415 static void
416 gst_pulse_audio_sink_set_property (GObject * object, guint prop_id,
417     const GValue * value, GParamSpec * pspec)
418 {
419   GstPulseAudioSink *pbin = GST_PULSE_AUDIO_SINK (object);
420   GstPulseAudioSinkClass *klass =
421       GST_PULSE_AUDIO_SINK_CLASS (G_OBJECT_GET_CLASS (object));
422
423   g_return_if_fail (prop_id <= klass->n_prop_total);
424
425   g_object_set_property (G_OBJECT (pbin->psink), g_param_spec_get_name (pspec),
426       value);
427 }
428
429 static void
430 gst_pulse_audio_sink_get_property (GObject * object, guint prop_id,
431     GValue * value, GParamSpec * pspec)
432 {
433   GstPulseAudioSink *pbin = GST_PULSE_AUDIO_SINK (object);
434   GstPulseAudioSinkClass *klass =
435       GST_PULSE_AUDIO_SINK_CLASS (G_OBJECT_GET_CLASS (object));
436
437   g_return_if_fail (prop_id <= klass->n_prop_total);
438
439   g_object_get_property (G_OBJECT (pbin->psink), g_param_spec_get_name (pspec),
440       value);
441 }
442
443 static void
444 gst_pulse_audio_sink_free_dbin (GstPulseAudioSink * pbin)
445 {
446   g_signal_handler_disconnect (pbin->dbin, pbin->pad_added_id);
447   gst_element_set_state (pbin->dbin, GST_STATE_NULL);
448
449   gst_bin_remove (GST_BIN (pbin), pbin->dbin);
450
451   pbin->dbin = NULL;
452 }
453
454 static void
455 gst_pulse_audio_sink_dispose (GObject * object)
456 {
457   GstPulseAudioSink *pbin = GST_PULSE_AUDIO_SINK (object);
458
459   if (pbin->lock) {
460     g_mutex_free (pbin->lock);
461     pbin->lock = NULL;
462   }
463
464   if (pbin->sink_proxypad) {
465     gst_object_unref (pbin->sink_proxypad);
466     pbin->sink_proxypad = NULL;
467   }
468
469   if (pbin->dbin) {
470     g_signal_handler_disconnect (pbin->dbin, pbin->pad_added_id);
471     pbin->dbin = NULL;
472   }
473
474   pbin->sinkpad = NULL;
475   pbin->psink = NULL;
476 }
477
478 static gboolean
479 gst_pulse_audio_sink_update_sinkpad (GstPulseAudioSink * pbin, GstPad * sinkpad)
480 {
481   gboolean ret;
482
483   ret = gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (pbin->sinkpad), sinkpad);
484
485   if (!ret)
486     GST_WARNING_OBJECT (pbin, "Could not update ghostpad target");
487
488   return ret;
489 }
490
491 static void
492 distribute_running_time (GstElement * element, const GstSegment * segment)
493 {
494   GstEvent *event;
495   GstPad *pad;
496
497   pad = gst_element_get_static_pad (element, "sink");
498
499   /* FIXME: Some decoders collect newsegments and send them out at once, making
500    * them lose accumulator events (and thus making dbin_event_probe() hard to
501    * do right if we're sending these as well. We can get away with not sending
502    * these at the moment, but this should be fixed! */
503 #if 0
504   if (segment->accum) {
505     event = gst_event_new_new_segment_full (FALSE, segment->rate,
506         segment->applied_rate, segment->format, 0, segment->accum, 0);
507     gst_pad_send_event (pad, event);
508   }
509 #endif
510
511   /* TODO review this copy, see if it can be avoided */
512   event = gst_event_new_segment (gst_segment_copy (segment));
513   gst_pad_send_event (pad, event);
514
515   gst_object_unref (pad);
516 }
517
518 static GstPadProbeReturn
519 dbin_event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
520 {
521   GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
522   GstPulseAudioSink *pbin = GST_PULSE_AUDIO_SINK (data);
523
524   if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
525     GST_DEBUG_OBJECT (pbin, "Got newsegment - dropping");
526     gst_pad_remove_probe (pad, pbin->event_probe_id);
527     gst_object_unref (pbin);
528     return GST_PAD_PROBE_DROP;
529   }
530
531   return GST_PAD_PROBE_OK;
532 }
533
534 static void
535 pad_added_cb (GstElement * dbin, GstPad * pad, gpointer * data)
536 {
537   GstPulseAudioSink *pbin = GST_PULSE_AUDIO_SINK (data);
538   GstPad *sinkpad = NULL;
539
540   pbin = GST_PULSE_AUDIO_SINK (data);
541   sinkpad = gst_element_get_static_pad (GST_ELEMENT (pbin->psink), "sink");
542
543   GST_PULSE_AUDIO_SINK_LOCK (pbin);
544   if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)
545     GST_ERROR_OBJECT (pbin, "Failed to link decodebin to pulsesink");
546   else
547     GST_DEBUG_OBJECT (pbin, "Linked new pad to pulsesink");
548   GST_PULSE_AUDIO_SINK_UNLOCK (pbin);
549
550   gst_object_unref (sinkpad);
551 }
552
553 /* Called with pbin lock held */
554 static void
555 gst_pulse_audio_sink_add_dbin (GstPulseAudioSink * pbin)
556 {
557   GstPad *sinkpad = NULL;
558
559   g_assert (pbin->dbin == NULL);
560
561   pbin->dbin = gst_element_factory_make ("decodebin", "pulseaudiosink-dbin");
562
563   if (!pbin->dbin) {
564     post_missing_element_message (pbin, "decodebin");
565     GST_ELEMENT_WARNING (pbin, CORE, MISSING_PLUGIN,
566         (_("Missing element '%s' - check your GStreamer installation."),
567             "decodebin"), ("audio playback might fail"));
568     goto out;
569   }
570
571   if (!gst_bin_add (GST_BIN (pbin), pbin->dbin)) {
572     GST_ERROR_OBJECT (pbin, "Failed to add decodebin to bin");
573     goto out;
574   }
575
576   pbin->pad_added_id = g_signal_connect (pbin->dbin, "pad-added",
577       G_CALLBACK (pad_added_cb), pbin);
578
579   if (!gst_element_sync_state_with_parent (pbin->dbin)) {
580     GST_ERROR_OBJECT (pbin, "Failed to set decodebin to parent state");
581     goto out;
582   }
583
584   /* Trap the newsegment events that we feed the decodebin and discard them */
585   sinkpad = gst_element_get_static_pad (GST_ELEMENT (pbin->psink), "sink");
586   pbin->event_probe_id =
587       gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
588       dbin_event_probe, gst_object_ref (pbin), NULL);
589   gst_object_unref (sinkpad);
590   sinkpad = NULL;
591
592   GST_DEBUG_OBJECT (pbin, "Distributing running time to decodebin");
593   distribute_running_time (pbin->dbin, &pbin->segment);
594
595   sinkpad = gst_element_get_static_pad (pbin->dbin, "sink");
596
597   gst_pulse_audio_sink_update_sinkpad (pbin, sinkpad);
598
599 out:
600   if (sinkpad)
601     gst_object_unref (sinkpad);
602 }
603
604 static void
605 update_eac3_alignment (GstPulseAudioSink * pbin)
606 {
607   GstCaps *caps = gst_pad_peer_get_caps (pbin->sinkpad, NULL);
608   GstStructure *st;
609
610   if (!caps)
611     return;
612
613   st = gst_caps_get_structure (caps, 0);
614
615   if (g_str_equal (gst_structure_get_name (st), "audio/x-eac3")) {
616     GstStructure *event_st = gst_structure_new ("ac3parse-set-alignment",
617         "alignment", G_TYPE_STRING, pbin->dbin ? "frame" : "iec61937", NULL);
618
619     if (!gst_pad_push_event (pbin->sinkpad,
620             gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, event_st)))
621       GST_WARNING_OBJECT (pbin->sinkpad, "Could not update alignment");
622   }
623
624   gst_caps_unref (caps);
625 }
626
627 static GstPadProbeReturn
628 proxypad_blocked_cb (GstPad * pad, GstPadProbeInfo * info, gpointer data)
629 {
630   GstPulseAudioSink *pbin = GST_PULSE_AUDIO_SINK (data);
631   GstCaps *caps;
632   GstPad *sinkpad = NULL;
633
634   GST_DEBUG_OBJECT (pbin, "blocked");
635
636   GST_PULSE_AUDIO_SINK_LOCK (pbin);
637
638   if (!pbin->format_lost) {
639     sinkpad = gst_element_get_static_pad (GST_ELEMENT (pbin->psink), "sink");
640
641     if (gst_pad_has_current_caps (pbin->sinkpad)) {
642       /* See if we already got caps on our sinkpad */
643       caps = gst_pad_get_current_caps (pbin->sinkpad);
644     } else {
645       /* We haven't, so get caps from upstream */
646       caps = gst_pad_get_caps (pad, NULL);
647     }
648
649     if (gst_pad_accept_caps (sinkpad, caps)) {
650       if (pbin->dbin) {
651         GST_DEBUG_OBJECT (pbin, "Removing decodebin");
652         gst_pulse_audio_sink_free_dbin (pbin);
653         gst_pulse_audio_sink_update_sinkpad (pbin, sinkpad);
654       } else {
655         GST_DEBUG_OBJECT (pbin, "Doing nothing");
656         gst_pad_send_event (sinkpad, gst_event_new_caps (caps));
657       }
658
659       gst_caps_unref (caps);
660       gst_object_unref (sinkpad);
661       goto done;
662     }
663     /* pulsesink doesn't accept the incoming caps, so add a decodebin
664      * (potentially after removing the existing once, since decodebin can't
665      * renegotiate). */
666   } else {
667     /* Format lost, proceed to try plugging a decodebin */
668     pbin->format_lost = FALSE;
669   }
670
671   if (pbin->dbin != NULL) {
672     /* decodebin doesn't support reconfiguration, so throw this one away and
673      * create a new one. */
674     gst_pulse_audio_sink_free_dbin (pbin);
675   }
676
677   GST_DEBUG_OBJECT (pbin, "Adding decodebin");
678   gst_pulse_audio_sink_add_dbin (pbin);
679
680 done:
681   update_eac3_alignment (pbin);
682
683   pbin->block_probe_id = 0;
684   GST_PULSE_AUDIO_SINK_UNLOCK (pbin);
685
686   return GST_PAD_PROBE_REMOVE;
687 }
688
689 static gboolean
690 gst_pulse_audio_sink_src_event (GstPad * pad, GstEvent * event)
691 {
692   GstPulseAudioSink *pbin = NULL;
693   GstPad *ghostpad = NULL;
694   gboolean ret = FALSE;
695
696   ghostpad = GST_PAD_CAST (gst_pad_get_parent (pad));
697   if (G_UNLIKELY (!ghostpad)) {
698     GST_WARNING_OBJECT (pad, "Could not get ghostpad");
699     goto out;
700   }
701
702   pbin = GST_PULSE_AUDIO_SINK (gst_pad_get_parent (ghostpad));
703   if (G_UNLIKELY (!pbin)) {
704     GST_WARNING_OBJECT (pad, "Could not get pulseaudiosink");
705     goto out;
706   }
707
708   if (G_UNLIKELY (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_UPSTREAM) &&
709       (gst_event_has_name (event, "pulse-format-lost") ||
710           gst_event_has_name (event, "pulse-sink-changed"))) {
711     g_return_val_if_fail (pad->mode != GST_PAD_ACTIVATE_PULL, FALSE);
712
713     GST_PULSE_AUDIO_SINK_LOCK (pbin);
714     if (gst_event_has_name (event, "pulse-format-lost"))
715       pbin->format_lost = TRUE;
716
717     if (pbin->block_probe_id == 0)
718       pbin->block_probe_id =
719           gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
720           proxypad_blocked_cb, gst_object_ref (pbin),
721           (GDestroyNotify) gst_object_unref);
722     GST_PULSE_AUDIO_SINK_UNLOCK (pbin);
723
724     ret = TRUE;
725   } else if (pbin->proxypad_old_eventfunc) {
726     ret = pbin->proxypad_old_eventfunc (pad, event);
727     event = NULL;
728   }
729
730 out:
731   if (ghostpad)
732     gst_object_unref (ghostpad);
733   if (pbin)
734     gst_object_unref (pbin);
735   if (event)
736     gst_event_unref (event);
737
738   return ret;
739 }
740
741 static gboolean
742 gst_pulse_audio_sink_sink_event (GstPad * pad, GstEvent * event)
743 {
744   GstPulseAudioSink *pbin = GST_PULSE_AUDIO_SINK (gst_pad_get_parent (pad));
745   gboolean ret;
746   gboolean forward = TRUE;
747
748   switch (GST_EVENT_TYPE (event)) {
749     case GST_EVENT_CAPS:
750     {
751       GstCaps *caps;
752
753       gst_event_parse_caps (event, &caps);
754       ret = gst_pulse_audio_sink_set_caps (pbin, caps);
755       forward = FALSE;
756       break;
757     }
758     case GST_EVENT_SEGMENT:
759     {
760       const GstSegment *segment = NULL;
761
762       GST_PULSE_AUDIO_SINK_LOCK (pbin);
763       gst_event_parse_segment (event, &segment);
764
765       GST_DEBUG_OBJECT (pbin, "newsegment: %" GST_SEGMENT_FORMAT, segment);
766
767       if (segment->format == GST_FORMAT_TIME) {
768         /* Store the values for feeding to sub-elements */
769         gst_segment_copy_into (segment, &pbin->segment);
770       } else {
771         GST_WARNING_OBJECT (pbin, "Got a non-TIME format segment");
772         gst_segment_init (&pbin->segment, GST_FORMAT_TIME);
773       }
774       GST_PULSE_AUDIO_SINK_UNLOCK (pbin);
775
776       break;
777     }
778
779     case GST_EVENT_FLUSH_STOP:
780       GST_PULSE_AUDIO_SINK_LOCK (pbin);
781       gst_segment_init (&pbin->segment, GST_FORMAT_UNDEFINED);
782       GST_PULSE_AUDIO_SINK_UNLOCK (pbin);
783       break;
784
785     default:
786       break;
787   }
788
789   if (forward)
790     ret = pbin->sinkpad_old_eventfunc (pad, event);
791   else
792     gst_event_unref (event);
793
794   gst_object_unref (pbin);
795
796   return ret;
797 }
798
799 /* The bin's acceptcaps should be exactly equivalent to a pulsesink that is
800  * connected to a sink that supports all the formats in template caps. This
801  * means that upstream will have to have everything possibly upto a parser
802  * plugged and we plugin a decoder whenever required. */
803 static gboolean
804 gst_pulse_audio_sink_sink_acceptcaps (GstPulseAudioSink * pbin, GstPad * pad,
805     GstCaps * caps)
806 {
807   GstAudioRingBufferSpec spec = { 0 };
808   const GstStructure *st;
809   GstCaps *pad_caps = NULL;
810   gboolean ret = FALSE;
811
812   pad_caps = gst_pad_get_caps (pad, caps);
813   if (!pad_caps || gst_caps_is_empty (pad_caps))
814     goto out;
815
816   /* If we've not got fixed caps, creating a stream might fail, so let's just
817    * return from here with default acceptcaps behaviour */
818   if (!gst_caps_is_fixed (caps))
819     goto out;
820
821   spec.latency_time = GST_BASE_AUDIO_SINK (pbin->psink)->latency_time;
822   if (!gst_audio_ring_buffer_parse_caps (&spec, caps))
823     goto out;
824
825   /* Make sure non-raw input is framed (one frame per buffer) and can be
826    * payloaded */
827   st = gst_caps_get_structure (caps, 0);
828
829   if (!g_str_has_prefix (gst_structure_get_name (st), "audio/x-raw")) {
830     gboolean framed = FALSE, parsed = FALSE;
831
832     gst_structure_get_boolean (st, "framed", &framed);
833     gst_structure_get_boolean (st, "parsed", &parsed);
834     if ((!framed && !parsed) || gst_audio_iec61937_frame_size (&spec) <= 0)
835       goto out;
836   }
837
838   ret = TRUE;
839
840 out:
841   if (pad_caps)
842     gst_caps_unref (pad_caps);
843
844   return ret;
845 }
846
847 static gboolean
848 gst_pulse_audio_sink_sink_query (GstPad * pad, GstQuery * query)
849 {
850   GstPulseAudioSink *pbin = GST_PULSE_AUDIO_SINK (gst_pad_get_parent (pad));
851   gboolean ret = FALSE;
852
853   switch (GST_QUERY_TYPE (query)) {
854     case GST_QUERY_ACCEPT_CAPS:
855     {
856       GstCaps *caps;
857
858       gst_query_parse_accept_caps (query, &caps);
859       ret = gst_pulse_audio_sink_sink_acceptcaps (pbin, pad, caps);
860       gst_query_set_accept_caps_result (query, ret);
861       ret = TRUE;
862       break;
863     }
864     default:
865       ret = gst_pad_query_default (pad, query);
866       break;
867   }
868
869   gst_object_unref (pbin);
870
871   return ret;
872
873 }
874
875 static gboolean
876 gst_pulse_audio_sink_set_caps (GstPulseAudioSink * pbin, GstCaps * caps)
877 {
878   gboolean ret = TRUE;
879
880   GST_PULSE_AUDIO_SINK_LOCK (pbin);
881
882   if (pbin->block_probe_id == 0)
883     pbin->block_probe_id =
884         gst_pad_add_probe (pbin->sink_proxypad,
885         GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, proxypad_blocked_cb,
886         gst_object_ref (pbin), (GDestroyNotify) gst_object_unref);
887
888   GST_PULSE_AUDIO_SINK_UNLOCK (pbin);
889
890   return ret;
891 }
892
893 static GstStateChangeReturn
894 gst_pulse_audio_sink_change_state (GstElement * element,
895     GstStateChange transition)
896 {
897   GstPulseAudioSink *pbin = GST_PULSE_AUDIO_SINK (element);
898   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
899
900   /* Nothing to do for upward transitions */
901   switch (transition) {
902     case GST_STATE_CHANGE_PAUSED_TO_READY:
903       GST_PULSE_AUDIO_SINK_LOCK (pbin);
904       if (pbin->block_probe_id) {
905         gst_pad_remove_probe (pbin->sink_proxypad, pbin->block_probe_id);
906         pbin->block_probe_id = 0;
907       }
908       GST_PULSE_AUDIO_SINK_UNLOCK (pbin);
909       break;
910
911     default:
912       break;
913   }
914
915   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
916   if (ret != GST_STATE_CHANGE_SUCCESS) {
917     GST_DEBUG_OBJECT (pbin, "Base class returned %d on state change", ret);
918     goto out;
919   }
920
921   switch (transition) {
922     case GST_STATE_CHANGE_PAUSED_TO_READY:
923       GST_PULSE_AUDIO_SINK_LOCK (pbin);
924       gst_segment_init (&pbin->segment, GST_FORMAT_UNDEFINED);
925
926       if (pbin->dbin) {
927         GstPad *pad = gst_element_get_static_pad (GST_ELEMENT (pbin->psink),
928             "sink");
929
930         gst_pulse_audio_sink_free_dbin (pbin);
931         gst_pulse_audio_sink_update_sinkpad (pbin, pad);
932
933         gst_object_unref (pad);
934
935       }
936       GST_PULSE_AUDIO_SINK_UNLOCK (pbin);
937
938       break;
939
940     default:
941       break;
942   }
943
944 out:
945   return ret;
946 }
947
948 #endif /* HAVE_PULSE_1_0 */