jack: add transport control handling
authorStefan Sauer <ensonic@users.sf.net>
Tue, 10 Jan 2012 21:27:11 +0000 (22:27 +0100)
committerStefan Sauer <ensonic@users.sf.net>
Tue, 10 Jan 2012 21:35:02 +0000 (22:35 +0100)
This feature allows to start and stop playback from other jack applications (e.g. qjackctl).

ext/jack/gstjackaudioclient.c
ext/jack/gstjackaudioclient.h
ext/jack/gstjackaudiosink.c
ext/jack/gstjackaudiosrc.c

index c5c8dc8..c33949f 100644 (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;
+}
index 5fb7e35..f2669c9 100644 (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__ */
index 078ca24..43b5240 100644 (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 */
index 3c37970..a8ca1ed 100644 (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 */