static gboolean gst_pulsesrc_close (GstAudioSrc * asrc) { GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc); pa_threaded_mainloop_lock (pulsesrc->mainloop); gst_pulsesrc_destroy_context (pulsesrc); pa_threaded_mainloop_unlock (pulsesrc->mainloop); return TRUE; }
static GstStateChangeReturn gst_pulsesrc_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret; GstPulseSrc *this = GST_PULSESRC_CAST (element); int e; switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: this->mainloop = pa_threaded_mainloop_new (); g_assert (this->mainloop); e = pa_threaded_mainloop_start (this->mainloop); g_assert (e == 0); if (!this->mixer) this->mixer = gst_pulsemixer_ctrl_new (G_OBJECT (this), this->server, this->device, GST_PULSEMIXER_SOURCE); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: /* uncork and start recording */ gst_pulsesrc_play (this); break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: /* stop recording ASAP by corking */ pa_threaded_mainloop_lock (this->mainloop); GST_DEBUG_OBJECT (this, "corking"); gst_pulsesrc_set_corked (this, TRUE, FALSE); pa_threaded_mainloop_unlock (this->mainloop); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: /* now make sure we get out of the _read method */ gst_pulsesrc_pause (this); break; case GST_STATE_CHANGE_READY_TO_NULL: if (this->mixer) { gst_pulsemixer_ctrl_free (this->mixer); this->mixer = NULL; } if (this->mainloop) pa_threaded_mainloop_stop (this->mainloop); gst_pulsesrc_destroy_context (this); if (this->mainloop) { pa_threaded_mainloop_free (this->mainloop); this->mainloop = NULL; } break; default: break; } return ret; }
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 GstStateChangeReturn gst_pulsesrc_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret; GstPulseSrc *this = GST_PULSESRC_CAST (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!(this->mainloop = pa_threaded_mainloop_new ())) goto mainloop_failed; if (pa_threaded_mainloop_start (this->mainloop) < 0) { pa_threaded_mainloop_free (this->mainloop); this->mainloop = NULL; goto mainloop_start_failed; } break; case GST_STATE_CHANGE_READY_TO_PAUSED: gst_element_post_message (element, gst_message_new_clock_provide (GST_OBJECT_CAST (element), GST_AUDIO_BASE_SRC (this)->clock, TRUE)); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: /* uncork and start recording */ gst_pulsesrc_play (this); break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: /* stop recording ASAP by corking */ pa_threaded_mainloop_lock (this->mainloop); GST_DEBUG_OBJECT (this, "corking"); gst_pulsesrc_set_corked (this, TRUE, FALSE); pa_threaded_mainloop_unlock (this->mainloop); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PLAYING_TO_PAUSED: /* now make sure we get out of the _read method */ gst_pulsesrc_pause (this); break; case GST_STATE_CHANGE_READY_TO_NULL: if (this->mainloop) pa_threaded_mainloop_stop (this->mainloop); gst_pulsesrc_destroy_context (this); if (this->mainloop) { pa_threaded_mainloop_free (this->mainloop); this->mainloop = NULL; } break; case GST_STATE_CHANGE_PAUSED_TO_READY: /* format_lost is reset in release() in baseaudiosink */ gst_element_post_message (element, gst_message_new_clock_lost (GST_OBJECT_CAST (element), GST_AUDIO_BASE_SRC (this)->clock)); break; default: break; } return ret; /* ERRORS */ mainloop_failed: { GST_ELEMENT_ERROR (this, RESOURCE, FAILED, ("pa_threaded_mainloop_new() failed"), (NULL)); return GST_STATE_CHANGE_FAILURE; } mainloop_start_failed: { GST_ELEMENT_ERROR (this, RESOURCE, FAILED, ("pa_threaded_mainloop_start() failed"), (NULL)); return GST_STATE_CHANGE_FAILURE; } }