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