1 /*-*- Mode: C; c-basic-offset: 2 -*-*/
3 /* GStreamer pulseaudio plugin
5 * Copyright (c) 2004-2008 Lennart Poettering
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.
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.
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
25 * SECTION:element-pulsesink
26 * @see_also: pulsesrc, pulsemixer
28 * This element outputs audio to a
29 * <ulink href="http://www.pulseaudio.org">PulseAudio sound server</ulink>.
32 * <title>Example pipelines</title>
34 * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! pulsesink
35 * ]| Play an Ogg/Vorbis file.
37 * gst-launch -v audiotestsrc ! audioconvert ! volume volume=0.4 ! pulsesink
38 * ]| Play a 440Hz sine wave.
49 #include <gst/base/gstbasesink.h>
50 #include <gst/gsttaglist.h>
51 #include <gst/interfaces/streamvolume.h>
52 #include <gst/gst-i18n-plugin.h>
54 #include <gst/pbutils/pbutils.h> /* only used for GST_PLUGINS_BASE_VERSION_* */
56 #include "pulsesink.h"
57 #include "pulseutil.h"
59 GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
60 #define GST_CAT_DEFAULT pulse_debug
63 * http://www.pulseaudio.org/ticket/314
64 * we need pulse-0.9.12 to use sink volume properties
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
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))
100 typedef struct _GstPulseRingBuffer GstPulseRingBuffer;
101 typedef struct _GstPulseRingBufferClass GstPulseRingBufferClass;
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
108 GstRingBuffer object;
115 pa_sample_spec sample_spec;
117 #ifdef HAVE_PULSE_0_9_16
126 gboolean in_commit:1;
129 struct _GstPulseRingBufferClass
131 GstRingBufferClass parent_class;
134 static GType gst_pulseringbuffer_get_type (void);
135 static void gst_pulseringbuffer_finalize (GObject * object);
137 static GstRingBufferClass *ring_parent_class = NULL;
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,
152 G_DEFINE_TYPE (GstPulseRingBuffer, gst_pulseringbuffer, GST_TYPE_RING_BUFFER);
155 gst_pulseringbuffer_class_init (GstPulseRingBufferClass * klass)
157 GObjectClass *gobject_class;
158 GstRingBufferClass *gstringbuffer_class;
160 gobject_class = (GObjectClass *) klass;
161 gstringbuffer_class = (GstRingBufferClass *) klass;
163 ring_parent_class = g_type_class_peek_parent (klass);
165 gobject_class->finalize = gst_pulseringbuffer_finalize;
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);
182 gstringbuffer_class->commit = GST_DEBUG_FUNCPTR (gst_pulseringbuffer_commit);
186 gst_pulseringbuffer_init (GstPulseRingBuffer * pbuf)
188 pbuf->stream_name = NULL;
189 pbuf->context = NULL;
192 #ifdef HAVE_PULSE_0_9_13
193 pa_sample_spec_init (&pbuf->sample_spec);
195 pbuf->sample_spec.format = PA_SAMPLE_INVALID;
196 pbuf->sample_spec.rate = 0;
197 pbuf->sample_spec.channels = 0;
200 #ifdef HAVE_PULSE_0_9_16
203 pbuf->m_writable = 0;
205 pbuf->m_lastoffset = 0;
209 pbuf->in_commit = FALSE;
210 pbuf->paused = FALSE;
214 gst_pulsering_destroy_stream (GstPulseRingBuffer * pbuf)
218 #ifdef HAVE_PULSE_0_9_16
220 /* drop shm memory buffer */
221 pa_stream_cancel_write (pbuf->stream);
223 /* reset internal variables */
226 pbuf->m_writable = 0;
228 pbuf->m_lastoffset = 0;
232 pa_stream_disconnect (pbuf->stream);
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);
240 pa_stream_unref (pbuf->stream);
244 g_free (pbuf->stream_name);
245 pbuf->stream_name = NULL;
249 gst_pulsering_destroy_context (GstPulseRingBuffer * pbuf)
251 gst_pulsering_destroy_stream (pbuf);
254 pa_context_disconnect (pbuf->context);
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);
262 pa_context_unref (pbuf->context);
263 pbuf->context = NULL;
268 gst_pulseringbuffer_finalize (GObject * object)
270 GstPulseRingBuffer *ringbuffer;
272 ringbuffer = GST_PULSERING_BUFFER_CAST (object);
274 gst_pulsering_destroy_context (ringbuffer);
276 G_OBJECT_CLASS (ring_parent_class)->finalize (object);
280 gst_pulsering_is_dead (GstPulseSink * psink, GstPulseRingBuffer * pbuf)
283 || !PA_CONTEXT_IS_GOOD (pa_context_get_state (pbuf->context))
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;
289 GST_ELEMENT_ERROR (psink, RESOURCE, FAILED, ("Disconnected: %s",
297 gst_pulsering_context_state_cb (pa_context * c, void *userdata)
300 GstPulseRingBuffer *pbuf;
301 pa_context_state_t state;
303 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
304 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
306 state = pa_context_get_state (c);
307 GST_LOG_OBJECT (psink, "got new context state %d", state);
309 /* psink can be null when we are shutting down and the ringbuffer is already
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);
322 case PA_CONTEXT_UNCONNECTED:
323 case PA_CONTEXT_CONNECTING:
324 case PA_CONTEXT_AUTHORIZING:
325 case PA_CONTEXT_SETTING_NAME:
330 #ifdef HAVE_PULSE_0_9_12
332 gst_pulsering_context_subscribe_cb (pa_context * c,
333 pa_subscription_event_type_t t, uint32_t idx, void *userdata)
336 GstPulseRingBuffer *pbuf;
338 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
339 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
341 GST_LOG_OBJECT (psink, "type %d, idx %u", t, idx);
343 if (t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_CHANGE) &&
344 t != (PA_SUBSCRIPTION_EVENT_SINK_INPUT | PA_SUBSCRIPTION_EVENT_NEW))
350 if (idx != pa_stream_get_index (pbuf->stream))
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. */
358 /* inform streaming thread to notify */
359 g_atomic_int_compare_and_exchange (&psink->notify, 0, 1);
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. */
366 gst_pulseringbuffer_open_device (GstRingBuffer * buf)
369 GstPulseRingBuffer *pbuf;
371 pa_mainloop_api *api;
373 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
374 pbuf = GST_PULSERING_BUFFER_CAST (buf);
376 g_assert (!pbuf->context);
377 g_assert (!pbuf->stream);
379 name = gst_pulse_client_name ();
381 pa_threaded_mainloop_lock (psink->mainloop);
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)))
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);
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,
405 pa_context_state_t state;
407 state = pa_context_get_state (pbuf->context);
409 GST_LOG_OBJECT (psink, "context state is now %d", state);
411 if (!PA_CONTEXT_IS_GOOD (state))
414 if (state == PA_CONTEXT_READY)
417 /* Wait until the context is ready */
418 GST_LOG_OBJECT (psink, "waiting..");
419 pa_threaded_mainloop_wait (psink->mainloop);
422 GST_LOG_OBJECT (psink, "opened the device");
424 pa_threaded_mainloop_unlock (psink->mainloop);
432 gst_pulsering_destroy_context (pbuf);
434 pa_threaded_mainloop_unlock (psink->mainloop);
440 GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
441 ("Failed to create context"), (NULL));
442 goto unlock_and_fail;
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;
452 /* close the device */
454 gst_pulseringbuffer_close_device (GstRingBuffer * buf)
457 GstPulseRingBuffer *pbuf;
459 pbuf = GST_PULSERING_BUFFER_CAST (buf);
460 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
462 GST_LOG_OBJECT (psink, "closing device");
464 pa_threaded_mainloop_lock (psink->mainloop);
465 gst_pulsering_destroy_context (pbuf);
466 pa_threaded_mainloop_unlock (psink->mainloop);
468 GST_LOG_OBJECT (psink, "closed device");
474 gst_pulsering_stream_state_cb (pa_stream * s, void *userdata)
477 GstPulseRingBuffer *pbuf;
478 pa_stream_state_t state;
480 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
481 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
483 state = pa_stream_get_state (s);
484 GST_LOG_OBJECT (psink, "got new stream state %d", 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);
493 case PA_STREAM_UNCONNECTED:
494 case PA_STREAM_CREATING:
500 gst_pulsering_stream_request_cb (pa_stream * s, size_t length, void *userdata)
504 GstPulseRingBuffer *pbuf;
506 rbuf = GST_RING_BUFFER_CAST (userdata);
507 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
508 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
510 GST_LOG_OBJECT (psink, "got request for length %" G_GSIZE_FORMAT, length);
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);
520 gst_pulsering_stream_underflow_cb (pa_stream * s, void *userdata)
523 GstPulseRingBuffer *pbuf;
525 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
526 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
528 GST_WARNING_OBJECT (psink, "Got underflow");
532 gst_pulsering_stream_overflow_cb (pa_stream * s, void *userdata)
535 GstPulseRingBuffer *pbuf;
537 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
538 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
540 GST_WARNING_OBJECT (psink, "Got overflow");
544 gst_pulsering_stream_latency_cb (pa_stream * s, void *userdata)
547 GstPulseRingBuffer *pbuf;
548 const pa_timing_info *info;
551 info = pa_stream_get_timing_info (s);
553 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
554 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
557 GST_LOG_OBJECT (psink, "latency update (information unknown)");
560 #ifdef HAVE_PULSE_0_9_11
561 sink_usec = info->configured_sink_usec;
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);
575 gst_pulsering_stream_suspended_cb (pa_stream * p, void *userdata)
578 GstPulseRingBuffer *pbuf;
580 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
581 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
583 if (pa_stream_is_suspended (p))
584 GST_DEBUG_OBJECT (psink, "stream suspended");
586 GST_DEBUG_OBJECT (psink, "stream resumed");
589 #ifdef HAVE_PULSE_0_9_11
591 gst_pulsering_stream_started_cb (pa_stream * p, void *userdata)
594 GstPulseRingBuffer *pbuf;
596 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
597 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
599 GST_DEBUG_OBJECT (psink, "stream started");
603 #ifdef HAVE_PULSE_0_9_15
605 gst_pulsering_stream_event_cb (pa_stream * p, const char *name,
606 pa_proplist * pl, void *userdata)
609 GstPulseRingBuffer *pbuf;
611 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
612 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
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),
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),
627 GST_DEBUG_OBJECT (psink, "got unknown event %s", name);
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. */
635 gst_pulseringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
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
646 pa_cvolume *pv = NULL;
647 pa_stream_flags_t flags;
649 GstAudioClock *clock;
651 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
652 pbuf = GST_PULSERING_BUFFER_CAST (buf);
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))
659 pa_threaded_mainloop_lock (psink->mainloop);
661 /* we need a context and a no stream */
662 g_assert (pbuf->context);
663 g_assert (!pbuf->stream);
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;
671 pa_operation_unref (o);
673 /* initialize the channel map */
674 gst_pulse_gst_to_channel_map (&channel_map, spec);
676 /* find a good name for the stream */
677 if (psink->stream_name)
678 name = psink->stream_name;
680 name = "Playback Stream";
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)))
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);
705 #ifdef HAVE_PULSE_0_9_15
706 pa_stream_set_event_callback (pbuf->stream,
707 gst_pulsering_stream_event_cb, pbuf);
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;
716 wanted.minreq = spec->segsize;
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);
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);
728 gst_pulse_cvolume_from_linear (pv, pbuf->sample_spec.channels,
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 |
740 PA_STREAM_START_CORKED;
742 #ifdef HAVE_PULSE_0_9_12
743 if (psink->mute_set && psink->mute)
744 flags |= PA_STREAM_START_MUTED;
747 /* we always start corked (see flags above) */
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)
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);
762 pa_stream_state_t state;
764 state = pa_stream_get_state (pbuf->stream);
766 GST_LOG_OBJECT (psink, "stream state is now %d", state);
768 if (!PA_STREAM_IS_GOOD (state))
771 if (state == PA_STREAM_READY)
774 /* Wait until the stream is ready */
775 pa_threaded_mainloop_wait (psink->mainloop);
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;
782 GST_LOG_OBJECT (psink, "stream is acquired now");
784 /* get the actual buffering properties now */
785 actual = pa_stream_get_buffer_attr (pbuf->stream);
787 GST_INFO_OBJECT (psink, "tlength: %d (wanted: %d)", actual->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,
794 spec->segsize = actual->minreq;
795 spec->segtotal = actual->tlength / spec->segsize;
797 pa_threaded_mainloop_unlock (psink->mainloop);
804 gst_pulsering_destroy_stream (pbuf);
805 pa_threaded_mainloop_unlock (psink->mainloop);
811 GST_ELEMENT_ERROR (psink, RESOURCE, SETTINGS,
812 ("Invalid sample specification."), (NULL));
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;
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;
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;
838 /* free the stream that we acquired before */
840 gst_pulseringbuffer_release (GstRingBuffer * buf)
843 GstPulseRingBuffer *pbuf;
845 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (buf));
846 pbuf = GST_PULSERING_BUFFER_CAST (buf);
848 pa_threaded_mainloop_lock (psink->mainloop);
849 gst_pulsering_destroy_stream (pbuf);
850 pa_threaded_mainloop_unlock (psink->mainloop);
856 gst_pulsering_success_cb (pa_stream * s, int success, void *userdata)
858 GstPulseRingBuffer *pbuf;
861 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
862 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
864 pa_threaded_mainloop_signal (psink->mainloop, 0);
867 /* update the corked state of a stream, must be called with the mainloop
870 gst_pulsering_set_corked (GstPulseRingBuffer * pbuf, gboolean corked,
873 pa_operation *o = NULL;
875 gboolean res = FALSE;
877 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
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)))
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))
890 pbuf->corked = corked;
892 GST_DEBUG_OBJECT (psink, "skipping, already in requested state");
898 pa_operation_unref (o);
905 GST_DEBUG_OBJECT (psink, "the server is dead");
910 GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
911 ("pa_stream_cork() failed: %s",
912 pa_strerror (pa_context_errno (pbuf->context))), (NULL));
918 gst_pulseringbuffer_clear (GstRingBuffer * buf)
921 GstPulseRingBuffer *pbuf;
922 pa_operation *o = NULL;
924 pbuf = GST_PULSERING_BUFFER_CAST (buf);
925 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
927 pa_threaded_mainloop_lock (psink->mainloop);
928 GST_DEBUG_OBJECT (psink, "clearing");
930 /* don't wait for the flush to complete */
931 if ((o = pa_stream_flush (pbuf->stream, NULL, pbuf)))
932 pa_operation_unref (o);
934 pa_threaded_mainloop_unlock (psink->mainloop);
938 mainloop_enter_defer_cb (pa_mainloop_api * api, void *userdata)
940 GstPulseSink *pulsesink = GST_PULSESINK (userdata);
944 g_value_init (&val, G_TYPE_POINTER);
945 g_value_set_pointer (&val, g_thread_self ());
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);
952 gst_element_post_message (GST_ELEMENT (pulsesink), message);
954 /* signal the waiter */
955 pulsesink->pa_defer_ran = TRUE;
956 pa_threaded_mainloop_signal (pulsesink->mainloop, 0);
959 /* start/resume playback ASAP, we don't uncork here but in the commit method */
961 gst_pulseringbuffer_start (GstRingBuffer * buf)
964 GstPulseRingBuffer *pbuf;
966 pbuf = GST_PULSERING_BUFFER_CAST (buf);
967 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
969 pa_threaded_mainloop_lock (psink->mainloop);
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);
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);
984 /* pause/stop playback ASAP */
986 gst_pulseringbuffer_pause (GstRingBuffer * buf)
989 GstPulseRingBuffer *pbuf;
992 pbuf = GST_PULSERING_BUFFER_CAST (buf);
993 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
995 pa_threaded_mainloop_lock (psink->mainloop);
996 GST_DEBUG_OBJECT (psink, "pausing and corking");
997 /* make sure the commit method stops writing */
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);
1005 pa_threaded_mainloop_unlock (psink->mainloop);
1011 mainloop_leave_defer_cb (pa_mainloop_api * api, void *userdata)
1013 GstPulseSink *pulsesink = GST_PULSESINK (userdata);
1014 GstMessage *message;
1017 g_value_init (&val, G_TYPE_POINTER);
1018 g_value_set_pointer (&val, g_thread_self ());
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);
1026 pulsesink->pa_defer_ran = TRUE;
1027 pa_threaded_mainloop_signal (pulsesink->mainloop, 0);
1028 gst_object_unref (pulsesink);
1031 /* stop playback, we flush everything. */
1033 gst_pulseringbuffer_stop (GstRingBuffer * buf)
1035 GstPulseSink *psink;
1036 GstPulseRingBuffer *pbuf;
1037 gboolean res = FALSE;
1038 pa_operation *o = NULL;
1040 pbuf = GST_PULSERING_BUFFER_CAST (buf);
1041 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
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);
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))
1062 GST_DEBUG_OBJECT (psink, "flush completed");
1069 pa_operation_cancel (o);
1070 pa_operation_unref (o);
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);
1079 GST_DEBUG_OBJECT (psink, "waiting for stream status");
1080 pa_threaded_mainloop_unlock (psink->mainloop);
1087 GST_DEBUG_OBJECT (psink, "the server is dead");
1092 /* in_samples >= out_samples, rate > 1.0 */
1093 #define FWD_UP_SAMPLES(s,se,d,de) \
1095 guint8 *sb = s, *db = d; \
1096 while (s <= se && d < de) { \
1097 memcpy (d, s, bps); \
1100 if ((*accum << 1) >= inr) { \
1105 in_samples -= (s - sb)/bps; \
1106 out_samples -= (d - db)/bps; \
1107 GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess); \
1110 /* out_samples > in_samples, for rates smaller than 1.0 */
1111 #define FWD_DOWN_SAMPLES(s,se,d,de) \
1113 guint8 *sb = s, *db = d; \
1114 while (s <= se && d < de) { \
1115 memcpy (d, s, bps); \
1118 if ((*accum << 1) >= outr) { \
1123 in_samples -= (s - sb)/bps; \
1124 out_samples -= (d - db)/bps; \
1125 GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess); \
1128 #define REV_UP_SAMPLES(s,se,d,de) \
1130 guint8 *sb = se, *db = d; \
1131 while (s <= se && d < de) { \
1132 memcpy (d, se, bps); \
1135 while (d < de && (*accum << 1) >= inr) { \
1140 in_samples -= (sb - se)/bps; \
1141 out_samples -= (d - db)/bps; \
1142 GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess); \
1145 #define REV_DOWN_SAMPLES(s,se,d,de) \
1147 guint8 *sb = se, *db = d; \
1148 while (s <= se && d < de) { \
1149 memcpy (d, se, bps); \
1152 while (s <= se && (*accum << 1) >= outr) { \
1157 in_samples -= (sb - se)/bps; \
1158 out_samples -= (d - db)/bps; \
1159 GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess); \
1163 /* our custom commit function because we write into the buffer of pulseaudio
1164 * instead of keeping our own buffer */
1166 gst_pulseringbuffer_commit (GstRingBuffer * buf, guint64 * sample,
1167 guchar * data, gint in_samples, gint out_samples, gint * accum)
1169 GstPulseSink *psink;
1170 GstPulseRingBuffer *pbuf;
1175 gint inr, outr, bps;
1179 pbuf = GST_PULSERING_BUFFER_CAST (buf);
1180 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
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");
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))
1195 GST_DEBUG_OBJECT (buf, "start!");
1196 if (!gst_ring_buffer_start (buf))
1200 pa_threaded_mainloop_lock (psink->mainloop);
1201 GST_DEBUG_OBJECT (psink, "entering commit");
1202 pbuf->in_commit = TRUE;
1204 bps = buf->spec.bytes_per_sample;
1205 bufsize = buf->spec.segsize * buf->spec.segtotal;
1207 /* our toy resampler for trick modes */
1208 reverse = out_samples < 0;
1209 out_samples = ABS (out_samples);
1211 if (in_samples >= out_samples)
1212 toprocess = &in_samples;
1214 toprocess = &out_samples;
1216 inr = in_samples - 1;
1217 outr = out_samples - 1;
1219 GST_DEBUG_OBJECT (psink, "in %d, out %d", inr, outr);
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);
1228 /* offset is in bytes */
1229 offset = *sample * bps;
1231 while (*toprocess > 0) {
1235 GST_LOG_OBJECT (psink,
1236 "need to write %d samples at offset %" G_GINT64_FORMAT, *toprocess,
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);
1244 towrite = out_samples * bps;
1246 /* Only ever write segsize bytes at once. This will
1247 * also limit the PA shm buffer to segsize
1249 if (towrite > buf->spec.segsize)
1250 towrite = buf->spec.segsize;
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 */
1256 /* flush the buffer if possible */
1257 if ((pbuf->m_data != NULL) && (pbuf->m_towrite > 0)) {
1259 GST_LOG_OBJECT (psink,
1260 "flushing %u samples at offset %" G_GINT64_FORMAT,
1261 (guint) pbuf->m_towrite / bps, pbuf->m_offset);
1263 if (pa_stream_write (pbuf->stream, (uint8_t *) pbuf->m_data,
1264 pbuf->m_towrite, NULL, pbuf->m_offset, PA_SEEK_ABSOLUTE) < 0) {
1268 pbuf->m_towrite = 0;
1269 pbuf->m_offset = offset; /* keep track of current offset */
1271 /* get a buffer to write in for now on */
1273 pbuf->m_writable = pa_stream_writable_size (pbuf->stream);
1275 if (pbuf->m_writable == (size_t) - 1)
1276 goto writable_size_failed;
1278 pbuf->m_writable /= bps;
1279 pbuf->m_writable *= bps; /* handle only complete samples */
1281 if (pbuf->m_writable >= towrite)
1284 /* see if we need to uncork because we have no free space */
1286 if (!gst_pulsering_set_corked (pbuf, FALSE, FALSE))
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);
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;
1303 GST_LOG_OBJECT (psink, "Limiting buffering to %" G_GSIZE_FORMAT,
1307 GST_LOG_OBJECT (psink, "requesting %" G_GSIZE_FORMAT " bytes of "
1308 "shared memory", pbuf->m_writable);
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;
1316 GST_LOG_OBJECT (psink, "got %" G_GSIZE_FORMAT " bytes of shared memory",
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;
1326 if (pbuf->m_writable < towrite)
1327 towrite = pbuf->m_writable;
1328 avail = towrite / bps;
1330 GST_LOG_OBJECT (psink, "writing %u samples at offset %" G_GUINT64_FORMAT,
1331 (guint) avail, offset);
1333 if (G_LIKELY (inr == outr && !reverse)) {
1334 /* no rate conversion, simply write out the samples */
1335 /* copy the data into internal buffer */
1337 memcpy ((guint8 *) pbuf->m_data + pbuf->m_towrite, data, towrite);
1338 pbuf->m_towrite += towrite;
1339 pbuf->m_writable -= towrite;
1342 in_samples -= avail;
1343 out_samples -= avail;
1345 guint8 *dest, *d, *d_end;
1347 /* write into the PulseAudio shm buffer */
1348 dest = d = (guint8 *) pbuf->m_data + pbuf->m_towrite;
1349 d_end = d + towrite;
1353 /* forward speed up */
1354 FWD_UP_SAMPLES (data, data_end, d, d_end);
1356 /* forward slow down */
1357 FWD_DOWN_SAMPLES (data, data_end, d, d_end);
1360 /* reverse speed up */
1361 REV_UP_SAMPLES (data, data_end, d, d_end);
1363 /* reverse slow down */
1364 REV_DOWN_SAMPLES (data, data_end, d, d_end);
1366 /* see what we have left to write */
1367 towrite = (d - dest);
1368 pbuf->m_towrite += towrite;
1369 pbuf->m_writable -= towrite;
1371 avail = towrite / bps;
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);
1380 if (pa_stream_write (pbuf->stream, (uint8_t *) pbuf->m_data,
1381 pbuf->m_towrite, NULL, pbuf->m_offset, PA_SEEK_ABSOLUTE) < 0) {
1384 pbuf->m_towrite = 0;
1385 pbuf->m_offset = offset + towrite; /* keep track of current offset */
1390 /* FIXME, this is not quite right */
1391 if ((avail = pa_stream_writable_size (pbuf->stream)) == (size_t) - 1)
1392 goto writable_size_failed;
1394 /* We always try to satisfy a request for data */
1395 GST_LOG_OBJECT (psink, "writable bytes %" G_GSIZE_FORMAT, avail);
1397 /* convert to samples, we can only deal with multiples of the
1404 /* see if we need to uncork because we have no free space */
1406 if (!gst_pulsering_set_corked (pbuf, FALSE, FALSE))
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);
1418 if (avail > out_samples)
1419 avail = out_samples;
1421 towrite = avail * bps;
1423 GST_LOG_OBJECT (psink, "writing %u samples at offset %" G_GUINT64_FORMAT,
1424 (guint) avail, offset);
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)
1433 in_samples -= avail;
1434 out_samples -= avail;
1436 guint8 *dest, *d, *d_end;
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;
1446 /* forward speed up */
1447 FWD_UP_SAMPLES (data, data_end, d, d_end);
1449 /* forward slow down */
1450 FWD_DOWN_SAMPLES (data, data_end, d, d_end);
1453 /* reverse speed up */
1454 REV_UP_SAMPLES (data, data_end, d, d_end);
1456 /* reverse slow down */
1457 REV_DOWN_SAMPLES (data, data_end, d, d_end);
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)
1465 avail = towrite / bps;
1467 #endif /* HAVE_PULSE_0_9_16 */
1470 offset += avail * bps;
1472 #ifdef HAVE_PULSE_0_9_16
1473 pbuf->m_lastoffset = offset;
1476 /* check if we need to uncork after writing the samples */
1478 const pa_timing_info *info;
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);
1485 /* we uncork when the read_index is too far behind the offset we need
1487 if (info->read_index + bufsize <= offset) {
1488 if (!gst_pulsering_set_corked (pbuf, FALSE, FALSE))
1492 GST_LOG_OBJECT (psink, "no timing info available yet");
1496 /* we consumed all samples here */
1497 data = data_end + bps;
1499 pbuf->in_commit = FALSE;
1500 pa_threaded_mainloop_unlock (psink->mainloop);
1503 result = inr - ((data_end - data) / bps);
1504 GST_LOG_OBJECT (psink, "wrote %d samples", result);
1511 pbuf->in_commit = FALSE;
1512 GST_LOG_OBJECT (psink, "we are reset");
1513 pa_threaded_mainloop_unlock (psink->mainloop);
1518 GST_LOG_OBJECT (psink, "we can not start");
1523 GST_LOG_OBJECT (psink, "failed to start the ringbuffer");
1528 pbuf->in_commit = FALSE;
1529 GST_ERROR_OBJECT (psink, "uncork failed");
1530 pa_threaded_mainloop_unlock (psink->mainloop);
1535 pbuf->in_commit = FALSE;
1536 GST_LOG_OBJECT (psink, "we are paused");
1537 pa_threaded_mainloop_unlock (psink->mainloop);
1540 writable_size_failed:
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;
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;
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);
1562 static gboolean gst_pulsesink_event (GstBaseSink * sink, GstEvent * event);
1564 static GstStateChangeReturn gst_pulsesink_change_state (GstElement * element,
1565 GstStateChange transition);
1567 static void gst_pulsesink_init_interfaces (GType type);
1569 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
1570 # define ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
1572 # define ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
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);
1580 gst_pulsesink_interface_supported (GstImplementsInterface *
1581 iface, GType interface_type)
1583 GstPulseSink *this = GST_PULSESINK_CAST (iface);
1585 if (interface_type == GST_TYPE_PROPERTY_PROBE && this->probe)
1587 if (interface_type == GST_TYPE_STREAM_VOLUME)
1594 gst_pulsesink_implements_interface_init (GstImplementsInterfaceClass * klass)
1596 klass->supported = gst_pulsesink_interface_supported;
1600 gst_pulsesink_init_interfaces (GType type)
1602 static const GInterfaceInfo implements_iface_info = {
1603 (GInterfaceInitFunc) gst_pulsesink_implements_interface_init,
1607 static const GInterfaceInfo probe_iface_info = {
1608 (GInterfaceInitFunc) gst_pulsesink_property_probe_interface_init,
1612 #ifdef HAVE_PULSE_0_9_12
1613 static const GInterfaceInfo svol_iface_info = {
1617 g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_iface_info);
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,
1627 gst_pulsesink_base_init (gpointer g_class)
1629 static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
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 ];"
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
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 ];"
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 ];"
1666 "signed = (boolean) FALSE, "
1669 "rate = (int) [ 1, MAX ], "
1670 "channels = (int) [ 1, 32 ];"
1672 "rate = (int) [ 1, MAX], "
1673 "channels = (int) [ 1, 32 ];"
1675 "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ]")
1678 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
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));
1687 static GstRingBuffer *
1688 gst_pulsesink_create_ringbuffer (GstBaseAudioSink * sink)
1690 GstRingBuffer *buffer;
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);
1700 gst_pulsesink_class_init (GstPulseSinkClass * klass)
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);
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;
1712 gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_pulsesink_event);
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);
1718 gstelement_class->change_state =
1719 GST_DEBUG_FUNCPTR (gst_pulsesink_change_state);
1721 gstaudiosink_class->create_ringbuffer =
1722 GST_DEBUG_FUNCPTR (gst_pulsesink_create_ringbuffer);
1724 /* Overwrite GObject fields */
1725 g_object_class_install_property (gobject_class,
1727 g_param_spec_string ("server", "Server",
1728 "The PulseAudio server to connect to", DEFAULT_SERVER,
1729 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
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));
1736 g_object_class_install_property (gobject_class,
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));
1742 #ifdef HAVE_PULSE_0_9_12
1743 g_object_class_install_property (gobject_class,
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,
1750 g_param_spec_boolean ("mute", "Mute",
1751 "Mute state of this stream", DEFAULT_MUTE,
1752 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1756 /* returns the current time of the sink ringbuffer */
1758 gst_pulsesink_get_time (GstClock * clock, GstBaseAudioSink * sink)
1760 GstPulseSink *psink;
1761 GstPulseRingBuffer *pbuf;
1764 if (!sink->ringbuffer || !sink->ringbuffer->acquired)
1765 return GST_CLOCK_TIME_NONE;
1767 pbuf = GST_PULSERING_BUFFER_CAST (sink->ringbuffer);
1768 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
1770 pa_threaded_mainloop_lock (psink->mainloop);
1771 if (gst_pulsering_is_dead (psink, pbuf))
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;
1781 pa_threaded_mainloop_unlock (psink->mainloop);
1783 GST_LOG_OBJECT (psink, "current time is %" GST_TIME_FORMAT,
1784 GST_TIME_ARGS (time));
1791 GST_DEBUG_OBJECT (psink, "the server is dead");
1792 pa_threaded_mainloop_unlock (psink->mainloop);
1794 return GST_CLOCK_TIME_NONE;
1799 gst_pulsesink_init (GstPulseSink * pulsesink, GstPulseSinkClass * klass)
1801 pulsesink->server = NULL;
1802 pulsesink->device = NULL;
1803 pulsesink->device_description = NULL;
1805 pulsesink->volume = DEFAULT_VOLUME;
1806 pulsesink->volume_set = FALSE;
1808 pulsesink->mute = DEFAULT_MUTE;
1809 pulsesink->mute_set = FALSE;
1811 pulsesink->notify = 0;
1813 /* needed for conditional execution */
1814 pulsesink->pa_version = pa_get_library_version ();
1816 GST_DEBUG_OBJECT (pulsesink, "using pulseaudio version %s",
1817 pulsesink->pa_version);
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,
1826 gst_pulsesink_finalize (GObject * object)
1828 GstPulseSink *pulsesink = GST_PULSESINK_CAST (object);
1830 g_free (pulsesink->server);
1831 g_free (pulsesink->device);
1832 g_free (pulsesink->device_description);
1834 if (pulsesink->probe) {
1835 gst_pulseprobe_free (pulsesink->probe);
1836 pulsesink->probe = NULL;
1839 G_OBJECT_CLASS (parent_class)->finalize (object);
1842 #ifdef HAVE_PULSE_0_9_12
1844 gst_pulsesink_set_volume (GstPulseSink * psink, gdouble volume)
1847 pa_operation *o = NULL;
1848 GstPulseRingBuffer *pbuf;
1851 if (!psink->mainloop)
1854 pa_threaded_mainloop_lock (psink->mainloop);
1856 GST_DEBUG_OBJECT (psink, "setting volume to %f", volume);
1858 pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
1859 if (pbuf == NULL || pbuf->stream == NULL)
1862 if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
1865 gst_pulse_cvolume_from_linear (&v, pbuf->sample_spec.channels, volume);
1867 if (!(o = pa_context_set_sink_input_volume (pbuf->context, idx,
1871 /* We don't really care about the result of this call */
1875 pa_operation_unref (o);
1877 pa_threaded_mainloop_unlock (psink->mainloop);
1884 psink->volume = volume;
1885 psink->volume_set = TRUE;
1887 GST_DEBUG_OBJECT (psink, "we have no mainloop");
1892 psink->volume = volume;
1893 psink->volume_set = TRUE;
1895 GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
1900 GST_DEBUG_OBJECT (psink, "we don't have a stream index");
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));
1913 gst_pulsesink_set_mute (GstPulseSink * psink, gboolean mute)
1915 pa_operation *o = NULL;
1916 GstPulseRingBuffer *pbuf;
1919 if (!psink->mainloop)
1922 pa_threaded_mainloop_lock (psink->mainloop);
1924 GST_DEBUG_OBJECT (psink, "setting mute state to %d", mute);
1926 pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
1927 if (pbuf == NULL || pbuf->stream == NULL)
1930 if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
1933 if (!(o = pa_context_set_sink_input_mute (pbuf->context, idx,
1937 /* We don't really care about the result of this call */
1941 pa_operation_unref (o);
1943 pa_threaded_mainloop_unlock (psink->mainloop);
1951 psink->mute_set = TRUE;
1953 GST_DEBUG_OBJECT (psink, "we have no mainloop");
1959 psink->mute_set = TRUE;
1961 GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
1966 GST_DEBUG_OBJECT (psink, "we don't have a stream index");
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));
1979 gst_pulsesink_sink_input_info_cb (pa_context * c, const pa_sink_input_info * i,
1980 int eol, void *userdata)
1982 GstPulseRingBuffer *pbuf;
1983 GstPulseSink *psink;
1985 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
1986 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
1994 /* If the index doesn't match our current stream,
1995 * it implies we just recreated the stream (caps change)
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;
2003 pa_threaded_mainloop_signal (psink->mainloop, 0);
2007 gst_pulsesink_get_volume (GstPulseSink * psink)
2009 GstPulseRingBuffer *pbuf;
2010 pa_operation *o = NULL;
2011 gdouble v = DEFAULT_VOLUME;
2014 if (!psink->mainloop)
2017 pa_threaded_mainloop_lock (psink->mainloop);
2019 pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
2020 if (pbuf == NULL || pbuf->stream == NULL)
2023 if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
2026 if (!(o = pa_context_get_sink_input_info (pbuf->context, idx,
2027 gst_pulsesink_sink_input_info_cb, pbuf)))
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))
2040 pa_operation_unref (o);
2042 pa_threaded_mainloop_unlock (psink->mainloop);
2044 if (v > MAX_VOLUME) {
2045 GST_WARNING_OBJECT (psink, "Clipped volume from %f to %f", v, MAX_VOLUME);
2055 GST_DEBUG_OBJECT (psink, "we have no mainloop");
2060 GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
2065 GST_DEBUG_OBJECT (psink, "we don't have a stream index");
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));
2078 gst_pulsesink_get_mute (GstPulseSink * psink)
2080 GstPulseRingBuffer *pbuf;
2081 pa_operation *o = NULL;
2083 gboolean mute = FALSE;
2085 if (!psink->mainloop)
2088 pa_threaded_mainloop_lock (psink->mainloop);
2091 pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
2092 if (pbuf == NULL || pbuf->stream == NULL)
2095 if ((idx = pa_stream_get_index (pbuf->stream)) == PA_INVALID_INDEX)
2098 if (!(o = pa_context_get_sink_input_info (pbuf->context, idx,
2099 gst_pulsesink_sink_input_info_cb, pbuf)))
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))
2110 pa_operation_unref (o);
2112 pa_threaded_mainloop_unlock (psink->mainloop);
2120 GST_DEBUG_OBJECT (psink, "we have no mainloop");
2125 GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
2130 GST_DEBUG_OBJECT (psink, "we don't have a stream index");
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));
2144 gst_pulsesink_sink_info_cb (pa_context * c, const pa_sink_info * i, int eol,
2147 GstPulseRingBuffer *pbuf;
2148 GstPulseSink *psink;
2150 pbuf = GST_PULSERING_BUFFER_CAST (userdata);
2151 psink = GST_PULSESINK_CAST (GST_OBJECT_PARENT (pbuf));
2159 g_assert (i->index == pa_stream_get_device_index (pbuf->stream));
2161 g_free (psink->device_description);
2162 psink->device_description = g_strdup (i->description);
2165 pa_threaded_mainloop_signal (psink->mainloop, 0);
2169 gst_pulsesink_device_description (GstPulseSink * psink)
2171 GstPulseRingBuffer *pbuf;
2172 pa_operation *o = NULL;
2175 if (!psink->mainloop)
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)
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)))
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))
2196 pa_operation_unref (o);
2198 t = g_strdup (psink->device_description);
2199 pa_threaded_mainloop_unlock (psink->mainloop);
2206 GST_DEBUG_OBJECT (psink, "we have no mainloop");
2211 GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
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));
2224 gst_pulsesink_set_property (GObject * object,
2225 guint prop_id, const GValue * value, GParamSpec * pspec)
2227 GstPulseSink *pulsesink = GST_PULSESINK_CAST (object);
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);
2237 g_free (pulsesink->device);
2238 pulsesink->device = g_value_dup_string (value);
2240 #ifdef HAVE_PULSE_0_9_12
2242 gst_pulsesink_set_volume (pulsesink, g_value_get_double (value));
2245 gst_pulsesink_set_mute (pulsesink, g_value_get_boolean (value));
2249 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2255 gst_pulsesink_get_property (GObject * object,
2256 guint prop_id, GValue * value, GParamSpec * pspec)
2259 GstPulseSink *pulsesink = GST_PULSESINK_CAST (object);
2263 g_value_set_string (value, pulsesink->server);
2266 g_value_set_string (value, pulsesink->device);
2268 case PROP_DEVICE_NAME:
2269 g_value_take_string (value, gst_pulsesink_device_description (pulsesink));
2271 #ifdef HAVE_PULSE_0_9_12
2273 g_value_set_double (value, gst_pulsesink_get_volume (pulsesink));
2276 g_value_set_boolean (value, gst_pulsesink_get_mute (pulsesink));
2280 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2286 gst_pulsesink_change_title (GstPulseSink * psink, const gchar * t)
2288 pa_operation *o = NULL;
2289 GstPulseRingBuffer *pbuf;
2291 pa_threaded_mainloop_lock (psink->mainloop);
2293 pbuf = GST_PULSERING_BUFFER_CAST (GST_BASE_AUDIO_SINK (psink)->ringbuffer);
2295 if (pbuf == NULL || pbuf->stream == NULL)
2298 g_free (pbuf->stream_name);
2299 pbuf->stream_name = g_strdup (t);
2301 if (!(o = pa_stream_set_name (pbuf->stream, pbuf->stream_name, NULL, NULL)))
2304 /* We're not interested if this operation failed or not */
2307 pa_operation_unref (o);
2308 pa_threaded_mainloop_unlock (psink->mainloop);
2315 GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
2320 GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
2321 ("pa_stream_set_name() failed: %s",
2322 pa_strerror (pa_context_errno (pbuf->context))), (NULL));
2327 #ifdef HAVE_PULSE_0_9_11
2329 gst_pulsesink_change_props (GstPulseSink * psink, GstTagList * l)
2331 static const gchar *const map[] = {
2332 GST_TAG_TITLE, PA_PROP_MEDIA_TITLE,
2334 /* might get overriden in the next iteration by GST_TAG_ARTIST */
2335 GST_TAG_PERFORMER, PA_PROP_MEDIA_ARTIST,
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 ... */
2343 pa_proplist *pl = NULL;
2344 const gchar *const *t;
2345 gboolean empty = TRUE;
2346 pa_operation *o = NULL;
2347 GstPulseRingBuffer *pbuf;
2349 pl = pa_proplist_new ();
2351 for (t = map; *t; t += 2) {
2354 if (gst_tag_list_get_string (l, *t, &n)) {
2357 pa_proplist_sets (pl, *(t + 1), n);
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)
2372 if (!(o = pa_stream_proplist_update (pbuf->stream, PA_UPDATE_REPLACE,
2376 /* We're not interested if this operation failed or not */
2380 pa_operation_unref (o);
2382 pa_threaded_mainloop_unlock (psink->mainloop);
2387 pa_proplist_free (pl);
2394 GST_DEBUG_OBJECT (psink, "we have no ringbuffer");
2399 GST_ELEMENT_ERROR (psink, RESOURCE, FAILED,
2400 ("pa_stream_proplist_update() failed: %s",
2401 pa_strerror (pa_context_errno (pbuf->context))), (NULL));
2408 gst_pulsesink_event (GstBaseSink * sink, GstEvent * event)
2410 GstPulseSink *pulsesink = GST_PULSESINK_CAST (sink);
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;
2418 gst_event_parse_tag (event, &l);
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);
2426 gst_tag_list_get_string (l, GST_TAG_PERFORMER, &artist);
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));
2433 t = g_strstrip (title);
2434 else if (description)
2435 t = g_strstrip (description);
2437 t = g_strstrip (location);
2440 gst_pulsesink_change_title (pulsesink, t);
2445 g_free (description);
2448 #ifdef HAVE_PULSE_0_9_11
2449 gst_pulsesink_change_props (pulsesink, l);
2458 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
2461 static GstStateChangeReturn
2462 gst_pulsesink_change_state (GstElement * element, GstStateChange transition)
2464 GstPulseSink *pulsesink = GST_PULSESINK (element);
2465 GstStateChangeReturn ret;
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);
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);
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);
2488 GST_BASE_AUDIO_SINK (pulsesink)->provided_clock =
2489 gst_audio_clock_new ("GstPulseSinkClock",
2490 (GstAudioClockGetTimeFunc) gst_pulsesink_get_time, pulsesink);
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));
2502 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
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;
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));
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;