From 7d4044aa46a947f96cbfff11e89fed395b289a08 Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Tue, 10 Jan 2012 22:27:11 +0100 Subject: [PATCH] jack: add transport control handling This feature allows to start and stop playback from other jack applications (e.g. qjackctl). --- ext/jack/gstjackaudioclient.c | 47 ++++++++++++++++++++++++++++++++++++++++++- ext/jack/gstjackaudioclient.h | 2 ++ ext/jack/gstjackaudiosink.c | 10 +++++++++ ext/jack/gstjackaudiosrc.c | 10 +++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/ext/jack/gstjackaudioclient.c b/ext/jack/gstjackaudioclient.c index c5c8dc8..c33949f 100644 --- a/ext/jack/gstjackaudioclient.c +++ b/ext/jack/gstjackaudioclient.c @@ -55,6 +55,10 @@ typedef struct gint n_clients; GList *src_clients; GList *sink_clients; + + /* transport state handling */ + gint cur_ts; + GstState transport_state; } GstJackAudioConnection; /* an object sharing a jack_client_t connection. */ @@ -87,6 +91,27 @@ jack_process_cb (jack_nframes_t nframes, void *arg) GstJackAudioConnection *conn = (GstJackAudioConnection *) arg; GList *walk; int res = 0; + jack_transport_state_t ts = jack_transport_query (conn->client, NULL); + + if (ts != conn->cur_ts) { + conn->cur_ts = ts; + switch (ts) { + case JackTransportStopped: + GST_DEBUG ("transport state is 'stopped'"); + conn->transport_state = GST_STATE_PAUSED; + break; + case JackTransportStarting: + GST_DEBUG ("transport state is 'starting'"); + conn->transport_state = GST_STATE_READY; + break; + case JackTransportRolling: + GST_DEBUG ("transport state is 'rolling'"); + conn->transport_state = GST_STATE_PLAYING; + break; + default: + break; + } + } g_mutex_lock (conn->lock); /* call sources first, then sinks. Sources will either push data into the @@ -117,7 +142,6 @@ jack_process_cb (jack_nframes_t nframes, void *arg) } } g_mutex_unlock (conn->lock); - return res; } @@ -224,6 +248,8 @@ gst_jack_audio_make_connection (const gchar * id, const gchar * server, conn->n_clients = 0; conn->src_clients = NULL; conn->sink_clients = NULL; + conn->cur_ts = -1; + conn->transport_state = GST_STATE_VOID_PENDING; /* set our callbacks */ jack_set_process_callback (jclient, jack_process_cb, conn); @@ -525,3 +551,22 @@ gst_jack_audio_client_set_active (GstJackAudioClient * client, gboolean active) return 0; } + +/** + * gst_jack_audio_client_get_transport_state: + * @client: a #GstJackAudioClient + * + * Check the current transport state. The client can use this to request a state + * change from the application. + * + * Returns: the state, %GST_STATE_VOID_PENDING for no change in the transport + * state + */ +GstState +gst_jack_audio_client_get_transport_state (GstJackAudioClient * client) +{ + GstState state = client->conn->transport_state; + + client->conn->transport_state = GST_STATE_VOID_PENDING; + return state; +} diff --git a/ext/jack/gstjackaudioclient.h b/ext/jack/gstjackaudioclient.h index 5fb7e35..f2669c9 100644 --- a/ext/jack/gstjackaudioclient.h +++ b/ext/jack/gstjackaudioclient.h @@ -54,6 +54,8 @@ jack_client_t * gst_jack_audio_client_get_client (GstJackAudioClient * gboolean gst_jack_audio_client_set_active (GstJackAudioClient *client, gboolean active); +GstState gst_jack_audio_client_get_transport_state (GstJackAudioClient *client); + G_END_DECLS #endif /* __GST_JACK_AUDIO_CLIENT_H__ */ diff --git a/ext/jack/gstjackaudiosink.c b/ext/jack/gstjackaudiosink.c index 078ca24..43b5240 100644 --- a/ext/jack/gstjackaudiosink.c +++ b/ext/jack/gstjackaudiosink.c @@ -191,10 +191,20 @@ jack_process_cb (jack_nframes_t nframes, void *arg) guint8 *readptr; gint i, j, flen, channels; sample_t *data; + GstState state; buf = GST_RING_BUFFER_CAST (arg); sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + /* handle transport state requisitions */ + state = gst_jack_audio_client_get_transport_state (sink->client); + if ((state != GST_STATE_VOID_PENDING) && (GST_STATE (sink) != state)) { + GST_DEBUG_OBJECT (sink, "requesting state change: %s", + gst_element_state_get_name (state)); + gst_element_post_message (GST_ELEMENT (sink), + gst_message_new_request_state (GST_OBJECT (sink), state)); + } + channels = buf->spec.channels; /* get target buffers */ diff --git a/ext/jack/gstjackaudiosrc.c b/ext/jack/gstjackaudiosrc.c index 3c37970..a8ca1ed 100644 --- a/ext/jack/gstjackaudiosrc.c +++ b/ext/jack/gstjackaudiosrc.c @@ -211,10 +211,20 @@ jack_process_cb (jack_nframes_t nframes, void *arg) gint writeseg; gint channels, i, j, flen; sample_t *data; + GstState state; buf = GST_RING_BUFFER_CAST (arg); src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); + /* handle transport state requisitions */ + state = gst_jack_audio_client_get_transport_state (src->client); + if ((state != GST_STATE_VOID_PENDING) && (GST_STATE (src) != state)) { + GST_DEBUG_OBJECT (src, "requesting state change: %s", + gst_element_state_get_name (state)); + gst_element_post_message (GST_ELEMENT (src), + gst_message_new_request_state (GST_OBJECT (src), state)); + } + channels = buf->spec.channels; /* get input buffers */ -- 2.7.4