static void gst_pulsesrc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (object); switch (prop_id) { case PROP_SERVER: g_free (pulsesrc->server); pulsesrc->server = g_value_dup_string (value); if (pulsesrc->probe) gst_pulseprobe_set_server (pulsesrc->probe, pulsesrc->server); break; case PROP_DEVICE: g_free (pulsesrc->device); pulsesrc->device = g_value_dup_string (value); break; case PROP_CLIENT_NAME: g_free (pulsesrc->client_name); if (!g_value_get_string (value)) { GST_WARNING_OBJECT (pulsesrc, "Empty PulseAudio client name not allowed. Resetting to default value"); pulsesrc->client_name = gst_pulse_client_name (); } else pulsesrc->client_name = g_value_dup_string (value); break; case PROP_STREAM_PROPERTIES: if (pulsesrc->properties) gst_structure_free (pulsesrc->properties); pulsesrc->properties = gst_structure_copy (gst_value_get_structure (value)); if (pulsesrc->proplist) pa_proplist_free (pulsesrc->proplist); pulsesrc->proplist = gst_pulse_make_proplist (pulsesrc->properties); break; case PROP_VOLUME: gst_pulsesrc_set_stream_volume (pulsesrc, g_value_get_double (value)); break; case PROP_MUTE: gst_pulsesrc_set_stream_mute (pulsesrc, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static void gst_pulsesrc_init (GstPulseSrc * pulsesrc) { pulsesrc->server = NULL; pulsesrc->device = NULL; pulsesrc->client_name = gst_pulse_client_name (); pulsesrc->device_description = NULL; pulsesrc->context = NULL; pulsesrc->stream = NULL; pulsesrc->stream_connected = FALSE; pulsesrc->source_output_idx = PA_INVALID_INDEX; pulsesrc->read_buffer = NULL; pulsesrc->read_buffer_length = 0; pa_sample_spec_init (&pulsesrc->sample_spec); pulsesrc->operation_success = FALSE; pulsesrc->paused = TRUE; pulsesrc->in_read = FALSE; pulsesrc->volume = DEFAULT_VOLUME; pulsesrc->volume_set = FALSE; pulsesrc->mute = DEFAULT_MUTE; pulsesrc->mute_set = FALSE; pulsesrc->notify = 0; pulsesrc->properties = NULL; pulsesrc->proplist = NULL; 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 */ /* this should be the default but it isn't yet */ gst_audio_base_src_set_slave_method (GST_AUDIO_BASE_SRC (pulsesrc), GST_AUDIO_BASE_SRC_SLAVE_SKEW); /* override with a custom clock */ if (GST_AUDIO_BASE_SRC (pulsesrc)->clock) gst_object_unref (GST_AUDIO_BASE_SRC (pulsesrc)->clock); GST_AUDIO_BASE_SRC (pulsesrc)->clock = gst_audio_clock_new ("GstPulseSrcClock", (GstAudioClockGetTimeFunc) gst_pulsesrc_get_time, pulsesrc, NULL); }
static void gst_pulsesrc_init (GstPulseSrc * pulsesrc, GstPulseSrcClass * klass) { pulsesrc->server = NULL; pulsesrc->device = NULL; pulsesrc->client_name = gst_pulse_client_name (); pulsesrc->device_description = NULL; pulsesrc->context = NULL; pulsesrc->stream = NULL; pulsesrc->read_buffer = NULL; pulsesrc->read_buffer_length = 0; #ifdef HAVE_PULSE_0_9_13 pa_sample_spec_init (&pulsesrc->sample_spec); #else pulsesrc->sample_spec.format = PA_SAMPLE_INVALID; pulsesrc->sample_spec.rate = 0; pulsesrc->sample_spec.channels = 0; #endif pulsesrc->operation_success = FALSE; pulsesrc->paused = FALSE; pulsesrc->in_read = FALSE; pulsesrc->mixer = NULL; pulsesrc->properties = NULL; pulsesrc->proplist = NULL; 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 */ /* this should be the default but it isn't yet */ gst_base_audio_src_set_slave_method (GST_BASE_AUDIO_SRC (pulsesrc), GST_BASE_AUDIO_SRC_SLAVE_SKEW); }
static gboolean gst_pulsesrc_open (GstAudioSrc * asrc) { GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc); gchar *name = gst_pulse_client_name (); pa_threaded_mainloop_lock (pulsesrc->mainloop); g_assert (!pulsesrc->context); g_assert (!pulsesrc->stream); GST_DEBUG_OBJECT (pulsesrc, "opening device"); if (!(pulsesrc->context = pa_context_new (pa_threaded_mainloop_get_api (pulsesrc->mainloop), name))) { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to create context"), (NULL)); goto unlock_and_fail; } pa_context_set_state_callback (pulsesrc->context, gst_pulsesrc_context_state_cb, pulsesrc); GST_DEBUG_OBJECT (pulsesrc, "connect to server %s", GST_STR_NULL (pulsesrc->server)); if (pa_context_connect (pulsesrc->context, pulsesrc->server, 0, NULL) < 0) { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s", pa_strerror (pa_context_errno (pulsesrc->context))), (NULL)); goto unlock_and_fail; } for (;;) { pa_context_state_t state; state = pa_context_get_state (pulsesrc->context); if (!PA_CONTEXT_IS_GOOD (state)) { GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s", pa_strerror (pa_context_errno (pulsesrc->context))), (NULL)); goto unlock_and_fail; } if (state == PA_CONTEXT_READY) break; /* Wait until the context is ready */ pa_threaded_mainloop_wait (pulsesrc->mainloop); } GST_DEBUG_OBJECT (pulsesrc, "connected"); pa_threaded_mainloop_unlock (pulsesrc->mainloop); g_free (name); return TRUE; /* ERRORS */ unlock_and_fail: { gst_pulsesrc_destroy_context (pulsesrc); pa_threaded_mainloop_unlock (pulsesrc->mainloop); g_free (name); return FALSE; } }
static gboolean gst_pulsemixer_ctrl_open (GstPulseMixerCtrl * c) { int e; gchar *name = gst_pulse_client_name (); pa_operation *o = NULL; g_assert (c); c->mainloop = pa_threaded_mainloop_new (); g_assert (c->mainloop); e = pa_threaded_mainloop_start (c->mainloop); g_assert (e == 0); pa_threaded_mainloop_lock (c->mainloop); if (!(c->context = pa_context_new (pa_threaded_mainloop_get_api (c->mainloop), name))) { GST_WARNING_OBJECT (c->object, "Failed to create context"); goto unlock_and_fail; } pa_context_set_state_callback (c->context, gst_pulsemixer_ctrl_context_state_cb, c); pa_context_set_subscribe_callback (c->context, gst_pulsemixer_ctrl_subscribe_cb, c); if (pa_context_connect (c->context, c->server, 0, NULL) < 0) { GST_WARNING_OBJECT (c->object, "Failed to connect context: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } /* Wait until the context is ready */ pa_threaded_mainloop_wait (c->mainloop); if (pa_context_get_state (c->context) != PA_CONTEXT_READY) { GST_WARNING_OBJECT (c->object, "Failed to connect context: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } /* Subscribe to events */ if (!(o = pa_context_subscribe (c->context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, gst_pulsemixer_ctrl_success_cb, c))) { GST_WARNING_OBJECT (c->object, "Failed to subscribe to events: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } c->operation_success = 0; while (pa_operation_get_state (o) != PA_OPERATION_DONE) { pa_threaded_mainloop_wait (c->mainloop); CHECK_DEAD_GOTO (c, unlock_and_fail); } if (!c->operation_success) { GST_WARNING_OBJECT (c->object, "Failed to subscribe to events: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } pa_operation_unref (o); o = NULL; /* Get sink info */ if (c->type == GST_PULSEMIXER_UNKNOWN || c->type == GST_PULSEMIXER_SINK) { if (!(o = pa_context_get_sink_info_by_name (c->context, c->device, gst_pulsemixer_ctrl_sink_info_cb, c))) { GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } c->operation_success = 0; while (pa_operation_get_state (o) != PA_OPERATION_DONE) { pa_threaded_mainloop_wait (c->mainloop); CHECK_DEAD_GOTO (c, unlock_and_fail); } pa_operation_unref (o); o = NULL; if (!c->operation_success && (c->type == GST_PULSEMIXER_SINK || pa_context_errno (c->context) != PA_ERR_NOENTITY)) { GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } } if (c->type == GST_PULSEMIXER_UNKNOWN || c->type == GST_PULSEMIXER_SOURCE) { if (!(o = pa_context_get_source_info_by_name (c->context, c->device, gst_pulsemixer_ctrl_source_info_cb, c))) { GST_WARNING_OBJECT (c->object, "Failed to get source info: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } c->operation_success = 0; while (pa_operation_get_state (o) != PA_OPERATION_DONE) { pa_threaded_mainloop_wait (c->mainloop); CHECK_DEAD_GOTO (c, unlock_and_fail); } pa_operation_unref (o); o = NULL; if (!c->operation_success) { GST_WARNING_OBJECT (c->object, "Failed to get source info: %s", pa_strerror (pa_context_errno (c->context))); goto unlock_and_fail; } } g_assert (c->type != GST_PULSEMIXER_UNKNOWN); c->track = gst_pulsemixer_track_new (c); c->tracklist = g_list_append (c->tracklist, c->track); pa_threaded_mainloop_unlock (c->mainloop); g_free (name); return TRUE; unlock_and_fail: if (o) pa_operation_unref (o); if (c->mainloop) pa_threaded_mainloop_unlock (c->mainloop); g_free (name); return FALSE; }
static void gst_pulsesrc_class_init (GstPulseSrcClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS (klass); GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass); GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); gchar *clientname; gobject_class->finalize = gst_pulsesrc_finalize; gobject_class->set_property = gst_pulsesrc_set_property; gobject_class->get_property = gst_pulsesrc_get_property; gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_pulsesrc_change_state); gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_pulsesrc_negotiate); gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_pulsesrc_open); gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_pulsesrc_close); gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_prepare); gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_unprepare); gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_pulsesrc_read); gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_pulsesrc_delay); gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_pulsesrc_reset); /* Overwrite GObject fields */ g_object_class_install_property (gobject_class, PROP_SERVER, g_param_spec_string ("server", "Server", "The PulseAudio server to connect to", DEFAULT_SERVER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_DEVICE, g_param_spec_string ("device", "Device", "The PulseAudio source device to connect to", DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, g_param_spec_string ("device-name", "Device name", "Human-readable name of the sound device", DEFAULT_DEVICE_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); clientname = gst_pulse_client_name (); /** * GstPulseSrc:client-name * * The PulseAudio client name to use. */ g_object_class_install_property (gobject_class, PROP_CLIENT_NAME, g_param_spec_string ("client-name", "Client Name", "The PulseAudio client_name_to_use", clientname, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_READY)); g_free (clientname); /** * GstPulseSrc:stream-properties * * List of pulseaudio stream properties. A list of defined properties can be * found in the <ulink href="http://0pointer.de/lennart/projects/pulseaudio/doxygen/proplist_8h.html">pulseaudio api docs</ulink>. * * Below is an example for registering as a music application to pulseaudio. * |[ * GstStructure *props; * * props = gst_structure_from_string ("props,media.role=music", NULL); * g_object_set (pulse, "stream-properties", props, NULL); * gst_structure_free (props); * ]| * * Since: 0.10.26 */ g_object_class_install_property (gobject_class, PROP_STREAM_PROPERTIES, g_param_spec_boxed ("stream-properties", "stream properties", "list of pulseaudio stream properties", GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** * GstPulseSrc:source-output-index * * The index of the PulseAudio source output corresponding to this element. * * Since: 0.10.31 */ g_object_class_install_property (gobject_class, PROP_SOURCE_OUTPUT_INDEX, g_param_spec_uint ("source-output-index", "source output index", "The index of the PulseAudio source output corresponding to this " "record stream", 0, G_MAXUINT, PA_INVALID_INDEX, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); gst_element_class_set_static_metadata (gstelement_class, "PulseAudio Audio Source", "Source/Audio", "Captures audio from a PulseAudio server", "Lennart Poettering"); gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&pad_template)); /** * GstPulseSrc:volume * * The volume of the record stream. */ g_object_class_install_property (gobject_class, PROP_VOLUME, g_param_spec_double ("volume", "Volume", "Linear volume of this stream, 1.0=100%", 0.0, MAX_VOLUME, DEFAULT_VOLUME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** * GstPulseSrc:mute * * Whether the stream is muted or not. */ g_object_class_install_property (gobject_class, PROP_MUTE, g_param_spec_boolean ("mute", "Mute", "Mute state of this stream", DEFAULT_MUTE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); }
static void gst_pulsesrc_class_init (GstPulseSrcClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstAudioSrcClass *gstaudiosrc_class = GST_AUDIO_SRC_CLASS (klass); GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS (klass); GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); gobject_class->finalize = gst_pulsesrc_finalize; gobject_class->set_property = gst_pulsesrc_set_property; gobject_class->get_property = gst_pulsesrc_get_property; gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_pulsesrc_change_state); gstbasesrc_class->negotiate = GST_DEBUG_FUNCPTR (gst_pulsesrc_negotiate); gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_pulsesrc_open); gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_pulsesrc_close); gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_prepare); gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_pulsesrc_unprepare); gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_pulsesrc_read); gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_pulsesrc_delay); gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_pulsesrc_reset); /* Overwrite GObject fields */ g_object_class_install_property (gobject_class, PROP_SERVER, g_param_spec_string ("server", "Server", "The PulseAudio server to connect to", DEFAULT_SERVER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_DEVICE, g_param_spec_string ("device", "Device", "The PulseAudio source device to connect to", DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, g_param_spec_string ("device-name", "Device name", "Human-readable name of the sound device", DEFAULT_DEVICE_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); /** * GstPulseSink:client * * The PulseAudio client name to use. * * Since: 0.10.27 */ g_object_class_install_property (gobject_class, PROP_CLIENT, g_param_spec_string ("client", "Client", "The PulseAudio client_name_to_use", gst_pulse_client_name (), G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_READY)); /** * GstPulseSrc:stream-properties * * List of pulseaudio stream properties. A list of defined properties can be * found in the <ulink href="http://0pointer.de/lennart/projects/pulseaudio/doxygen/proplist_8h.html">pulseaudio api docs</ulink>. * * Below is an example for registering as a music application to pulseaudio. * |[ * GstStructure *props; * * props = gst_structure_from_string ("props,media.role=music", NULL); * g_object_set (pulse, "stream-properties", props, NULL); * gst_structure_free (props); * ]| * * Since: 0.10.26 */ g_object_class_install_property (gobject_class, PROP_STREAM_PROPERTIES, g_param_spec_boxed ("stream-properties", "stream properties", "list of pulseaudio stream properties", GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); }