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