Merge remote-tracking branch 'remotes/origin/upstream/1.6' into tizen
[platform/upstream/gst-plugins-good.git] / ext / jack / gstjackaudioclient.c
1 /* GStreamer
2  * Copyright (C) 2006 Wim Taymans <wim@fluendo.com>
3  *
4  * gstjackaudioclient.c: jack audio client implementation
5  *
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.
10  *
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.
15  *
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.
20  */
21
22 #include <string.h>
23
24 #include "gstjackaudioclient.h"
25 #include "gstjack.h"
26
27 #include <gst/glib-compat-private.h>
28
29 GST_DEBUG_CATEGORY_STATIC (gst_jack_audio_client_debug);
30 #define GST_CAT_DEFAULT gst_jack_audio_client_debug
31
32 static void
33 jack_log_error (const gchar * msg)
34 {
35   GST_ERROR ("%s", msg);
36 }
37
38 static void
39 jack_info_error (const gchar * msg)
40 {
41   GST_INFO ("%s", msg);
42 }
43
44 void
45 gst_jack_audio_client_init (void)
46 {
47   GST_DEBUG_CATEGORY_INIT (gst_jack_audio_client_debug, "jackclient", 0,
48       "jackclient helpers");
49
50   jack_set_error_function (jack_log_error);
51   jack_set_info_function (jack_info_error);
52 }
53
54 /* a list of global connections indexed by id and server. */
55 G_LOCK_DEFINE_STATIC (connections_lock);
56 static GList *connections;
57
58 /* the connection to a server  */
59 typedef struct
60 {
61   gint refcount;
62   GMutex lock;
63   GCond flush_cond;
64
65   /* id/server pair and the connection */
66   gchar *id;
67   gchar *server;
68   jack_client_t *client;
69
70   /* lists of GstJackAudioClients */
71   gint n_clients;
72   GList *src_clients;
73   GList *sink_clients;
74
75   /* transport state handling */
76   gint cur_ts;
77   GstState transport_state;
78 } GstJackAudioConnection;
79
80 /* an object sharing a jack_client_t connection. */
81 struct _GstJackAudioClient
82 {
83   GstJackAudioConnection *conn;
84
85   GstJackClientType type;
86   gboolean active;
87   gboolean deactivate;
88
89   JackShutdownCallback shutdown;
90   JackProcessCallback process;
91   JackBufferSizeCallback buffer_size;
92   JackSampleRateCallback sample_rate;
93   gpointer user_data;
94 };
95
96 typedef struct
97 {
98   jack_nframes_t nframes;
99   gpointer user_data;
100 } JackCB;
101
102 static gboolean
103 jack_handle_transport_change (GstJackAudioClient * client, GstState state)
104 {
105   GstObject *obj = GST_OBJECT_PARENT (client->user_data);
106   guint mode;
107
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));
114     return TRUE;
115   }
116   return FALSE;
117 }
118
119 static int
120 jack_process_cb (jack_nframes_t nframes, void *arg)
121 {
122   GstJackAudioConnection *conn = (GstJackAudioConnection *) arg;
123   GList *walk;
124   int res = 0;
125   jack_transport_state_t ts = jack_transport_query (conn->client, NULL);
126
127   if (ts != conn->cur_ts) {
128     conn->cur_ts = ts;
129     switch (ts) {
130       case JackTransportStopped:
131         GST_DEBUG ("transport state is 'stopped'");
132         conn->transport_state = GST_STATE_PAUSED;
133         break;
134       case JackTransportStarting:
135         GST_DEBUG ("transport state is 'starting'");
136         conn->transport_state = GST_STATE_READY;
137         break;
138       case JackTransportRolling:
139         GST_DEBUG ("transport state is 'rolling'");
140         conn->transport_state = GST_STATE_PLAYING;
141         break;
142       default:
143         break;
144     }
145     GST_DEBUG ("num of clients: src=%d, sink=%d",
146         g_list_length (conn->src_clients), g_list_length (conn->sink_clients));
147   }
148
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;
155
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);
162       }
163     }
164   }
165   for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
166     GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
167
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);
174       }
175     }
176   }
177
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;
185         break;
186       }
187     }
188   }
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;
194         break;
195       }
196     }
197   }
198   g_mutex_unlock (&conn->lock);
199
200   return res;
201 }
202
203 /* we error out */
204 static int
205 jack_sample_rate_cb (jack_nframes_t nframes, void *arg)
206 {
207   return 0;
208 }
209
210 /* we error out */
211 static int
212 jack_buffer_size_cb (jack_nframes_t nframes, void *arg)
213 {
214   return 0;
215 }
216
217 static void
218 jack_shutdown_cb (void *arg)
219 {
220   GstJackAudioConnection *conn = (GstJackAudioConnection *) arg;
221   GList *walk;
222
223   GST_DEBUG ("disconnect client %s from server %s", conn->id,
224       GST_STR_NULL (conn->server));
225
226   g_mutex_lock (&conn->lock);
227   for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
228     GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
229
230     if (client->shutdown)
231       client->shutdown (client->user_data);
232   }
233   for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
234     GstJackAudioClient *client = (GstJackAudioClient *) walk->data;
235
236     if (client->shutdown)
237       client->shutdown (client->user_data);
238   }
239   g_mutex_unlock (&conn->lock);
240 }
241
242 typedef struct
243 {
244   const gchar *id;
245   const gchar *server;
246 } FindData;
247
248 static gint
249 connection_find (GstJackAudioConnection * conn, FindData * data)
250 {
251   /* id's must match */
252   if (strcmp (conn->id, data->id))
253     return 1;
254
255   /* both the same or NULL */
256   if (conn->server == data->server)
257     return 0;
258
259   /* we cannot compare NULL */
260   if (conn->server == NULL || data->server == NULL)
261     return 1;
262
263   if (strcmp (conn->server, data->server))
264     return 1;
265
266   return 0;
267 }
268
269 /* make a connection with @id and @server. Returns NULL on failure with the
270  * status set. */
271 static GstJackAudioConnection *
272 gst_jack_audio_make_connection (const gchar * id, const gchar * server,
273     jack_client_t * jclient, jack_status_t * status)
274 {
275   GstJackAudioConnection *conn;
276   jack_options_t options;
277   gint res;
278
279   *status = 0;
280
281   GST_DEBUG ("new client %s, connecting to server %s", id,
282       GST_STR_NULL (server));
283
284   /* never start a server */
285   options = JackNoStartServer;
286   /* if we have a servername, use it */
287   if (server != NULL)
288     options |= JackServerName;
289   /* open the client */
290   if (jclient == NULL)
291     jclient = jack_client_open (id, options, status, server);
292   if (jclient == NULL)
293     goto could_not_open;
294
295   /* now create object */
296   conn = g_new (GstJackAudioConnection, 1);
297   conn->refcount = 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;
303   conn->n_clients = 0;
304   conn->src_clients = NULL;
305   conn->sink_clients = NULL;
306   conn->cur_ts = -1;
307   conn->transport_state = GST_STATE_VOID_PENDING;
308
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);
315
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;
320
321   GST_DEBUG ("opened connection %p", conn);
322
323   return conn;
324
325   /* ERRORS */
326 could_not_open:
327   {
328     GST_DEBUG ("failed to open jack client, %d", *status);
329     return NULL;
330   }
331 could_not_activate:
332   {
333     GST_ERROR ("Could not activate client (%d)", res);
334     *status = JackFailure;
335     g_mutex_clear (&conn->lock);
336     g_free (conn->id);
337     g_free (conn->server);
338     g_free (conn);
339     return NULL;
340   }
341 }
342
343 static GstJackAudioConnection *
344 gst_jack_audio_get_connection (const gchar * id, const gchar * server,
345     jack_client_t * jclient, jack_status_t * status)
346 {
347   GstJackAudioConnection *conn;
348   GList *found;
349   FindData data;
350
351   GST_DEBUG ("getting connection for id %s, server %s", id,
352       GST_STR_NULL (server));
353
354   data.id = id;
355   data.server = server;
356
357   G_LOCK (connections_lock);
358   found =
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;
363     conn->refcount++;
364
365     GST_DEBUG ("found connection %p", conn);
366   } else {
367     /* make new connection */
368     conn = gst_jack_audio_make_connection (id, server, jclient, status);
369     if (conn != NULL) {
370       GST_DEBUG ("created connection %p", conn);
371       /* add to list on success */
372       connections = g_list_prepend (connections, conn);
373     } else {
374       GST_WARNING ("could not create connection");
375     }
376   }
377   G_UNLOCK (connections_lock);
378
379   return conn;
380 }
381
382 static void
383 gst_jack_audio_unref_connection (GstJackAudioConnection * conn)
384 {
385   gint res;
386   gboolean zero;
387
388   GST_DEBUG ("unref connection %p refcnt %d", conn, conn->refcount);
389
390   G_LOCK (connections_lock);
391   conn->refcount--;
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);
397   }
398   G_UNLOCK (connections_lock);
399
400   /* if we are zero, close and cleanup the connection */
401   if (zero) {
402     /* don't use conn->lock here. two reasons:
403      *
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.
407      *
408      * 2) it would deadlock anyway, because jack_deactivate() will sleep
409      *      waiting for the JACK thread, and can thus cause deadlock in 
410      *      jack_process_cb()
411      */
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
415        * is gone anyway. */
416       GST_WARNING ("Could not deactivate Jack client (%d)", res);
417     }
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);
422     }
423
424     /* free resources */
425     g_mutex_clear (&conn->lock);
426     g_cond_clear (&conn->flush_cond);
427     g_free (conn->id);
428     g_free (conn->server);
429     g_free (conn);
430   }
431 }
432
433 static void
434 gst_jack_audio_connection_add_client (GstJackAudioConnection * conn,
435     GstJackAudioClient * client)
436 {
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);
441       conn->n_clients++;
442       break;
443     case GST_JACK_CLIENT_SINK:
444       conn->sink_clients = g_list_append (conn->sink_clients, client);
445       conn->n_clients++;
446       break;
447     default:
448       g_warning ("trying to add unknown client type");
449       break;
450   }
451   g_mutex_unlock (&conn->lock);
452 }
453
454 static void
455 gst_jack_audio_connection_remove_client (GstJackAudioConnection * conn,
456     GstJackAudioClient * client)
457 {
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);
462       conn->n_clients--;
463       break;
464     case GST_JACK_CLIENT_SINK:
465       conn->sink_clients = g_list_remove (conn->sink_clients, client);
466       conn->n_clients--;
467       break;
468     default:
469       g_warning ("trying to remove unknown client type");
470       break;
471   }
472   g_mutex_unlock (&conn->lock);
473 }
474
475 /**
476  * gst_jack_audio_client_get:
477  * @id: the client id
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
486  *
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.
490  * 
491  * Returns: a #GstJackAudioClient.
492  */
493 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)
499 {
500   GstJackAudioClient *client;
501   GstJackAudioConnection *conn;
502
503   g_return_val_if_fail (id != NULL, NULL);
504   g_return_val_if_fail (status != NULL, NULL);
505
506   /* first get a connection for the id/server pair */
507   conn = gst_jack_audio_get_connection (id, server, jclient, status);
508   if (conn == NULL)
509     goto no_connection;
510
511   GST_INFO ("new client %s", id);
512
513   /* make new client using the connection */
514   client = g_new (GstJackAudioClient, 1);
515   client->active = client->deactivate = FALSE;
516   client->conn = conn;
517   client->type = type;
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;
523
524   /* add the client to the connection */
525   gst_jack_audio_connection_add_client (conn, client);
526
527   return client;
528
529   /* ERRORS */
530 no_connection:
531   {
532     GST_DEBUG ("Could not get server connection (%d)", *status);
533     return NULL;
534   }
535 }
536
537 /**
538  * gst_jack_audio_client_free:
539  * @client: a #GstJackAudioClient
540  *
541  * Free the resources used by @client.
542  */
543 void
544 gst_jack_audio_client_free (GstJackAudioClient * client)
545 {
546   GstJackAudioConnection *conn;
547
548   g_return_if_fail (client != NULL);
549
550   GST_INFO ("free client");
551
552   conn = client->conn;
553
554   /* remove from connection first so that it's not scheduled anymore after this
555    * call */
556   gst_jack_audio_connection_remove_client (conn, client);
557   gst_jack_audio_unref_connection (conn);
558
559   g_free (client);
560 }
561
562 /**
563  * gst_jack_audio_client_get_client:
564  * @client: a #GstJackAudioClient
565  *
566  * Get the jack audio client for @client. This function is used to perform
567  * operations on the jack server from this client.
568  *
569  * Returns: The jack audio client.
570  */
571 jack_client_t *
572 gst_jack_audio_client_get_client (GstJackAudioClient * client)
573 {
574   g_return_val_if_fail (client != NULL, NULL);
575
576   /* no lock needed, the connection and the client does not change 
577    * once the client is created. */
578   return client->conn->client;
579 }
580
581 /**
582  * gst_jack_audio_client_set_active:
583  * @client: a #GstJackAudioClient
584  * @active: new mode for the client
585  *
586  * Activate or deactive @client. When a client is activated it will receive
587  * callbacks when data should be processed.
588  *
589  * Returns: 0 if all ok.
590  */
591 gint
592 gst_jack_audio_client_set_active (GstJackAudioClient * client, gboolean active)
593 {
594   g_return_val_if_fail (client != NULL, -1);
595
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;
601
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);
605   }
606   client->active = active;
607   g_mutex_unlock (&client->conn->lock);
608
609   return 0;
610 }
611
612 /**
613  * gst_jack_audio_client_get_transport_state:
614  * @client: a #GstJackAudioClient
615  *
616  * Check the current transport state. The client can use this to request a state
617  * change from the application.
618  *
619  * Returns: the state, %GST_STATE_VOID_PENDING for no change in the transport
620  * state
621  */
622 GstState
623 gst_jack_audio_client_get_transport_state (GstJackAudioClient * client)
624 {
625   GstState state = client->conn->transport_state;
626
627   client->conn->transport_state = GST_STATE_VOID_PENDING;
628   return state;
629 }