Add documentation to the pulseaudio plugin and run make update in docs/plugins.
[platform/upstream/gstreamer.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  *  USA.
20  */
21
22 /**
23  * SECTION:element-pulsesrc
24  * @short_description: Capture audio from a PulseAudio sound server
25  * @see_also: pulsesink, pulsemixer
26  *
27  * <refsect2>
28  * <para>
29  * This element captures audio from a PulseAudio sound server.
30  * </para>
31  * <title>Example pipelines</title>
32  * <para>
33  * <programlisting>
34  * gst-launch -v pulsesrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
35  * </programlisting>
36  * Record from a sound card using ALSA and encode to Ogg/Vorbis.
37  * </para>
38  * </refsect2>
39  */
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 #include <string.h>
46 #include <stdio.h>
47
48 #include <gst/base/gstbasesrc.h>
49 #include <gst/gsttaglist.h>
50
51 #include "pulsesrc.h"
52 #include "pulseutil.h"
53 #include "pulsemixerctrl.h"
54
55 GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
56 #define GST_CAT_DEFAULT pulse_debug
57
58 enum
59 {
60   PROP_SERVER = 1,
61   PROP_DEVICE
62 };
63
64 static GstAudioSrcClass *parent_class = NULL;
65
66 GST_IMPLEMENT_PULSEMIXER_CTRL_METHODS (GstPulseSrc, gst_pulsesrc)
67
68      static void gst_pulsesrc_destroy_stream (GstPulseSrc * pulsesrc);
69
70      static void gst_pulsesrc_destroy_context (GstPulseSrc * pulsesrc);
71
72      static void gst_pulsesrc_set_property (GObject * object, guint prop_id,
73     const GValue * value, GParamSpec * pspec);
74      static void gst_pulsesrc_get_property (GObject * object, guint prop_id,
75     GValue * value, GParamSpec * pspec);
76      static void gst_pulsesrc_finalize (GObject * object);
77
78      static void gst_pulsesrc_dispose (GObject * object);
79
80      static gboolean gst_pulsesrc_open (GstAudioSrc * asrc);
81
82      static gboolean gst_pulsesrc_close (GstAudioSrc * asrc);
83
84      static gboolean gst_pulsesrc_prepare (GstAudioSrc * asrc,
85     GstRingBufferSpec * spec);
86      static gboolean gst_pulsesrc_unprepare (GstAudioSrc * asrc);
87
88      static guint gst_pulsesrc_read (GstAudioSrc * asrc, gpointer data,
89     guint length);
90      static guint gst_pulsesrc_delay (GstAudioSrc * asrc);
91
92      static GstStateChangeReturn gst_pulsesrc_change_state (GstElement *
93     element, GstStateChange transition);
94
95 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
96 # define ENDIANNESS   "LITTLE_ENDIAN, BIG_ENDIAN"
97 #else
98 # define ENDIANNESS   "BIG_ENDIAN, LITTLE_ENDIAN"
99 #endif
100
101      static gboolean gst_pulsesrc_interface_supported (GstImplementsInterface *
102     iface, GType interface_type)
103 {
104   GstPulseSrc *this = GST_PULSESRC (iface);
105
106   if (interface_type == GST_TYPE_MIXER && this->mixer)
107     return TRUE;
108
109   return FALSE;
110 }
111
112 static void
113 gst_pulsesrc_implements_interface_init (GstImplementsInterfaceClass * klass)
114 {
115   klass->supported = gst_pulsesrc_interface_supported;
116 }
117
118 static void
119 gst_pulsesrc_init_interfaces (GType type)
120 {
121   static const GInterfaceInfo implements_iface_info = {
122     (GInterfaceInitFunc) gst_pulsesrc_implements_interface_init,
123     NULL,
124     NULL,
125   };
126   static const GInterfaceInfo mixer_iface_info = {
127     (GInterfaceInitFunc) gst_pulsesrc_mixer_interface_init,
128     NULL,
129     NULL,
130   };
131
132   g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
133       &implements_iface_info);
134   g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
135 }
136
137 static void
138 gst_pulsesrc_base_init (gpointer g_class)
139 {
140
141   static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("src",
142       GST_PAD_SRC,
143       GST_PAD_ALWAYS,
144       GST_STATIC_CAPS ("audio/x-raw-int, "
145           "endianness = (int) { " ENDIANNESS " }, "
146           "signed = (boolean) TRUE, "
147           "width = (int) 16, "
148           "depth = (int) 16, "
149           "rate = (int) [ 1, MAX ], "
150           "channels = (int) [ 1, 16 ];"
151           "audio/x-raw-int, "
152           "endianness = (int) { " ENDIANNESS " }, "
153           "signed = (boolean) TRUE, "
154           "width = (int) 32, "
155           "depth = (int) 32, "
156           "rate = (int) [ 1, MAX ], "
157           "channels = (int) [ 1, 16 ];"
158           "audio/x-raw-float, "
159           "endianness = (int) { " ENDIANNESS " }, "
160           "width = (int) 32, "
161           "rate = (int) [ 1, MAX ], "
162           "channels = (int) [ 1, 16 ];"
163           "audio/x-raw-int, "
164           "signed = (boolean) FALSE, "
165           "width = (int) 8, "
166           "depth = (int) 8, "
167           "rate = (int) [ 1, MAX ], "
168           "channels = (int) [ 1, 16 ];"
169           "audio/x-alaw, "
170           "rate = (int) [ 1, MAX], "
171           "channels = (int) [ 1, 16 ];"
172           "audio/x-mulaw, "
173           "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 16 ]")
174       );
175
176   static const GstElementDetails details =
177       GST_ELEMENT_DETAILS ("PulseAudio Audio Source",
178       "Source/Audio",
179       "Captures audio from a PulseAudio server",
180       "Lennart Poettering");
181
182   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
183
184   gst_element_class_set_details (element_class, &details);
185   gst_element_class_add_pad_template (element_class,
186       gst_static_pad_template_get (&pad_template));
187 }
188
189 static void
190 gst_pulsesrc_class_init (gpointer g_class, gpointer class_data)
191 {
192
193   GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
194
195   GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS (g_class);
196
197   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
198
199   parent_class = g_type_class_peek_parent (g_class);
200
201   gstelement_class->change_state =
202       GST_DEBUG_FUNCPTR (gst_pulsesrc_change_state);
203
204   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pulsesrc_dispose);
205   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_pulsesrc_finalize);
206   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pulsesrc_set_property);
207   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pulsesrc_get_property);
208
209   gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_pulsesrc_open);
210   gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_pulsesrc_close);
211   gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_prepare);
212   gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_unprepare);
213   gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_pulsesrc_read);
214   gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_pulsesrc_delay);
215
216   /* Overwrite GObject fields */
217   g_object_class_install_property (gobject_class,
218       PROP_SERVER,
219       g_param_spec_string ("server", "Server",
220           "The PulseAudio server to connect to", NULL, G_PARAM_READWRITE));
221   g_object_class_install_property (gobject_class, PROP_DEVICE,
222       g_param_spec_string ("device", "Source",
223           "The PulseAudio source device to connect to", NULL,
224           G_PARAM_READWRITE));
225 }
226
227 static void
228 gst_pulsesrc_init (GTypeInstance * instance, gpointer g_class)
229 {
230
231   GstPulseSrc *pulsesrc = GST_PULSESRC (instance);
232
233   int e;
234
235   pulsesrc->server = pulsesrc->device = NULL;
236
237   pulsesrc->context = NULL;
238   pulsesrc->stream = NULL;
239
240   pulsesrc->read_buffer = NULL;
241   pulsesrc->read_buffer_length = 0;
242
243   pulsesrc->mainloop = pa_threaded_mainloop_new ();
244   g_assert (pulsesrc->mainloop);
245
246   e = pa_threaded_mainloop_start (pulsesrc->mainloop);
247   g_assert (e == 0);
248
249   pulsesrc->mixer = NULL;
250 }
251
252 static void
253 gst_pulsesrc_destroy_stream (GstPulseSrc * pulsesrc)
254 {
255   if (pulsesrc->stream) {
256     pa_stream_disconnect (pulsesrc->stream);
257     pa_stream_unref (pulsesrc->stream);
258     pulsesrc->stream = NULL;
259   }
260 }
261
262 static void
263 gst_pulsesrc_destroy_context (GstPulseSrc * pulsesrc)
264 {
265
266   gst_pulsesrc_destroy_stream (pulsesrc);
267
268   if (pulsesrc->context) {
269     pa_context_disconnect (pulsesrc->context);
270     pa_context_unref (pulsesrc->context);
271     pulsesrc->context = NULL;
272   }
273 }
274
275 static void
276 gst_pulsesrc_finalize (GObject * object)
277 {
278   GstPulseSrc *pulsesrc = GST_PULSESRC (object);
279
280   pa_threaded_mainloop_stop (pulsesrc->mainloop);
281
282   gst_pulsesrc_destroy_context (pulsesrc);
283
284   g_free (pulsesrc->server);
285   g_free (pulsesrc->device);
286
287   pa_threaded_mainloop_free (pulsesrc->mainloop);
288
289   if (pulsesrc->mixer)
290     gst_pulsemixer_ctrl_free (pulsesrc->mixer);
291
292   G_OBJECT_CLASS (parent_class)->finalize (object);
293 }
294
295 static void
296 gst_pulsesrc_dispose (GObject * object)
297 {
298   G_OBJECT_CLASS (parent_class)->dispose (object);
299 }
300
301 static void
302 gst_pulsesrc_set_property (GObject * object,
303     guint prop_id, const GValue * value, GParamSpec * pspec)
304 {
305
306   GstPulseSrc *pulsesrc = GST_PULSESRC (object);
307
308   switch (prop_id) {
309     case PROP_SERVER:
310       g_free (pulsesrc->server);
311       pulsesrc->server = g_value_dup_string (value);
312       break;
313
314     case PROP_DEVICE:
315       g_free (pulsesrc->device);
316       pulsesrc->device = g_value_dup_string (value);
317       break;
318
319     default:
320       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
321       break;
322   }
323 }
324
325 static void
326 gst_pulsesrc_get_property (GObject * object,
327     guint prop_id, GValue * value, GParamSpec * pspec)
328 {
329
330   GstPulseSrc *pulsesrc = GST_PULSESRC (object);
331
332   switch (prop_id) {
333     case PROP_SERVER:
334       g_value_set_string (value, pulsesrc->server);
335       break;
336
337     case PROP_DEVICE:
338       g_value_set_string (value, pulsesrc->device);
339       break;
340
341     default:
342       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
343       break;
344   }
345 }
346
347 static void
348 gst_pulsesrc_context_state_cb (pa_context * c, void *userdata)
349 {
350   GstPulseSrc *pulsesrc = GST_PULSESRC (userdata);
351
352   switch (pa_context_get_state (c)) {
353     case PA_CONTEXT_READY:
354     case PA_CONTEXT_TERMINATED:
355     case PA_CONTEXT_FAILED:
356       pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
357       break;
358
359     case PA_CONTEXT_UNCONNECTED:
360     case PA_CONTEXT_CONNECTING:
361     case PA_CONTEXT_AUTHORIZING:
362     case PA_CONTEXT_SETTING_NAME:
363       break;
364   }
365 }
366
367 static void
368 gst_pulsesrc_stream_state_cb (pa_stream * s, void *userdata)
369 {
370   GstPulseSrc *pulsesrc = GST_PULSESRC (userdata);
371
372   switch (pa_stream_get_state (s)) {
373
374     case PA_STREAM_READY:
375     case PA_STREAM_FAILED:
376     case PA_STREAM_TERMINATED:
377       pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
378       break;
379
380     case PA_STREAM_UNCONNECTED:
381     case PA_STREAM_CREATING:
382       break;
383   }
384 }
385
386 static void
387 gst_pulsesrc_stream_request_cb (pa_stream * s, size_t length, void *userdata)
388 {
389   GstPulseSrc *pulsesrc = GST_PULSESRC (userdata);
390
391   pa_threaded_mainloop_signal (pulsesrc->mainloop, 0);
392 }
393
394 static gboolean
395 gst_pulsesrc_open (GstAudioSrc * asrc)
396 {
397   GstPulseSrc *pulsesrc = GST_PULSESRC (asrc);
398
399   gchar *name = gst_pulse_client_name ();
400
401   pa_threaded_mainloop_lock (pulsesrc->mainloop);
402
403   if (!(pulsesrc->context =
404           pa_context_new (pa_threaded_mainloop_get_api (pulsesrc->mainloop),
405               name))) {
406     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to create context"),
407         (NULL));
408     goto unlock_and_fail;
409   }
410
411   pa_context_set_state_callback (pulsesrc->context,
412       gst_pulsesrc_context_state_cb, pulsesrc);
413
414   if (pa_context_connect (pulsesrc->context, pulsesrc->server, 0, NULL) < 0) {
415     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
416             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
417     goto unlock_and_fail;
418   }
419
420   /* Wait until the context is ready */
421   pa_threaded_mainloop_wait (pulsesrc->mainloop);
422
423   if (pa_context_get_state (pulsesrc->context) != PA_CONTEXT_READY) {
424     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
425             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
426     goto unlock_and_fail;
427   }
428
429   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
430
431   g_free (name);
432   return TRUE;
433
434 unlock_and_fail:
435
436   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
437
438   g_free (name);
439   return FALSE;
440 }
441
442 static gboolean
443 gst_pulsesrc_close (GstAudioSrc * asrc)
444 {
445   GstPulseSrc *pulsesrc = GST_PULSESRC (asrc);
446
447   pa_threaded_mainloop_lock (pulsesrc->mainloop);
448   gst_pulsesrc_destroy_context (pulsesrc);
449   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
450
451   return TRUE;
452 }
453
454 static gboolean
455 gst_pulsesrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
456 {
457   pa_buffer_attr buf_attr;
458
459   pa_channel_map channel_map;
460
461   GstPulseSrc *pulsesrc = GST_PULSESRC (asrc);
462
463   if (!gst_pulse_fill_sample_spec (spec, &pulsesrc->sample_spec)) {
464     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, SETTINGS,
465         ("Invalid sample specification."), (NULL));
466     goto unlock_and_fail;
467   }
468
469   pa_threaded_mainloop_lock (pulsesrc->mainloop);
470
471   if (!pulsesrc->context
472       || pa_context_get_state (pulsesrc->context) != PA_CONTEXT_READY) {
473     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Bad context state: %s",
474             pulsesrc->
475             context ? pa_strerror (pa_context_errno (pulsesrc->context)) :
476             NULL), (NULL));
477     goto unlock_and_fail;
478   }
479
480   if (!(pulsesrc->stream = pa_stream_new (pulsesrc->context,
481               "Record Stream",
482               &pulsesrc->sample_spec,
483               gst_pulse_gst_to_channel_map (&channel_map, spec)))) {
484     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
485         ("Failed to create stream: %s",
486             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
487     goto unlock_and_fail;
488   }
489
490   pa_stream_set_state_callback (pulsesrc->stream, gst_pulsesrc_stream_state_cb,
491       pulsesrc);
492   pa_stream_set_read_callback (pulsesrc->stream, gst_pulsesrc_stream_request_cb,
493       pulsesrc);
494
495   memset (&buf_attr, 0, sizeof (buf_attr));
496   buf_attr.maxlength = spec->segtotal * spec->segsize * 2;
497   buf_attr.fragsize = spec->segsize;
498
499   if (pa_stream_connect_record (pulsesrc->stream, pulsesrc->device, &buf_attr,
500           PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE |
501           PA_STREAM_NOT_MONOTONOUS) < 0) {
502     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
503         ("Failed to connect stream: %s",
504             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
505     goto unlock_and_fail;
506   }
507
508   /* Wait until the stream is ready */
509   pa_threaded_mainloop_wait (pulsesrc->mainloop);
510
511   if (pa_stream_get_state (pulsesrc->stream) != PA_STREAM_READY) {
512     GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
513         ("Failed to connect stream: %s",
514             pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
515     goto unlock_and_fail;
516   }
517
518   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
519
520   spec->bytes_per_sample = pa_frame_size (&pulsesrc->sample_spec);
521   memset (spec->silence_sample, 0, spec->bytes_per_sample);
522
523   return TRUE;
524
525 unlock_and_fail:
526
527   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
528   return FALSE;
529 }
530
531 static gboolean
532 gst_pulsesrc_unprepare (GstAudioSrc * asrc)
533 {
534   GstPulseSrc *pulsesrc = GST_PULSESRC (asrc);
535
536   pa_threaded_mainloop_lock (pulsesrc->mainloop);
537   gst_pulsesrc_destroy_stream (pulsesrc);
538
539   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
540
541   pulsesrc->read_buffer = NULL;
542   pulsesrc->read_buffer_length = 0;
543
544   return TRUE;
545 }
546
547 #define CHECK_DEAD_GOTO(pulsesrc, label) \
548 if (!(pulsesrc)->context || pa_context_get_state((pulsesrc)->context) != PA_CONTEXT_READY || \
549     !(pulsesrc)->stream || pa_stream_get_state((pulsesrc)->stream) != PA_STREAM_READY) { \
550     GST_ELEMENT_ERROR((pulsesrc), RESOURCE, FAILED, ("Disconnected: %s", (pulsesrc)->context ? pa_strerror(pa_context_errno((pulsesrc)->context)) : NULL), (NULL)); \
551     goto label; \
552 }
553
554 static guint
555 gst_pulsesrc_read (GstAudioSrc * asrc, gpointer data, guint length)
556 {
557   GstPulseSrc *pulsesrc = GST_PULSESRC (asrc);
558
559   size_t sum = 0;
560
561   pa_threaded_mainloop_lock (pulsesrc->mainloop);
562
563   CHECK_DEAD_GOTO (pulsesrc, unlock_and_fail);
564
565   while (length > 0) {
566     size_t l;
567
568     if (!pulsesrc->read_buffer) {
569
570       for (;;) {
571         if (pa_stream_peek (pulsesrc->stream, &pulsesrc->read_buffer,
572                 &pulsesrc->read_buffer_length) < 0) {
573           GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
574               ("pa_stream_peek() failed: %s",
575                   pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
576           goto unlock_and_fail;
577         }
578
579         if (pulsesrc->read_buffer)
580           break;
581
582         pa_threaded_mainloop_wait (pulsesrc->mainloop);
583
584         CHECK_DEAD_GOTO (pulsesrc, unlock_and_fail);
585       }
586     }
587
588     g_assert (pulsesrc->read_buffer && pulsesrc->read_buffer_length);
589
590     l = pulsesrc->read_buffer_length >
591         length ? length : pulsesrc->read_buffer_length;
592
593     memcpy (data, pulsesrc->read_buffer, l);
594
595     pulsesrc->read_buffer = (const guint8 *) pulsesrc->read_buffer + l;
596     pulsesrc->read_buffer_length -= l;
597
598     data = (guint8 *) data + l;
599     length -= l;
600
601     sum += l;
602
603     if (pulsesrc->read_buffer_length <= 0) {
604
605       if (pa_stream_drop (pulsesrc->stream) < 0) {
606         GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
607             ("pa_stream_drop() failed: %s",
608                 pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
609         goto unlock_and_fail;
610       }
611
612       pulsesrc->read_buffer = NULL;
613       pulsesrc->read_buffer_length = 0;
614     }
615   }
616
617   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
618
619   return sum;
620
621 unlock_and_fail:
622   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
623   return 0;
624 }
625
626 static guint
627 gst_pulsesrc_delay (GstAudioSrc * asrc)
628 {
629   GstPulseSrc *pulsesrc = GST_PULSESRC (asrc);
630
631   pa_usec_t t;
632
633   int negative;
634
635   pa_threaded_mainloop_lock (pulsesrc->mainloop);
636
637   CHECK_DEAD_GOTO (pulsesrc, unlock_and_fail);
638
639   if (pa_stream_get_latency (pulsesrc->stream, &t, &negative) < 0) {
640
641     if (pa_context_errno (pulsesrc->context) != PA_ERR_NODATA) {
642       GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED,
643           ("pa_stream_get_latency() failed: %s",
644               pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
645       goto unlock_and_fail;
646     }
647
648     GST_WARNING ("Not data while querying latency");
649     t = 0;
650   } else if (negative)
651     t = 0;
652
653   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
654
655   return (guint) ((t * pulsesrc->sample_spec.rate) / 1000000LL);
656
657 unlock_and_fail:
658
659   pa_threaded_mainloop_unlock (pulsesrc->mainloop);
660   return 0;
661 }
662
663 static GstStateChangeReturn
664 gst_pulsesrc_change_state (GstElement * element, GstStateChange transition)
665 {
666   GstPulseSrc *this = GST_PULSESRC (element);
667
668   switch (transition) {
669     case GST_STATE_CHANGE_NULL_TO_READY:
670
671       if (!this->mixer)
672         this->mixer =
673             gst_pulsemixer_ctrl_new (this->server, this->device,
674             GST_PULSEMIXER_SOURCE);
675
676       break;
677
678     case GST_STATE_CHANGE_READY_TO_NULL:
679
680       if (this->mixer) {
681         gst_pulsemixer_ctrl_free (this->mixer);
682         this->mixer = NULL;
683       }
684
685       break;
686
687     default:
688       ;
689   }
690
691   if (GST_ELEMENT_CLASS (parent_class)->change_state)
692     return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
693
694   return GST_STATE_CHANGE_SUCCESS;
695 }
696
697 GType
698 gst_pulsesrc_get_type (void)
699 {
700   static GType pulsesrc_type = 0;
701
702   if (!pulsesrc_type) {
703
704     static const GTypeInfo pulsesrc_info = {
705       sizeof (GstPulseSrcClass),
706       gst_pulsesrc_base_init,
707       NULL,
708       gst_pulsesrc_class_init,
709       NULL,
710       NULL,
711       sizeof (GstPulseSrc),
712       0,
713       gst_pulsesrc_init,
714     };
715
716     pulsesrc_type = g_type_register_static (GST_TYPE_AUDIO_SRC,
717         "GstPulseSrc", &pulsesrc_info, 0);
718
719     gst_pulsesrc_init_interfaces (pulsesrc_type);
720   }
721
722   return pulsesrc_type;
723 }