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., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, 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 jack_log_error (const gchar * msg)
35 GST_ERROR ("%s", msg);
39 jack_info_error (const gchar * msg)
45 gst_jack_audio_client_init (void)
47 GST_DEBUG_CATEGORY_INIT (gst_jack_audio_client_debug, "jackclient", 0,
48 "jackclient helpers");
50 jack_set_error_function (jack_log_error);
51 jack_set_info_function (jack_info_error);
54 /* a list of global connections indexed by id and server. */
55 G_LOCK_DEFINE_STATIC (connections_lock);
56 static GList *connections;
58 /* the connection to a server */
65 /* id/server pair and the connection */
68 jack_client_t *client;
70 /* lists of GstJackAudioClients */
75 /* transport state handling */
77 GstState transport_state;
78 } GstJackAudioConnection;
80 /* an object sharing a jack_client_t connection. */
81 struct _GstJackAudioClient
83 GstJackAudioConnection *conn;
85 GstJackClientType type;
89 JackShutdownCallback shutdown;
90 JackProcessCallback process;
91 JackBufferSizeCallback buffer_size;
92 JackSampleRateCallback sample_rate;
98 jack_nframes_t nframes;
103 jack_handle_transport_change (GstJackAudioClient * client, GstState state)
105 GstObject *obj = GST_OBJECT_PARENT (client->user_data);
108 g_object_get (obj, "transport", &mode, NULL);
109 if ((mode & GST_JACK_TRANSPORT_SLAVE) && (GST_STATE (obj) != state)) {
110 GST_INFO_OBJECT (obj, "requesting state change: %s",
111 gst_element_state_get_name (state));
112 gst_element_post_message (GST_ELEMENT (obj),
113 gst_message_new_request_state (obj, state));
120 jack_process_cb (jack_nframes_t nframes, void *arg)
122 GstJackAudioConnection *conn = (GstJackAudioConnection *) arg;
125 jack_transport_state_t ts = jack_transport_query (conn->client, NULL);
127 if (ts != conn->cur_ts) {
130 case JackTransportStopped:
131 GST_DEBUG ("transport state is 'stopped'");
132 conn->transport_state = GST_STATE_PAUSED;
134 case JackTransportStarting:
135 GST_DEBUG ("transport state is 'starting'");
136 conn->transport_state = GST_STATE_READY;
138 case JackTransportRolling:
139 GST_DEBUG ("transport state is 'rolling'");
140 conn->transport_state = GST_STATE_PLAYING;
145 GST_DEBUG ("num of clients: src=%d, sink=%d",
146 g_list_length (conn->src_clients), g_list_length (conn->sink_clients));
149 g_mutex_lock (&conn->lock);
150 /* call sources first, then sinks. Sources will either push data into the
151 * ringbuffer of the sinks, which will then pull the data out of it, or
152 * sinks will pull the data from the sources. */
153 for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
154 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
156 /* only call active clients */
157 if ((client->active || client->deactivate) && client->process) {
158 res = client->process (nframes, client->user_data);
159 if (client->deactivate) {
160 client->deactivate = FALSE;
161 g_cond_signal (&conn->flush_cond);
165 for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
166 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
168 /* only call active clients */
169 if ((client->active || client->deactivate) && client->process) {
170 res = client->process (nframes, client->user_data);
171 if (client->deactivate) {
172 client->deactivate = FALSE;
173 g_cond_signal (&conn->flush_cond);
178 /* handle transport state requisition, do sinks first, stop after the first
179 * element that handled it */
180 if (conn->transport_state != GST_STATE_VOID_PENDING) {
181 for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
182 if (jack_handle_transport_change ((GstJackAudioClient *) walk->data,
183 conn->transport_state)) {
184 conn->transport_state = GST_STATE_VOID_PENDING;
189 if (conn->transport_state != GST_STATE_VOID_PENDING) {
190 for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
191 if (jack_handle_transport_change ((GstJackAudioClient *) walk->data,
192 conn->transport_state)) {
193 conn->transport_state = GST_STATE_VOID_PENDING;
198 g_mutex_unlock (&conn->lock);
205 jack_sample_rate_cb (jack_nframes_t nframes, void *arg)
212 jack_buffer_size_cb (jack_nframes_t nframes, void *arg)
218 jack_shutdown_cb (void *arg)
220 GstJackAudioConnection *conn = (GstJackAudioConnection *) arg;
223 GST_DEBUG ("disconnect client %s from server %s", conn->id,
224 GST_STR_NULL (conn->server));
226 g_mutex_lock (&conn->lock);
227 for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
228 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
230 if (client->shutdown)
231 client->shutdown (client->user_data);
233 for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
234 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
236 if (client->shutdown)
237 client->shutdown (client->user_data);
239 g_mutex_unlock (&conn->lock);
249 connection_find (GstJackAudioConnection * conn, FindData * data)
251 /* id's must match */
252 if (strcmp (conn->id, data->id))
255 /* both the same or NULL */
256 if (conn->server == data->server)
259 /* we cannot compare NULL */
260 if (conn->server == NULL || data->server == NULL)
263 if (strcmp (conn->server, data->server))
269 /* make a connection with @id and @server. Returns NULL on failure with the
271 static GstJackAudioConnection *
272 gst_jack_audio_make_connection (const gchar * id, const gchar * server,
273 jack_client_t * jclient, jack_status_t * status)
275 GstJackAudioConnection *conn;
276 jack_options_t options;
281 GST_DEBUG ("new client %s, connecting to server %s", id,
282 GST_STR_NULL (server));
284 /* never start a server */
285 options = JackNoStartServer;
286 /* if we have a servername, use it */
288 options |= JackServerName;
289 /* open the client */
291 jclient = jack_client_open (id, options, status, server);
295 /* now create object */
296 conn = g_new (GstJackAudioConnection, 1);
298 g_mutex_init (&conn->lock);
299 g_cond_init (&conn->flush_cond);
300 conn->id = g_strdup (id);
301 conn->server = g_strdup (server);
302 conn->client = jclient;
304 conn->src_clients = NULL;
305 conn->sink_clients = NULL;
307 conn->transport_state = GST_STATE_VOID_PENDING;
309 /* set our callbacks */
310 jack_set_process_callback (jclient, jack_process_cb, conn);
311 /* these callbacks cause us to error */
312 jack_set_buffer_size_callback (jclient, jack_buffer_size_cb, conn);
313 jack_set_sample_rate_callback (jclient, jack_sample_rate_cb, conn);
314 jack_on_shutdown (jclient, jack_shutdown_cb, conn);
316 /* all callbacks are set, activate the client */
317 GST_INFO ("activate jack_client %p", jclient);
318 if ((res = jack_activate (jclient)))
319 goto could_not_activate;
321 GST_DEBUG ("opened connection %p", conn);
328 GST_DEBUG ("failed to open jack client, %d", *status);
333 GST_ERROR ("Could not activate client (%d)", res);
334 *status = JackFailure;
335 g_mutex_clear (&conn->lock);
337 g_free (conn->server);
343 static GstJackAudioConnection *
344 gst_jack_audio_get_connection (const gchar * id, const gchar * server,
345 jack_client_t * jclient, jack_status_t * status)
347 GstJackAudioConnection *conn;
351 GST_DEBUG ("getting connection for id %s, server %s", id,
352 GST_STR_NULL (server));
355 data.server = server;
357 G_LOCK (connections_lock);
359 g_list_find_custom (connections, &data, (GCompareFunc) connection_find);
360 if (found != NULL && jclient != NULL) {
361 /* we found it, increase refcount and return it */
362 conn = (GstJackAudioConnection *) found->data;
365 GST_DEBUG ("found connection %p", conn);
367 /* make new connection */
368 conn = gst_jack_audio_make_connection (id, server, jclient, status);
370 GST_DEBUG ("created connection %p", conn);
371 /* add to list on success */
372 connections = g_list_prepend (connections, conn);
374 GST_WARNING ("could not create connection");
377 G_UNLOCK (connections_lock);
383 gst_jack_audio_unref_connection (GstJackAudioConnection * conn)
388 GST_DEBUG ("unref connection %p refcnt %d", conn, conn->refcount);
390 G_LOCK (connections_lock);
392 if ((zero = (conn->refcount == 0))) {
393 GST_DEBUG ("closing connection %p", conn);
394 /* remove from list, we can release the mutex after removing the connection
395 * from the list because after that, nobody can access the connection anymore. */
396 connections = g_list_remove (connections, conn);
398 G_UNLOCK (connections_lock);
400 /* if we are zero, close and cleanup the connection */
402 /* don't use conn->lock here. two reasons:
404 * 1) its not necessary: jack_deactivate() will not return until the JACK thread
405 * associated with this connection is cleaned up by a thread join, hence
406 * no more callbacks can occur or be in progress.
408 * 2) it would deadlock anyway, because jack_deactivate() will sleep
409 * waiting for the JACK thread, and can thus cause deadlock in
412 GST_INFO ("deactivate jack_client %p", conn->client);
413 if ((res = jack_deactivate (conn->client))) {
414 /* we only warn, this means the server is probably shut down and the client
416 GST_WARNING ("Could not deactivate Jack client (%d)", res);
418 /* close connection */
419 if ((res = jack_client_close (conn->client))) {
420 /* we assume the client is gone. */
421 GST_WARNING ("close failed (%d)", res);
425 g_mutex_clear (&conn->lock);
426 g_cond_clear (&conn->flush_cond);
428 g_free (conn->server);
434 gst_jack_audio_connection_add_client (GstJackAudioConnection * conn,
435 GstJackAudioClient * client)
437 g_mutex_lock (&conn->lock);
438 switch (client->type) {
439 case GST_JACK_CLIENT_SOURCE:
440 conn->src_clients = g_list_append (conn->src_clients, client);
443 case GST_JACK_CLIENT_SINK:
444 conn->sink_clients = g_list_append (conn->sink_clients, client);
448 g_warning ("trying to add unknown client type");
451 g_mutex_unlock (&conn->lock);
455 gst_jack_audio_connection_remove_client (GstJackAudioConnection * conn,
456 GstJackAudioClient * client)
458 g_mutex_lock (&conn->lock);
459 switch (client->type) {
460 case GST_JACK_CLIENT_SOURCE:
461 conn->src_clients = g_list_remove (conn->src_clients, client);
464 case GST_JACK_CLIENT_SINK:
465 conn->sink_clients = g_list_remove (conn->sink_clients, client);
469 g_warning ("trying to remove unknown client type");
472 g_mutex_unlock (&conn->lock);
476 * gst_jack_audio_client_get:
478 * @server: the server to connect to or NULL for the default server
479 * @type: the client type
480 * @shutdown: a callback when the jack server shuts down
481 * @process: a callback when samples are available
482 * @buffer_size: a callback when the buffer_size changes
483 * @sample_rate: a callback when the sample_rate changes
484 * @user_data: user data passed to the callbacks
485 * @status: pointer to hold the jack status code in case of errors
487 * Get the jack client connection for @id and @server. Connections to the same
488 * @id and @server will receive the same physical Jack client connection and
489 * will therefore be scheduled in the same process callback.
491 * Returns: a #GstJackAudioClient.
494 gst_jack_audio_client_new (const gchar * id, const gchar * server,
495 jack_client_t * jclient, GstJackClientType type,
496 void (*shutdown) (void *arg), JackProcessCallback process,
497 JackBufferSizeCallback buffer_size, JackSampleRateCallback sample_rate,
498 gpointer user_data, jack_status_t * status)
500 GstJackAudioClient *client;
501 GstJackAudioConnection *conn;
503 g_return_val_if_fail (id != NULL, NULL);
504 g_return_val_if_fail (status != NULL, NULL);
506 /* first get a connection for the id/server pair */
507 conn = gst_jack_audio_get_connection (id, server, jclient, status);
511 GST_INFO ("new client %s", id);
513 /* make new client using the connection */
514 client = g_new (GstJackAudioClient, 1);
515 client->active = client->deactivate = FALSE;
518 client->shutdown = shutdown;
519 client->process = process;
520 client->buffer_size = buffer_size;
521 client->sample_rate = sample_rate;
522 client->user_data = user_data;
524 /* add the client to the connection */
525 gst_jack_audio_connection_add_client (conn, client);
532 GST_DEBUG ("Could not get server connection (%d)", *status);
538 * gst_jack_audio_client_free:
539 * @client: a #GstJackAudioClient
541 * Free the resources used by @client.
544 gst_jack_audio_client_free (GstJackAudioClient * client)
546 GstJackAudioConnection *conn;
548 g_return_if_fail (client != NULL);
550 GST_INFO ("free client");
554 /* remove from connection first so that it's not scheduled anymore after this
556 gst_jack_audio_connection_remove_client (conn, client);
557 gst_jack_audio_unref_connection (conn);
563 * gst_jack_audio_client_get_client:
564 * @client: a #GstJackAudioClient
566 * Get the jack audio client for @client. This function is used to perform
567 * operations on the jack server from this client.
569 * Returns: The jack audio client.
572 gst_jack_audio_client_get_client (GstJackAudioClient * client)
574 g_return_val_if_fail (client != NULL, NULL);
576 /* no lock needed, the connection and the client does not change
577 * once the client is created. */
578 return client->conn->client;
582 * gst_jack_audio_client_set_active:
583 * @client: a #GstJackAudioClient
584 * @active: new mode for the client
586 * Activate or deactive @client. When a client is activated it will receive
587 * callbacks when data should be processed.
589 * Returns: 0 if all ok.
592 gst_jack_audio_client_set_active (GstJackAudioClient * client, gboolean active)
594 g_return_val_if_fail (client != NULL, -1);
596 /* make sure that we are not dispatching the client */
597 g_mutex_lock (&client->conn->lock);
598 if (client->active && !active) {
599 /* we need to process once more to flush the port */
600 client->deactivate = TRUE;
602 /* need to wait for process_cb run once more */
603 while (client->deactivate)
604 g_cond_wait (&client->conn->flush_cond, &client->conn->lock);
606 client->active = active;
607 g_mutex_unlock (&client->conn->lock);
613 * gst_jack_audio_client_get_transport_state:
614 * @client: a #GstJackAudioClient
616 * Check the current transport state. The client can use this to request a state
617 * change from the application.
619 * Returns: the state, %GST_STATE_VOID_PENDING for no change in the transport
623 gst_jack_audio_client_get_transport_state (GstJackAudioClient * client)
625 GstState state = client->conn->transport_state;
627 client->conn->transport_state = GST_STATE_VOID_PENDING;