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
32 #include "backends/base.h"
34 #include <jack/jack.h>
35 #include <jack/ringbuffer.h>
38 static const ALCchar jackDevice
[] = "JACK Default";
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); \
56 MAGIC(jack_get_sample_rate); \
57 MAGIC(jack_set_error_function); \
58 MAGIC(jack_set_process_callback); \
59 MAGIC(jack_set_buffer_size_callback); \
60 MAGIC(jack_set_buffer_size); \
61 MAGIC(jack_get_buffer_size);
63 static void *jack_handle
;
64 #define MAKE_FUNC(f) static __typeof(f) * p##f
65 JACK_FUNCS(MAKE_FUNC
);
68 #define jack_client_open pjack_client_open
69 #define jack_client_close pjack_client_close
70 #define jack_client_name_size pjack_client_name_size
71 #define jack_get_client_name pjack_get_client_name
72 #define jack_connect pjack_connect
73 #define jack_activate pjack_activate
74 #define jack_deactivate pjack_deactivate
75 #define jack_port_register pjack_port_register
76 #define jack_port_unregister pjack_port_unregister
77 #define jack_port_get_buffer pjack_port_get_buffer
78 #define jack_port_name pjack_port_name
79 #define jack_get_ports pjack_get_ports
80 #define jack_free pjack_free
81 #define jack_get_sample_rate pjack_get_sample_rate
82 #define jack_set_error_function pjack_set_error_function
83 #define jack_set_process_callback pjack_set_process_callback
84 #define jack_set_buffer_size_callback pjack_set_buffer_size_callback
85 #define jack_set_buffer_size pjack_set_buffer_size
86 #define jack_get_buffer_size pjack_get_buffer_size
90 static jack_options_t ClientOptions
= JackNullOption
;
92 static ALCboolean
jack_load(void)
94 ALCboolean error
= ALC_FALSE
;
99 al_string missing_funcs
= AL_STRING_INIT_STATIC();
102 #define JACKLIB "libjack.dll"
104 #define JACKLIB "libjack.so.0"
106 jack_handle
= LoadLib(JACKLIB
);
109 WARN("Failed to load %s\n", JACKLIB
);
114 #define LOAD_FUNC(f) do { \
115 p##f = GetSymbol(jack_handle, #f); \
118 alstr_append_cstr(&missing_funcs, "\n" #f); \
121 JACK_FUNCS(LOAD_FUNC
);
126 WARN("Missing expected functions:%s\n", alstr_get_cstr(missing_funcs
));
127 CloseLib(jack_handle
);
130 alstr_reset(&missing_funcs
);
138 typedef struct ALCjackPlayback
{
139 DERIVE_FROM_TYPE(ALCbackend
);
141 jack_client_t
*Client
;
142 jack_port_t
*Port
[MAX_OUTPUT_CHANNELS
];
144 ll_ringbuffer_t
*Ring
;
147 volatile int killNow
;
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 ClockLatency
ALCjackPlayback_getClockLatency(ALCjackPlayback
*self
);
166 static DECLARE_FORWARD(ALCjackPlayback
, ALCbackend
, void, lock
)
167 static DECLARE_FORWARD(ALCjackPlayback
, ALCbackend
, void, unlock
)
168 DECLARE_DEFAULT_ALLOCATORS(ALCjackPlayback
)
170 DEFINE_ALCBACKEND_VTABLE(ALCjackPlayback
);
173 static void ALCjackPlayback_Construct(ALCjackPlayback
*self
, ALCdevice
*device
)
177 ALCbackend_Construct(STATIC_CAST(ALCbackend
, self
), device
);
178 SET_VTABLE2(ALCjackPlayback
, ALCbackend
, self
);
180 alcnd_init(&self
->Cond
);
183 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
184 self
->Port
[i
] = NULL
;
190 static void ALCjackPlayback_Destruct(ALCjackPlayback
*self
)
196 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
199 jack_port_unregister(self
->Client
, self
->Port
[i
]);
200 self
->Port
[i
] = NULL
;
202 jack_client_close(self
->Client
);
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
;
218 ALCjackPlayback_lock(self
);
219 device
->UpdateSize
= numframes
;
220 device
->NumUpdates
= 2;
222 bufsize
= device
->UpdateSize
;
223 if(ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), "jack", "buffer-size", &bufsize
))
224 bufsize
= maxu(NextPowerOf2(bufsize
), device
->UpdateSize
);
225 bufsize
+= device
->UpdateSize
;
226 device
->NumUpdates
= bufsize
/ device
->UpdateSize
;
228 TRACE("%u update size x%u\n", device
->UpdateSize
, device
->NumUpdates
);
230 ll_ringbuffer_free(self
->Ring
);
231 self
->Ring
= ll_ringbuffer_create(bufsize
,
232 FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
, device
->AmbiOrder
)
236 ERR("Failed to reallocate ringbuffer\n");
237 aluHandleDisconnect(device
);
239 ALCjackPlayback_unlock(self
);
244 static int ALCjackPlayback_process(jack_nframes_t numframes
, void *arg
)
246 ALCjackPlayback
*self
= arg
;
247 jack_default_audio_sample_t
*out
[MAX_OUTPUT_CHANNELS
];
248 ll_ringbuffer_data_t data
[2];
249 jack_nframes_t total
= 0;
251 ALsizei i
, c
, numchans
;
253 ll_ringbuffer_get_read_vector(self
->Ring
, data
);
255 for(c
= 0;c
< MAX_OUTPUT_CHANNELS
&& self
->Port
[c
];c
++)
256 out
[c
] = jack_port_get_buffer(self
->Port
[c
], numframes
);
259 todo
= minu(numframes
, data
[0].len
);
260 for(c
= 0;c
< numchans
;c
++)
262 const ALfloat
*restrict in
= ((ALfloat
*)data
[0].buf
) + c
;
263 for(i
= 0;(jack_nframes_t
)i
< todo
;i
++)
264 out
[c
][i
] = in
[i
*numchans
];
269 todo
= minu(numframes
-total
, data
[1].len
);
272 for(c
= 0;c
< numchans
;c
++)
274 const ALfloat
*restrict in
= ((ALfloat
*)data
[1].buf
) + c
;
275 for(i
= 0;(jack_nframes_t
)i
< todo
;i
++)
276 out
[c
][i
] = in
[i
*numchans
];
282 ll_ringbuffer_read_advance(self
->Ring
, total
);
283 alcnd_signal(&self
->Cond
);
285 if(numframes
> total
)
287 todo
= numframes
-total
;
288 for(c
= 0;c
< numchans
;c
++)
290 for(i
= 0;(jack_nframes_t
)i
< todo
;i
++)
298 static int ALCjackPlayback_mixerProc(void *arg
)
300 ALCjackPlayback
*self
= arg
;
301 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
302 ll_ringbuffer_data_t data
[2];
305 althrd_setname(althrd_current(), MIXER_THREAD_NAME
);
307 ALCjackPlayback_lock(self
);
308 while(!self
->killNow
&& device
->Connected
)
310 ALuint todo
, len1
, len2
;
312 /* NOTE: Unfortunately, there is an unavoidable race condition here.
313 * It's possible for the process() method to run, updating the read
314 * pointer and signaling the condition variable, in between the mixer
315 * loop checking the write size and waiting for the condition variable.
316 * This will cause the mixer loop to wait until the *next* process()
317 * invocation, most likely writing silence for it.
319 * However, this should only happen if the mixer is running behind
320 * anyway (as ideally we'll be asleep in alcnd_wait by the time the
321 * process() method is invoked), so this behavior is not unwarranted.
322 * It's unfortunate since it'll be wasting time sleeping that could be
323 * used to catch up, but there's no way around it without blocking in
324 * the process() method.
326 if(ll_ringbuffer_write_space(self
->Ring
) < device
->UpdateSize
)
328 alcnd_wait(&self
->Cond
, &STATIC_CAST(ALCbackend
,self
)->mMutex
);
332 ll_ringbuffer_get_write_vector(self
->Ring
, data
);
333 todo
= data
[0].len
+ data
[1].len
;
334 todo
-= todo
%device
->UpdateSize
;
336 len1
= minu(data
[0].len
, todo
);
337 len2
= minu(data
[1].len
, todo
-len1
);
339 aluMixData(device
, data
[0].buf
, len1
);
341 aluMixData(device
, data
[1].buf
, len2
);
342 ll_ringbuffer_write_advance(self
->Ring
, todo
);
344 ALCjackPlayback_unlock(self
);
350 static ALCenum
ALCjackPlayback_open(ALCjackPlayback
*self
, const ALCchar
*name
)
352 ALCdevice
*device
= STATIC_CAST(ALCbackend
, self
)->mDevice
;
353 const char *client_name
= "alsoft";
354 jack_status_t status
;
358 else if(strcmp(name
, jackDevice
) != 0)
359 return ALC_INVALID_VALUE
;
361 self
->Client
= jack_client_open(client_name
, ClientOptions
, &status
, NULL
);
362 if(self
->Client
== NULL
)
364 ERR("jack_client_open() failed, status = 0x%02x\n", status
);
365 return ALC_INVALID_VALUE
;
367 if((status
&JackServerStarted
))
368 TRACE("JACK server started\n");
369 if((status
&JackNameNotUnique
))
371 client_name
= jack_get_client_name(self
->Client
);
372 TRACE("Client name not unique, got `%s' instead\n", client_name
);
375 jack_set_process_callback(self
->Client
, ALCjackPlayback_process
, self
);
376 jack_set_buffer_size_callback(self
->Client
, ALCjackPlayback_bufferSizeNotify
, self
);
378 alstr_copy_cstr(&device
->DeviceName
, name
);
383 static void ALCjackPlayback_close(ALCjackPlayback
*self
)
387 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
390 jack_port_unregister(self
->Client
, self
->Port
[i
]);
391 self
->Port
[i
] = NULL
;
393 jack_client_close(self
->Client
);
397 static ALCboolean
ALCjackPlayback_reset(ALCjackPlayback
*self
)
399 ALCdevice
*device
= STATIC_CAST(ALCbackend
, self
)->mDevice
;
403 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
406 jack_port_unregister(self
->Client
, self
->Port
[i
]);
407 self
->Port
[i
] = NULL
;
410 /* Ignore the requested buffer metrics and just keep one JACK-sized buffer
411 * ready for when requested. Note that one period's worth of audio in the
412 * ring buffer will always be left unfilled because one element of the ring
413 * buffer will not be writeable, and we only write in period-sized chunks.
415 device
->Frequency
= jack_get_sample_rate(self
->Client
);
416 device
->UpdateSize
= jack_get_buffer_size(self
->Client
);
417 device
->NumUpdates
= 2;
419 bufsize
= device
->UpdateSize
;
420 if(ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), "jack", "buffer-size", &bufsize
))
421 bufsize
= maxu(NextPowerOf2(bufsize
), device
->UpdateSize
);
422 bufsize
+= device
->UpdateSize
;
423 device
->NumUpdates
= bufsize
/ device
->UpdateSize
;
425 /* Force 32-bit float output. */
426 device
->FmtType
= DevFmtFloat
;
428 numchans
= ChannelsFromDevFmt(device
->FmtChans
, device
->AmbiOrder
);
429 for(i
= 0;i
< numchans
;i
++)
432 snprintf(name
, sizeof(name
), "channel_%d", i
+1);
433 self
->Port
[i
] = jack_port_register(self
->Client
, name
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
434 if(self
->Port
[i
] == NULL
)
436 ERR("Not enough JACK ports available for %s output\n", DevFmtChannelsString(device
->FmtChans
));
437 if(i
== 0) return ALC_FALSE
;
444 device
->FmtChans
= DevFmtMono
;
449 jack_port_unregister(self
->Client
, self
->Port
[i
]);
450 self
->Port
[i
] = NULL
;
452 device
->FmtChans
= DevFmtStereo
;
456 ll_ringbuffer_free(self
->Ring
);
457 self
->Ring
= ll_ringbuffer_create(bufsize
,
458 FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
, device
->AmbiOrder
)
462 ERR("Failed to allocate ringbuffer\n");
466 SetDefaultChannelOrder(device
);
471 static ALCboolean
ALCjackPlayback_start(ALCjackPlayback
*self
)
476 if(jack_activate(self
->Client
))
478 ERR("Failed to activate client\n");
482 ports
= jack_get_ports(self
->Client
, NULL
, NULL
, JackPortIsPhysical
|JackPortIsInput
);
485 ERR("No physical playback ports found\n");
486 jack_deactivate(self
->Client
);
489 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
&& self
->Port
[i
];i
++)
493 ERR("No physical playback port for \"%s\"\n", jack_port_name(self
->Port
[i
]));
496 if(jack_connect(self
->Client
, jack_port_name(self
->Port
[i
]), ports
[i
]))
497 ERR("Failed to connect output port \"%s\" to \"%s\"\n", jack_port_name(self
->Port
[i
]), ports
[i
]);
502 if(althrd_create(&self
->thread
, ALCjackPlayback_mixerProc
, self
) != althrd_success
)
504 jack_deactivate(self
->Client
);
511 static void ALCjackPlayback_stop(ALCjackPlayback
*self
)
519 /* Lock the backend to ensure we don't flag the mixer to die and signal the
520 * mixer to wake up in between it checking the flag and going to sleep and
521 * wait for a wakeup (potentially leading to it never waking back up to see
523 ALCjackPlayback_lock(self
);
524 ALCjackPlayback_unlock(self
);
525 alcnd_signal(&self
->Cond
);
526 althrd_join(self
->thread
, &res
);
528 jack_deactivate(self
->Client
);
532 static ClockLatency
ALCjackPlayback_getClockLatency(ALCjackPlayback
*self
)
534 ALCdevice
*device
= STATIC_CAST(ALCbackend
, self
)->mDevice
;
537 ALCjackPlayback_lock(self
);
538 ret
.ClockTime
= GetDeviceClockTime(device
);
539 ret
.Latency
= ll_ringbuffer_read_space(self
->Ring
) * DEVICE_CLOCK_RES
/
541 ALCjackPlayback_unlock(self
);
547 static void jack_msg_handler(const char *message
)
549 WARN("%s\n", message
);
552 typedef struct ALCjackBackendFactory
{
553 DERIVE_FROM_TYPE(ALCbackendFactory
);
554 } ALCjackBackendFactory
;
555 #define ALCJACKBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCjackBackendFactory, ALCbackendFactory) } }
557 static ALCboolean
ALCjackBackendFactory_init(ALCjackBackendFactory
* UNUSED(self
))
559 jack_client_t
*client
;
560 jack_status_t status
;
565 if(!GetConfigValueBool(NULL
, "jack", "spawn-server", 0))
566 ClientOptions
|= JackNoStartServer
;
568 jack_set_error_function(jack_msg_handler
);
569 client
= jack_client_open("alsoft", ClientOptions
, &status
, NULL
);
570 jack_set_error_function(NULL
);
573 WARN("jack_client_open() failed, 0x%02x\n", status
);
574 if((status
&JackServerFailed
) && !(ClientOptions
&JackNoStartServer
))
575 ERR("Unable to connect to JACK server\n");
579 jack_client_close(client
);
583 static void ALCjackBackendFactory_deinit(ALCjackBackendFactory
* UNUSED(self
))
587 CloseLib(jack_handle
);
592 static ALCboolean
ALCjackBackendFactory_querySupport(ALCjackBackendFactory
* UNUSED(self
), ALCbackend_Type type
)
594 if(type
== ALCbackend_Playback
)
599 static void ALCjackBackendFactory_probe(ALCjackBackendFactory
* UNUSED(self
), enum DevProbe type
)
603 case ALL_DEVICE_PROBE
:
604 AppendAllDevicesList(jackDevice
);
607 case CAPTURE_DEVICE_PROBE
:
612 static ALCbackend
* ALCjackBackendFactory_createBackend(ALCjackBackendFactory
* UNUSED(self
), ALCdevice
*device
, ALCbackend_Type type
)
614 if(type
== ALCbackend_Playback
)
616 ALCjackPlayback
*backend
;
617 NEW_OBJ(backend
, ALCjackPlayback
)(device
);
618 if(!backend
) return NULL
;
619 return STATIC_CAST(ALCbackend
, backend
);
625 DEFINE_ALCBACKENDFACTORY_VTABLE(ALCjackBackendFactory
);
628 ALCbackendFactory
*ALCjackBackendFactory_getFactory(void)
630 static ALCjackBackendFactory factory
= ALCJACKBACKENDFACTORY_INITIALIZER
;
631 return STATIC_CAST(ALCbackendFactory
, &factory
);