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-pulsesrc
24 * @see_also: pulsesink, pulsemixer
26 * This element captures audio from a
27 * <ulink href="http://www.pulseaudio.org">PulseAudio sound server</ulink>.
30 * <title>Example pipelines</title>
32 * gst-launch -v pulsesrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
33 * ]| Record from a sound card using pulseaudio and encode to Ogg/Vorbis.
44 #include <gst/base/gstbasesrc.h>
45 #include <gst/gsttaglist.h>
47 #include <gst/interfaces/streamvolume.h>
51 #include "pulseutil.h"
52 #include "pulsemixerctrl.h"
54 GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
55 #define GST_CAT_DEFAULT pulse_debug
57 #define DEFAULT_SERVER NULL
58 #define DEFAULT_DEVICE NULL
59 #define DEFAULT_DEVICE_NAME NULL
62 #define DEFAULT_VOLUME 1.0
63 #define DEFAULT_MUTE FALSE
64 #define MAX_VOLUME 10.0
74 PROP_STREAM_PROPERTIES,
75 PROP_SOURCE_OUTPUT_INDEX,
83 static void gst_pulsesrc_destroy_stream (GstPulseSrc * pulsesrc);
84 static void gst_pulsesrc_destroy_context (GstPulseSrc * pulsesrc);
86 static void gst_pulsesrc_set_property (GObject * object, guint prop_id,
87 const GValue * value, GParamSpec * pspec);
88 static void gst_pulsesrc_get_property (GObject * object, guint prop_id,
89 GValue * value, GParamSpec * pspec);
90 static void gst_pulsesrc_finalize (GObject * object);
92 static gboolean gst_pulsesrc_open (GstAudioSrc * asrc);
94 static gboolean gst_pulsesrc_close (GstAudioSrc * asrc);
96 static gboolean gst_pulsesrc_prepare (GstAudioSrc * asrc,
97 GstRingBufferSpec * spec);
99 static gboolean gst_pulsesrc_unprepare (GstAudioSrc * asrc);
101 static guint gst_pulsesrc_read (GstAudioSrc * asrc, gpointer data,
103 static guint gst_pulsesrc_delay (GstAudioSrc * asrc);
105 static void gst_pulsesrc_reset (GstAudioSrc * src);
107 static gboolean gst_pulsesrc_negotiate (GstBaseSrc * basesrc);
109 static GstStateChangeReturn gst_pulsesrc_change_state (GstElement *
110 element, GstStateChange transition);
112 static void gst_pulsesrc_init_interfaces (GType type);
114 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
115 # define ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
117 # define ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
120 GST_IMPLEMENT_PULSEMIXER_CTRL_METHODS (GstPulseSrc, gst_pulsesrc);
121 GST_IMPLEMENT_PULSEPROBE_METHODS (GstPulseSrc, gst_pulsesrc);
122 GST_BOILERPLATE_FULL (GstPulseSrc, gst_pulsesrc, GstAudioSrc,
123 GST_TYPE_AUDIO_SRC, gst_pulsesrc_init_interfaces);
126 gst_pulsesrc_interface_supported (GstImplementsInterface *
127 iface, GType interface_type)
129 GstPulseSrc *this = GST_PULSESRC_CAST (iface);
131 if (interface_type == GST_TYPE_MIXER && this->mixer)
134 if (interface_type == GST_TYPE_PROPERTY_PROBE && this->probe)
137 #ifdef HAVE_PULSE_1_0
138 if (interface_type == GST_TYPE_STREAM_VOLUME)
146 gst_pulsesrc_implements_interface_init (GstImplementsInterfaceClass * klass)
148 klass->supported = gst_pulsesrc_interface_supported;
152 gst_pulsesrc_init_interfaces (GType type)
154 #ifdef HAVE_PULSE_1_0
155 static const GInterfaceInfo svol_iface_info = {
159 static const GInterfaceInfo implements_iface_info = {
160 (GInterfaceInitFunc) gst_pulsesrc_implements_interface_init,
164 static const GInterfaceInfo mixer_iface_info = {
165 (GInterfaceInitFunc) gst_pulsesrc_mixer_interface_init,
169 static const GInterfaceInfo probe_iface_info = {
170 (GInterfaceInitFunc) gst_pulsesrc_property_probe_interface_init,
175 #ifdef HAVE_PULSE_1_0
176 g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_iface_info);
178 g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
179 &implements_iface_info);
180 g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
181 g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
186 gst_pulsesrc_base_init (gpointer g_class)
189 static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("src",
192 GST_STATIC_CAPS ("audio/x-raw-int, "
193 "endianness = (int) { " ENDIANNESS " }, "
194 "signed = (boolean) TRUE, "
197 "rate = (int) [ 1, MAX ], "
198 "channels = (int) [ 1, 32 ];"
199 "audio/x-raw-float, "
200 "endianness = (int) { " ENDIANNESS " }, "
202 "rate = (int) [ 1, MAX ], "
203 "channels = (int) [ 1, 32 ];"
205 "endianness = (int) { " ENDIANNESS " }, "
206 "signed = (boolean) TRUE, "
209 "rate = (int) [ 1, MAX ], "
210 "channels = (int) [ 1, 32 ];"
212 "signed = (boolean) FALSE, "
215 "rate = (int) [ 1, MAX ], "
216 "channels = (int) [ 1, 32 ];"
218 "rate = (int) [ 1, MAX], "
219 "channels = (int) [ 1, 32 ];"
221 "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ]")
224 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
226 gst_element_class_set_details_simple (element_class,
227 "PulseAudio Audio Source",
229 "Captures audio from a PulseAudio server", "Lennart Poettering");
230 gst_element_class_add_static_pad_template (element_class, &pad_template);
234 gst_pulsesrc_class_init (GstPulseSrcClass * klass)
236 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
237 GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS (klass);
238 GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
239 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
242 gobject_class->finalize = gst_pulsesrc_finalize;
243 gobject_class->set_property = gst_pulsesrc_set_property;
244 gobject_class->get_property = gst_pulsesrc_get_property;
246 gstelement_class->change_state =
247 GST_DEBUG_FUNCPTR (gst_pulsesrc_change_state);
249 gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_pulsesrc_negotiate);
251 gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_pulsesrc_open);
252 gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_pulsesrc_close);
253 gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_prepare);
254 gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_unprepare);
255 gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_pulsesrc_read);
256 gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_pulsesrc_delay);
257 gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_pulsesrc_reset);
259 /* Overwrite GObject fields */
260 g_object_class_install_property (gobject_class,
262 g_param_spec_string ("server", "Server",
263 "The PulseAudio server to connect to", DEFAULT_SERVER,
264 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
266 g_object_class_install_property (gobject_class, PROP_DEVICE,
267 g_param_spec_string ("device", "Device",
268 "The PulseAudio source device to connect to", DEFAULT_DEVICE,
269 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
271 g_object_class_install_property (gobject_class,
273 g_param_spec_string ("device-name", "Device name",
274 "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
275 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
277 clientname = gst_pulse_client_name ();
281 * The PulseAudio client name to use.
285 g_object_class_install_property (gobject_class,
287 g_param_spec_string ("client", "Client",
288 "The PulseAudio client_name_to_use", clientname,
289 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
290 GST_PARAM_MUTABLE_READY));
294 * GstPulseSrc:stream-properties
296 * List of pulseaudio stream properties. A list of defined properties can be
297 * found in the <ulink href="http://0pointer.de/lennart/projects/pulseaudio/doxygen/proplist_8h.html">pulseaudio api docs</ulink>.
299 * Below is an example for registering as a music application to pulseaudio.
301 * GstStructure *props;
303 * props = gst_structure_from_string ("props,media.role=music", NULL);
304 * g_object_set (pulse, "stream-properties", props, NULL);
305 * gst_structure_free (props);
310 g_object_class_install_property (gobject_class,
311 PROP_STREAM_PROPERTIES,
312 g_param_spec_boxed ("stream-properties", "stream properties",
313 "list of pulseaudio stream properties",
314 GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
317 * GstPulseSrc:source-output-index
319 * The index of the PulseAudio source output corresponding to this element.
323 g_object_class_install_property (gobject_class,
324 PROP_SOURCE_OUTPUT_INDEX,
325 g_param_spec_uint ("source-output-index", "source output index",
326 "The index of the PulseAudio source output corresponding to this "
327 "record stream", 0, G_MAXUINT, PA_INVALID_INDEX,
328 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
330 #ifdef HAVE_PULSE_1_0
334 * The volume of the record stream. Only works when using PulseAudio 1.0 or
339 g_object_class_install_property (gobject_class,
340 PROP_VOLUME, g_param_spec_double ("volume", "Volume",
341 "Linear volume of this stream, 1.0=100%",
342 0.0, MAX_VOLUME, DEFAULT_VOLUME,
343 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
348 * Whether the stream is muted or not. Only works when using PulseAudio 1.0
353 g_object_class_install_property (gobject_class,
354 PROP_MUTE, g_param_spec_boolean ("mute", "Mute",
355 "Mute state of this stream",
356 DEFAULT_MUTE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
361 gst_pulsesrc_init (GstPulseSrc * pulsesrc, GstPulseSrcClass * klass)
363 pulsesrc->server = NULL;
364 pulsesrc->device = NULL;
365 pulsesrc->client_name = gst_pulse_client_name ();
366 pulsesrc->device_description = NULL;
368 pulsesrc->context = NULL;
369 pulsesrc->stream = NULL;
370 pulsesrc->source_output_idx = PA_INVALID_INDEX;
372 pulsesrc->read_buffer = NULL;
373 pulsesrc->read_buffer_length = 0;
375 pa_sample_spec_init (&pulsesrc->sample_spec);
377 pulsesrc->operation_success = FALSE;
378 pulsesrc->paused = FALSE;
379 pulsesrc->in_read = FALSE;
381 #ifdef HAVE_PULSE_1_0
382 pulsesrc->volume = DEFAULT_VOLUME;
383 pulsesrc->volume_set = FALSE;
385 pulsesrc->mute = DEFAULT_MUTE;
386 pulsesrc->mute_set = FALSE;
388 pulsesrc->notify = 0;
391 pulsesrc->mixer = NULL;
393 pulsesrc->properties = NULL;
394 pulsesrc->proplist = NULL;
396 pulsesrc->probe = gst_pulseprobe_new (G_OBJECT (pulsesrc), G_OBJECT_GET_CLASS (pulsesrc), PROP_DEVICE, pulsesrc->server, FALSE, TRUE); /* FALSE for sinks, TRUE for sources */
398 /* this should be the default but it isn't yet */
399 gst_base_audio_src_set_slave_method (GST_BASE_AUDIO_SRC (pulsesrc),
400 GST_BASE_AUDIO_SRC_SLAVE_SKEW);
404 gst_pulsesrc_destroy_stream (GstPulseSrc * pulsesrc)
406 if (pulsesrc->stream) {
407 pa_stream_disconnect (pulsesrc->stream);
408 pa_stream_unref (pulsesrc->stream);
409 pulsesrc->stream = NULL;
410 pulsesrc->source_output_idx = PA_INVALID_INDEX;
411 g_object_notify (G_OBJECT (pulsesrc), "source-output-index");
414 g_free (pulsesrc->device_description);
415 pulsesrc->device_description = NULL;
419 gst_pulsesrc_destroy_context (GstPulseSrc * pulsesrc)
422 gst_pulsesrc_destroy_stream (pulsesrc);
424 if (pulsesrc->context) {
425 pa_context_disconnect (pulsesrc->context);
427 /* Make sure we don't get any further callbacks */
428 pa_context_set_state_callback (pulsesrc->context, NULL, NULL);
429 #ifdef HAVE_PULSE_1_0
430 pa_context_set_subscribe_callback (pulsesrc->context, NULL, NULL);
433 pa_context_unref (pulsesrc->context);
435 pulsesrc->context = NULL;
440 gst_pulsesrc_finalize (GObject * object)
442 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (object);
444 g_free (pulsesrc->server);
445 g_free (pulsesrc->device);
446 g_free (pulsesrc->client_name);
448 if (pulsesrc->properties)
449 gst_structure_free (pulsesrc->properties);
450 if (pulsesrc->proplist)
451 pa_proplist_free (pulsesrc->proplist);
453 if (pulsesrc->mixer) {
454 gst_pulsemixer_ctrl_free (pulsesrc->mixer);
455 pulsesrc->mixer = NULL;
458 if (pulsesrc->probe) {
459 gst_pulseprobe_free (pulsesrc->probe);
460 pulsesrc->probe = NULL;
463 G_OBJECT_CLASS (parent_class)->finalize (object);
466 #define CONTEXT_OK(c) ((c) && PA_CONTEXT_IS_GOOD (pa_context_get_state ((c))))
467 #define STREAM_OK(s) ((s) && PA_STREAM_IS_GOOD (pa_stream_get_state ((s))))
470 gst_pulsesrc_is_dead (GstPulseSrc * pulsesrc, gboolean check_stream)
472 if (!CONTEXT_OK (pulsesrc->context))
475 if (check_stream && !STREAM_OK (pulsesrc->stream))
482 const gchar *err_str = pulsesrc->context ?
483 pa_strerror (pa_context_errno (pulsesrc->context)) : NULL;
484 GST_ELEMENT_ERROR ((pulsesrc), RESOURCE, FAILED, ("Disconnected: %s",
491 gst_pulsesrc_source_info_cb (pa_context * c, const pa_source_info * i, int eol,
494 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
499 g_free (pulsesrc->device_description);
500 pulsesrc->device_description = g_strdup (i->description);
503 pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
507 gst_pulsesrc_device_description (GstPulseSrc * pulsesrc)
509 pa_operation *o = NULL;
512 if (!pulsesrc->mainloop)
515 pa_threaded_mainloop_lock (pulsesrc->mainloop);
517 if (!(o = pa_context_get_source_info_by_name (pulsesrc->context,
518 pulsesrc->device, gst_pulsesrc_source_info_cb, pulsesrc))) {
520 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
521 ("pa_stream_get_source_info() failed: %s",
522 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
526 while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
528 if (gst_pulsesrc_is_dead (pulsesrc, FALSE))
531 pa_threaded_mainloop_wait (pulsesrc->mainloop);
537 pa_operation_unref (o);
539 t = g_strdup (pulsesrc->device_description);
541 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
547 GST_DEBUG_OBJECT (pulsesrc, "have no mainloop");
552 #ifdef HAVE_PULSE_1_0
554 gst_pulsesrc_source_output_info_cb (pa_context * c,
555 const pa_source_output_info * i, int eol, void *userdata)
559 psrc = GST_PULSESRC_CAST (userdata);
564 /* If the index doesn't match our current stream,
565 * it implies we just recreated the stream (caps change)
567 if (i->index == psrc->source_output_idx) {
568 psrc->volume = pa_sw_volume_to_linear (pa_cvolume_max (&i->volume));
569 psrc->mute = i->mute;
573 pa_threaded_mainloop_signal (psrc->mainloop, 0);
577 gst_pulsesrc_get_stream_volume (GstPulseSrc * pulsesrc)
579 pa_operation *o = NULL;
582 if (!pulsesrc->mainloop)
585 if (pulsesrc->source_output_idx == PA_INVALID_INDEX)
588 pa_threaded_mainloop_lock (pulsesrc->mainloop);
590 if (!(o = pa_context_get_source_output_info (pulsesrc->context,
591 pulsesrc->source_output_idx, gst_pulsesrc_source_output_info_cb,
595 while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
596 pa_threaded_mainloop_wait (pulsesrc->mainloop);
597 if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
602 v = pulsesrc->volume;
605 pa_operation_unref (o);
607 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
609 if (v > MAX_VOLUME) {
610 GST_WARNING_OBJECT (pulsesrc, "Clipped volume from %f to %f", v,
620 v = pulsesrc->volume;
621 GST_DEBUG_OBJECT (pulsesrc, "we have no mainloop");
626 v = pulsesrc->volume;
627 GST_DEBUG_OBJECT (pulsesrc, "we don't have a stream index");
632 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
633 ("pa_context_get_source_output_info() failed: %s",
634 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
640 gst_pulsesrc_get_stream_mute (GstPulseSrc * pulsesrc)
642 pa_operation *o = NULL;
645 if (!pulsesrc->mainloop)
648 if (pulsesrc->source_output_idx == PA_INVALID_INDEX)
651 pa_threaded_mainloop_lock (pulsesrc->mainloop);
653 if (!(o = pa_context_get_source_output_info (pulsesrc->context,
654 pulsesrc->source_output_idx, gst_pulsesrc_source_output_info_cb,
658 while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
659 pa_threaded_mainloop_wait (pulsesrc->mainloop);
660 if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
665 mute = pulsesrc->mute;
668 pa_operation_unref (o);
670 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
677 mute = pulsesrc->mute;
678 GST_DEBUG_OBJECT (pulsesrc, "we have no mainloop");
683 mute = pulsesrc->mute;
684 GST_DEBUG_OBJECT (pulsesrc, "we don't have a stream index");
689 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
690 ("pa_context_get_source_output_info() failed: %s",
691 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
697 gst_pulsesrc_set_stream_volume (GstPulseSrc * pulsesrc, gdouble volume)
700 pa_operation *o = NULL;
702 if (!pulsesrc->mainloop)
705 if (!pulsesrc->source_output_idx)
708 pa_threaded_mainloop_lock (pulsesrc->mainloop);
710 GST_DEBUG_OBJECT (pulsesrc, "setting volume to %f", volume);
712 gst_pulse_cvolume_from_linear (&v, pulsesrc->sample_spec.channels, volume);
714 if (!(o = pa_context_set_source_output_volume (pulsesrc->context,
715 pulsesrc->source_output_idx, &v, NULL, NULL)))
718 /* We don't really care about the result of this call */
722 pa_operation_unref (o);
724 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
731 pulsesrc->volume = volume;
732 pulsesrc->volume_set = TRUE;
733 GST_DEBUG_OBJECT (pulsesrc, "we have no mainloop");
738 pulsesrc->volume = volume;
739 pulsesrc->volume_set = TRUE;
740 GST_DEBUG_OBJECT (pulsesrc, "we don't have a stream index");
745 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
746 ("pa_stream_set_source_output_volume() failed: %s",
747 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
753 gst_pulsesrc_set_stream_mute (GstPulseSrc * pulsesrc, gboolean mute)
755 pa_operation *o = NULL;
757 if (!pulsesrc->mainloop)
760 if (!pulsesrc->source_output_idx)
763 pa_threaded_mainloop_lock (pulsesrc->mainloop);
765 GST_DEBUG_OBJECT (pulsesrc, "setting mute state to %d", mute);
767 if (!(o = pa_context_set_source_output_mute (pulsesrc->context,
768 pulsesrc->source_output_idx, mute, NULL, NULL)))
771 /* We don't really care about the result of this call */
775 pa_operation_unref (o);
777 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
784 pulsesrc->mute = mute;
785 pulsesrc->mute_set = TRUE;
786 GST_DEBUG_OBJECT (pulsesrc, "we have no mainloop");
791 pulsesrc->mute = mute;
792 pulsesrc->mute_set = TRUE;
793 GST_DEBUG_OBJECT (pulsesrc, "we don't have a stream index");
798 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
799 ("pa_stream_set_source_output_mute() failed: %s",
800 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
807 gst_pulsesrc_set_property (GObject * object,
808 guint prop_id, const GValue * value, GParamSpec * pspec)
811 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (object);
815 g_free (pulsesrc->server);
816 pulsesrc->server = g_value_dup_string (value);
818 gst_pulseprobe_set_server (pulsesrc->probe, pulsesrc->server);
821 g_free (pulsesrc->device);
822 pulsesrc->device = g_value_dup_string (value);
825 g_free (pulsesrc->client_name);
826 if (!g_value_get_string (value)) {
827 GST_WARNING_OBJECT (pulsesrc,
828 "Empty PulseAudio client name not allowed. Resetting to default value");
829 pulsesrc->client_name = gst_pulse_client_name ();
831 pulsesrc->client_name = g_value_dup_string (value);
833 case PROP_STREAM_PROPERTIES:
834 if (pulsesrc->properties)
835 gst_structure_free (pulsesrc->properties);
836 pulsesrc->properties =
837 gst_structure_copy (gst_value_get_structure (value));
838 if (pulsesrc->proplist)
839 pa_proplist_free (pulsesrc->proplist);
840 pulsesrc->proplist = gst_pulse_make_proplist (pulsesrc->properties);
842 #ifdef HAVE_PULSE_1_0
844 gst_pulsesrc_set_stream_volume (pulsesrc, g_value_get_double (value));
847 gst_pulsesrc_set_stream_mute (pulsesrc, g_value_get_boolean (value));
851 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
857 gst_pulsesrc_get_property (GObject * object,
858 guint prop_id, GValue * value, GParamSpec * pspec)
861 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (object);
865 g_value_set_string (value, pulsesrc->server);
868 g_value_set_string (value, pulsesrc->device);
870 case PROP_DEVICE_NAME:
871 g_value_take_string (value, gst_pulsesrc_device_description (pulsesrc));
874 g_value_set_string (value, pulsesrc->client_name);
876 case PROP_STREAM_PROPERTIES:
877 gst_value_set_structure (value, pulsesrc->properties);
879 case PROP_SOURCE_OUTPUT_INDEX:
880 g_value_set_uint (value, pulsesrc->source_output_idx);
882 #ifdef HAVE_PULSE_1_0
884 g_value_set_double (value, gst_pulsesrc_get_stream_volume (pulsesrc));
887 g_value_set_boolean (value, gst_pulsesrc_get_stream_mute (pulsesrc));
891 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
897 gst_pulsesrc_context_state_cb (pa_context * c, void *userdata)
899 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
901 switch (pa_context_get_state (c)) {
902 case PA_CONTEXT_READY:
903 case PA_CONTEXT_TERMINATED:
904 case PA_CONTEXT_FAILED:
905 pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
908 case PA_CONTEXT_UNCONNECTED:
909 case PA_CONTEXT_CONNECTING:
910 case PA_CONTEXT_AUTHORIZING:
911 case PA_CONTEXT_SETTING_NAME:
917 gst_pulsesrc_stream_state_cb (pa_stream * s, void *userdata)
919 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
921 switch (pa_stream_get_state (s)) {
923 case PA_STREAM_READY:
924 case PA_STREAM_FAILED:
925 case PA_STREAM_TERMINATED:
926 pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
929 case PA_STREAM_UNCONNECTED:
930 case PA_STREAM_CREATING:
936 gst_pulsesrc_stream_request_cb (pa_stream * s, size_t length, void *userdata)
938 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
940 GST_LOG_OBJECT (pulsesrc, "got request for length %" G_GSIZE_FORMAT, length);
942 if (pulsesrc->in_read) {
943 /* only signal when reading */
944 pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
949 gst_pulsesrc_stream_latency_update_cb (pa_stream * s, void *userdata)
951 const pa_timing_info *info;
952 pa_usec_t source_usec;
954 info = pa_stream_get_timing_info (s);
957 GST_LOG_OBJECT (GST_PULSESRC_CAST (userdata),
958 "latency update (information unknown)");
961 source_usec = info->configured_source_usec;
963 GST_LOG_OBJECT (GST_PULSESRC_CAST (userdata),
964 "latency_update, %" G_GUINT64_FORMAT ", %d:%" G_GINT64_FORMAT ", %d:%"
965 G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT,
966 GST_TIMEVAL_TO_TIME (info->timestamp), info->write_index_corrupt,
967 info->write_index, info->read_index_corrupt, info->read_index,
968 info->source_usec, source_usec);
972 gst_pulsesrc_stream_underflow_cb (pa_stream * s, void *userdata)
974 GST_WARNING_OBJECT (GST_PULSESRC_CAST (userdata), "Got underflow");
978 gst_pulsesrc_stream_overflow_cb (pa_stream * s, void *userdata)
980 GST_WARNING_OBJECT (GST_PULSESRC_CAST (userdata), "Got overflow");
983 #ifdef HAVE_PULSE_1_0
985 gst_pulsesrc_context_subscribe_cb (pa_context * c,
986 pa_subscription_event_type_t t, uint32_t idx, void *userdata)
988 GstPulseSrc *psrc = GST_PULSESRC (userdata);
990 if (t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT | PA_SUBSCRIPTION_EVENT_CHANGE)
991 && t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT | PA_SUBSCRIPTION_EVENT_NEW))
994 if (idx != psrc->source_output_idx)
997 /* Actually this event is also triggered when other properties of the stream
998 * change that are unrelated to the volume. However it is probably cheaper to
999 * signal the change here and check for the volume when the GObject property
1000 * is read instead of querying it always. */
1002 /* inform streaming thread to notify */
1003 g_atomic_int_compare_and_exchange (&psrc->notify, 0, 1);
1008 gst_pulsesrc_open (GstAudioSrc * asrc)
1010 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1012 pa_threaded_mainloop_lock (pulsesrc->mainloop);
1014 g_assert (!pulsesrc->context);
1015 g_assert (!pulsesrc->stream);
1017 GST_DEBUG_OBJECT (pulsesrc, "opening device");
1019 if (!(pulsesrc->context =
1020 pa_context_new (pa_threaded_mainloop_get_api (pulsesrc->mainloop),
1021 pulsesrc->client_name))) {
1022 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to create context"),
1024 goto unlock_and_fail;
1027 pa_context_set_state_callback (pulsesrc->context,
1028 gst_pulsesrc_context_state_cb, pulsesrc);
1029 #ifdef HAVE_PULSE_1_0
1030 pa_context_set_subscribe_callback (pulsesrc->context,
1031 gst_pulsesrc_context_subscribe_cb, pulsesrc);
1034 GST_DEBUG_OBJECT (pulsesrc, "connect to server %s",
1035 GST_STR_NULL (pulsesrc->server));
1037 if (pa_context_connect (pulsesrc->context, pulsesrc->server, 0, NULL) < 0) {
1038 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
1039 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1040 goto unlock_and_fail;
1044 pa_context_state_t state;
1046 state = pa_context_get_state (pulsesrc->context);
1048 if (!PA_CONTEXT_IS_GOOD (state)) {
1049 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
1050 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1051 goto unlock_and_fail;
1054 if (state == PA_CONTEXT_READY)
1057 /* Wait until the context is ready */
1058 pa_threaded_mainloop_wait (pulsesrc->mainloop);
1060 GST_DEBUG_OBJECT (pulsesrc, "connected");
1062 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1069 gst_pulsesrc_destroy_context (pulsesrc);
1071 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1078 gst_pulsesrc_close (GstAudioSrc * asrc)
1080 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1082 pa_threaded_mainloop_lock (pulsesrc->mainloop);
1083 gst_pulsesrc_destroy_context (pulsesrc);
1084 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1090 gst_pulsesrc_unprepare (GstAudioSrc * asrc)
1092 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1094 pa_threaded_mainloop_lock (pulsesrc->mainloop);
1095 gst_pulsesrc_destroy_stream (pulsesrc);
1097 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1099 pulsesrc->read_buffer = NULL;
1100 pulsesrc->read_buffer_length = 0;
1106 gst_pulsesrc_read (GstAudioSrc * asrc, gpointer data, guint length)
1108 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1111 pa_threaded_mainloop_lock (pulsesrc->mainloop);
1112 pulsesrc->in_read = TRUE;
1114 #ifdef HAVE_PULSE_1_0
1115 if (g_atomic_int_compare_and_exchange (&pulsesrc->notify, 1, 0)) {
1116 g_object_notify (G_OBJECT (pulsesrc), "volume");
1117 g_object_notify (G_OBJECT (pulsesrc), "mute");
1121 if (pulsesrc->paused)
1124 while (length > 0) {
1127 GST_LOG_OBJECT (pulsesrc, "reading %u bytes", length);
1129 /*check if we have a leftover buffer */
1130 if (!pulsesrc->read_buffer) {
1132 if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
1133 goto unlock_and_fail;
1135 /* read all available data, we keep a pointer to the data and the length
1136 * and take from it what we need. */
1137 if (pa_stream_peek (pulsesrc->stream, &pulsesrc->read_buffer,
1138 &pulsesrc->read_buffer_length) < 0)
1141 GST_LOG_OBJECT (pulsesrc, "have data of %" G_GSIZE_FORMAT " bytes",
1142 pulsesrc->read_buffer_length);
1144 /* if we have data, process if */
1145 if (pulsesrc->read_buffer && pulsesrc->read_buffer_length)
1148 /* now wait for more data to become available */
1149 GST_LOG_OBJECT (pulsesrc, "waiting for data");
1150 pa_threaded_mainloop_wait (pulsesrc->mainloop);
1152 if (pulsesrc->paused)
1157 l = pulsesrc->read_buffer_length >
1158 length ? length : pulsesrc->read_buffer_length;
1160 memcpy (data, pulsesrc->read_buffer, l);
1162 pulsesrc->read_buffer = (const guint8 *) pulsesrc->read_buffer + l;
1163 pulsesrc->read_buffer_length -= l;
1165 data = (guint8 *) data + l;
1169 if (pulsesrc->read_buffer_length <= 0) {
1170 /* we copied all of the data, drop it now */
1171 if (pa_stream_drop (pulsesrc->stream) < 0)
1174 /* reset pointer to data */
1175 pulsesrc->read_buffer = NULL;
1176 pulsesrc->read_buffer_length = 0;
1180 pulsesrc->in_read = FALSE;
1181 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1188 GST_LOG_OBJECT (pulsesrc, "we are paused");
1189 goto unlock_and_fail;
1193 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1194 ("pa_stream_peek() failed: %s",
1195 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1196 goto unlock_and_fail;
1200 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1201 ("pa_stream_drop() failed: %s",
1202 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1203 goto unlock_and_fail;
1207 pulsesrc->in_read = FALSE;
1208 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1214 /* return the delay in samples */
1216 gst_pulsesrc_delay (GstAudioSrc * asrc)
1218 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1223 pa_threaded_mainloop_lock (pulsesrc->mainloop);
1224 if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
1227 /* get the latency, this can fail when we don't have a latency update yet.
1228 * We don't want to wait for latency updates here but we just return 0. */
1229 res = pa_stream_get_latency (pulsesrc->stream, &t, &negative);
1231 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1234 GST_DEBUG_OBJECT (pulsesrc, "could not get latency");
1240 result = (guint) ((t * pulsesrc->sample_spec.rate) / 1000000LL);
1247 GST_DEBUG_OBJECT (pulsesrc, "the server is dead");
1248 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1254 gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps * caps)
1256 pa_channel_map channel_map;
1258 gboolean need_channel_layout = FALSE;
1259 GstRingBufferSpec spec;
1262 memset (&spec, 0, sizeof (GstRingBufferSpec));
1263 spec.latency_time = GST_SECOND;
1264 if (!gst_ring_buffer_parse_caps (&spec, caps)) {
1265 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, SETTINGS,
1266 ("Can't parse caps."), (NULL));
1269 /* Keep the refcount of the caps at 1 to make them writable */
1270 gst_caps_unref (spec.caps);
1272 if (!gst_pulse_fill_sample_spec (&spec, &pulsesrc->sample_spec)) {
1273 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, SETTINGS,
1274 ("Invalid sample specification."), (NULL));
1278 pa_threaded_mainloop_lock (pulsesrc->mainloop);
1280 if (!pulsesrc->context) {
1281 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Bad context"), (NULL));
1282 goto unlock_and_fail;
1285 s = gst_caps_get_structure (caps, 0);
1286 if (!gst_structure_has_field (s, "channel-layout") ||
1287 !gst_pulse_gst_to_channel_map (&channel_map, &spec)) {
1288 if (spec.channels == 1)
1289 pa_channel_map_init_mono (&channel_map);
1290 else if (spec.channels == 2)
1291 pa_channel_map_init_stereo (&channel_map);
1293 need_channel_layout = TRUE;
1296 name = "Record Stream";
1297 if (pulsesrc->proplist) {
1298 if (!(pulsesrc->stream = pa_stream_new_with_proplist (pulsesrc->context,
1299 name, &pulsesrc->sample_spec,
1300 (need_channel_layout) ? NULL : &channel_map,
1301 pulsesrc->proplist))) {
1302 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1303 ("Failed to create stream: %s",
1304 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1305 goto unlock_and_fail;
1307 } else if (!(pulsesrc->stream = pa_stream_new (pulsesrc->context,
1308 name, &pulsesrc->sample_spec,
1309 (need_channel_layout) ? NULL : &channel_map))) {
1310 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1311 ("Failed to create stream: %s",
1312 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1313 goto unlock_and_fail;
1316 if (need_channel_layout) {
1317 const pa_channel_map *m = pa_stream_get_channel_map (pulsesrc->stream);
1319 gst_pulse_channel_map_to_gst (m, &spec);
1323 GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, caps);
1325 pa_stream_set_state_callback (pulsesrc->stream, gst_pulsesrc_stream_state_cb,
1327 pa_stream_set_read_callback (pulsesrc->stream, gst_pulsesrc_stream_request_cb,
1329 pa_stream_set_underflow_callback (pulsesrc->stream,
1330 gst_pulsesrc_stream_underflow_cb, pulsesrc);
1331 pa_stream_set_overflow_callback (pulsesrc->stream,
1332 gst_pulsesrc_stream_overflow_cb, pulsesrc);
1333 pa_stream_set_latency_update_callback (pulsesrc->stream,
1334 gst_pulsesrc_stream_latency_update_cb, pulsesrc);
1336 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1341 gst_pulsesrc_destroy_stream (pulsesrc);
1343 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1349 /* This is essentially gst_base_src_negotiate_default() but the caps
1350 * are guaranteed to have a channel layout for > 2 channels
1353 gst_pulsesrc_negotiate (GstBaseSrc * basesrc)
1356 GstCaps *caps = NULL;
1357 GstCaps *peercaps = NULL;
1358 gboolean result = FALSE;
1360 /* first see what is possible on our source pad */
1361 thiscaps = gst_pad_get_caps_reffed (GST_BASE_SRC_PAD (basesrc));
1362 GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
1363 /* nothing or anything is allowed, we're done */
1364 if (thiscaps == NULL || gst_caps_is_any (thiscaps))
1365 goto no_nego_needed;
1367 /* get the peer caps */
1368 peercaps = gst_pad_peer_get_caps_reffed (GST_BASE_SRC_PAD (basesrc));
1369 GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
1371 /* get intersection */
1372 caps = gst_caps_intersect (thiscaps, peercaps);
1373 GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, caps);
1374 gst_caps_unref (thiscaps);
1375 gst_caps_unref (peercaps);
1377 /* no peer, work with our own caps then */
1381 /* take first (and best, since they are sorted) possibility */
1382 caps = gst_caps_make_writable (caps);
1383 gst_caps_truncate (caps);
1386 if (!gst_caps_is_empty (caps)) {
1387 gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
1388 GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
1390 if (gst_caps_is_any (caps)) {
1391 /* hmm, still anything, so element can do anything and
1392 * nego is not needed */
1394 } else if (gst_caps_is_fixed (caps)) {
1395 /* yay, fixed caps, use those then */
1396 result = gst_pulsesrc_create_stream (GST_PULSESRC_CAST (basesrc), caps);
1398 result = gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
1401 gst_caps_unref (caps);
1407 GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
1409 gst_caps_unref (thiscaps);
1415 gst_pulsesrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
1417 pa_buffer_attr wanted;
1418 const pa_buffer_attr *actual;
1419 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1420 pa_stream_flags_t flags;
1421 #ifdef HAVE_PULSE_1_0
1425 pa_threaded_mainloop_lock (pulsesrc->mainloop);
1427 #ifdef HAVE_PULSE_1_0
1428 /* enable event notifications */
1429 GST_LOG_OBJECT (pulsesrc, "subscribing to context events");
1430 if (!(o = pa_context_subscribe (pulsesrc->context,
1431 PA_SUBSCRIPTION_MASK_SINK_INPUT, NULL, NULL))) {
1432 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1433 ("pa_context_subscribe() failed: %s",
1434 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1435 goto unlock_and_fail;
1438 pa_operation_unref (o);
1441 wanted.maxlength = -1;
1442 wanted.tlength = -1;
1445 wanted.fragsize = spec->segsize;
1447 GST_INFO_OBJECT (pulsesrc, "maxlength: %d", wanted.maxlength);
1448 GST_INFO_OBJECT (pulsesrc, "tlength: %d", wanted.tlength);
1449 GST_INFO_OBJECT (pulsesrc, "prebuf: %d", wanted.prebuf);
1450 GST_INFO_OBJECT (pulsesrc, "minreq: %d", wanted.minreq);
1451 GST_INFO_OBJECT (pulsesrc, "fragsize: %d", wanted.fragsize);
1453 flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE |
1454 PA_STREAM_NOT_MONOTONIC | PA_STREAM_ADJUST_LATENCY |
1455 PA_STREAM_START_CORKED;
1457 #ifdef HAVE_PULSE_1_0
1458 if (pulsesrc->mute_set && pulsesrc->mute)
1459 flags |= PA_STREAM_START_MUTED;
1462 if (pa_stream_connect_record (pulsesrc->stream, pulsesrc->device, &wanted,
1464 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1465 ("Failed to connect stream: %s",
1466 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1467 goto unlock_and_fail;
1470 pulsesrc->corked = TRUE;
1473 pa_stream_state_t state;
1475 state = pa_stream_get_state (pulsesrc->stream);
1477 if (!PA_STREAM_IS_GOOD (state)) {
1478 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1479 ("Failed to connect stream: %s",
1480 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1481 goto unlock_and_fail;
1484 if (state == PA_STREAM_READY)
1487 /* Wait until the stream is ready */
1488 pa_threaded_mainloop_wait (pulsesrc->mainloop);
1491 /* store the source output index so it can be accessed via a property */
1492 pulsesrc->source_output_idx = pa_stream_get_index (pulsesrc->stream);
1493 g_object_notify (G_OBJECT (pulsesrc), "source-output-index");
1495 #ifdef HAVE_PULSE_1_0
1496 if (pulsesrc->volume_set) {
1497 gst_pulsesrc_set_stream_volume (pulsesrc, pulsesrc->volume);
1498 pulsesrc->volume_set = FALSE;
1502 /* get the actual buffering properties now */
1503 actual = pa_stream_get_buffer_attr (pulsesrc->stream);
1505 GST_INFO_OBJECT (pulsesrc, "maxlength: %d", actual->maxlength);
1506 GST_INFO_OBJECT (pulsesrc, "tlength: %d (wanted: %d)",
1507 actual->tlength, wanted.tlength);
1508 GST_INFO_OBJECT (pulsesrc, "prebuf: %d", actual->prebuf);
1509 GST_INFO_OBJECT (pulsesrc, "minreq: %d (wanted %d)", actual->minreq,
1511 GST_INFO_OBJECT (pulsesrc, "fragsize: %d (wanted %d)",
1512 actual->fragsize, wanted.fragsize);
1514 if (actual->fragsize >= wanted.fragsize) {
1515 spec->segsize = actual->fragsize;
1517 spec->segsize = actual->fragsize * (wanted.fragsize / actual->fragsize);
1519 spec->segtotal = actual->maxlength / spec->segsize;
1521 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1527 gst_pulsesrc_destroy_stream (pulsesrc);
1529 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1535 gst_pulsesrc_success_cb (pa_stream * s, int success, void *userdata)
1537 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
1539 pulsesrc->operation_success = ! !success;
1540 pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
1544 gst_pulsesrc_reset (GstAudioSrc * asrc)
1546 GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1547 pa_operation *o = NULL;
1549 pa_threaded_mainloop_lock (pulsesrc->mainloop);
1550 GST_DEBUG_OBJECT (pulsesrc, "reset");
1552 if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
1553 goto unlock_and_fail;
1556 pa_stream_flush (pulsesrc->stream, gst_pulsesrc_success_cb,
1558 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1559 ("pa_stream_flush() failed: %s",
1560 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1561 goto unlock_and_fail;
1564 pulsesrc->paused = TRUE;
1565 /* Inform anyone waiting in _write() call that it shall wakeup */
1566 if (pulsesrc->in_read) {
1567 pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
1570 pulsesrc->operation_success = FALSE;
1571 while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
1573 if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
1574 goto unlock_and_fail;
1576 pa_threaded_mainloop_wait (pulsesrc->mainloop);
1579 if (!pulsesrc->operation_success) {
1580 GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Flush failed: %s",
1581 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1582 goto unlock_and_fail;
1588 pa_operation_cancel (o);
1589 pa_operation_unref (o);
1592 pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1595 /* update the corked state of a stream, must be called with the mainloop
1598 gst_pulsesrc_set_corked (GstPulseSrc * psrc, gboolean corked, gboolean wait)
1600 pa_operation *o = NULL;
1601 gboolean res = FALSE;
1603 GST_DEBUG_OBJECT (psrc, "setting corked state to %d", corked);
1604 if (psrc->corked != corked) {
1605 if (!(o = pa_stream_cork (psrc->stream, corked,
1606 gst_pulsesrc_success_cb, psrc)))
1609 while (wait && pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
1610 pa_threaded_mainloop_wait (psrc->mainloop);
1611 if (gst_pulsesrc_is_dead (psrc, TRUE))
1614 psrc->corked = corked;
1616 GST_DEBUG_OBJECT (psrc, "skipping, already in requested state");
1622 pa_operation_unref (o);
1629 GST_DEBUG_OBJECT (psrc, "the server is dead");
1634 GST_ELEMENT_ERROR (psrc, RESOURCE, FAILED,
1635 ("pa_stream_cork() failed: %s",
1636 pa_strerror (pa_context_errno (psrc->context))), (NULL));
1641 /* start/resume playback ASAP */
1643 gst_pulsesrc_play (GstPulseSrc * psrc)
1645 pa_threaded_mainloop_lock (psrc->mainloop);
1646 GST_DEBUG_OBJECT (psrc, "playing");
1647 psrc->paused = FALSE;
1648 gst_pulsesrc_set_corked (psrc, FALSE, FALSE);
1649 pa_threaded_mainloop_unlock (psrc->mainloop);
1654 /* pause/stop playback ASAP */
1656 gst_pulsesrc_pause (GstPulseSrc * psrc)
1658 pa_threaded_mainloop_lock (psrc->mainloop);
1659 GST_DEBUG_OBJECT (psrc, "pausing");
1660 /* make sure the commit method stops writing */
1661 psrc->paused = TRUE;
1662 if (psrc->in_read) {
1663 /* we are waiting in a read, signal */
1664 GST_DEBUG_OBJECT (psrc, "signal read");
1665 pa_threaded_mainloop_signal (psrc->mainloop, 0);
1667 pa_threaded_mainloop_unlock (psrc->mainloop);
1672 static GstStateChangeReturn
1673 gst_pulsesrc_change_state (GstElement * element, GstStateChange transition)
1675 GstStateChangeReturn ret;
1676 GstPulseSrc *this = GST_PULSESRC_CAST (element);
1678 switch (transition) {
1679 case GST_STATE_CHANGE_NULL_TO_READY:
1680 this->mainloop = pa_threaded_mainloop_new ();
1681 g_assert (this->mainloop);
1683 pa_threaded_mainloop_start (this->mainloop);
1687 gst_pulsemixer_ctrl_new (G_OBJECT (this), this->server,
1688 this->device, GST_PULSEMIXER_SOURCE);
1690 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1691 /* uncork and start recording */
1692 gst_pulsesrc_play (this);
1694 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1695 /* stop recording ASAP by corking */
1696 pa_threaded_mainloop_lock (this->mainloop);
1697 GST_DEBUG_OBJECT (this, "corking");
1698 gst_pulsesrc_set_corked (this, TRUE, FALSE);
1699 pa_threaded_mainloop_unlock (this->mainloop);
1705 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1707 switch (transition) {
1708 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1709 /* now make sure we get out of the _read method */
1710 gst_pulsesrc_pause (this);
1712 case GST_STATE_CHANGE_READY_TO_NULL:
1714 gst_pulsemixer_ctrl_free (this->mixer);
1719 pa_threaded_mainloop_stop (this->mainloop);
1721 gst_pulsesrc_destroy_context (this);
1723 if (this->mainloop) {
1724 pa_threaded_mainloop_free (this->mainloop);
1725 this->mainloop = NULL;