2 * Copyright (C) 2006 Wim Taymans <wim@fluendo.com>
4 * gstjackaudioclient.c: jack audio client implementation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
24 #include "gstjackaudioclient.h"
27 #include <gst/glib-compat-private.h>
29 GST_DEBUG_CATEGORY_STATIC (gst_jack_audio_client_debug);
30 #define GST_CAT_DEFAULT gst_jack_audio_client_debug
33 gst_jack_audio_client_init (void)
35 GST_DEBUG_CATEGORY_INIT (gst_jack_audio_client_debug, "jackclient", 0,
36 "jackclient helpers");
39 /* a list of global connections indexed by id and server. */
40 G_LOCK_DEFINE_STATIC (connections_lock);
41 static GList *connections;
43 /* the connection to a server */
50 /* id/server pair and the connection */
53 jack_client_t *client;
55 /* lists of GstJackAudioClients */
60 /* transport state handling */
62 GstState transport_state;
63 } GstJackAudioConnection;
65 /* an object sharing a jack_client_t connection. */
66 struct _GstJackAudioClient
68 GstJackAudioConnection *conn;
70 GstJackClientType type;
74 JackShutdownCallback shutdown;
75 JackProcessCallback process;
76 JackBufferSizeCallback buffer_size;
77 JackSampleRateCallback sample_rate;
83 jack_nframes_t nframes;
88 jack_handle_transport_change (GstJackAudioClient * client, GstState state)
90 GstObject *obj = GST_OBJECT_PARENT (client->user_data);
93 g_object_get (obj, "transport", &mode, NULL);
94 if ((mode & GST_JACK_TRANSPORT_SLAVE) && (GST_STATE (obj) != state)) {
95 GST_INFO_OBJECT (obj, "requesting state change: %s",
96 gst_element_state_get_name (state));
97 gst_element_post_message (GST_ELEMENT (obj),
98 gst_message_new_request_state (obj, state));
105 jack_process_cb (jack_nframes_t nframes, void *arg)
107 GstJackAudioConnection *conn = (GstJackAudioConnection *) arg;
110 jack_transport_state_t ts = jack_transport_query (conn->client, NULL);
112 if (ts != conn->cur_ts) {
115 case JackTransportStopped:
116 GST_DEBUG ("transport state is 'stopped'");
117 conn->transport_state = GST_STATE_PAUSED;
119 case JackTransportStarting:
120 GST_DEBUG ("transport state is 'starting'");
121 conn->transport_state = GST_STATE_READY;
123 case JackTransportRolling:
124 GST_DEBUG ("transport state is 'rolling'");
125 conn->transport_state = GST_STATE_PLAYING;
130 GST_DEBUG ("num of clients: src=%d, sink=%d",
131 g_list_length (conn->src_clients), g_list_length (conn->sink_clients));
134 g_mutex_lock (&conn->lock);
135 /* call sources first, then sinks. Sources will either push data into the
136 * ringbuffer of the sinks, which will then pull the data out of it, or
137 * sinks will pull the data from the sources. */
138 for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
139 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
141 /* only call active clients */
142 if ((client->active || client->deactivate) && client->process) {
143 res = client->process (nframes, client->user_data);
144 if (client->deactivate) {
145 client->deactivate = FALSE;
146 g_cond_signal (&conn->flush_cond);
150 for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
151 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
153 /* only call active clients */
154 if ((client->active || client->deactivate) && client->process) {
155 res = client->process (nframes, client->user_data);
156 if (client->deactivate) {
157 client->deactivate = FALSE;
158 g_cond_signal (&conn->flush_cond);
163 /* handle transport state requisition, do sinks first, stop after the first
164 * element that handled it */
165 if (conn->transport_state != GST_STATE_VOID_PENDING) {
166 for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
167 if (jack_handle_transport_change ((GstJackAudioClient *) walk->data,
168 conn->transport_state)) {
169 conn->transport_state = GST_STATE_VOID_PENDING;
174 if (conn->transport_state != GST_STATE_VOID_PENDING) {
175 for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
176 if (jack_handle_transport_change ((GstJackAudioClient *) walk->data,
177 conn->transport_state)) {
178 conn->transport_state = GST_STATE_VOID_PENDING;
183 g_mutex_unlock (&conn->lock);
190 jack_sample_rate_cb (jack_nframes_t nframes, void *arg)
197 jack_buffer_size_cb (jack_nframes_t nframes, void *arg)
203 jack_shutdown_cb (void *arg)
205 GstJackAudioConnection *conn = (GstJackAudioConnection *) arg;
208 GST_DEBUG ("disconnect client %s from server %s", conn->id,
209 GST_STR_NULL (conn->server));
211 g_mutex_lock (&conn->lock);
212 for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
213 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
215 if (client->shutdown)
216 client->shutdown (client->user_data);
218 for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
219 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
221 if (client->shutdown)
222 client->shutdown (client->user_data);
224 g_mutex_unlock (&conn->lock);
234 connection_find (GstJackAudioConnection * conn, FindData * data)
236 /* id's must match */
237 if (strcmp (conn->id, data->id))
240 /* both the same or NULL */
241 if (conn->server == data->server)
244 /* we cannot compare NULL */
245 if (conn->server == NULL || data->server == NULL)
248 if (strcmp (conn->server, data->server))
254 /* make a connection with @id and @server. Returns NULL on failure with the
256 static GstJackAudioConnection *
257 gst_jack_audio_make_connection (const gchar * id, const gchar * server,
258 jack_client_t * jclient, jack_status_t * status)
260 GstJackAudioConnection *conn;
261 jack_options_t options;
266 GST_DEBUG ("new client %s, connecting to server %s", id,
267 GST_STR_NULL (server));
269 /* never start a server */
270 options = JackNoStartServer;
271 /* if we have a servername, use it */
273 options |= JackServerName;
274 /* open the client */
276 jclient = jack_client_open (id, options, status, server);
280 /* now create object */
281 conn = g_new (GstJackAudioConnection, 1);
283 g_mutex_init (&conn->lock);
284 g_cond_init (&conn->flush_cond);
285 conn->id = g_strdup (id);
286 conn->server = g_strdup (server);
287 conn->client = jclient;
289 conn->src_clients = NULL;
290 conn->sink_clients = NULL;
292 conn->transport_state = GST_STATE_VOID_PENDING;
294 /* set our callbacks */
295 jack_set_process_callback (jclient, jack_process_cb, conn);
296 /* these callbacks cause us to error */
297 jack_set_buffer_size_callback (jclient, jack_buffer_size_cb, conn);
298 jack_set_sample_rate_callback (jclient, jack_sample_rate_cb, conn);
299 jack_on_shutdown (jclient, jack_shutdown_cb, conn);
301 /* all callbacks are set, activate the client */
302 GST_INFO ("activate jack_client %p", jclient);
303 if ((res = jack_activate (jclient)))
304 goto could_not_activate;
306 GST_DEBUG ("opened connection %p", conn);
313 GST_DEBUG ("failed to open jack client, %d", *status);
318 GST_ERROR ("Could not activate client (%d)", res);
319 *status = JackFailure;
320 g_mutex_clear (&conn->lock);
322 g_free (conn->server);
328 static GstJackAudioConnection *
329 gst_jack_audio_get_connection (const gchar * id, const gchar * server,
330 jack_client_t * jclient, jack_status_t * status)
332 GstJackAudioConnection *conn;
336 GST_DEBUG ("getting connection for id %s, server %s", id,
337 GST_STR_NULL (server));
340 data.server = server;
342 G_LOCK (connections_lock);
344 g_list_find_custom (connections, &data, (GCompareFunc) connection_find);
345 if (found != NULL && jclient != NULL) {
346 /* we found it, increase refcount and return it */
347 conn = (GstJackAudioConnection *) found->data;
350 GST_DEBUG ("found connection %p", conn);
352 /* make new connection */
353 conn = gst_jack_audio_make_connection (id, server, jclient, status);
355 GST_DEBUG ("created connection %p", conn);
356 /* add to list on success */
357 connections = g_list_prepend (connections, conn);
359 GST_WARNING ("could not create connection");
362 G_UNLOCK (connections_lock);
368 gst_jack_audio_unref_connection (GstJackAudioConnection * conn)
373 GST_DEBUG ("unref connection %p refcnt %d", conn, conn->refcount);
375 G_LOCK (connections_lock);
377 if ((zero = (conn->refcount == 0))) {
378 GST_DEBUG ("closing connection %p", conn);
379 /* remove from list, we can release the mutex after removing the connection
380 * from the list because after that, nobody can access the connection anymore. */
381 connections = g_list_remove (connections, conn);
383 G_UNLOCK (connections_lock);
385 /* if we are zero, close and cleanup the connection */
387 /* don't use conn->lock here. two reasons:
389 * 1) its not necessary: jack_deactivate() will not return until the JACK thread
390 * associated with this connection is cleaned up by a thread join, hence
391 * no more callbacks can occur or be in progress.
393 * 2) it would deadlock anyway, because jack_deactivate() will sleep
394 * waiting for the JACK thread, and can thus cause deadlock in
397 GST_INFO ("deactivate jack_client %p", conn->client);
398 if ((res = jack_deactivate (conn->client))) {
399 /* we only warn, this means the server is probably shut down and the client
401 GST_WARNING ("Could not deactivate Jack client (%d)", res);
403 /* close connection */
404 if ((res = jack_client_close (conn->client))) {
405 /* we assume the client is gone. */
406 GST_WARNING ("close failed (%d)", res);
410 g_mutex_clear (&conn->lock);
411 g_cond_clear (&conn->flush_cond);
413 g_free (conn->server);
419 gst_jack_audio_connection_add_client (GstJackAudioConnection * conn,
420 GstJackAudioClient * client)
422 g_mutex_lock (&conn->lock);
423 switch (client->type) {
424 case GST_JACK_CLIENT_SOURCE:
425 conn->src_clients = g_list_append (conn->src_clients, client);
428 case GST_JACK_CLIENT_SINK:
429 conn->sink_clients = g_list_append (conn->sink_clients, client);
433 g_warning ("trying to add unknown client type");
436 g_mutex_unlock (&conn->lock);
440 gst_jack_audio_connection_remove_client (GstJackAudioConnection * conn,
441 GstJackAudioClient * client)
443 g_mutex_lock (&conn->lock);
444 switch (client->type) {
445 case GST_JACK_CLIENT_SOURCE:
446 conn->src_clients = g_list_remove (conn->src_clients, client);
449 case GST_JACK_CLIENT_SINK:
450 conn->sink_clients = g_list_remove (conn->sink_clients, client);
454 g_warning ("trying to remove unknown client type");
457 g_mutex_unlock (&conn->lock);
461 * gst_jack_audio_client_get:
463 * @server: the server to connect to or NULL for the default server
464 * @type: the client type
465 * @shutdown: a callback when the jack server shuts down
466 * @process: a callback when samples are available
467 * @buffer_size: a callback when the buffer_size changes
468 * @sample_rate: a callback when the sample_rate changes
469 * @user_data: user data passed to the callbacks
470 * @status: pointer to hold the jack status code in case of errors
472 * Get the jack client connection for @id and @server. Connections to the same
473 * @id and @server will receive the same physical Jack client connection and
474 * will therefore be scheduled in the same process callback.
476 * Returns: a #GstJackAudioClient.
479 gst_jack_audio_client_new (const gchar * id, const gchar * server,
480 jack_client_t * jclient, GstJackClientType type,
481 void (*shutdown) (void *arg), JackProcessCallback process,
482 JackBufferSizeCallback buffer_size, JackSampleRateCallback sample_rate,
483 gpointer user_data, jack_status_t * status)
485 GstJackAudioClient *client;
486 GstJackAudioConnection *conn;
488 g_return_val_if_fail (id != NULL, NULL);
489 g_return_val_if_fail (status != NULL, NULL);
491 /* first get a connection for the id/server pair */
492 conn = gst_jack_audio_get_connection (id, server, jclient, status);
496 GST_INFO ("new client %s", id);
498 /* make new client using the connection */
499 client = g_new (GstJackAudioClient, 1);
500 client->active = client->deactivate = FALSE;
503 client->shutdown = shutdown;
504 client->process = process;
505 client->buffer_size = buffer_size;
506 client->sample_rate = sample_rate;
507 client->user_data = user_data;
509 /* add the client to the connection */
510 gst_jack_audio_connection_add_client (conn, client);
517 GST_DEBUG ("Could not get server connection (%d)", *status);
523 * gst_jack_audio_client_free:
524 * @client: a #GstJackAudioClient
526 * Free the resources used by @client.
529 gst_jack_audio_client_free (GstJackAudioClient * client)
531 GstJackAudioConnection *conn;
533 g_return_if_fail (client != NULL);
535 GST_INFO ("free client");
539 /* remove from connection first so that it's not scheduled anymore after this
541 gst_jack_audio_connection_remove_client (conn, client);
542 gst_jack_audio_unref_connection (conn);
548 * gst_jack_audio_client_get_client:
549 * @client: a #GstJackAudioClient
551 * Get the jack audio client for @client. This function is used to perform
552 * operations on the jack server from this client.
554 * Returns: The jack audio client.
557 gst_jack_audio_client_get_client (GstJackAudioClient * client)
559 g_return_val_if_fail (client != NULL, NULL);
561 /* no lock needed, the connection and the client does not change
562 * once the client is created. */
563 return client->conn->client;
567 * gst_jack_audio_client_set_active:
568 * @client: a #GstJackAudioClient
569 * @active: new mode for the client
571 * Activate or deactive @client. When a client is activated it will receive
572 * callbacks when data should be processed.
574 * Returns: 0 if all ok.
577 gst_jack_audio_client_set_active (GstJackAudioClient * client, gboolean active)
579 g_return_val_if_fail (client != NULL, -1);
581 /* make sure that we are not dispatching the client */
582 g_mutex_lock (&client->conn->lock);
583 if (client->active && !active) {
584 /* we need to process once more to flush the port */
585 client->deactivate = TRUE;
587 /* need to wait for process_cb run once more */
588 while (client->deactivate)
589 g_cond_wait (&client->conn->flush_cond, &client->conn->lock);
591 client->active = active;
592 g_mutex_unlock (&client->conn->lock);
598 * gst_jack_audio_client_get_transport_state:
599 * @client: a #GstJackAudioClient
601 * Check the current transport state. The client can use this to request a state
602 * change from the application.
604 * Returns: the state, %GST_STATE_VOID_PENDING for no change in the transport
608 gst_jack_audio_client_get_transport_state (GstJackAudioClient * client)
610 GstState state = client->conn->transport_state;
612 client->conn->transport_state = GST_STATE_VOID_PENDING;