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"
26 #include <gst/glib-compat-private.h>
28 GST_DEBUG_CATEGORY_STATIC (gst_jack_audio_client_debug);
29 #define GST_CAT_DEFAULT gst_jack_audio_client_debug
32 gst_jack_audio_client_init (void)
34 GST_DEBUG_CATEGORY_INIT (gst_jack_audio_client_debug, "jackclient", 0,
35 "jackclient helpers");
38 /* a list of global connections indexed by id and server. */
39 G_LOCK_DEFINE_STATIC (connections_lock);
40 static GList *connections;
42 /* the connection to a server */
49 /* id/server pair and the connection */
52 jack_client_t *client;
54 /* lists of GstJackAudioClients */
58 } GstJackAudioConnection;
60 /* an object sharing a jack_client_t connection. */
61 struct _GstJackAudioClient
63 GstJackAudioConnection *conn;
65 GstJackClientType type;
69 void (*shutdown) (void *arg);
70 JackProcessCallback process;
71 JackBufferSizeCallback buffer_size;
72 JackSampleRateCallback sample_rate;
76 typedef jack_default_audio_sample_t sample_t;
80 jack_nframes_t nframes;
85 jack_process_cb (jack_nframes_t nframes, void *arg)
87 GstJackAudioConnection *conn = (GstJackAudioConnection *) arg;
91 g_mutex_lock (conn->lock);
92 /* call sources first, then sinks. Sources will either push data into the
93 * ringbuffer of the sinks, which will then pull the data out of it, or
94 * sinks will pull the data from the sources. */
95 for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
96 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
98 /* only call active clients */
99 if ((client->active || client->deactivate) && client->process) {
100 res = client->process (nframes, client->user_data);
101 if (client->deactivate) {
102 client->deactivate = FALSE;
103 g_cond_signal (conn->flush_cond);
107 for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
108 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
110 /* only call active clients */
111 if ((client->active || client->deactivate) && client->process) {
112 res = client->process (nframes, client->user_data);
113 if (client->deactivate) {
114 client->deactivate = FALSE;
115 g_cond_signal (conn->flush_cond);
119 g_mutex_unlock (conn->lock);
126 jack_sample_rate_cb (jack_nframes_t nframes, void *arg)
133 jack_buffer_size_cb (jack_nframes_t nframes, void *arg)
139 jack_shutdown_cb (void *arg)
141 GstJackAudioConnection *conn = (GstJackAudioConnection *) arg;
144 GST_DEBUG ("disconnect client %s from server %s", conn->id,
145 GST_STR_NULL (conn->server));
147 g_mutex_lock (conn->lock);
148 for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
149 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
151 if (client->shutdown)
152 client->shutdown (client->user_data);
154 for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
155 GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
157 if (client->shutdown)
158 client->shutdown (client->user_data);
160 g_mutex_unlock (conn->lock);
170 connection_find (GstJackAudioConnection * conn, FindData * data)
172 /* id's must match */
173 if (strcmp (conn->id, data->id))
176 /* both the same or NULL */
177 if (conn->server == data->server)
180 /* we cannot compare NULL */
181 if (conn->server == NULL || data->server == NULL)
184 if (strcmp (conn->server, data->server))
190 /* make a connection with @id and @server. Returns NULL on failure with the
192 static GstJackAudioConnection *
193 gst_jack_audio_make_connection (const gchar * id, const gchar * server,
194 jack_client_t * jclient, jack_status_t * status)
196 GstJackAudioConnection *conn;
197 jack_options_t options;
202 GST_DEBUG ("new client %s, connecting to server %s", id,
203 GST_STR_NULL (server));
205 /* never start a server */
206 options = JackNoStartServer;
207 /* if we have a servername, use it */
209 options |= JackServerName;
210 /* open the client */
212 jclient = jack_client_open (id, options, status, server);
216 /* now create object */
217 conn = g_new (GstJackAudioConnection, 1);
219 conn->lock = g_mutex_new ();
220 conn->flush_cond = g_cond_new ();
221 conn->id = g_strdup (id);
222 conn->server = g_strdup (server);
223 conn->client = jclient;
225 conn->src_clients = NULL;
226 conn->sink_clients = NULL;
228 /* set our callbacks */
229 jack_set_process_callback (jclient, jack_process_cb, conn);
230 /* these callbacks cause us to error */
231 jack_set_buffer_size_callback (jclient, jack_buffer_size_cb, conn);
232 jack_set_sample_rate_callback (jclient, jack_sample_rate_cb, conn);
233 jack_on_shutdown (jclient, jack_shutdown_cb, conn);
235 /* all callbacks are set, activate the client */
236 if ((res = jack_activate (jclient)))
237 goto could_not_activate;
239 GST_DEBUG ("opened connection %p", conn);
246 GST_DEBUG ("failed to open jack client, %d", *status);
251 GST_ERROR ("Could not activate client (%d)", res);
252 *status = JackFailure;
253 g_mutex_free (conn->lock);
255 g_free (conn->server);
261 static GstJackAudioConnection *
262 gst_jack_audio_get_connection (const gchar * id, const gchar * server,
263 jack_client_t * jclient, jack_status_t * status)
265 GstJackAudioConnection *conn;
269 GST_DEBUG ("getting connection for id %s, server %s", id,
270 GST_STR_NULL (server));
273 data.server = server;
275 G_LOCK (connections_lock);
277 g_list_find_custom (connections, &data, (GCompareFunc) connection_find);
278 if (found != NULL && jclient != NULL) {
279 /* we found it, increase refcount and return it */
280 conn = (GstJackAudioConnection *) found->data;
283 GST_DEBUG ("found connection %p", conn);
285 /* make new connection */
286 conn = gst_jack_audio_make_connection (id, server, jclient, status);
288 GST_DEBUG ("created connection %p", conn);
289 /* add to list on success */
290 connections = g_list_prepend (connections, conn);
292 GST_WARNING ("could not create connection");
295 G_UNLOCK (connections_lock);
301 gst_jack_audio_unref_connection (GstJackAudioConnection * conn)
306 GST_DEBUG ("unref connection %p refcnt %d", conn, conn->refcount);
308 G_LOCK (connections_lock);
310 if ((zero = (conn->refcount == 0))) {
311 GST_DEBUG ("closing connection %p", conn);
312 /* remove from list, we can release the mutex after removing the connection
313 * from the list because after that, nobody can access the connection anymore. */
314 connections = g_list_remove (connections, conn);
316 G_UNLOCK (connections_lock);
318 /* if we are zero, close and cleanup the connection */
320 /* don't use conn->lock here. two reasons:
322 * 1) its not necessary: jack_deactivate() will not return until the JACK thread
323 * associated with this connection is cleaned up by a thread join, hence
324 * no more callbacks can occur or be in progress.
326 * 2) it would deadlock anyway, because jack_deactivate() will sleep
327 * waiting for the JACK thread, and can thus cause deadlock in
330 if ((res = jack_deactivate (conn->client))) {
331 /* we only warn, this means the server is probably shut down and the client
333 GST_WARNING ("Could not deactivate Jack client (%d)", res);
335 /* close connection */
336 if ((res = jack_client_close (conn->client))) {
337 /* we assume the client is gone. */
338 GST_WARNING ("close failed (%d)", res);
342 g_mutex_free (conn->lock);
343 g_cond_free (conn->flush_cond);
345 g_free (conn->server);
351 gst_jack_audio_connection_add_client (GstJackAudioConnection * conn,
352 GstJackAudioClient * client)
354 g_mutex_lock (conn->lock);
355 switch (client->type) {
356 case GST_JACK_CLIENT_SOURCE:
357 conn->src_clients = g_list_append (conn->src_clients, client);
360 case GST_JACK_CLIENT_SINK:
361 conn->sink_clients = g_list_append (conn->sink_clients, client);
365 g_warning ("trying to add unknown client type");
368 g_mutex_unlock (conn->lock);
372 gst_jack_audio_connection_remove_client (GstJackAudioConnection * conn,
373 GstJackAudioClient * client)
375 g_mutex_lock (conn->lock);
376 switch (client->type) {
377 case GST_JACK_CLIENT_SOURCE:
378 conn->src_clients = g_list_remove (conn->src_clients, client);
381 case GST_JACK_CLIENT_SINK:
382 conn->sink_clients = g_list_remove (conn->sink_clients, client);
386 g_warning ("trying to remove unknown client type");
389 g_mutex_unlock (conn->lock);
393 * gst_jack_audio_client_get:
395 * @server: the server to connect to or NULL for the default server
396 * @type: the client type
397 * @shutdown: a callback when the jack server shuts down
398 * @process: a callback when samples are available
399 * @buffer_size: a callback when the buffer_size changes
400 * @sample_rate: a callback when the sample_rate changes
401 * @user_data: user data passed to the callbacks
402 * @status: pointer to hold the jack status code in case of errors
404 * Get the jack client connection for @id and @server. Connections to the same
405 * @id and @server will receive the same physical Jack client connection and
406 * will therefore be scheduled in the same process callback.
408 * Returns: a #GstJackAudioClient.
411 gst_jack_audio_client_new (const gchar * id, const gchar * server,
412 jack_client_t * jclient, GstJackClientType type,
413 void (*shutdown) (void *arg), JackProcessCallback process,
414 JackBufferSizeCallback buffer_size, JackSampleRateCallback sample_rate,
415 gpointer user_data, jack_status_t * status)
417 GstJackAudioClient *client;
418 GstJackAudioConnection *conn;
420 g_return_val_if_fail (id != NULL, NULL);
421 g_return_val_if_fail (status != NULL, NULL);
423 /* first get a connection for the id/server pair */
424 conn = gst_jack_audio_get_connection (id, server, jclient, status);
428 GST_INFO ("new client %s", id);
430 /* make new client using the connection */
431 client = g_new (GstJackAudioClient, 1);
432 client->active = client->deactivate = FALSE;
435 client->shutdown = shutdown;
436 client->process = process;
437 client->buffer_size = buffer_size;
438 client->sample_rate = sample_rate;
439 client->user_data = user_data;
441 /* add the client to the connection */
442 gst_jack_audio_connection_add_client (conn, client);
449 GST_DEBUG ("Could not get server connection (%d)", *status);
455 * gst_jack_audio_client_free:
456 * @client: a #GstJackAudioClient
458 * Free the resources used by @client.
461 gst_jack_audio_client_free (GstJackAudioClient * client)
463 GstJackAudioConnection *conn;
465 g_return_if_fail (client != NULL);
467 GST_INFO ("free client");
471 /* remove from connection first so that it's not scheduled anymore after this
473 gst_jack_audio_connection_remove_client (conn, client);
474 gst_jack_audio_unref_connection (conn);
480 * gst_jack_audio_client_get_client:
481 * @client: a #GstJackAudioClient
483 * Get the jack audio client for @client. This function is used to perform
484 * operations on the jack server from this client.
486 * Returns: The jack audio client.
489 gst_jack_audio_client_get_client (GstJackAudioClient * client)
491 g_return_val_if_fail (client != NULL, NULL);
493 /* no lock needed, the connection and the client does not change
494 * once the client is created. */
495 return client->conn->client;
499 * gst_jack_audio_client_set_active:
500 * @client: a #GstJackAudioClient
501 * @active: new mode for the client
503 * Activate or deactive @client. When a client is activated it will receive
504 * callbacks when data should be processed.
506 * Returns: 0 if all ok.
509 gst_jack_audio_client_set_active (GstJackAudioClient * client, gboolean active)
511 g_return_val_if_fail (client != NULL, -1);
513 /* make sure that we are not dispatching the client */
514 g_mutex_lock (client->conn->lock);
515 if (client->active && !active) {
516 /* we need to process once more to flush the port */
517 client->deactivate = TRUE;
519 /* need to wait for process_cb run once more */
520 while (client->deactivate)
521 g_cond_wait (client->conn->flush_cond, client->conn->lock);
523 client->active = active;
524 g_mutex_unlock (client->conn->lock);