Add an option to prevent spawning a JACK server
[openal-soft.git] / Alc / backends / jack.c
blobf4d4e181985e56bc1a5eaeab0c610e0e6c7727e2
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <memory.h>
27 #include "alMain.h"
28 #include "alu.h"
29 #include "threads.h"
30 #include "compat.h"
32 #include "backends/base.h"
34 #include <jack/jack.h>
35 #include <jack/ringbuffer.h>
38 static const ALCchar jackDevice[] = "JACK Default";
41 #ifdef HAVE_DYNLOAD
42 #define JACK_FUNCS(MAGIC) \
43 MAGIC(jack_client_open); \
44 MAGIC(jack_client_close); \
45 MAGIC(jack_client_name_size); \
46 MAGIC(jack_get_client_name); \
47 MAGIC(jack_connect); \
48 MAGIC(jack_activate); \
49 MAGIC(jack_deactivate); \
50 MAGIC(jack_port_register); \
51 MAGIC(jack_port_unregister); \
52 MAGIC(jack_port_get_buffer); \
53 MAGIC(jack_port_name); \
54 MAGIC(jack_get_ports); \
55 MAGIC(jack_free); \
56 MAGIC(jack_get_sample_rate); \
57 MAGIC(jack_ringbuffer_create); \
58 MAGIC(jack_ringbuffer_free); \
59 MAGIC(jack_ringbuffer_get_read_vector); \
60 MAGIC(jack_ringbuffer_get_write_vector); \
61 MAGIC(jack_ringbuffer_read_advance); \
62 MAGIC(jack_ringbuffer_write_advance); \
63 MAGIC(jack_ringbuffer_write_space); \
64 MAGIC(jack_set_process_callback); \
65 MAGIC(jack_set_buffer_size_callback); \
66 MAGIC(jack_set_buffer_size); \
67 MAGIC(jack_get_buffer_size);
69 static void *jack_handle;
70 #define MAKE_FUNC(f) static __typeof(f) * p##f
71 JACK_FUNCS(MAKE_FUNC);
72 #undef MAKE_FUNC
74 #define jack_client_open pjack_client_open
75 #define jack_client_close pjack_client_close
76 #define jack_client_name_size pjack_client_name_size
77 #define jack_get_client_name pjack_get_client_name
78 #define jack_connect pjack_connect
79 #define jack_activate pjack_activate
80 #define jack_deactivate pjack_deactivate
81 #define jack_port_register pjack_port_register
82 #define jack_port_unregister pjack_port_unregister
83 #define jack_port_get_buffer pjack_port_get_buffer
84 #define jack_port_name pjack_port_name
85 #define jack_get_ports pjack_get_ports
86 #define jack_free pjack_free
87 #define jack_get_sample_rate pjack_get_sample_rate
88 #define jack_ringbuffer_create pjack_ringbuffer_create
89 #define jack_ringbuffer_free pjack_ringbuffer_free
90 #define jack_ringbuffer_get_read_vector pjack_ringbuffer_get_read_vector
91 #define jack_ringbuffer_get_write_vector pjack_ringbuffer_get_write_vector
92 #define jack_ringbuffer_read_advance pjack_ringbuffer_read_advance
93 #define jack_ringbuffer_write_advance pjack_ringbuffer_write_advance
94 #define jack_ringbuffer_write_space pjack_ringbuffer_write_space
95 #define jack_set_process_callback pjack_set_process_callback
96 #define jack_set_buffer_size_callback pjack_set_buffer_size_callback
97 #define jack_set_buffer_size pjack_set_buffer_size
98 #define jack_get_buffer_size pjack_get_buffer_size
99 #endif
102 static jack_options_t ClientOptions = JackNullOption;
104 static ALCboolean jack_load(void)
106 ALCboolean error = ALC_FALSE;
108 #ifdef HAVE_DYNLOAD
109 if(!jack_handle)
111 jack_handle = LoadLib("libjack.so.0");
112 if(!jack_handle)
113 return ALC_FALSE;
115 error = ALC_FALSE;
116 #define LOAD_FUNC(f) do { \
117 p##f = GetSymbol(jack_handle, #f); \
118 if(p##f == NULL) { \
119 error = ALC_TRUE; \
121 } while(0)
122 JACK_FUNCS(LOAD_FUNC);
123 #undef LOAD_FUNC
125 if(error)
127 CloseLib(jack_handle);
128 jack_handle = NULL;
129 return ALC_FALSE;
132 #endif
134 return !error;
138 typedef struct ALCjackPlayback {
139 DERIVE_FROM_TYPE(ALCbackend);
141 jack_client_t *Client;
142 jack_port_t *Port[MAX_OUTPUT_CHANNELS];
144 jack_ringbuffer_t *Ring;
145 alcnd_t Cond;
147 volatile int killNow;
148 althrd_t thread;
149 } ALCjackPlayback;
151 static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg);
153 static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg);
154 static int ALCjackPlayback_mixerProc(void *arg);
156 static void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device);
157 static void ALCjackPlayback_Destruct(ALCjackPlayback *self);
158 static ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name);
159 static void ALCjackPlayback_close(ALCjackPlayback *self);
160 static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self);
161 static ALCboolean ALCjackPlayback_start(ALCjackPlayback *self);
162 static void ALCjackPlayback_stop(ALCjackPlayback *self);
163 static DECLARE_FORWARD2(ALCjackPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
164 static DECLARE_FORWARD(ALCjackPlayback, ALCbackend, ALCuint, availableSamples)
165 static DECLARE_FORWARD(ALCjackPlayback, ALCbackend, ALint64, getLatency)
166 static void ALCjackPlayback_lock(ALCjackPlayback *self);
167 static void ALCjackPlayback_unlock(ALCjackPlayback *self);
168 DECLARE_DEFAULT_ALLOCATORS(ALCjackPlayback)
170 DEFINE_ALCBACKEND_VTABLE(ALCjackPlayback);
173 static void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device)
175 ALuint i;
177 ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
178 SET_VTABLE2(ALCjackPlayback, ALCbackend, self);
180 alcnd_init(&self->Cond);
182 self->Client = NULL;
183 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
184 self->Port[i] = NULL;
185 self->Ring = NULL;
187 self->killNow = 1;
190 static void ALCjackPlayback_Destruct(ALCjackPlayback *self)
192 ALuint i;
194 if(self->Client)
196 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
198 if(self->Port[i])
199 jack_port_unregister(self->Client, self->Port[i]);
200 self->Port[i] = NULL;
202 jack_client_close(self->Client);
203 self->Client = NULL;
206 alcnd_destroy(&self->Cond);
208 ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
212 static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg)
214 ALCjackPlayback *self = arg;
215 ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
216 ALuint bufsize;
218 ALCjackPlayback_lock(self);
219 if(ConfigValueUInt("jack", "buffer-size", &bufsize))
220 device->UpdateSize = maxu(numframes, NextPowerOf2(bufsize));
221 else
222 device->UpdateSize = numframes;
223 TRACE("%u update size x%u\n", device->UpdateSize, device->NumUpdates);
225 jack_ringbuffer_free(self->Ring);
226 self->Ring = jack_ringbuffer_create(device->UpdateSize * device->NumUpdates *
227 FrameSizeFromDevFmt(device->FmtChans, device->FmtType));
228 if(!self->Ring)
230 ERR("Failed to reallocate ringbuffer\n");
231 aluHandleDisconnect(device);
233 ALCjackPlayback_unlock(self);
234 return 0;
238 static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg)
240 ALCjackPlayback *self = arg;
241 ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
242 ALuint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
243 jack_default_audio_sample_t *out[MAX_OUTPUT_CHANNELS];
244 jack_ringbuffer_data_t data[2];
245 jack_nframes_t total = 0;
246 jack_nframes_t todo;
247 ALuint i, c, numchans;
249 jack_ringbuffer_get_read_vector(self->Ring, data);
251 for(c = 0;c < MAX_OUTPUT_CHANNELS && self->Port[c];c++)
252 out[c] = jack_port_get_buffer(self->Port[c], numframes);
253 numchans = c;
254 for(;c < MAX_OUTPUT_CHANNELS;c++)
255 out[c] = NULL;
257 todo = minu(numframes, data[0].len/frame_size);
258 for(c = 0;c < numchans;c++)
260 for(i = 0;i < todo;i++)
261 out[c][i] = ((ALfloat*)data[0].buf)[i*numchans + c];
262 out[c] += todo;
264 total += todo;
266 todo = minu(numframes-total, data[1].len/frame_size);
267 for(c = 0;c < numchans;c++)
269 for(i = 0;i < todo;i++)
270 out[c][i] = ((ALfloat*)data[1].buf)[i*numchans + c];
271 out[c] += todo;
273 total += todo;
275 jack_ringbuffer_read_advance(self->Ring, total*frame_size);
276 alcnd_signal(&self->Cond);
278 if(numframes > total)
280 todo = numframes-total;
281 for(c = 0;c < numchans;c++)
283 for(i = 0;i < todo;i++)
284 out[c][i] = 0.0f;
288 return 0;
291 static int ALCjackPlayback_mixerProc(void *arg)
293 ALCjackPlayback *self = arg;
294 ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
295 ALuint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
296 jack_ringbuffer_data_t data[2];
298 SetRTPriority();
299 althrd_setname(althrd_current(), MIXER_THREAD_NAME);
301 ALCjackPlayback_lock(self);
302 while(!self->killNow && device->Connected)
304 ALuint todo, len1, len2;
306 if(jack_ringbuffer_write_space(self->Ring)/frame_size < device->UpdateSize)
308 alcnd_wait(&self->Cond, &STATIC_CAST(ALCbackend,self)->mMutex);
309 continue;
312 jack_ringbuffer_get_write_vector(self->Ring, data);
313 todo = (data[0].len+data[1].len)/frame_size;
314 todo -= todo%device->UpdateSize;
316 len1 = minu(data[0].len/frame_size, todo);
317 len2 = minu(data[1].len/frame_size, todo-len1);
319 aluMixData(device, data[0].buf, len1);
320 if(len2 > 0)
321 aluMixData(device, data[1].buf, len2);
322 jack_ringbuffer_write_advance(self->Ring, todo*frame_size);
324 ALCjackPlayback_unlock(self);
326 return 0;
330 static ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name)
332 ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
333 const char *client_name = "alsoft";
334 jack_status_t status;
336 if(!name)
337 name = jackDevice;
338 else if(strcmp(name, jackDevice) != 0)
339 return ALC_INVALID_VALUE;
341 self->Client = jack_client_open(client_name, ClientOptions, &status, NULL);
342 if(self->Client == NULL)
344 ERR("jack_client_open() failed, status = 0x%02x\n", status);
345 return ALC_INVALID_VALUE;
347 if((status&JackServerStarted))
348 TRACE("JACK server started\n");
349 if((status&JackNameNotUnique))
351 client_name = jack_get_client_name(self->Client);
352 TRACE("Client name not unique, got `%s' instead\n", client_name);
355 jack_set_process_callback(self->Client, ALCjackPlayback_process, self);
356 jack_set_buffer_size_callback(self->Client, ALCjackPlayback_bufferSizeNotify, self);
358 al_string_copy_cstr(&device->DeviceName, name);
360 return ALC_NO_ERROR;
363 static void ALCjackPlayback_close(ALCjackPlayback *self)
365 ALuint i;
367 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
369 if(self->Port[i])
370 jack_port_unregister(self->Client, self->Port[i]);
371 self->Port[i] = NULL;
373 jack_client_close(self->Client);
374 self->Client = NULL;
377 static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self)
379 ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
380 ALuint numchans, i;
381 ALuint bufsize;
383 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
385 if(self->Port[i])
386 jack_port_unregister(self->Client, self->Port[i]);
387 self->Port[i] = NULL;
390 /* Ignore the requested buffer metrics and just keep one JACK-sized buffer
391 * ready for when requested. Note that even though the ringbuffer will have
392 * 2 periods worth of space, only half of it will be filled at a given time
393 * because there's one byte less of it that's writeable, and we only write
394 * in update-sized chunks. */
395 device->Frequency = jack_get_sample_rate(self->Client);
396 if(ConfigValueUInt("jack", "buffer-size", &bufsize))
397 device->UpdateSize = maxu(jack_get_buffer_size(self->Client), NextPowerOf2(bufsize));
398 else
399 device->UpdateSize = jack_get_buffer_size(self->Client);
400 device->NumUpdates = 2;
402 /* FIXME: Force stereo, 32-bit float output. */
403 device->FmtChans = DevFmtStereo;
404 device->FmtType = DevFmtFloat;
406 numchans = ChannelsFromDevFmt(device->FmtChans);
407 for(i = 0;i < numchans;i++)
409 char name[64];
410 snprintf(name, sizeof(name), "channel_%d", i+1);
411 self->Port[i] = jack_port_register(self->Client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
412 if(self->Port[i] == NULL)
414 ERR("Not enough JACK ports available for %s output\n", DevFmtChannelsString(device->FmtChans));
415 return ALC_FALSE;
419 if(self->Ring)
420 jack_ringbuffer_free(self->Ring);
421 self->Ring = jack_ringbuffer_create(device->UpdateSize * device->NumUpdates *
422 FrameSizeFromDevFmt(device->FmtChans, device->FmtType));
423 if(!self->Ring)
425 ERR("Failed to allocate ringbuffer\n");
426 return ALC_FALSE;
429 SetDefaultChannelOrder(device);
431 return ALC_TRUE;
434 static ALCboolean ALCjackPlayback_start(ALCjackPlayback *self)
436 const char **ports;
437 ALuint i;
439 if(jack_activate(self->Client))
441 ERR("Failed to activate client\n");
442 return ALC_FALSE;
445 ports = jack_get_ports(self->Client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
446 if(ports == NULL)
448 ERR("No physical playback ports found\n");
449 jack_deactivate(self->Client);
450 return ALC_FALSE;
452 for(i = 0;i < MAX_OUTPUT_CHANNELS && self->Port[i];i++)
454 if(!ports[i])
456 ERR("No physical playback port for \"%s\"\n", jack_port_name(self->Port[i]));
457 break;
459 if(jack_connect(self->Client, jack_port_name(self->Port[i]), ports[i]))
460 ERR("Failed to connect output port \"%s\" to \"%s\"\n", jack_port_name(self->Port[i]), ports[i]);
462 jack_free(ports);
464 self->killNow = 0;
465 if(althrd_create(&self->thread, ALCjackPlayback_mixerProc, self) != althrd_success)
467 jack_deactivate(self->Client);
468 return ALC_FALSE;
471 return ALC_TRUE;
474 static void ALCjackPlayback_stop(ALCjackPlayback *self)
476 int res;
478 if(self->killNow)
479 return;
481 self->killNow = 1;
482 ALCjackPlayback_lock(self);
483 alcnd_signal(&self->Cond);
484 ALCjackPlayback_unlock(self);
485 althrd_join(self->thread, &res);
487 jack_deactivate(self->Client);
491 static void ALCjackPlayback_lock(ALCjackPlayback *self)
493 almtx_lock(&STATIC_CAST(ALCbackend,self)->mMutex);
496 static void ALCjackPlayback_unlock(ALCjackPlayback *self)
498 almtx_unlock(&STATIC_CAST(ALCbackend,self)->mMutex);
502 typedef struct ALCjackBackendFactory {
503 DERIVE_FROM_TYPE(ALCbackendFactory);
504 } ALCjackBackendFactory;
505 #define ALCJACKBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCjackBackendFactory, ALCbackendFactory) } }
507 static ALCboolean ALCjackBackendFactory_init(ALCjackBackendFactory* UNUSED(self))
509 jack_client_t *client;
510 jack_status_t status;
512 if(!jack_load())
513 return ALC_FALSE;
515 if(!GetConfigValueBool("jack", "spawn-server", 1))
516 ClientOptions |= JackNoStartServer;
517 client = jack_client_open("alsoft", ClientOptions, &status, NULL);
518 if(client == NULL)
520 WARN("jack_client_open() failed, 0x%02x\n", status);
521 if((status&JackServerFailed))
522 ERR("Unable to connect to JACK server\n");
523 return ALC_FALSE;
526 jack_client_close(client);
527 return ALC_TRUE;
530 static void ALCjackBackendFactory_deinit(ALCjackBackendFactory* UNUSED(self))
532 #ifdef HAVE_DYNLOAD
533 if(jack_handle)
534 CloseLib(jack_handle);
535 jack_handle = NULL;
536 #endif
539 static ALCboolean ALCjackBackendFactory_querySupport(ALCjackBackendFactory* UNUSED(self), ALCbackend_Type type)
541 if(type == ALCbackend_Playback)
542 return ALC_TRUE;
543 return ALC_FALSE;
546 static void ALCjackBackendFactory_probe(ALCjackBackendFactory* UNUSED(self), enum DevProbe type)
548 switch(type)
550 case ALL_DEVICE_PROBE:
551 AppendAllDevicesList(jackDevice);
552 break;
554 case CAPTURE_DEVICE_PROBE:
555 break;
559 static ALCbackend* ALCjackBackendFactory_createBackend(ALCjackBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
561 if(type == ALCbackend_Playback)
563 ALCjackPlayback *backend;
565 backend = ALCjackPlayback_New(sizeof(*backend));
566 if(!backend) return NULL;
567 memset(backend, 0, sizeof(*backend));
569 ALCjackPlayback_Construct(backend, device);
571 return STATIC_CAST(ALCbackend, backend);
574 return NULL;
577 DEFINE_ALCBACKENDFACTORY_VTABLE(ALCjackBackendFactory);
580 ALCbackendFactory *ALCjackBackendFactory_getFactory(void)
582 static ALCjackBackendFactory factory = ALCJACKBACKENDFACTORY_INITIALIZER;
583 return STATIC_CAST(ALCbackendFactory, &factory);