• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  GStreamer pulseaudio plugin
3  *
4  *  Copyright (c) 2004-2008 Lennart Poettering
5  *
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.
10  *
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.
15  *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19  *  USA.
20  */
21 
22 /**
23  * SECTION:element-pulsesrc
24  * @title: pulsesrc
25  * @see_also: pulsesink
26  *
27  * This element captures audio from a
28  * [PulseAudio sound server](http://www.pulseaudio.org).
29  *
30  * ## Example pipelines
31  * |[
32  * gst-launch-1.0 -v pulsesrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
33  * ]| Record from a sound card using pulseaudio and encode to Ogg/Vorbis.
34  *
35  */
36 
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40 
41 #include <string.h>
42 #include <stdio.h>
43 
44 #include <gst/base/gstbasesrc.h>
45 #include <gst/gsttaglist.h>
46 #include <gst/audio/audio.h>
47 
48 #include "gstpulseelements.h"
49 #include "pulsesrc.h"
50 #include "pulseutil.h"
51 
52 GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
53 #define GST_CAT_DEFAULT pulse_debug
54 
55 #define DEFAULT_SERVER            NULL
56 #define DEFAULT_DEVICE            NULL
57 #define DEFAULT_CURRENT_DEVICE    NULL
58 #define DEFAULT_DEVICE_NAME       NULL
59 
60 #define DEFAULT_VOLUME          1.0
61 #define DEFAULT_MUTE            FALSE
62 #define MAX_VOLUME              10.0
63 
64 /* See the pulsesink code for notes on how we interact with the PA mainloop
65  * thread. */
66 
67 enum
68 {
69   PROP_0,
70   PROP_SERVER,
71   PROP_DEVICE,
72   PROP_DEVICE_NAME,
73   PROP_CURRENT_DEVICE,
74   PROP_CLIENT_NAME,
75   PROP_STREAM_PROPERTIES,
76   PROP_SOURCE_OUTPUT_INDEX,
77   PROP_VOLUME,
78   PROP_MUTE,
79   PROP_LAST
80 };
81 
82 static void gst_pulsesrc_destroy_stream (GstPulseSrc * pulsesrc);
83 static void gst_pulsesrc_destroy_context (GstPulseSrc * pulsesrc);
84 
85 static void gst_pulsesrc_set_property (GObject * object, guint prop_id,
86     const GValue * value, GParamSpec * pspec);
87 static void gst_pulsesrc_get_property (GObject * object, guint prop_id,
88     GValue * value, GParamSpec * pspec);
89 static void gst_pulsesrc_finalize (GObject * object);
90 
91 static gboolean gst_pulsesrc_set_corked (GstPulseSrc * psrc, gboolean corked,
92     gboolean wait);
93 static gboolean gst_pulsesrc_open (GstAudioSrc * asrc);
94 
95 static gboolean gst_pulsesrc_close (GstAudioSrc * asrc);
96 
97 static gboolean gst_pulsesrc_prepare (GstAudioSrc * asrc,
98     GstAudioRingBufferSpec * spec);
99 
100 static gboolean gst_pulsesrc_unprepare (GstAudioSrc * asrc);
101 
102 static guint gst_pulsesrc_read (GstAudioSrc * asrc, gpointer data,
103     guint length, GstClockTime * timestamp);
104 static guint gst_pulsesrc_delay (GstAudioSrc * asrc);
105 
106 static void gst_pulsesrc_reset (GstAudioSrc * src);
107 
108 static gboolean gst_pulsesrc_negotiate (GstBaseSrc * basesrc);
109 static gboolean gst_pulsesrc_event (GstBaseSrc * basesrc, GstEvent * event);
110 
111 static GstStateChangeReturn gst_pulsesrc_change_state (GstElement *
112     element, GstStateChange transition);
113 
114 static GstClockTime gst_pulsesrc_get_time (GstClock * clock, GstPulseSrc * src);
115 
116 #define gst_pulsesrc_parent_class parent_class
117 G_DEFINE_TYPE_WITH_CODE (GstPulseSrc, gst_pulsesrc, GST_TYPE_AUDIO_SRC,
118     G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL));
119 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (pulsesrc, "pulsesrc",
120     GST_RANK_PRIMARY + 10, GST_TYPE_PULSESRC, pulse_element_init (plugin));
121 
122 static void
gst_pulsesrc_class_init(GstPulseSrcClass * klass)123 gst_pulsesrc_class_init (GstPulseSrcClass * klass)
124 {
125   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
126   GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS (klass);
127   GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
128   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
129   GstCaps *caps;
130   gchar *clientname;
131 
132   gobject_class->finalize = gst_pulsesrc_finalize;
133   gobject_class->set_property = gst_pulsesrc_set_property;
134   gobject_class->get_property = gst_pulsesrc_get_property;
135 
136   gstelement_class->change_state =
137       GST_DEBUG_FUNCPTR (gst_pulsesrc_change_state);
138 
139   gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_pulsesrc_event);
140   gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_pulsesrc_negotiate);
141 
142   gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_pulsesrc_open);
143   gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_pulsesrc_close);
144   gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_prepare);
145   gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_unprepare);
146   gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_pulsesrc_read);
147   gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_pulsesrc_delay);
148   gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_pulsesrc_reset);
149 
150   /* Overwrite GObject fields */
151   g_object_class_install_property (gobject_class,
152       PROP_SERVER,
153       g_param_spec_string ("server", "Server",
154           "The PulseAudio server to connect to", DEFAULT_SERVER,
155           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
156 
157   g_object_class_install_property (gobject_class, PROP_DEVICE,
158       g_param_spec_string ("device", "Device",
159           "The PulseAudio source device to connect to", DEFAULT_DEVICE,
160           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
161 
162   g_object_class_install_property (gobject_class, PROP_CURRENT_DEVICE,
163       g_param_spec_string ("current-device", "Current Device",
164           "The current PulseAudio source device", DEFAULT_CURRENT_DEVICE,
165           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
166 
167   g_object_class_install_property (gobject_class,
168       PROP_DEVICE_NAME,
169       g_param_spec_string ("device-name", "Device name",
170           "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
171           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
172 
173   clientname = gst_pulse_client_name ();
174   /**
175    * GstPulseSrc:client-name
176    *
177    * The PulseAudio client name to use.
178    */
179   g_object_class_install_property (gobject_class,
180       PROP_CLIENT_NAME,
181       g_param_spec_string ("client-name", "Client Name",
182           "The PulseAudio client_name_to_use", clientname,
183           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
184           GST_PARAM_MUTABLE_READY));
185   g_free (clientname);
186 
187   /**
188    * GstPulseSrc:stream-properties:
189    *
190    * List of pulseaudio stream properties. A list of defined properties can be
191    * found in the [pulseaudio api docs](http://0pointer.de/lennart/projects/pulseaudio/doxygen/proplist_8h.html).
192    *
193    * Below is an example for registering as a music application to pulseaudio.
194    * |[
195    * GstStructure *props;
196    *
197    * props = gst_structure_from_string ("props,media.role=music", NULL);
198    * g_object_set (pulse, "stream-properties", props, NULL);
199    * gst_structure_free (props);
200    * ]|
201    */
202   g_object_class_install_property (gobject_class,
203       PROP_STREAM_PROPERTIES,
204       g_param_spec_boxed ("stream-properties", "stream properties",
205           "list of pulseaudio stream properties",
206           GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
207   /**
208    * GstPulseSrc:source-output-index:
209    *
210    * The index of the PulseAudio source output corresponding to this element.
211    */
212   g_object_class_install_property (gobject_class,
213       PROP_SOURCE_OUTPUT_INDEX,
214       g_param_spec_uint ("source-output-index", "source output index",
215           "The index of the PulseAudio source output corresponding to this "
216           "record stream", 0, G_MAXUINT, PA_INVALID_INDEX,
217           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
218 
219   gst_element_class_set_static_metadata (gstelement_class,
220       "PulseAudio Audio Source",
221       "Source/Audio",
222       "Captures audio from a PulseAudio server", "Lennart Poettering");
223 
224   caps = gst_pulse_fix_pcm_caps (gst_caps_from_string (_PULSE_CAPS_PCM));
225   gst_element_class_add_pad_template (gstelement_class,
226       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps));
227   gst_caps_unref (caps);
228 
229   /**
230    * GstPulseSrc:volume:
231    *
232    * The volume of the record stream.
233    */
234   g_object_class_install_property (gobject_class,
235       PROP_VOLUME, g_param_spec_double ("volume", "Volume",
236           "Linear volume of this stream, 1.0=100%",
237           0.0, MAX_VOLUME, DEFAULT_VOLUME,
238           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
239 
240   /**
241    * GstPulseSrc:mute:
242    *
243    * Whether the stream is muted or not.
244    */
245   g_object_class_install_property (gobject_class,
246       PROP_MUTE, g_param_spec_boolean ("mute", "Mute",
247           "Mute state of this stream",
248           DEFAULT_MUTE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
249 }
250 
251 static void
gst_pulsesrc_init(GstPulseSrc * pulsesrc)252 gst_pulsesrc_init (GstPulseSrc * pulsesrc)
253 {
254   pulsesrc->server = NULL;
255   pulsesrc->device = NULL;
256   pulsesrc->client_name = gst_pulse_client_name ();
257   pulsesrc->device_description = NULL;
258 
259   pulsesrc->context = NULL;
260   pulsesrc->stream = NULL;
261   pulsesrc->stream_connected = FALSE;
262   pulsesrc->source_output_idx = PA_INVALID_INDEX;
263 
264   pulsesrc->read_buffer = NULL;
265   pulsesrc->read_buffer_length = 0;
266 
267   pa_sample_spec_init (&pulsesrc->sample_spec);
268 
269   pulsesrc->operation_success = FALSE;
270   pulsesrc->paused = TRUE;
271   pulsesrc->in_read = FALSE;
272 
273   pulsesrc->volume = DEFAULT_VOLUME;
274   pulsesrc->volume_set = FALSE;
275 
276   pulsesrc->mute = DEFAULT_MUTE;
277   pulsesrc->mute_set = FALSE;
278 
279   pulsesrc->notify = 0;
280 
281   pulsesrc->properties = NULL;
282   pulsesrc->proplist = NULL;
283 
284   /* this should be the default but it isn't yet */
285   gst_audio_base_src_set_slave_method (GST_AUDIO_BASE_SRC (pulsesrc),
286       GST_AUDIO_BASE_SRC_SLAVE_SKEW);
287 
288   /* override with a custom clock */
289   if (GST_AUDIO_BASE_SRC (pulsesrc)->clock)
290     gst_object_unref (GST_AUDIO_BASE_SRC (pulsesrc)->clock);
291 
292   GST_AUDIO_BASE_SRC (pulsesrc)->clock =
293       gst_audio_clock_new ("GstPulseSrcClock",
294       (GstAudioClockGetTimeFunc) gst_pulsesrc_get_time, pulsesrc, NULL);
295 }
296 
297 static void
gst_pulsesrc_destroy_stream(GstPulseSrc * pulsesrc)298 gst_pulsesrc_destroy_stream (GstPulseSrc * pulsesrc)
299 {
300   if (pulsesrc->stream) {
301     pa_stream_disconnect (pulsesrc->stream);
302     pa_stream_unref (pulsesrc->stream);
303     pulsesrc->stream = NULL;
304     pulsesrc->stream_connected = FALSE;
305     pulsesrc->source_output_idx = PA_INVALID_INDEX;
306     g_object_notify (G_OBJECT (pulsesrc), "source-output-index");
307   }
308 
309   g_free (pulsesrc->device_description);
310   pulsesrc->device_description = NULL;
311 }
312 
313 static void
gst_pulsesrc_destroy_context(GstPulseSrc * pulsesrc)314 gst_pulsesrc_destroy_context (GstPulseSrc * pulsesrc)
315 {
316 
317   gst_pulsesrc_destroy_stream (pulsesrc);
318 
319   if (pulsesrc->context) {
320     pa_context_disconnect (pulsesrc->context);
321 
322     /* Make sure we don't get any further callbacks */
323     pa_context_set_state_callback (pulsesrc->context, NULL, NULL);
324     pa_context_set_subscribe_callback (pulsesrc->context, NULL, NULL);
325 
326     pa_context_unref (pulsesrc->context);
327 
328     pulsesrc->context = NULL;
329   }
330 }
331 
332 static void
gst_pulsesrc_finalize(GObject * object)333 gst_pulsesrc_finalize (GObject * object)
334 {
335   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (object);
336 
337   g_free (pulsesrc->server);
338   g_free (pulsesrc->device);
339   g_free (pulsesrc->client_name);
340   g_free (pulsesrc->current_source_name);
341 
342   if (pulsesrc->properties)
343     gst_structure_free (pulsesrc->properties);
344   if (pulsesrc->proplist)
345     pa_proplist_free (pulsesrc->proplist);
346 
347   G_OBJECT_CLASS (parent_class)->finalize (object);
348 }
349 
350 #define CONTEXT_OK(c) ((c) && PA_CONTEXT_IS_GOOD (pa_context_get_state ((c))))
351 #define STREAM_OK(s) ((s) && PA_STREAM_IS_GOOD (pa_stream_get_state ((s))))
352 
353 static gboolean
gst_pulsesrc_is_dead(GstPulseSrc * pulsesrc,gboolean check_stream)354 gst_pulsesrc_is_dead (GstPulseSrc * pulsesrc, gboolean check_stream)
355 {
356   if (!pulsesrc->stream_connected)
357     return TRUE;
358 
359   if (!CONTEXT_OK (pulsesrc->context))
360     goto error;
361 
362   if (check_stream && !STREAM_OK (pulsesrc->stream))
363     goto error;
364 
365   return FALSE;
366 
367 error:
368   {
369     const gchar *err_str = pulsesrc->context ?
370         pa_strerror (pa_context_errno (pulsesrc->context)) : NULL;
371     GST_ELEMENT_ERROR ((pulsesrc), RESOURCE, FAILED, ("Disconnected: %s",
372             err_str), (NULL));
373     return TRUE;
374   }
375 }
376 
377 static void
gst_pulsesrc_source_info_cb(pa_context * c,const pa_source_info * i,int eol,void * userdata)378 gst_pulsesrc_source_info_cb (pa_context * c, const pa_source_info * i, int eol,
379     void *userdata)
380 {
381   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
382 
383   if (!i)
384     goto done;
385 
386   g_free (pulsesrc->device_description);
387   pulsesrc->device_description = g_strdup (i->description);
388 
389 done:
390   pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
391 }
392 
393 static gchar *
gst_pulsesrc_device_description(GstPulseSrc * pulsesrc)394 gst_pulsesrc_device_description (GstPulseSrc * pulsesrc)
395 {
396   pa_operation *o = NULL;
397   gchar *t;
398 
399   if (!pulsesrc->mainloop)
400     goto no_mainloop;
401 
402   pa_threaded_mainloop_lock (pulsesrc->mainloop);
403 
404   if (!(o = pa_context_get_source_info_by_name (pulsesrc->context,
405               pulsesrc->device, gst_pulsesrc_source_info_cb, pulsesrc))) {
406 
407     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
408         ("pa_stream_get_source_info() failed: %s",
409             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
410     goto unlock;
411   }
412 
413   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
414 
415     if (gst_pulsesrc_is_dead (pulsesrc, FALSE))
416       goto unlock;
417 
418     pa_threaded_mainloop_wait (pulsesrc->mainloop);
419   }
420 
421 unlock:
422 
423   if (o)
424     pa_operation_unref (o);
425 
426   t = g_strdup (pulsesrc->device_description);
427 
428   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
429 
430   return t;
431 
432 no_mainloop:
433   {
434     GST_DEBUG_OBJECT (pulsesrc, "have no mainloop");
435     return NULL;
436   }
437 }
438 
439 static void
gst_pulsesrc_source_output_info_cb(pa_context * c,const pa_source_output_info * i,int eol,void * userdata)440 gst_pulsesrc_source_output_info_cb (pa_context * c,
441     const pa_source_output_info * i, int eol, void *userdata)
442 {
443   GstPulseSrc *psrc;
444 
445   psrc = GST_PULSESRC_CAST (userdata);
446 
447   if (!i)
448     goto done;
449 
450   /* If the index doesn't match our current stream,
451    * it implies we just recreated the stream (caps change)
452    */
453   if (i->index == psrc->source_output_idx) {
454     psrc->volume = pa_sw_volume_to_linear (pa_cvolume_max (&i->volume));
455     psrc->mute = i->mute;
456     psrc->current_source_idx = i->source;
457 
458     if (G_UNLIKELY (psrc->volume > MAX_VOLUME)) {
459       GST_WARNING_OBJECT (psrc, "Clipped volume from %f to %f",
460           psrc->volume, MAX_VOLUME);
461       psrc->volume = MAX_VOLUME;
462     }
463   }
464 
465 done:
466   pa_threaded_mainloop_signal (psrc->mainloop, 0);
467 }
468 
469 static void
gst_pulsesrc_get_source_output_info(GstPulseSrc * pulsesrc,gdouble * volume,gboolean * mute)470 gst_pulsesrc_get_source_output_info (GstPulseSrc * pulsesrc, gdouble * volume,
471     gboolean * mute)
472 {
473   pa_operation *o = NULL;
474 
475   if (!pulsesrc->mainloop)
476     goto no_mainloop;
477 
478   if (pulsesrc->source_output_idx == PA_INVALID_INDEX)
479     goto no_index;
480 
481   pa_threaded_mainloop_lock (pulsesrc->mainloop);
482 
483   if (!(o = pa_context_get_source_output_info (pulsesrc->context,
484               pulsesrc->source_output_idx, gst_pulsesrc_source_output_info_cb,
485               pulsesrc)))
486     goto info_failed;
487 
488   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
489     pa_threaded_mainloop_wait (pulsesrc->mainloop);
490     if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
491       goto unlock;
492   }
493 
494 unlock:
495 
496   if (volume)
497     *volume = pulsesrc->volume;
498   if (mute)
499     *mute = pulsesrc->mute;
500 
501   if (o)
502     pa_operation_unref (o);
503 
504   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
505 
506   return;
507 
508   /* ERRORS */
509 no_mainloop:
510   {
511     GST_DEBUG_OBJECT (pulsesrc, "we have no mainloop");
512     if (volume)
513       *volume = pulsesrc->volume;
514     if (mute)
515       *mute = pulsesrc->mute;
516     return;
517   }
518 no_index:
519   {
520     GST_DEBUG_OBJECT (pulsesrc, "we don't have a stream index");
521     if (volume)
522       *volume = pulsesrc->volume;
523     if (mute)
524       *mute = pulsesrc->mute;
525     return;
526   }
527 info_failed:
528   {
529     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
530         ("pa_context_get_source_output_info() failed: %s",
531             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
532     goto unlock;
533   }
534 }
535 
536 static void
gst_pulsesrc_current_source_info_cb(pa_context * c,const pa_source_info * i,int eol,void * userdata)537 gst_pulsesrc_current_source_info_cb (pa_context * c, const pa_source_info * i,
538     int eol, void *userdata)
539 {
540   GstPulseSrc *psrc;
541 
542   psrc = GST_PULSESRC_CAST (userdata);
543 
544   if (!i)
545     goto done;
546 
547   /* If the index doesn't match our current stream,
548    * it implies we just recreated the stream (caps change)
549    */
550   if (i->index == psrc->current_source_idx) {
551     g_free (psrc->current_source_name);
552     psrc->current_source_name = g_strdup (i->name);
553   }
554 
555 done:
556   pa_threaded_mainloop_signal (psrc->mainloop, 0);
557 }
558 
559 static gchar *
gst_pulsesrc_get_current_device(GstPulseSrc * pulsesrc)560 gst_pulsesrc_get_current_device (GstPulseSrc * pulsesrc)
561 {
562   pa_operation *o = NULL;
563   gchar *current_src;
564 
565   if (!pulsesrc->mainloop)
566     goto no_mainloop;
567 
568   if (pulsesrc->source_output_idx == PA_INVALID_INDEX)
569     goto no_index;
570 
571   gst_pulsesrc_get_source_output_info (pulsesrc, NULL, NULL);
572 
573   pa_threaded_mainloop_lock (pulsesrc->mainloop);
574 
575 
576   if (!(o = pa_context_get_source_info_by_index (pulsesrc->context,
577               pulsesrc->current_source_idx, gst_pulsesrc_current_source_info_cb,
578               pulsesrc)))
579     goto info_failed;
580 
581   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
582     pa_threaded_mainloop_wait (pulsesrc->mainloop);
583     if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
584       goto unlock;
585   }
586 
587 unlock:
588 
589   current_src = g_strdup (pulsesrc->current_source_name);
590 
591   if (o)
592     pa_operation_unref (o);
593 
594   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
595 
596   return current_src;
597 
598   /* ERRORS */
599 no_mainloop:
600   {
601     GST_DEBUG_OBJECT (pulsesrc, "we have no mainloop");
602     return NULL;
603   }
604 no_index:
605   {
606     GST_DEBUG_OBJECT (pulsesrc, "we don't have a stream index");
607     return NULL;
608   }
609 info_failed:
610   {
611     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
612         ("pa_context_get_source_output_info() failed: %s",
613             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
614     goto unlock;
615   }
616 }
617 
618 static void
gst_pulsesrc_set_stream_volume(GstPulseSrc * pulsesrc,gdouble volume)619 gst_pulsesrc_set_stream_volume (GstPulseSrc * pulsesrc, gdouble volume)
620 {
621   pa_cvolume v;
622   pa_operation *o = NULL;
623 
624   if (!pulsesrc->mainloop)
625     goto no_mainloop;
626 
627   if (pulsesrc->source_output_idx == PA_INVALID_INDEX)
628     goto no_index;
629 
630   pa_threaded_mainloop_lock (pulsesrc->mainloop);
631 
632   GST_DEBUG_OBJECT (pulsesrc, "setting volume to %f", volume);
633 
634   gst_pulse_cvolume_from_linear (&v, pulsesrc->sample_spec.channels, volume);
635 
636   if (!(o = pa_context_set_source_output_volume (pulsesrc->context,
637               pulsesrc->source_output_idx, &v, NULL, NULL)))
638     goto volume_failed;
639 
640   /* We don't really care about the result of this call */
641 unlock:
642 
643   if (o)
644     pa_operation_unref (o);
645 
646   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
647 
648   return;
649 
650   /* ERRORS */
651 no_mainloop:
652   {
653     pulsesrc->volume = volume;
654     pulsesrc->volume_set = TRUE;
655     GST_DEBUG_OBJECT (pulsesrc, "we have no mainloop");
656     return;
657   }
658 no_index:
659   {
660     pulsesrc->volume = volume;
661     pulsesrc->volume_set = TRUE;
662     GST_DEBUG_OBJECT (pulsesrc, "we don't have a stream index");
663     return;
664   }
665 volume_failed:
666   {
667     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
668         ("pa_stream_set_source_output_volume() failed: %s",
669             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
670     goto unlock;
671   }
672 }
673 
674 static void
gst_pulsesrc_set_stream_mute(GstPulseSrc * pulsesrc,gboolean mute)675 gst_pulsesrc_set_stream_mute (GstPulseSrc * pulsesrc, gboolean mute)
676 {
677   pa_operation *o = NULL;
678 
679   if (!pulsesrc->mainloop)
680     goto no_mainloop;
681 
682   if (pulsesrc->source_output_idx == PA_INVALID_INDEX)
683     goto no_index;
684 
685   pa_threaded_mainloop_lock (pulsesrc->mainloop);
686 
687   GST_DEBUG_OBJECT (pulsesrc, "setting mute state to %d", mute);
688 
689   if (!(o = pa_context_set_source_output_mute (pulsesrc->context,
690               pulsesrc->source_output_idx, mute, NULL, NULL)))
691     goto mute_failed;
692 
693   /* We don't really care about the result of this call */
694 unlock:
695 
696   if (o)
697     pa_operation_unref (o);
698 
699   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
700 
701   return;
702 
703   /* ERRORS */
704 no_mainloop:
705   {
706     pulsesrc->mute = mute;
707     pulsesrc->mute_set = TRUE;
708     GST_DEBUG_OBJECT (pulsesrc, "we have no mainloop");
709     return;
710   }
711 no_index:
712   {
713     pulsesrc->mute = mute;
714     pulsesrc->mute_set = TRUE;
715     GST_DEBUG_OBJECT (pulsesrc, "we don't have a stream index");
716     return;
717   }
718 mute_failed:
719   {
720     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
721         ("pa_stream_set_source_output_mute() failed: %s",
722             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
723     goto unlock;
724   }
725 }
726 
727 static void
gst_pulsesrc_set_stream_device(GstPulseSrc * pulsesrc,const gchar * device)728 gst_pulsesrc_set_stream_device (GstPulseSrc * pulsesrc, const gchar * device)
729 {
730   pa_operation *o = NULL;
731 
732   if (!pulsesrc->mainloop)
733     goto no_mainloop;
734 
735   if (pulsesrc->source_output_idx == PA_INVALID_INDEX)
736     goto no_index;
737 
738   pa_threaded_mainloop_lock (pulsesrc->mainloop);
739 
740   GST_DEBUG_OBJECT (pulsesrc, "setting stream device to %s", device);
741 
742   if (!(o = pa_context_move_source_output_by_name (pulsesrc->context,
743               pulsesrc->source_output_idx, device, NULL, NULL)))
744     goto move_failed;
745 
746 unlock:
747 
748   if (o)
749     pa_operation_unref (o);
750 
751   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
752 
753   return;
754 
755   /* ERRORS */
756 no_mainloop:
757   {
758     GST_DEBUG_OBJECT (pulsesrc, "we have no mainloop");
759     return;
760   }
761 no_index:
762   {
763     GST_DEBUG_OBJECT (pulsesrc, "we don't have a stream index");
764     return;
765   }
766 move_failed:
767   {
768     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
769         ("pa_context_move_source_output_by_name(%s) failed: %s",
770             device, pa_strerror (pa_context_errno (pulsesrc->context))),
771         (NULL));
772     goto unlock;
773   }
774 }
775 
776 static void
gst_pulsesrc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)777 gst_pulsesrc_set_property (GObject * object,
778     guint prop_id, const GValue * value, GParamSpec * pspec)
779 {
780 
781   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (object);
782 
783   switch (prop_id) {
784     case PROP_SERVER:
785       g_free (pulsesrc->server);
786       pulsesrc->server = g_value_dup_string (value);
787       break;
788     case PROP_DEVICE:
789       g_free (pulsesrc->device);
790       pulsesrc->device = g_value_dup_string (value);
791       gst_pulsesrc_set_stream_device (pulsesrc, pulsesrc->device);
792       break;
793     case PROP_CLIENT_NAME:
794       g_free (pulsesrc->client_name);
795       if (!g_value_get_string (value)) {
796         GST_WARNING_OBJECT (pulsesrc,
797             "Empty PulseAudio client name not allowed. Resetting to default value");
798         pulsesrc->client_name = gst_pulse_client_name ();
799       } else
800         pulsesrc->client_name = g_value_dup_string (value);
801       break;
802     case PROP_STREAM_PROPERTIES:
803       if (pulsesrc->properties)
804         gst_structure_free (pulsesrc->properties);
805       pulsesrc->properties =
806           gst_structure_copy (gst_value_get_structure (value));
807       if (pulsesrc->proplist)
808         pa_proplist_free (pulsesrc->proplist);
809       pulsesrc->proplist = gst_pulse_make_proplist (pulsesrc->properties);
810       break;
811     case PROP_VOLUME:
812       gst_pulsesrc_set_stream_volume (pulsesrc, g_value_get_double (value));
813       break;
814     case PROP_MUTE:
815       gst_pulsesrc_set_stream_mute (pulsesrc, g_value_get_boolean (value));
816       break;
817     default:
818       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
819       break;
820   }
821 }
822 
823 static void
gst_pulsesrc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)824 gst_pulsesrc_get_property (GObject * object,
825     guint prop_id, GValue * value, GParamSpec * pspec)
826 {
827 
828   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (object);
829 
830   switch (prop_id) {
831     case PROP_SERVER:
832       g_value_set_string (value, pulsesrc->server);
833       break;
834     case PROP_DEVICE:
835       g_value_set_string (value, pulsesrc->device);
836       break;
837     case PROP_CURRENT_DEVICE:
838     {
839       gchar *current_device = gst_pulsesrc_get_current_device (pulsesrc);
840       if (current_device)
841         g_value_take_string (value, current_device);
842       else
843         g_value_set_string (value, "");
844       break;
845     }
846     case PROP_DEVICE_NAME:
847       g_value_take_string (value, gst_pulsesrc_device_description (pulsesrc));
848       break;
849     case PROP_CLIENT_NAME:
850       g_value_set_string (value, pulsesrc->client_name);
851       break;
852     case PROP_STREAM_PROPERTIES:
853       gst_value_set_structure (value, pulsesrc->properties);
854       break;
855     case PROP_SOURCE_OUTPUT_INDEX:
856       g_value_set_uint (value, pulsesrc->source_output_idx);
857       break;
858     case PROP_VOLUME:
859     {
860       gdouble volume;
861       gst_pulsesrc_get_source_output_info (pulsesrc, &volume, NULL);
862       g_value_set_double (value, volume);
863       break;
864     }
865     case PROP_MUTE:
866     {
867       gboolean mute;
868       gst_pulsesrc_get_source_output_info (pulsesrc, NULL, &mute);
869       g_value_set_boolean (value, mute);
870       break;
871     }
872     default:
873       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
874       break;
875   }
876 }
877 
878 static void
gst_pulsesrc_context_state_cb(pa_context * c,void * userdata)879 gst_pulsesrc_context_state_cb (pa_context * c, void *userdata)
880 {
881   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
882 
883   switch (pa_context_get_state (c)) {
884     case PA_CONTEXT_READY:
885     case PA_CONTEXT_TERMINATED:
886     case PA_CONTEXT_FAILED:
887       pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
888       break;
889 
890     case PA_CONTEXT_UNCONNECTED:
891     case PA_CONTEXT_CONNECTING:
892     case PA_CONTEXT_AUTHORIZING:
893     case PA_CONTEXT_SETTING_NAME:
894       break;
895   }
896 }
897 
898 static void
gst_pulsesrc_stream_state_cb(pa_stream * s,void * userdata)899 gst_pulsesrc_stream_state_cb (pa_stream * s, void *userdata)
900 {
901   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
902 
903   switch (pa_stream_get_state (s)) {
904 
905     case PA_STREAM_READY:
906     case PA_STREAM_FAILED:
907     case PA_STREAM_TERMINATED:
908       pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
909       break;
910 
911     case PA_STREAM_UNCONNECTED:
912     case PA_STREAM_CREATING:
913       break;
914   }
915 }
916 
917 static void
gst_pulsesrc_stream_request_cb(pa_stream * s,size_t length,void * userdata)918 gst_pulsesrc_stream_request_cb (pa_stream * s, size_t length, void *userdata)
919 {
920   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
921 
922   GST_LOG_OBJECT (pulsesrc, "got request for length %" G_GSIZE_FORMAT, length);
923 
924   if (pulsesrc->in_read) {
925     /* only signal when reading */
926     pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
927   }
928 }
929 
930 static void
gst_pulsesrc_stream_latency_update_cb(pa_stream * s,void * userdata)931 gst_pulsesrc_stream_latency_update_cb (pa_stream * s, void *userdata)
932 {
933   const pa_timing_info *info;
934   pa_usec_t source_usec;
935 
936   info = pa_stream_get_timing_info (s);
937 
938   if (!info) {
939     GST_LOG_OBJECT (GST_PULSESRC_CAST (userdata),
940         "latency update (information unknown)");
941     return;
942   }
943   source_usec = info->configured_source_usec;
944 
945   GST_LOG_OBJECT (GST_PULSESRC_CAST (userdata),
946       "latency_update, %" G_GUINT64_FORMAT ", %d:%" G_GINT64_FORMAT ", %d:%"
947       G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT,
948       GST_TIMEVAL_TO_TIME (info->timestamp), info->write_index_corrupt,
949       info->write_index, info->read_index_corrupt, info->read_index,
950       info->source_usec, source_usec);
951 }
952 
953 static void
gst_pulsesrc_stream_underflow_cb(pa_stream * s,void * userdata)954 gst_pulsesrc_stream_underflow_cb (pa_stream * s, void *userdata)
955 {
956   GST_WARNING_OBJECT (GST_PULSESRC_CAST (userdata), "Got underflow");
957 }
958 
959 static void
gst_pulsesrc_stream_overflow_cb(pa_stream * s,void * userdata)960 gst_pulsesrc_stream_overflow_cb (pa_stream * s, void *userdata)
961 {
962   GST_WARNING_OBJECT (GST_PULSESRC_CAST (userdata), "Got overflow");
963 }
964 
965 static void
gst_pulsesrc_context_subscribe_cb(pa_context * c,pa_subscription_event_type_t t,uint32_t idx,void * userdata)966 gst_pulsesrc_context_subscribe_cb (pa_context * c,
967     pa_subscription_event_type_t t, uint32_t idx, void *userdata)
968 {
969   GstPulseSrc *psrc = GST_PULSESRC (userdata);
970 
971   if (t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT | PA_SUBSCRIPTION_EVENT_CHANGE)
972       && t != (PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT | PA_SUBSCRIPTION_EVENT_NEW))
973     return;
974 
975   if (idx != psrc->source_output_idx)
976     return;
977 
978   /* Actually this event is also triggered when other properties of the stream
979    * change that are unrelated to the volume. However it is probably cheaper to
980    * signal the change here and check for the volume when the GObject property
981    * is read instead of querying it always. */
982 
983   /* inform streaming thread to notify */
984   g_atomic_int_compare_and_exchange (&psrc->notify, 0, 1);
985 }
986 
987 static gboolean
gst_pulsesrc_open(GstAudioSrc * asrc)988 gst_pulsesrc_open (GstAudioSrc * asrc)
989 {
990   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
991 
992   pa_threaded_mainloop_lock (pulsesrc->mainloop);
993 
994   g_assert (!pulsesrc->context);
995   g_assert (!pulsesrc->stream);
996 
997   GST_DEBUG_OBJECT (pulsesrc, "opening device");
998 
999   if (!(pulsesrc->context =
1000           pa_context_new (pa_threaded_mainloop_get_api (pulsesrc->mainloop),
1001               pulsesrc->client_name))) {
1002     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to create context"),
1003         (NULL));
1004     goto unlock_and_fail;
1005   }
1006 
1007   pa_context_set_state_callback (pulsesrc->context,
1008       gst_pulsesrc_context_state_cb, pulsesrc);
1009   pa_context_set_subscribe_callback (pulsesrc->context,
1010       gst_pulsesrc_context_subscribe_cb, pulsesrc);
1011 
1012   GST_DEBUG_OBJECT (pulsesrc, "connect to server %s",
1013       GST_STR_NULL (pulsesrc->server));
1014 
1015   if (pa_context_connect (pulsesrc->context, pulsesrc->server, 0, NULL) < 0) {
1016     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
1017             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1018     goto unlock_and_fail;
1019   }
1020 
1021   for (;;) {
1022     pa_context_state_t state;
1023 
1024     state = pa_context_get_state (pulsesrc->context);
1025 
1026     if (!PA_CONTEXT_IS_GOOD (state)) {
1027       GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
1028               pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1029       goto unlock_and_fail;
1030     }
1031 
1032     if (state == PA_CONTEXT_READY)
1033       break;
1034 
1035     /* Wait until the context is ready */
1036     pa_threaded_mainloop_wait (pulsesrc->mainloop);
1037   }
1038   GST_DEBUG_OBJECT (pulsesrc, "connected");
1039 
1040   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1041 
1042   return TRUE;
1043 
1044   /* ERRORS */
1045 unlock_and_fail:
1046   {
1047     gst_pulsesrc_destroy_context (pulsesrc);
1048 
1049     pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1050 
1051     return FALSE;
1052   }
1053 }
1054 
1055 static gboolean
gst_pulsesrc_close(GstAudioSrc * asrc)1056 gst_pulsesrc_close (GstAudioSrc * asrc)
1057 {
1058   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1059 
1060   pa_threaded_mainloop_lock (pulsesrc->mainloop);
1061   gst_pulsesrc_destroy_context (pulsesrc);
1062   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1063 
1064   return TRUE;
1065 }
1066 
1067 static gboolean
gst_pulsesrc_unprepare(GstAudioSrc * asrc)1068 gst_pulsesrc_unprepare (GstAudioSrc * asrc)
1069 {
1070   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1071 
1072   pa_threaded_mainloop_lock (pulsesrc->mainloop);
1073   gst_pulsesrc_destroy_stream (pulsesrc);
1074 
1075   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1076 
1077   pulsesrc->read_buffer = NULL;
1078   pulsesrc->read_buffer_length = 0;
1079 
1080   return TRUE;
1081 }
1082 
1083 static guint
gst_pulsesrc_read(GstAudioSrc * asrc,gpointer data,guint length,GstClockTime * timestamp)1084 gst_pulsesrc_read (GstAudioSrc * asrc, gpointer data, guint length,
1085     GstClockTime * timestamp)
1086 {
1087   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1088   size_t sum = 0;
1089 
1090   if (g_atomic_int_compare_and_exchange (&pulsesrc->notify, 1, 0)) {
1091     g_object_notify (G_OBJECT (pulsesrc), "volume");
1092     g_object_notify (G_OBJECT (pulsesrc), "mute");
1093     g_object_notify (G_OBJECT (pulsesrc), "current-device");
1094   }
1095 
1096   pa_threaded_mainloop_lock (pulsesrc->mainloop);
1097   pulsesrc->in_read = TRUE;
1098 
1099   if (!pulsesrc->stream_connected)
1100     goto not_connected;
1101 
1102   if (pulsesrc->paused)
1103     goto was_paused;
1104 
1105   while (length > 0) {
1106     size_t l;
1107 
1108     GST_LOG_OBJECT (pulsesrc, "reading %u bytes", length);
1109 
1110     /*check if we have a leftover buffer */
1111     if (!pulsesrc->read_buffer) {
1112       for (;;) {
1113         if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
1114           goto unlock_and_fail;
1115 
1116         /* read all available data, we keep a pointer to the data and the length
1117          * and take from it what we need. */
1118         if (pa_stream_peek (pulsesrc->stream, &pulsesrc->read_buffer,
1119                 &pulsesrc->read_buffer_length) < 0)
1120           goto peek_failed;
1121 
1122         GST_LOG_OBJECT (pulsesrc, "have data of %" G_GSIZE_FORMAT " bytes",
1123             pulsesrc->read_buffer_length);
1124 
1125         /* if we have data, process if */
1126         if (pulsesrc->read_buffer && pulsesrc->read_buffer_length)
1127           break;
1128 
1129         /* now wait for more data to become available */
1130         GST_LOG_OBJECT (pulsesrc, "waiting for data");
1131         pa_threaded_mainloop_wait (pulsesrc->mainloop);
1132 
1133         if (pulsesrc->paused)
1134           goto was_paused;
1135       }
1136     }
1137 
1138     l = pulsesrc->read_buffer_length >
1139         length ? length : pulsesrc->read_buffer_length;
1140 
1141     memcpy (data, pulsesrc->read_buffer, l);
1142 
1143     pulsesrc->read_buffer = (const guint8 *) pulsesrc->read_buffer + l;
1144     pulsesrc->read_buffer_length -= l;
1145 
1146     data = (guint8 *) data + l;
1147     length -= l;
1148     sum += l;
1149 
1150     if (pulsesrc->read_buffer_length <= 0) {
1151       /* we copied all of the data, drop it now */
1152       if (pa_stream_drop (pulsesrc->stream) < 0)
1153         goto drop_failed;
1154 
1155       /* reset pointer to data */
1156       pulsesrc->read_buffer = NULL;
1157       pulsesrc->read_buffer_length = 0;
1158     }
1159   }
1160 
1161   pulsesrc->in_read = FALSE;
1162   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1163 
1164   return sum;
1165 
1166   /* ERRORS */
1167 not_connected:
1168   {
1169     GST_LOG_OBJECT (pulsesrc, "we are not connected");
1170     goto unlock_and_fail;
1171   }
1172 was_paused:
1173   {
1174     GST_LOG_OBJECT (pulsesrc, "we are paused");
1175     goto unlock_and_fail;
1176   }
1177 peek_failed:
1178   {
1179     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1180         ("pa_stream_peek() failed: %s",
1181             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1182     goto unlock_and_fail;
1183   }
1184 drop_failed:
1185   {
1186     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1187         ("pa_stream_drop() failed: %s",
1188             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1189     goto unlock_and_fail;
1190   }
1191 unlock_and_fail:
1192   {
1193     pulsesrc->in_read = FALSE;
1194     pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1195 
1196     return (guint) - 1;
1197   }
1198 }
1199 
1200 /* return the delay in samples */
1201 static guint
gst_pulsesrc_delay(GstAudioSrc * asrc)1202 gst_pulsesrc_delay (GstAudioSrc * asrc)
1203 {
1204   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1205   pa_usec_t t;
1206   int negative, res;
1207   guint result;
1208 
1209   pa_threaded_mainloop_lock (pulsesrc->mainloop);
1210   if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
1211     goto server_dead;
1212 
1213   /* get the latency, this can fail when we don't have a latency update yet.
1214    * We don't want to wait for latency updates here but we just return 0. */
1215   res = pa_stream_get_latency (pulsesrc->stream, &t, &negative);
1216 
1217   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1218 
1219   if (res < 0) {
1220     GST_DEBUG_OBJECT (pulsesrc, "could not get latency");
1221     result = 0;
1222   } else {
1223     if (negative)
1224       result = 0;
1225     else
1226       result = (guint) ((t * pulsesrc->sample_spec.rate) / 1000000LL);
1227   }
1228   return result;
1229 
1230   /* ERRORS */
1231 server_dead:
1232   {
1233     GST_DEBUG_OBJECT (pulsesrc, "the server is dead");
1234     pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1235     return 0;
1236   }
1237 }
1238 
1239 static gboolean
gst_pulsesrc_create_stream(GstPulseSrc * pulsesrc,GstCaps ** caps,GstAudioRingBufferSpec * rspec)1240 gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps,
1241     GstAudioRingBufferSpec * rspec)
1242 {
1243   pa_channel_map channel_map;
1244   const pa_channel_map *m;
1245   GstStructure *s;
1246   gboolean need_channel_layout = FALSE;
1247   GstAudioRingBufferSpec new_spec, *spec = NULL;
1248   const gchar *name;
1249   int i;
1250 
1251   /* If we already have a stream (renegotiation), free it first */
1252   if (pulsesrc->stream)
1253     gst_pulsesrc_destroy_stream (pulsesrc);
1254 
1255   if (rspec) {
1256     /* Post-negotiation, we already have a ringbuffer spec, so we just need to
1257      * use it to create a stream. */
1258     spec = rspec;
1259 
1260     /* At this point, we expect the channel-mask to be set in caps, so we just
1261      * use that */
1262     if (!gst_pulse_gst_to_channel_map (&channel_map, spec))
1263       goto invalid_spec;
1264 
1265   } else if (caps) {
1266     /* At negotiation time, we get a fixed caps and use it to set up a stream */
1267     s = gst_caps_get_structure (*caps, 0);
1268     gst_structure_get_int (s, "channels", &new_spec.info.channels);
1269     if (!gst_structure_has_field (s, "channel-mask")) {
1270       if (new_spec.info.channels == 1) {
1271         pa_channel_map_init_mono (&channel_map);
1272       } else if (new_spec.info.channels == 2) {
1273         pa_channel_map_init_stereo (&channel_map);
1274       } else {
1275         need_channel_layout = TRUE;
1276         gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
1277             G_GUINT64_CONSTANT (0), NULL);
1278       }
1279     }
1280 
1281     memset (&new_spec, 0, sizeof (GstAudioRingBufferSpec));
1282     new_spec.latency_time = GST_SECOND;
1283     if (!gst_audio_ring_buffer_parse_caps (&new_spec, *caps))
1284       goto invalid_caps;
1285 
1286     /* Keep the refcount of the caps at 1 to make them writable */
1287     gst_caps_unref (new_spec.caps);
1288 
1289     if (!need_channel_layout
1290         && !gst_pulse_gst_to_channel_map (&channel_map, &new_spec)) {
1291       need_channel_layout = TRUE;
1292       gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
1293           G_GUINT64_CONSTANT (0), NULL);
1294       for (i = 0; i < G_N_ELEMENTS (new_spec.info.position); i++)
1295         new_spec.info.position[i] = GST_AUDIO_CHANNEL_POSITION_INVALID;
1296     }
1297 
1298     spec = &new_spec;
1299   } else {
1300     /* !rspec && !caps */
1301     g_assert_not_reached ();
1302   }
1303 
1304   if (!gst_pulse_fill_sample_spec (spec, &pulsesrc->sample_spec))
1305     goto invalid_spec;
1306 
1307   pa_threaded_mainloop_lock (pulsesrc->mainloop);
1308 
1309   if (!pulsesrc->context)
1310     goto bad_context;
1311 
1312   name = "Record Stream";
1313   if (pulsesrc->proplist) {
1314     if (!(pulsesrc->stream = pa_stream_new_with_proplist (pulsesrc->context,
1315                 name, &pulsesrc->sample_spec,
1316                 (need_channel_layout) ? NULL : &channel_map,
1317                 pulsesrc->proplist)))
1318       goto create_failed;
1319 
1320   } else if (!(pulsesrc->stream = pa_stream_new (pulsesrc->context,
1321               name, &pulsesrc->sample_spec,
1322               (need_channel_layout) ? NULL : &channel_map)))
1323     goto create_failed;
1324 
1325   if (caps) {
1326     m = pa_stream_get_channel_map (pulsesrc->stream);
1327     gst_pulse_channel_map_to_gst (m, &new_spec);
1328     gst_audio_channel_positions_to_valid_order (new_spec.info.position,
1329         new_spec.info.channels);
1330     gst_caps_unref (*caps);
1331     *caps = gst_audio_info_to_caps (&new_spec.info);
1332 
1333     GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, *caps);
1334   }
1335 
1336 
1337   pa_stream_set_state_callback (pulsesrc->stream, gst_pulsesrc_stream_state_cb,
1338       pulsesrc);
1339   pa_stream_set_read_callback (pulsesrc->stream, gst_pulsesrc_stream_request_cb,
1340       pulsesrc);
1341   pa_stream_set_underflow_callback (pulsesrc->stream,
1342       gst_pulsesrc_stream_underflow_cb, pulsesrc);
1343   pa_stream_set_overflow_callback (pulsesrc->stream,
1344       gst_pulsesrc_stream_overflow_cb, pulsesrc);
1345   pa_stream_set_latency_update_callback (pulsesrc->stream,
1346       gst_pulsesrc_stream_latency_update_cb, pulsesrc);
1347 
1348   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1349 
1350   return TRUE;
1351 
1352   /* ERRORS */
1353 invalid_caps:
1354   {
1355     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, SETTINGS,
1356         ("Can't parse caps."), (NULL));
1357     goto fail;
1358   }
1359 invalid_spec:
1360   {
1361     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, SETTINGS,
1362         ("Invalid sample specification."), (NULL));
1363     goto fail;
1364   }
1365 bad_context:
1366   {
1367     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Bad context"), (NULL));
1368     goto unlock_and_fail;
1369   }
1370 create_failed:
1371   {
1372     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1373         ("Failed to create stream: %s",
1374             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1375     goto unlock_and_fail;
1376   }
1377 unlock_and_fail:
1378   {
1379     gst_pulsesrc_destroy_stream (pulsesrc);
1380 
1381     pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1382 
1383   fail:
1384     return FALSE;
1385   }
1386 }
1387 
1388 static gboolean
gst_pulsesrc_event(GstBaseSrc * basesrc,GstEvent * event)1389 gst_pulsesrc_event (GstBaseSrc * basesrc, GstEvent * event)
1390 {
1391   GST_DEBUG_OBJECT (basesrc, "handle event %" GST_PTR_FORMAT, event);
1392 
1393   switch (GST_EVENT_TYPE (event)) {
1394     case GST_EVENT_RECONFIGURE:
1395       gst_pad_check_reconfigure (GST_BASE_SRC_PAD (basesrc));
1396       break;
1397     default:
1398       break;
1399   }
1400   return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
1401 }
1402 
1403 /* This is essentially gst_base_src_negotiate_default() but the caps
1404  * are guaranteed to have a channel layout for > 2 channels
1405  */
1406 static gboolean
gst_pulsesrc_negotiate(GstBaseSrc * basesrc)1407 gst_pulsesrc_negotiate (GstBaseSrc * basesrc)
1408 {
1409   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (basesrc);
1410   GstCaps *thiscaps;
1411   GstCaps *caps = NULL;
1412   GstCaps *peercaps = NULL;
1413   gboolean result = FALSE;
1414 
1415   /* first see what is possible on our source pad */
1416   thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
1417   GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps);
1418   /* nothing or anything is allowed, we're done */
1419   if (thiscaps == NULL || gst_caps_is_any (thiscaps))
1420     goto no_nego_needed;
1421 
1422   /* get the peer caps */
1423   peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), NULL);
1424   GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps);
1425   if (peercaps) {
1426     /* get intersection */
1427     caps = gst_caps_intersect (thiscaps, peercaps);
1428     GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, caps);
1429     gst_caps_unref (thiscaps);
1430     gst_caps_unref (peercaps);
1431   } else {
1432     /* no peer, work with our own caps then */
1433     caps = thiscaps;
1434   }
1435   if (caps) {
1436     /* take first (and best, since they are sorted) possibility */
1437     caps = gst_caps_truncate (caps);
1438 
1439     /* now fixate */
1440     if (!gst_caps_is_empty (caps)) {
1441       caps = GST_BASE_SRC_CLASS (parent_class)->fixate (basesrc, caps);
1442       GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
1443 
1444       if (gst_caps_is_any (caps)) {
1445         /* hmm, still anything, so element can do anything and
1446          * nego is not needed */
1447         result = TRUE;
1448       } else if (gst_caps_is_fixed (caps)) {
1449         /* yay, fixed caps, use those then */
1450         result = gst_pulsesrc_create_stream (pulsesrc, &caps, NULL);
1451         if (result)
1452           result = gst_base_src_set_caps (basesrc, caps);
1453       }
1454     }
1455     gst_caps_unref (caps);
1456   }
1457   return result;
1458 
1459 no_nego_needed:
1460   {
1461     GST_DEBUG_OBJECT (basesrc, "no negotiation needed");
1462     if (thiscaps)
1463       gst_caps_unref (thiscaps);
1464     return TRUE;
1465   }
1466 }
1467 
1468 static gboolean
gst_pulsesrc_prepare(GstAudioSrc * asrc,GstAudioRingBufferSpec * spec)1469 gst_pulsesrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
1470 {
1471   pa_buffer_attr wanted;
1472   const pa_buffer_attr *actual;
1473   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1474   pa_stream_flags_t flags;
1475   pa_operation *o;
1476   GstAudioClock *clock;
1477 
1478   pa_threaded_mainloop_lock (pulsesrc->mainloop);
1479 
1480   if (!pulsesrc->stream)
1481     gst_pulsesrc_create_stream (pulsesrc, NULL, spec);
1482 
1483   {
1484     GstAudioRingBufferSpec s = *spec;
1485     const pa_channel_map *m;
1486 
1487     m = pa_stream_get_channel_map (pulsesrc->stream);
1488     gst_pulse_channel_map_to_gst (m, &s);
1489     gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
1490         (pulsesrc)->ringbuffer, s.info.position);
1491   }
1492 
1493   /* enable event notifications */
1494   GST_LOG_OBJECT (pulsesrc, "subscribing to context events");
1495   if (!(o = pa_context_subscribe (pulsesrc->context,
1496               PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, NULL, NULL))) {
1497     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1498         ("pa_context_subscribe() failed: %s",
1499             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1500     goto unlock_and_fail;
1501   }
1502 
1503   pa_operation_unref (o);
1504 
1505   /* There's a bit of a disconnect here between the audio ringbuffer and what
1506    * PulseAudio provides. The audio ringbuffer provide a total of buffer_time
1507    * worth of buffering, divided into segments of latency_time size. We're
1508    * asking PulseAudio to provide a total latency of latency_time, which, with
1509    * PA_STREAM_ADJUST_LATENCY, effectively sets itself up as a ringbuffer with
1510    * one segment being the hardware buffer, and the other the software buffer.
1511    * This segment size is returned as the fragsize.
1512    *
1513    * Since the two concepts don't map very well, what we do is keep segsize as
1514    * it is (unless fragsize is even larger, in which case we use that). We'll
1515    * get data from PulseAudio in smaller chunks than we want to pass on as an
1516    * element, and we coalesce those chunks in the ringbuffer memory and pass it
1517    * on in the expected chunk size. */
1518   wanted.maxlength = spec->segsize * spec->segtotal;
1519   wanted.tlength = -1;
1520   wanted.prebuf = 0;
1521   wanted.minreq = -1;
1522   wanted.fragsize = spec->segsize;
1523 
1524   GST_INFO_OBJECT (pulsesrc, "maxlength: %d", wanted.maxlength);
1525   GST_INFO_OBJECT (pulsesrc, "tlength:   %d", wanted.tlength);
1526   GST_INFO_OBJECT (pulsesrc, "prebuf:    %d", wanted.prebuf);
1527   GST_INFO_OBJECT (pulsesrc, "minreq:    %d", wanted.minreq);
1528   GST_INFO_OBJECT (pulsesrc, "fragsize:  %d", wanted.fragsize);
1529 
1530   flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE |
1531       PA_STREAM_NOT_MONOTONIC | PA_STREAM_ADJUST_LATENCY |
1532       PA_STREAM_START_CORKED;
1533 
1534   if (pa_stream_connect_record (pulsesrc->stream, pulsesrc->device, &wanted,
1535           flags) < 0) {
1536     goto connect_failed;
1537   }
1538 
1539   /* our clock will now start from 0 again */
1540   clock = GST_AUDIO_CLOCK (GST_AUDIO_BASE_SRC (pulsesrc)->clock);
1541   gst_audio_clock_reset (clock, 0);
1542 
1543   pulsesrc->corked = TRUE;
1544 
1545   for (;;) {
1546     pa_stream_state_t state;
1547 
1548     state = pa_stream_get_state (pulsesrc->stream);
1549 
1550     if (!PA_STREAM_IS_GOOD (state))
1551       goto stream_is_bad;
1552 
1553     if (state == PA_STREAM_READY)
1554       break;
1555 
1556     /* Wait until the stream is ready */
1557     pa_threaded_mainloop_wait (pulsesrc->mainloop);
1558   }
1559   pulsesrc->stream_connected = TRUE;
1560 
1561   /* store the source output index so it can be accessed via a property */
1562   pulsesrc->source_output_idx = pa_stream_get_index (pulsesrc->stream);
1563   g_object_notify (G_OBJECT (pulsesrc), "source-output-index");
1564 
1565   /* Although source output stream muting is supported, there is a bug in
1566    * PulseAudio that doesn't allow us to do this at startup, so we mute
1567    * manually post-connect. This should be moved back pre-connect once things
1568    * are fixed on the PulseAudio side. */
1569   if (pulsesrc->mute_set && pulsesrc->mute) {
1570     gst_pulsesrc_set_stream_mute (pulsesrc, pulsesrc->mute);
1571     pulsesrc->mute_set = FALSE;
1572   }
1573 
1574   if (pulsesrc->volume_set) {
1575     gst_pulsesrc_set_stream_volume (pulsesrc, pulsesrc->volume);
1576     pulsesrc->volume_set = FALSE;
1577   }
1578 
1579   /* get the actual buffering properties now */
1580   actual = pa_stream_get_buffer_attr (pulsesrc->stream);
1581 
1582   GST_INFO_OBJECT (pulsesrc, "maxlength: %d", actual->maxlength);
1583   GST_INFO_OBJECT (pulsesrc, "tlength:   %d (wanted: %d)",
1584       actual->tlength, wanted.tlength);
1585   GST_INFO_OBJECT (pulsesrc, "prebuf:    %d", actual->prebuf);
1586   GST_INFO_OBJECT (pulsesrc, "minreq:    %d (wanted %d)", actual->minreq,
1587       wanted.minreq);
1588   GST_INFO_OBJECT (pulsesrc, "fragsize:  %d (wanted %d)",
1589       actual->fragsize, wanted.fragsize);
1590 
1591   if (actual->fragsize >= spec->segsize) {
1592     spec->segsize = actual->fragsize;
1593   } else {
1594     /* fragsize is smaller than what we wanted, so let the read function
1595      * coalesce the smaller chunks as they come in */
1596   }
1597 
1598   /* Fix up the total ringbuffer size based on what we actually got */
1599   spec->segtotal = actual->maxlength / spec->segsize;
1600   /* Don't buffer less than 2 segments as the ringbuffer can't deal with it */
1601   if (spec->segtotal < 2)
1602     spec->segtotal = 2;
1603 
1604   if (!pulsesrc->paused) {
1605     GST_DEBUG_OBJECT (pulsesrc, "uncorking because we are playing");
1606     gst_pulsesrc_set_corked (pulsesrc, FALSE, FALSE);
1607   }
1608   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1609 
1610   return TRUE;
1611 
1612   /* ERRORS */
1613 connect_failed:
1614   {
1615     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1616         ("Failed to connect stream: %s",
1617             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1618     goto unlock_and_fail;
1619   }
1620 stream_is_bad:
1621   {
1622     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1623         ("Failed to connect stream: %s",
1624             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1625     goto unlock_and_fail;
1626   }
1627 unlock_and_fail:
1628   {
1629     gst_pulsesrc_destroy_stream (pulsesrc);
1630 
1631     pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1632     return FALSE;
1633   }
1634 }
1635 
1636 static void
gst_pulsesrc_success_cb(pa_stream * s,int success,void * userdata)1637 gst_pulsesrc_success_cb (pa_stream * s, int success, void *userdata)
1638 {
1639   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (userdata);
1640 
1641   pulsesrc->operation_success = ! !success;
1642   pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
1643 }
1644 
1645 static void
gst_pulsesrc_reset(GstAudioSrc * asrc)1646 gst_pulsesrc_reset (GstAudioSrc * asrc)
1647 {
1648   GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
1649   pa_operation *o = NULL;
1650 
1651   pa_threaded_mainloop_lock (pulsesrc->mainloop);
1652   GST_DEBUG_OBJECT (pulsesrc, "reset");
1653 
1654   if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
1655     goto unlock_and_fail;
1656 
1657   if (!(o =
1658           pa_stream_flush (pulsesrc->stream, gst_pulsesrc_success_cb,
1659               pulsesrc))) {
1660     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
1661         ("pa_stream_flush() failed: %s",
1662             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1663     goto unlock_and_fail;
1664   }
1665 
1666   pulsesrc->paused = TRUE;
1667   /* Inform anyone waiting in _write() call that it shall wakeup */
1668   if (pulsesrc->in_read) {
1669     pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
1670   }
1671 
1672   pulsesrc->operation_success = FALSE;
1673   while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
1674 
1675     if (gst_pulsesrc_is_dead (pulsesrc, TRUE))
1676       goto unlock_and_fail;
1677 
1678     pa_threaded_mainloop_wait (pulsesrc->mainloop);
1679   }
1680 
1681   if (!pulsesrc->operation_success) {
1682     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Flush failed: %s",
1683             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
1684     goto unlock_and_fail;
1685   }
1686 
1687 unlock_and_fail:
1688 
1689   if (o) {
1690     pa_operation_cancel (o);
1691     pa_operation_unref (o);
1692   }
1693 
1694   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
1695 }
1696 
1697 /* update the corked state of a stream, must be called with the mainloop
1698  * lock */
1699 static gboolean
gst_pulsesrc_set_corked(GstPulseSrc * psrc,gboolean corked,gboolean wait)1700 gst_pulsesrc_set_corked (GstPulseSrc * psrc, gboolean corked, gboolean wait)
1701 {
1702   pa_operation *o = NULL;
1703   gboolean res = FALSE;
1704 
1705   GST_DEBUG_OBJECT (psrc, "setting corked state to %d", corked);
1706   if (!psrc->stream_connected)
1707     return TRUE;
1708 
1709   if (psrc->corked != corked) {
1710     if (!(o = pa_stream_cork (psrc->stream, corked,
1711                 gst_pulsesrc_success_cb, psrc)))
1712       goto cork_failed;
1713 
1714     while (wait && pa_operation_get_state (o) == PA_OPERATION_RUNNING) {
1715       pa_threaded_mainloop_wait (psrc->mainloop);
1716       if (gst_pulsesrc_is_dead (psrc, TRUE))
1717         goto server_dead;
1718     }
1719     psrc->corked = corked;
1720   } else {
1721     GST_DEBUG_OBJECT (psrc, "skipping, already in requested state");
1722   }
1723   res = TRUE;
1724 
1725 cleanup:
1726   if (o)
1727     pa_operation_unref (o);
1728 
1729   return res;
1730 
1731   /* ERRORS */
1732 server_dead:
1733   {
1734     GST_DEBUG_OBJECT (psrc, "the server is dead");
1735     goto cleanup;
1736   }
1737 cork_failed:
1738   {
1739     GST_ELEMENT_ERROR (psrc, RESOURCE, FAILED,
1740         ("pa_stream_cork() failed: %s",
1741             pa_strerror (pa_context_errno (psrc->context))), (NULL));
1742     goto cleanup;
1743   }
1744 }
1745 
1746 /* start/resume playback ASAP */
1747 static gboolean
gst_pulsesrc_play(GstPulseSrc * psrc)1748 gst_pulsesrc_play (GstPulseSrc * psrc)
1749 {
1750   pa_threaded_mainloop_lock (psrc->mainloop);
1751   GST_DEBUG_OBJECT (psrc, "playing");
1752   psrc->paused = FALSE;
1753   gst_pulsesrc_set_corked (psrc, FALSE, FALSE);
1754   pa_threaded_mainloop_unlock (psrc->mainloop);
1755 
1756   return TRUE;
1757 }
1758 
1759 /* pause/stop playback ASAP */
1760 static gboolean
gst_pulsesrc_pause(GstPulseSrc * psrc)1761 gst_pulsesrc_pause (GstPulseSrc * psrc)
1762 {
1763   pa_threaded_mainloop_lock (psrc->mainloop);
1764   GST_DEBUG_OBJECT (psrc, "pausing");
1765   /* make sure the commit method stops writing */
1766   psrc->paused = TRUE;
1767   if (psrc->in_read) {
1768     /* we are waiting in a read, signal */
1769     GST_DEBUG_OBJECT (psrc, "signal read");
1770     pa_threaded_mainloop_signal (psrc->mainloop, 0);
1771   }
1772   pa_threaded_mainloop_unlock (psrc->mainloop);
1773 
1774   return TRUE;
1775 }
1776 
1777 static GstStateChangeReturn
gst_pulsesrc_change_state(GstElement * element,GstStateChange transition)1778 gst_pulsesrc_change_state (GstElement * element, GstStateChange transition)
1779 {
1780   GstStateChangeReturn ret;
1781   GstPulseSrc *this = GST_PULSESRC_CAST (element);
1782 
1783   switch (transition) {
1784     case GST_STATE_CHANGE_NULL_TO_READY:
1785       if (!(this->mainloop = pa_threaded_mainloop_new ()))
1786         goto mainloop_failed;
1787       if (pa_threaded_mainloop_start (this->mainloop) < 0) {
1788         pa_threaded_mainloop_free (this->mainloop);
1789         this->mainloop = NULL;
1790         goto mainloop_start_failed;
1791       }
1792       break;
1793     case GST_STATE_CHANGE_READY_TO_PAUSED:
1794       gst_element_post_message (element,
1795           gst_message_new_clock_provide (GST_OBJECT_CAST (element),
1796               GST_AUDIO_BASE_SRC (this)->clock, TRUE));
1797       break;
1798     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1799       /* uncork and start recording */
1800       gst_pulsesrc_play (this);
1801       break;
1802     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1803       /* stop recording ASAP by corking */
1804       pa_threaded_mainloop_lock (this->mainloop);
1805       GST_DEBUG_OBJECT (this, "corking");
1806       gst_pulsesrc_set_corked (this, TRUE, FALSE);
1807       pa_threaded_mainloop_unlock (this->mainloop);
1808       break;
1809     default:
1810       break;
1811   }
1812 
1813   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1814 
1815   switch (transition) {
1816     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1817       /* now make sure we get out of the _read method */
1818       gst_pulsesrc_pause (this);
1819       break;
1820     case GST_STATE_CHANGE_READY_TO_NULL:
1821       if (this->mainloop)
1822         pa_threaded_mainloop_stop (this->mainloop);
1823 
1824       gst_pulsesrc_destroy_context (this);
1825 
1826       if (this->mainloop) {
1827         pa_threaded_mainloop_free (this->mainloop);
1828         this->mainloop = NULL;
1829       }
1830       break;
1831     case GST_STATE_CHANGE_PAUSED_TO_READY:
1832       /* format_lost is reset in release() in baseaudiosink */
1833       gst_element_post_message (element,
1834           gst_message_new_clock_lost (GST_OBJECT_CAST (element),
1835               GST_AUDIO_BASE_SRC (this)->clock));
1836       break;
1837     default:
1838       break;
1839   }
1840 
1841   return ret;
1842 
1843   /* ERRORS */
1844 mainloop_failed:
1845   {
1846     GST_ELEMENT_ERROR (this, RESOURCE, FAILED,
1847         ("pa_threaded_mainloop_new() failed"), (NULL));
1848     return GST_STATE_CHANGE_FAILURE;
1849   }
1850 mainloop_start_failed:
1851   {
1852     GST_ELEMENT_ERROR (this, RESOURCE, FAILED,
1853         ("pa_threaded_mainloop_start() failed"), (NULL));
1854     return GST_STATE_CHANGE_FAILURE;
1855   }
1856 }
1857 
1858 static GstClockTime
gst_pulsesrc_get_time(GstClock * clock,GstPulseSrc * src)1859 gst_pulsesrc_get_time (GstClock * clock, GstPulseSrc * src)
1860 {
1861   pa_usec_t time = 0;
1862 
1863   if (src->mainloop == NULL)
1864     goto out;
1865 
1866   pa_threaded_mainloop_lock (src->mainloop);
1867   if (!src->stream)
1868     goto unlock_and_out;
1869 
1870   if (gst_pulsesrc_is_dead (src, TRUE))
1871     goto unlock_and_out;
1872 
1873   if (pa_stream_get_time (src->stream, &time) < 0) {
1874     GST_DEBUG_OBJECT (src, "could not get time");
1875     time = GST_CLOCK_TIME_NONE;
1876   } else {
1877     time *= 1000;
1878   }
1879 
1880 
1881 unlock_and_out:
1882   pa_threaded_mainloop_unlock (src->mainloop);
1883 
1884 out:
1885   return time;
1886 }
1887