Initial revision 6759
[qball-mpd.git] / src / audioOutputs / .svn / text-base / audioOutput_jack.c.svn-base
blob1fdfaf4bb514e263d62bdfd6ff9b36429888956a
1 /* jack plug in for the Music Player Daemon (MPD)
2  * (c)2006 by anarch(anarchsss@gmail.com)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
18 #include "../audioOutput.h"
20 #ifdef HAVE_JACK
22 #include <stdlib.h>
23 #include <errno.h>
25 #include "../conf.h"
26 #include "../log.h"
28 #include <string.h>
29 #include <pthread.h>
31 #include <jack/jack.h>
32 #include <jack/types.h>
33 #include <jack/ringbuffer.h>
35 pthread_mutex_t play_audio_lock = PTHREAD_MUTEX_INITIALIZER;
36 pthread_cond_t  play_audio = PTHREAD_COND_INITIALIZER;
38 /*#include "dmalloc.h"*/
40 #define MIN(a, b) ((a) < (b) ? (a) : (b))
41 /*#define SAMPLE_SIZE  sizeof(jack_default_audio_sample_t);*/
44 static char *name = "mpd";
45 static char *output_ports[2];
46 static int ringbuf_sz = 32768;
47 size_t sample_size = sizeof(jack_default_audio_sample_t);
49 typedef struct _JackData {
50         jack_port_t *ports[2];
51         jack_client_t *client;
52         jack_ringbuffer_t *ringbuffer[2];
53         int bps;
54         int shutdown;
55 } JackData;
57 /*JackData *jd = NULL;*/
59 static JackData *newJackData(void)
61         JackData *ret;
62         ret = xcalloc(sizeof(JackData), 1);
64         return ret;
67 static void freeJackData(AudioOutput *audioOutput)
69         JackData *jd = audioOutput->data;
70         if (jd) {
71                 if (jd->ringbuffer[0])
72                         jack_ringbuffer_free(jd->ringbuffer[0]);
73                 if (jd->ringbuffer[1])
74                         jack_ringbuffer_free(jd->ringbuffer[1]);
75                 free(jd);
76                 audioOutput->data = NULL;
77         }
80 static void jack_finishDriver(AudioOutput *audioOutput)
82         JackData *jd = audioOutput->data;
83         int i;
85         if ( jd && jd->client ) {
86                 jack_deactivate(jd->client);
87                 jack_client_close(jd->client);
88         }
89         DEBUG("disconnect_jack (pid=%d)\n", getpid ());
91         if ( strcmp(name, "mpd") ) {
92                 free(name);
93                 name = "mpd";
94         }
96         for ( i = ARRAY_SIZE(output_ports); --i >= 0; ) {
97                 if (!output_ports[i])
98                         continue;
99                 free(output_ports[i]);
100                 output_ports[i] = NULL;
101         }
103         freeJackData(audioOutput);
106 static int srate(jack_nframes_t rate, void *data)
108         JackData *jd = (JackData *) ((AudioOutput*) data)->data;
109         AudioFormat *audioFormat = &(((AudioOutput*) data)->outAudioFormat);
111         audioFormat->sampleRate = (int)jack_get_sample_rate(jd->client);
113         return 0;
116 static int process(jack_nframes_t nframes, void *arg)
118         size_t i;
119         JackData *jd = (JackData *) arg;
120         jack_default_audio_sample_t *out[2];
121         size_t avail_data, avail_frames;
123         if ( nframes <= 0 )
124                 return 0;
126         out[0] = jack_port_get_buffer(jd->ports[0], nframes);
127         out[1] = jack_port_get_buffer(jd->ports[1], nframes);
129         while ( nframes ) {
130                 avail_data = jack_ringbuffer_read_space(jd->ringbuffer[1]);
132                 if ( avail_data > 0 ) {
133                     avail_frames = avail_data / sample_size;
135                     if (avail_frames > nframes) {
136                         avail_frames = nframes;
137                         avail_data = nframes*sample_size;
138                     }
140                     jack_ringbuffer_read(jd->ringbuffer[0], (char *)out[0],
141                                          avail_data);
142                     jack_ringbuffer_read(jd->ringbuffer[1], (char *)out[1],
143                                          avail_data);
145                     nframes -= avail_frames;
146                     out[0] += avail_data;
147                     out[1] += avail_data;
148                 } else {
149                     for (i = 0; i < nframes; i++)
150                         out[0][i] = out[1][i] = 0.0;
151                     nframes = 0;
152                 }
154                 if (pthread_mutex_trylock (&play_audio_lock) == 0) {
155                         pthread_cond_signal (&play_audio);
156                         pthread_mutex_unlock (&play_audio_lock);
157                 }
158         }
161         /*DEBUG("process (pid=%d)\n", getpid());*/
162         return 0;
165 static void shutdown_callback(void *arg)
167         JackData *jd = (JackData *) arg;
168         jd->shutdown = 1;
171 static void set_audioformat(AudioOutput *audioOutput)
173         JackData *jd = audioOutput->data;
174         AudioFormat *audioFormat = &audioOutput->outAudioFormat;
176         audioFormat->sampleRate = (int) jack_get_sample_rate(jd->client);
177         DEBUG("samplerate = %d\n", audioFormat->sampleRate);
178         audioFormat->channels = 2;
179         audioFormat->bits = 16;
180         jd->bps = audioFormat->channels
181                 * sizeof(jack_default_audio_sample_t)
182                 * audioFormat->sampleRate;
185 static void error_callback(const char *msg)
187         ERROR("jack: %s\n", msg);
190 static int jack_initDriver(AudioOutput *audioOutput, ConfigParam *param)
192         BlockParam *bp;
193         char *endptr;
194         int val;
195         char *cp = NULL;
197         DEBUG("jack_initDriver (pid=%d)\n", getpid());
198         if ( ! param ) return 0;
200         if ( (bp = getBlockParam(param, "ports")) ) {
201                 DEBUG("output_ports=%s\n", bp->value);
203                 if (!(cp = strchr(bp->value, ',')))
204                         FATAL("expected comma and a second value for '%s' "
205                               "at line %d: %s\n",
206                               bp->name, bp->line, bp->value);
208                 *cp = '\0';
209                 output_ports[0] = xstrdup(bp->value);
210                 *cp++ = ',';
212                 if (!*cp)
213                         FATAL("expected a second value for '%s' at line %d: "
214                               "%s\n", bp->name, bp->line, bp->value);
216                 output_ports[1] = xstrdup(cp);
218                 if (strchr(cp,','))
219                         FATAL("Only %d values are supported for '%s' "
220                               "at line %d\n", (int)ARRAY_SIZE(output_ports),
221                               bp->name, bp->line);
222         }
224         if ( (bp = getBlockParam(param, "ringbuffer_size")) ) {
225                 errno = 0;
226                 val = strtol(bp->value, &endptr, 10);
228                 if ( errno == 0 && endptr != bp->value) {
229                         ringbuf_sz = val < 32768 ? 32768 : val;
230                         DEBUG("ringbuffer_size=%d\n", ringbuf_sz);
231                 } else {
232                         FATAL("%s is not a number; ringbuf_size=%d\n",
233                               bp->value, ringbuf_sz);
234                 }
235         }
237         if ( (bp = getBlockParam(param, "name"))
238              && (strcmp(bp->value, "mpd") != 0) ) {
239                 name = xstrdup(bp->value);
240                 DEBUG("name=%s\n", name);
241         }
243         return 0;
246 static int jack_testDefault(void)
248         return 0;
251 static int connect_jack(AudioOutput *audioOutput)
253         JackData *jd = audioOutput->data;
254         char **jports;
255         char *port_name;
257         if ( (jd->client = jack_client_new(name)) == NULL ) {
258                 ERROR("jack server not running?\n");
259                 freeJackData(audioOutput);
260                 return -1;
261         }
263         jack_set_error_function(error_callback);
264         jack_set_process_callback(jd->client, process, (void *)jd);
265         jack_set_sample_rate_callback(jd->client, (JackProcessCallback)srate,
266                                       (void *)audioOutput);
267         jack_on_shutdown(jd->client, shutdown_callback, (void *)jd);
269         if ( jack_activate(jd->client) ) {
270                 ERROR("cannot activate client");
271                 freeJackData(audioOutput);
272                 return -1;
273         }
275         jd->ports[0] = jack_port_register(jd->client, "left",
276                                           JACK_DEFAULT_AUDIO_TYPE,
277                                           JackPortIsOutput, 0);
278         if ( !jd->ports[0] ) {
279                 ERROR("Cannot register left output port.\n");
280                 freeJackData(audioOutput);
281                 return -1;
282         }
284         jd->ports[1] = jack_port_register(jd->client, "right",
285                                           JACK_DEFAULT_AUDIO_TYPE,
286                                           JackPortIsOutput, 0);
287         if ( !jd->ports[1] ) {
288                 ERROR("Cannot register right output port.\n");
289                 freeJackData(audioOutput);
290                 return -1;
291         }
293         /*  hay que buscar que hay  */
294         if ( !output_ports[1]
295              && (jports = (char **)jack_get_ports(jd->client, NULL, NULL,
296                                                         JackPortIsPhysical|
297                                                         JackPortIsInput)) ) {
298                 output_ports[0] = jports[0];
299                 output_ports[1] = jports[1] ? jports[1] : jports[0];
300                 DEBUG("output_ports: %s %s\n", output_ports[0], output_ports[1]);
301                 free(jports);
302         }
304         if ( output_ports[1] ) {
305                 jd->ringbuffer[0] = jack_ringbuffer_create(ringbuf_sz);
306                 jd->ringbuffer[1] = jack_ringbuffer_create(ringbuf_sz);
307                 memset(jd->ringbuffer[0]->buf, 0, jd->ringbuffer[0]->size);
308                 memset(jd->ringbuffer[1]->buf, 0, jd->ringbuffer[1]->size);
310                 port_name = xmalloc(sizeof(char)*(7+strlen(name)));
312                 sprintf(port_name, "%s:left", name);
313                 if ( (jack_connect(jd->client, port_name,
314                                    output_ports[0])) != 0 ) {
315                         ERROR("%s is not a valid Jack Client / Port ",
316                               output_ports[0]);
317                         freeJackData(audioOutput);
318                         free(port_name);
319                         return -1;
320                 }
321                 sprintf(port_name, "%s:right", name);
322                 if ( (jack_connect(jd->client, port_name,
323                                    output_ports[1])) != 0 ) {
324                         ERROR("%s is not a valid Jack Client / Port ",
325                               output_ports[1]);
326                         freeJackData(audioOutput);
327                         free(port_name);
328                         return -1;
329                 }
330                 free(port_name);
331         }
333         DEBUG("connect_jack (pid=%d)\n", getpid());
334         return 1;
337 static int jack_openDevice(AudioOutput *audioOutput)
339         JackData *jd = audioOutput->data;
341         if ( !jd ) {
342                 DEBUG("connect!\n");
343                 jd = newJackData();
344                 audioOutput->data = jd;
346                 if (connect_jack(audioOutput) < 0) {
347                         freeJackData(audioOutput);
348                         audioOutput->open = 0;
349                         return -1;
350                 }
351         }
353         set_audioformat(audioOutput);
354         audioOutput->open = 1;
356         DEBUG("jack_openDevice (pid=%d)!\n", getpid ());
357         return 0;
361 static void jack_closeDevice(AudioOutput * audioOutput)
363         /*jack_finishDriver(audioOutput);*/
364         audioOutput->open = 0;
365         DEBUG("jack_closeDevice (pid=%d)\n", getpid());
368 static void jack_dropBufferedAudio (AudioOutput * audioOutput)
372 static int jack_playAudio(AudioOutput * audioOutput, char *buff, int size)
374         JackData *jd = audioOutput->data;
375         size_t space;
376         int i;
377         short *buffer = (short *) buff;
378         jack_default_audio_sample_t sample;
379         size_t samples = size/4;
381         /*DEBUG("jack_playAudio: (pid=%d)!\n", getpid());*/
383         if ( jd->shutdown ) {
384                 ERROR("Refusing to play, because there is no client thread.\n");
385                 freeJackData(audioOutput);
386                 audioOutput->open = 0;
387                 return 0;
388         }
390         while ( samples && !jd->shutdown ) {
392                 if ( (space = jack_ringbuffer_write_space(jd->ringbuffer[0]))
393                      >= samples*sample_size ) {
395                         /*space = MIN(space, samples*sample_size);*/
396                         /*space = samples*sample_size;*/
398                         /*for(i=0; i<space/sample_size; i++) {*/
399                         for(i=0; i<samples; i++) {
400                                 sample = (jack_default_audio_sample_t) *(buffer++)/32768.0;
402                                 jack_ringbuffer_write(jd->ringbuffer[0], (void*)&sample,
403                                                       sample_size);
405                                 sample = (jack_default_audio_sample_t) *(buffer++)/32768.0;
407                                 jack_ringbuffer_write(jd->ringbuffer[1], (void*)&sample,
408                                                       sample_size);
410                                 /*samples--;*/
411                         }
412                         samples=0;
414                 } else {
415                         pthread_mutex_lock(&play_audio_lock);
416                         pthread_cond_wait(&play_audio, &play_audio_lock);
417                         pthread_mutex_unlock(&play_audio_lock);
418                 }
420         }
421         return 0;
424 AudioOutputPlugin jackPlugin = {
425         "jack",
426         jack_testDefault,
427         jack_initDriver,
428         jack_finishDriver,
429         jack_openDevice,
430         jack_playAudio,
431         jack_dropBufferedAudio,
432         jack_closeDevice,
433         NULL,   /* sendMetadataFunc */
436 #else /* HAVE JACK */
438 DISABLED_AUDIO_OUTPUT_PLUGIN(jackPlugin)
440 #endif /* HAVE_JACK */