1 /* jack plug in for the Music Player Daemon (MPD)
2 * (c)2006 by anarch(anarchsss@gmail.com)
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.
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
18 #include "../audioOutput.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];
57 /*JackData *jd = NULL;*/
59 static JackData
*newJackData(void)
62 ret
= xcalloc(sizeof(JackData
), 1);
67 static void freeJackData(AudioOutput
*audioOutput
)
69 JackData
*jd
= audioOutput
->data
;
71 if (jd
->ringbuffer
[0])
72 jack_ringbuffer_free(jd
->ringbuffer
[0]);
73 if (jd
->ringbuffer
[1])
74 jack_ringbuffer_free(jd
->ringbuffer
[1]);
76 audioOutput
->data
= NULL
;
80 static void jack_finishDriver(AudioOutput
*audioOutput
)
82 JackData
*jd
= audioOutput
->data
;
85 if ( jd
&& jd
->client
) {
86 jack_deactivate(jd
->client
);
87 jack_client_close(jd
->client
);
89 DEBUG("disconnect_jack (pid=%d)\n", getpid ());
91 if ( strcmp(name
, "mpd") ) {
96 for ( i
= ARRAY_SIZE(output_ports
); --i
>= 0; ) {
99 free(output_ports
[i
]);
100 output_ports
[i
] = NULL
;
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
);
116 static int process(jack_nframes_t nframes
, void *arg
)
119 JackData
*jd
= (JackData
*) arg
;
120 jack_default_audio_sample_t
*out
[2];
121 size_t avail_data
, avail_frames
;
126 out
[0] = jack_port_get_buffer(jd
->ports
[0], nframes
);
127 out
[1] = jack_port_get_buffer(jd
->ports
[1], 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
;
140 jack_ringbuffer_read(jd
->ringbuffer
[0], (char *)out
[0],
142 jack_ringbuffer_read(jd
->ringbuffer
[1], (char *)out
[1],
145 nframes
-= avail_frames
;
146 out
[0] += avail_data
;
147 out
[1] += avail_data
;
149 for (i
= 0; i
< nframes
; i
++)
150 out
[0][i
] = out
[1][i
] = 0.0;
154 if (pthread_mutex_trylock (&play_audio_lock
) == 0) {
155 pthread_cond_signal (&play_audio
);
156 pthread_mutex_unlock (&play_audio_lock
);
161 /*DEBUG("process (pid=%d)\n", getpid());*/
165 static void shutdown_callback(void *arg
)
167 JackData
*jd
= (JackData
*) arg
;
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
)
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' "
206 bp
->name
, bp
->line
, bp
->value
);
209 output_ports
[0] = xstrdup(bp
->value
);
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
);
219 FATAL("Only %d values are supported for '%s' "
220 "at line %d\n", (int)ARRAY_SIZE(output_ports
),
224 if ( (bp
= getBlockParam(param
, "ringbuffer_size")) ) {
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
);
232 FATAL("%s is not a number; ringbuf_size=%d\n",
233 bp
->value
, ringbuf_sz
);
237 if ( (bp
= getBlockParam(param
, "name"))
238 && (strcmp(bp
->value
, "mpd") != 0) ) {
239 name
= xstrdup(bp
->value
);
240 DEBUG("name=%s\n", name
);
246 static int jack_testDefault(void)
251 static int connect_jack(AudioOutput
*audioOutput
)
253 JackData
*jd
= audioOutput
->data
;
257 if ( (jd
->client
= jack_client_new(name
)) == NULL
) {
258 ERROR("jack server not running?\n");
259 freeJackData(audioOutput
);
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
);
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
);
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
);
293 /* hay que buscar que hay */
294 if ( !output_ports
[1]
295 && (jports
= (char **)jack_get_ports(jd
->client
, NULL
, NULL
,
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]);
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 ",
317 freeJackData(audioOutput
);
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 ",
326 freeJackData(audioOutput
);
333 DEBUG("connect_jack (pid=%d)\n", getpid());
337 static int jack_openDevice(AudioOutput
*audioOutput
)
339 JackData
*jd
= audioOutput
->data
;
344 audioOutput
->data
= jd
;
346 if (connect_jack(audioOutput
) < 0) {
347 freeJackData(audioOutput
);
348 audioOutput
->open
= 0;
353 set_audioformat(audioOutput
);
354 audioOutput
->open
= 1;
356 DEBUG("jack_openDevice (pid=%d)!\n", getpid ());
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
;
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;
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
,
405 sample
= (jack_default_audio_sample_t
) *(buffer
++)/32768.0;
407 jack_ringbuffer_write(jd
->ringbuffer
[1], (void*)&sample
,
415 pthread_mutex_lock(&play_audio_lock
);
416 pthread_cond_wait(&play_audio
, &play_audio_lock
);
417 pthread_mutex_unlock(&play_audio_lock
);
424 AudioOutputPlugin jackPlugin
= {
431 jack_dropBufferedAudio
,
433 NULL
, /* sendMetadataFunc */
436 #else /* HAVE JACK */
438 DISABLED_AUDIO_OUTPUT_PLUGIN(jackPlugin
)
440 #endif /* HAVE_JACK */