2 * GStreamer pulseaudio plugin
4 * Copyright (c) 2004-2008 Lennart Poettering
6 * gst-pulse is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of the
9 * License, or (at your option) any later version.
11 * gst-pulse is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with gst-pulse; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 * SECTION:element-pulsesink
24 * @short_description: Output audio to a PulseAudio sound server
25 * @see_also: pulsesrc, pulsemixer
29 * This element outputs audio to a PulseAudio sound server.
31 * <title>Example pipelines</title>
34 * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! pulsesink
36 * Play an Ogg/Vorbis file.
40 * gst-launch -v audiotestsrc ! audioconvert ! volume volume=0.4 ! pulsesink
42 * Play a 440Hz sine wave.
55 #include <gst/base/gstbasesink.h>
56 #include <gst/gsttaglist.h>
58 #include "pulsesink.h"
59 #include "pulseutil.h"
61 GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
62 #define GST_CAT_DEFAULT pulse_debug
70 static GstAudioSinkClass *parent_class = NULL;
72 static void gst_pulsesink_destroy_stream (GstPulseSink * pulsesink);
74 static void gst_pulsesink_destroy_context (GstPulseSink * pulsesink);
76 static void gst_pulsesink_set_property (GObject * object, guint prop_id,
77 const GValue * value, GParamSpec * pspec);
78 static void gst_pulsesink_get_property (GObject * object, guint prop_id,
79 GValue * value, GParamSpec * pspec);
80 static void gst_pulsesink_finalize (GObject * object);
82 static void gst_pulsesink_dispose (GObject * object);
84 static gboolean gst_pulsesink_open (GstAudioSink * asink);
86 static gboolean gst_pulsesink_close (GstAudioSink * asink);
88 static gboolean gst_pulsesink_prepare (GstAudioSink * asink,
89 GstRingBufferSpec * spec);
90 static gboolean gst_pulsesink_unprepare (GstAudioSink * asink);
92 static guint gst_pulsesink_write (GstAudioSink * asink, gpointer data,
94 static guint gst_pulsesink_delay (GstAudioSink * asink);
96 static void gst_pulsesink_reset (GstAudioSink * asink);
98 static gboolean gst_pulsesink_event (GstBaseSink * sink, GstEvent * event);
100 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
101 # define ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
103 # define ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
107 gst_pulsesink_base_init (gpointer g_class)
110 static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
113 GST_STATIC_CAPS ("audio/x-raw-int, "
114 "endianness = (int) { " ENDIANNESS " }, "
115 "signed = (boolean) TRUE, "
118 "rate = (int) [ 1, MAX ], "
119 "channels = (int) [ 1, 16 ];"
120 "audio/x-raw-float, "
121 "endianness = (int) { " ENDIANNESS " }, "
123 "rate = (int) [ 1, MAX ], "
124 "channels = (int) [ 1, 16 ];"
126 "endianness = (int) { " ENDIANNESS " }, "
127 "signed = (boolean) TRUE, "
130 "rate = (int) [ 1, MAX ], "
131 "channels = (int) [ 1, 16 ];"
133 "signed = (boolean) FALSE, "
136 "rate = (int) [ 1, MAX ], "
137 "channels = (int) [ 1, 16 ];"
139 "rate = (int) [ 1, MAX], "
140 "channels = (int) [ 1, 16 ];"
142 "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 16 ]")
145 static const GstElementDetails details =
146 GST_ELEMENT_DETAILS ("PulseAudio Audio Sink",
148 "Plays audio to a PulseAudio server",
149 "Lennart Poettering");
151 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
153 gst_element_class_set_details (element_class, &details);
154 gst_element_class_add_pad_template (element_class,
155 gst_static_pad_template_get (&pad_template));
159 gst_pulsesink_class_init (gpointer g_class, gpointer class_data)
162 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
164 GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (g_class);
166 GstAudioSinkClass *gstaudiosink_class = GST_AUDIO_SINK_CLASS (g_class);
168 parent_class = g_type_class_peek_parent (g_class);
170 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pulsesink_dispose);
171 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_pulsesink_finalize);
172 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pulsesink_set_property);
173 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pulsesink_get_property);
175 gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_pulsesink_event);
177 gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_pulsesink_open);
178 gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_pulsesink_close);
179 gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_pulsesink_prepare);
180 gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_pulsesink_unprepare);
181 gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_pulsesink_write);
182 gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_pulsesink_delay);
183 gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_pulsesink_reset);
185 /* Overwrite GObject fields */
186 g_object_class_install_property (gobject_class,
188 g_param_spec_string ("server", "Server",
189 "The PulseAudio server to connect to", NULL, G_PARAM_READWRITE));
190 g_object_class_install_property (gobject_class, PROP_DEVICE,
191 g_param_spec_string ("device", "Sink",
192 "The PulseAudio sink device to connect to", NULL, G_PARAM_READWRITE));
196 gst_pulsesink_init (GTypeInstance * instance, gpointer g_class)
199 GstPulseSink *pulsesink = GST_PULSESINK (instance);
203 pulsesink->server = pulsesink->device = pulsesink->stream_name = NULL;
205 pulsesink->context = NULL;
206 pulsesink->stream = NULL;
208 pulsesink->mainloop = pa_threaded_mainloop_new ();
209 g_assert (pulsesink->mainloop);
211 e = pa_threaded_mainloop_start (pulsesink->mainloop);
216 gst_pulsesink_destroy_stream (GstPulseSink * pulsesink)
218 if (pulsesink->stream) {
219 pa_stream_disconnect (pulsesink->stream);
220 pa_stream_unref (pulsesink->stream);
221 pulsesink->stream = NULL;
224 g_free (pulsesink->stream_name);
225 pulsesink->stream_name = NULL;
229 gst_pulsesink_destroy_context (GstPulseSink * pulsesink)
232 gst_pulsesink_destroy_stream (pulsesink);
234 if (pulsesink->context) {
235 pa_context_disconnect (pulsesink->context);
236 pa_context_unref (pulsesink->context);
237 pulsesink->context = NULL;
242 gst_pulsesink_finalize (GObject * object)
244 GstPulseSink *pulsesink = GST_PULSESINK (object);
246 pa_threaded_mainloop_stop (pulsesink->mainloop);
248 gst_pulsesink_destroy_context (pulsesink);
250 g_free (pulsesink->server);
251 g_free (pulsesink->device);
252 g_free (pulsesink->stream_name);
254 pa_threaded_mainloop_free (pulsesink->mainloop);
256 G_OBJECT_CLASS (parent_class)->finalize (object);
260 gst_pulsesink_dispose (GObject * object)
262 G_OBJECT_CLASS (parent_class)->dispose (object);
266 gst_pulsesink_set_property (GObject * object,
267 guint prop_id, const GValue * value, GParamSpec * pspec)
269 GstPulseSink *pulsesink = GST_PULSESINK (object);
273 g_free (pulsesink->server);
274 pulsesink->server = g_value_dup_string (value);
278 g_free (pulsesink->device);
279 pulsesink->device = g_value_dup_string (value);
283 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
289 gst_pulsesink_get_property (GObject * object,
290 guint prop_id, GValue * value, GParamSpec * pspec)
293 GstPulseSink *pulsesink = GST_PULSESINK (object);
297 g_value_set_string (value, pulsesink->server);
301 g_value_set_string (value, pulsesink->device);
305 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
311 gst_pulsesink_context_state_cb (pa_context * c, void *userdata)
313 GstPulseSink *pulsesink = GST_PULSESINK (userdata);
315 switch (pa_context_get_state (c)) {
316 case PA_CONTEXT_READY:
317 case PA_CONTEXT_TERMINATED:
318 case PA_CONTEXT_FAILED:
319 pa_threaded_mainloop_signal (pulsesink->mainloop, 0);
322 case PA_CONTEXT_UNCONNECTED:
323 case PA_CONTEXT_CONNECTING:
324 case PA_CONTEXT_AUTHORIZING:
325 case PA_CONTEXT_SETTING_NAME:
331 gst_pulsesink_stream_state_cb (pa_stream * s, void *userdata)
333 GstPulseSink *pulsesink = GST_PULSESINK (userdata);
335 switch (pa_stream_get_state (s)) {
337 case PA_STREAM_READY:
338 case PA_STREAM_FAILED:
339 case PA_STREAM_TERMINATED:
340 pa_threaded_mainloop_signal (pulsesink->mainloop, 0);
343 case PA_STREAM_UNCONNECTED:
344 case PA_STREAM_CREATING:
350 gst_pulsesink_stream_request_cb (pa_stream * s, size_t length, void *userdata)
352 GstPulseSink *pulsesink = GST_PULSESINK (userdata);
354 pa_threaded_mainloop_signal (pulsesink->mainloop, 0);
358 gst_pulsesink_stream_latency_update_cb (pa_stream * s, void *userdata)
360 GstPulseSink *pulsesink = GST_PULSESINK (userdata);
362 pa_threaded_mainloop_signal (pulsesink->mainloop, 0);
366 gst_pulsesink_open (GstAudioSink * asink)
368 GstPulseSink *pulsesink = GST_PULSESINK (asink);
370 gchar *name = gst_pulse_client_name ();
372 pa_threaded_mainloop_lock (pulsesink->mainloop);
374 if (!(pulsesink->context =
375 pa_context_new (pa_threaded_mainloop_get_api (pulsesink->mainloop),
377 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED,
378 ("Failed to create context"), (NULL));
379 goto unlock_and_fail;
382 pa_context_set_state_callback (pulsesink->context,
383 gst_pulsesink_context_state_cb, pulsesink);
385 if (pa_context_connect (pulsesink->context, pulsesink->server, 0, NULL) < 0) {
386 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED, ("Failed to connect: %s",
387 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
388 goto unlock_and_fail;
391 /* Wait until the context is ready */
392 pa_threaded_mainloop_wait (pulsesink->mainloop);
394 if (pa_context_get_state (pulsesink->context) != PA_CONTEXT_READY) {
395 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED, ("Failed to connect: %s",
396 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
397 goto unlock_and_fail;
400 pa_threaded_mainloop_unlock (pulsesink->mainloop);
406 pa_threaded_mainloop_unlock (pulsesink->mainloop);
412 gst_pulsesink_close (GstAudioSink * asink)
414 GstPulseSink *pulsesink = GST_PULSESINK (asink);
416 pa_threaded_mainloop_lock (pulsesink->mainloop);
417 gst_pulsesink_destroy_context (pulsesink);
418 pa_threaded_mainloop_unlock (pulsesink->mainloop);
424 gst_pulsesink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
426 pa_buffer_attr buf_attr;
428 pa_channel_map channel_map;
430 GstPulseSink *pulsesink = GST_PULSESINK (asink);
432 if (!gst_pulse_fill_sample_spec (spec, &pulsesink->sample_spec)) {
433 GST_ELEMENT_ERROR (pulsesink, RESOURCE, SETTINGS,
434 ("Invalid sample specification."), (NULL));
435 goto unlock_and_fail;
438 pa_threaded_mainloop_lock (pulsesink->mainloop);
440 if (!pulsesink->context
441 || pa_context_get_state (pulsesink->context) != PA_CONTEXT_READY) {
442 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED, ("Bad context state: %s",
444 context ? pa_strerror (pa_context_errno (pulsesink->context)) :
446 goto unlock_and_fail;
449 if (!(pulsesink->stream = pa_stream_new (pulsesink->context,
451 stream_name ? pulsesink->stream_name : "Playback Stream",
452 &pulsesink->sample_spec,
453 gst_pulse_gst_to_channel_map (&channel_map, spec)))) {
454 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED,
455 ("Failed to create stream: %s",
456 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
457 goto unlock_and_fail;
460 pa_stream_set_state_callback (pulsesink->stream,
461 gst_pulsesink_stream_state_cb, pulsesink);
462 pa_stream_set_write_callback (pulsesink->stream,
463 gst_pulsesink_stream_request_cb, pulsesink);
464 pa_stream_set_latency_update_callback (pulsesink->stream,
465 gst_pulsesink_stream_latency_update_cb, pulsesink);
467 memset (&buf_attr, 0, sizeof (buf_attr));
468 buf_attr.tlength = spec->segtotal * spec->segsize;
469 buf_attr.maxlength = buf_attr.tlength * 2;
470 buf_attr.prebuf = buf_attr.tlength - spec->segsize;
471 buf_attr.minreq = spec->segsize;
473 if (pa_stream_connect_playback (pulsesink->stream, pulsesink->device,
475 PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE |
476 PA_STREAM_NOT_MONOTONOUS, NULL, NULL) < 0) {
477 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED,
478 ("Failed to connect stream: %s",
479 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
480 goto unlock_and_fail;
483 /* Wait until the stream is ready */
484 pa_threaded_mainloop_wait (pulsesink->mainloop);
486 if (pa_stream_get_state (pulsesink->stream) != PA_STREAM_READY) {
487 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED,
488 ("Failed to connect stream: %s",
489 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
490 goto unlock_and_fail;
493 pa_threaded_mainloop_unlock (pulsesink->mainloop);
495 spec->bytes_per_sample = pa_frame_size (&pulsesink->sample_spec);
496 memset (spec->silence_sample, 0, spec->bytes_per_sample);
502 pa_threaded_mainloop_unlock (pulsesink->mainloop);
507 gst_pulsesink_unprepare (GstAudioSink * asink)
509 GstPulseSink *pulsesink = GST_PULSESINK (asink);
511 pa_threaded_mainloop_lock (pulsesink->mainloop);
512 gst_pulsesink_destroy_stream (pulsesink);
513 pa_threaded_mainloop_unlock (pulsesink->mainloop);
518 #define CHECK_DEAD_GOTO(pulsesink, label) \
519 if (!(pulsesink)->context || pa_context_get_state((pulsesink)->context) != PA_CONTEXT_READY || \
520 !(pulsesink)->stream || pa_stream_get_state((pulsesink)->stream) != PA_STREAM_READY) { \
521 GST_ELEMENT_ERROR((pulsesink), RESOURCE, FAILED, ("Disconnected: %s", (pulsesink)->context ? pa_strerror(pa_context_errno((pulsesink)->context)) : NULL), (NULL)); \
526 gst_pulsesink_write (GstAudioSink * asink, gpointer data, guint length)
528 GstPulseSink *pulsesink = GST_PULSESINK (asink);
532 pa_threaded_mainloop_lock (pulsesink->mainloop);
538 CHECK_DEAD_GOTO (pulsesink, unlock_and_fail);
540 if ((l = pa_stream_writable_size (pulsesink->stream)) == (size_t) - 1) {
541 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED,
542 ("pa_stream_writable_size() failed: %s",
543 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
544 goto unlock_and_fail;
550 pa_threaded_mainloop_wait (pulsesink->mainloop);
556 if (pa_stream_write (pulsesink->stream, data, l, NULL, 0,
557 PA_SEEK_RELATIVE) < 0) {
558 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED,
559 ("pa_stream_write() failed: %s",
560 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
561 goto unlock_and_fail;
564 data = (guint8 *) data + l;
570 pa_threaded_mainloop_unlock (pulsesink->mainloop);
576 pa_threaded_mainloop_unlock (pulsesink->mainloop);
581 gst_pulsesink_delay (GstAudioSink * asink)
583 GstPulseSink *pulsesink = GST_PULSESINK (asink);
587 pa_threaded_mainloop_lock (pulsesink->mainloop);
590 CHECK_DEAD_GOTO (pulsesink, unlock_and_fail);
592 if (pa_stream_get_latency (pulsesink->stream, &t, NULL) >= 0)
595 if (pa_context_errno (pulsesink->context) != PA_ERR_NODATA) {
596 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED,
597 ("pa_stream_get_latency() failed: %s",
598 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
599 goto unlock_and_fail;
602 pa_threaded_mainloop_wait (pulsesink->mainloop);
605 pa_threaded_mainloop_unlock (pulsesink->mainloop);
607 return gst_util_uint64_scale_int (t, pulsesink->sample_spec.rate, 1000000LL);
611 pa_threaded_mainloop_unlock (pulsesink->mainloop);
616 gst_pulsesink_success_cb (pa_stream * s, int success, void *userdata)
618 GstPulseSink *pulsesink = GST_PULSESINK (userdata);
620 pulsesink->operation_success = success;
621 pa_threaded_mainloop_signal (pulsesink->mainloop, 0);
625 gst_pulsesink_reset (GstAudioSink * asink)
627 GstPulseSink *pulsesink = GST_PULSESINK (asink);
629 pa_operation *o = NULL;
631 pa_threaded_mainloop_lock (pulsesink->mainloop);
633 CHECK_DEAD_GOTO (pulsesink, unlock_and_fail);
636 pa_stream_flush (pulsesink->stream, gst_pulsesink_success_cb,
638 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED,
639 ("pa_stream_flush() failed: %s",
640 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
641 goto unlock_and_fail;
644 pulsesink->operation_success = 0;
645 while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
646 CHECK_DEAD_GOTO (pulsesink, unlock_and_fail);
648 pa_threaded_mainloop_wait (pulsesink->mainloop);
651 if (!pulsesink->operation_success) {
652 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED, ("Flush failed: %s",
653 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
654 goto unlock_and_fail;
660 pa_operation_cancel (o);
661 pa_operation_unref (o);
664 pa_threaded_mainloop_unlock (pulsesink->mainloop);
668 gst_pulsesink_change_title (GstPulseSink * pulsesink, const gchar * t)
670 pa_operation *o = NULL;
672 pa_threaded_mainloop_lock (pulsesink->mainloop);
674 g_free (pulsesink->stream_name);
675 pulsesink->stream_name = g_strdup (t);
677 if (!(pulsesink)->context
678 || pa_context_get_state ((pulsesink)->context) != PA_CONTEXT_READY
679 || !(pulsesink)->stream
680 || pa_stream_get_state ((pulsesink)->stream) != PA_STREAM_READY) {
681 goto unlock_and_fail;
685 pa_stream_set_name (pulsesink->stream, pulsesink->stream_name, NULL,
687 GST_ELEMENT_ERROR (pulsesink, RESOURCE, FAILED,
688 ("pa_stream_set_name() failed: %s",
689 pa_strerror (pa_context_errno (pulsesink->context))), (NULL));
690 goto unlock_and_fail;
693 /* We're not interested if this operation failed or not */
698 pa_operation_unref (o);
700 pa_threaded_mainloop_unlock (pulsesink->mainloop);
704 gst_pulsesink_event (GstBaseSink * sink, GstEvent * event)
706 GstPulseSink *pulsesink = GST_PULSESINK (sink);
708 switch (GST_EVENT_TYPE (event)) {
710 gchar *title = NULL, *artist = NULL, *location = NULL, *description =
711 NULL, *t = NULL, *buf = NULL;
714 gst_event_parse_tag (event, &l);
716 gst_tag_list_get_string (l, GST_TAG_TITLE, &title);
717 gst_tag_list_get_string (l, GST_TAG_ARTIST, &artist);
718 gst_tag_list_get_string (l, GST_TAG_LOCATION, &location);
719 gst_tag_list_get_string (l, GST_TAG_DESCRIPTION, &description);
723 g_strdup_printf ("'%s' by '%s'", g_strstrip (title),
724 g_strstrip (artist));
726 t = g_strstrip (title);
727 else if (description)
728 t = g_strstrip (description);
730 t = g_strstrip (location);
733 gst_pulsesink_change_title (pulsesink, t);
738 g_free (description);
747 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
751 gst_pulsesink_get_type (void)
753 static GType pulsesink_type = 0;
755 if (!pulsesink_type) {
757 static const GTypeInfo pulsesink_info = {
758 sizeof (GstPulseSinkClass),
759 gst_pulsesink_base_init,
761 gst_pulsesink_class_init,
764 sizeof (GstPulseSink),
769 pulsesink_type = g_type_register_static (GST_TYPE_AUDIO_SINK,
770 "GstPulseSink", &pulsesink_info, 0);
773 return pulsesink_type;