jack: add transport control handling

This feature allows to start and stop playback from other jack applications (e.g. qjackctl).
This commit is contained in:
Stefan Sauer 2012-01-10 22:27:11 +01:00
parent d1bb060d71
commit 7d4044aa46
4 changed files with 68 additions and 1 deletions

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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 */

View file

@ -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 */