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_process_callback); \
58 MAGIC(jack_set_buffer_size_callback); \
59 MAGIC(jack_set_buffer_size); \
60 MAGIC(jack_get_buffer_size);
62 static void *jack_handle
;
63 #define MAKE_FUNC(f) static __typeof(f) * p##f
64 JACK_FUNCS(MAKE_FUNC
);
67 #define jack_client_open pjack_client_open
68 #define jack_client_close pjack_client_close
69 #define jack_client_name_size pjack_client_name_size
70 #define jack_get_client_name pjack_get_client_name
71 #define jack_connect pjack_connect
72 #define jack_activate pjack_activate
73 #define jack_deactivate pjack_deactivate
74 #define jack_port_register pjack_port_register
75 #define jack_port_unregister pjack_port_unregister
76 #define jack_port_get_buffer pjack_port_get_buffer
77 #define jack_port_name pjack_port_name
78 #define jack_get_ports pjack_get_ports
79 #define jack_free pjack_free
80 #define jack_get_sample_rate pjack_get_sample_rate
81 #define jack_set_process_callback pjack_set_process_callback
82 #define jack_set_buffer_size_callback pjack_set_buffer_size_callback
83 #define jack_set_buffer_size pjack_set_buffer_size
84 #define jack_get_buffer_size pjack_get_buffer_size
88 static jack_options_t ClientOptions
= JackNullOption
;
90 static ALCboolean
jack_load(void)
92 ALCboolean error
= ALC_FALSE
;
97 jack_handle
= LoadLib("libjack.so.0");
102 #define LOAD_FUNC(f) do { \
103 p##f = GetSymbol(jack_handle, #f); \
108 JACK_FUNCS(LOAD_FUNC
);
113 CloseLib(jack_handle
);
124 typedef struct ALCjackPlayback
{
125 DERIVE_FROM_TYPE(ALCbackend
);
127 jack_client_t
*Client
;
128 jack_port_t
*Port
[MAX_OUTPUT_CHANNELS
];
130 ll_ringbuffer_t
*Ring
;
133 volatile int killNow
;
137 static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes
, void *arg
);
139 static int ALCjackPlayback_process(jack_nframes_t numframes
, void *arg
);
140 static int ALCjackPlayback_mixerProc(void *arg
);
142 static void ALCjackPlayback_Construct(ALCjackPlayback
*self
, ALCdevice
*device
);
143 static void ALCjackPlayback_Destruct(ALCjackPlayback
*self
);
144 static ALCenum
ALCjackPlayback_open(ALCjackPlayback
*self
, const ALCchar
*name
);
145 static void ALCjackPlayback_close(ALCjackPlayback
*self
);
146 static ALCboolean
ALCjackPlayback_reset(ALCjackPlayback
*self
);
147 static ALCboolean
ALCjackPlayback_start(ALCjackPlayback
*self
);
148 static void ALCjackPlayback_stop(ALCjackPlayback
*self
);
149 static DECLARE_FORWARD2(ALCjackPlayback
, ALCbackend
, ALCenum
, captureSamples
, void*, ALCuint
)
150 static DECLARE_FORWARD(ALCjackPlayback
, ALCbackend
, ALCuint
, availableSamples
)
151 static ALint64
ALCjackPlayback_getLatency(ALCjackPlayback
*self
);
152 static void ALCjackPlayback_lock(ALCjackPlayback
*self
);
153 static void ALCjackPlayback_unlock(ALCjackPlayback
*self
);
154 DECLARE_DEFAULT_ALLOCATORS(ALCjackPlayback
)
156 DEFINE_ALCBACKEND_VTABLE(ALCjackPlayback
);
159 static void ALCjackPlayback_Construct(ALCjackPlayback
*self
, ALCdevice
*device
)
163 ALCbackend_Construct(STATIC_CAST(ALCbackend
, self
), device
);
164 SET_VTABLE2(ALCjackPlayback
, ALCbackend
, self
);
166 alcnd_init(&self
->Cond
);
169 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
170 self
->Port
[i
] = NULL
;
176 static void ALCjackPlayback_Destruct(ALCjackPlayback
*self
)
182 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
185 jack_port_unregister(self
->Client
, self
->Port
[i
]);
186 self
->Port
[i
] = NULL
;
188 jack_client_close(self
->Client
);
192 alcnd_destroy(&self
->Cond
);
194 ALCbackend_Destruct(STATIC_CAST(ALCbackend
, self
));
198 static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes
, void *arg
)
200 ALCjackPlayback
*self
= arg
;
201 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
204 ALCjackPlayback_lock(self
);
205 device
->UpdateSize
= numframes
;
206 device
->NumUpdates
= 2;
207 TRACE("%u update size x%u\n", device
->UpdateSize
, device
->NumUpdates
);
209 bufsize
= device
->UpdateSize
;
210 if(ConfigValueUInt("jack", "buffer-size", &bufsize
))
211 bufsize
= maxu(NextPowerOf2(bufsize
), device
->UpdateSize
);
212 bufsize
+= device
->UpdateSize
;
214 ll_ringbuffer_free(self
->Ring
);
215 self
->Ring
= ll_ringbuffer_create(bufsize
, FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
));
218 ERR("Failed to reallocate ringbuffer\n");
219 aluHandleDisconnect(device
);
221 ALCjackPlayback_unlock(self
);
226 static int ALCjackPlayback_process(jack_nframes_t numframes
, void *arg
)
228 ALCjackPlayback
*self
= arg
;
229 jack_default_audio_sample_t
*out
[MAX_OUTPUT_CHANNELS
];
230 ll_ringbuffer_data_t data
[2];
231 jack_nframes_t total
= 0;
233 ALuint i
, c
, numchans
;
235 ll_ringbuffer_get_read_vector(self
->Ring
, data
);
237 for(c
= 0;c
< MAX_OUTPUT_CHANNELS
&& self
->Port
[c
];c
++)
238 out
[c
] = jack_port_get_buffer(self
->Port
[c
], numframes
);
241 todo
= minu(numframes
, data
[0].len
);
242 for(c
= 0;c
< numchans
;c
++)
244 for(i
= 0;i
< todo
;i
++)
245 out
[c
][i
] = ((ALfloat
*)data
[0].buf
)[i
*numchans
+ c
];
250 todo
= minu(numframes
-total
, data
[1].len
);
253 for(c
= 0;c
< numchans
;c
++)
255 for(i
= 0;i
< todo
;i
++)
256 out
[c
][i
] = ((ALfloat
*)data
[1].buf
)[i
*numchans
+ c
];
262 ll_ringbuffer_read_advance(self
->Ring
, total
);
263 alcnd_signal(&self
->Cond
);
265 if(numframes
> total
)
267 todo
= numframes
-total
;
268 for(c
= 0;c
< numchans
;c
++)
270 for(i
= 0;i
< todo
;i
++)
278 static int ALCjackPlayback_mixerProc(void *arg
)
280 ALCjackPlayback
*self
= arg
;
281 ALCdevice
*device
= STATIC_CAST(ALCbackend
,self
)->mDevice
;
282 ll_ringbuffer_data_t data
[2];
285 althrd_setname(althrd_current(), MIXER_THREAD_NAME
);
287 ALCjackPlayback_lock(self
);
288 while(!self
->killNow
&& device
->Connected
)
290 ALuint todo
, len1
, len2
;
292 if(ll_ringbuffer_write_space(self
->Ring
) < device
->UpdateSize
)
294 alcnd_wait(&self
->Cond
, &STATIC_CAST(ALCbackend
,self
)->mMutex
);
298 ll_ringbuffer_get_write_vector(self
->Ring
, data
);
299 todo
= data
[0].len
+ data
[1].len
;
300 todo
-= todo
%device
->UpdateSize
;
302 len1
= minu(data
[0].len
, todo
);
303 len2
= minu(data
[1].len
, todo
-len1
);
305 aluMixData(device
, data
[0].buf
, len1
);
307 aluMixData(device
, data
[1].buf
, len2
);
308 ll_ringbuffer_write_advance(self
->Ring
, todo
);
310 ALCjackPlayback_unlock(self
);
316 static ALCenum
ALCjackPlayback_open(ALCjackPlayback
*self
, const ALCchar
*name
)
318 ALCdevice
*device
= STATIC_CAST(ALCbackend
, self
)->mDevice
;
319 const char *client_name
= "alsoft";
320 jack_status_t status
;
324 else if(strcmp(name
, jackDevice
) != 0)
325 return ALC_INVALID_VALUE
;
327 self
->Client
= jack_client_open(client_name
, ClientOptions
, &status
, NULL
);
328 if(self
->Client
== NULL
)
330 ERR("jack_client_open() failed, status = 0x%02x\n", status
);
331 return ALC_INVALID_VALUE
;
333 if((status
&JackServerStarted
))
334 TRACE("JACK server started\n");
335 if((status
&JackNameNotUnique
))
337 client_name
= jack_get_client_name(self
->Client
);
338 TRACE("Client name not unique, got `%s' instead\n", client_name
);
341 jack_set_process_callback(self
->Client
, ALCjackPlayback_process
, self
);
342 jack_set_buffer_size_callback(self
->Client
, ALCjackPlayback_bufferSizeNotify
, self
);
344 al_string_copy_cstr(&device
->DeviceName
, name
);
349 static void ALCjackPlayback_close(ALCjackPlayback
*self
)
353 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
356 jack_port_unregister(self
->Client
, self
->Port
[i
]);
357 self
->Port
[i
] = NULL
;
359 jack_client_close(self
->Client
);
363 static ALCboolean
ALCjackPlayback_reset(ALCjackPlayback
*self
)
365 ALCdevice
*device
= STATIC_CAST(ALCbackend
, self
)->mDevice
;
369 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
372 jack_port_unregister(self
->Client
, self
->Port
[i
]);
373 self
->Port
[i
] = NULL
;
376 /* Ignore the requested buffer metrics and just keep one JACK-sized buffer
377 * ready for when requested. Note that one period's worth of audio in the
378 * ring buffer will always be left unfilled because one element of the ring
379 * buffer will not be writeable, and we only write in period-sized chunks.
381 device
->Frequency
= jack_get_sample_rate(self
->Client
);
382 device
->UpdateSize
= jack_get_buffer_size(self
->Client
);
383 device
->NumUpdates
= 2;
385 bufsize
= device
->UpdateSize
;
386 if(ConfigValueUInt("jack", "buffer-size", &bufsize
))
387 bufsize
= maxu(NextPowerOf2(bufsize
), device
->UpdateSize
);
388 bufsize
+= device
->UpdateSize
;
390 /* Force 32-bit float output. */
391 device
->FmtType
= DevFmtFloat
;
393 numchans
= ChannelsFromDevFmt(device
->FmtChans
);
394 for(i
= 0;i
< numchans
;i
++)
397 snprintf(name
, sizeof(name
), "channel_%d", i
+1);
398 self
->Port
[i
] = jack_port_register(self
->Client
, name
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
399 if(self
->Port
[i
] == NULL
)
401 ERR("Not enough JACK ports available for %s output\n", DevFmtChannelsString(device
->FmtChans
));
402 if(i
== 0) return ALC_FALSE
;
409 device
->FmtChans
= DevFmtMono
;
414 jack_port_unregister(self
->Client
, self
->Port
[i
]);
415 self
->Port
[i
] = NULL
;
417 device
->FmtChans
= DevFmtStereo
;
421 ll_ringbuffer_free(self
->Ring
);
422 self
->Ring
= ll_ringbuffer_create(bufsize
, FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
));
425 ERR("Failed to allocate ringbuffer\n");
429 SetDefaultChannelOrder(device
);
434 static ALCboolean
ALCjackPlayback_start(ALCjackPlayback
*self
)
439 if(jack_activate(self
->Client
))
441 ERR("Failed to activate client\n");
445 ports
= jack_get_ports(self
->Client
, NULL
, NULL
, JackPortIsPhysical
|JackPortIsInput
);
448 ERR("No physical playback ports found\n");
449 jack_deactivate(self
->Client
);
452 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
&& self
->Port
[i
];i
++)
456 ERR("No physical playback port for \"%s\"\n", jack_port_name(self
->Port
[i
]));
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
]);
465 if(althrd_create(&self
->thread
, ALCjackPlayback_mixerProc
, self
) != althrd_success
)
467 jack_deactivate(self
->Client
);
474 static void ALCjackPlayback_stop(ALCjackPlayback
*self
)
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 ALint64
ALCjackPlayback_getLatency(ALCjackPlayback
*self
)
493 ALCdevice
*device
= STATIC_CAST(ALCbackend
, self
)->mDevice
;
496 ALCjackPlayback_lock(self
);
497 latency
= ll_ringbuffer_read_space(self
->Ring
);
498 ALCjackPlayback_unlock(self
);
500 return latency
* 1000000000 / device
->Frequency
;
504 static void ALCjackPlayback_lock(ALCjackPlayback
*self
)
506 almtx_lock(&STATIC_CAST(ALCbackend
,self
)->mMutex
);
509 static void ALCjackPlayback_unlock(ALCjackPlayback
*self
)
511 almtx_unlock(&STATIC_CAST(ALCbackend
,self
)->mMutex
);
515 typedef struct ALCjackBackendFactory
{
516 DERIVE_FROM_TYPE(ALCbackendFactory
);
517 } ALCjackBackendFactory
;
518 #define ALCJACKBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCjackBackendFactory, ALCbackendFactory) } }
520 static ALCboolean
ALCjackBackendFactory_init(ALCjackBackendFactory
* UNUSED(self
))
522 jack_client_t
*client
;
523 jack_status_t status
;
528 if(!GetConfigValueBool("jack", "spawn-server", 0))
529 ClientOptions
|= JackNoStartServer
;
530 client
= jack_client_open("alsoft", ClientOptions
, &status
, NULL
);
533 WARN("jack_client_open() failed, 0x%02x\n", status
);
534 if((status
&JackServerFailed
) && !(ClientOptions
&JackNoStartServer
))
535 ERR("Unable to connect to JACK server\n");
539 jack_client_close(client
);
543 static void ALCjackBackendFactory_deinit(ALCjackBackendFactory
* UNUSED(self
))
547 CloseLib(jack_handle
);
552 static ALCboolean
ALCjackBackendFactory_querySupport(ALCjackBackendFactory
* UNUSED(self
), ALCbackend_Type type
)
554 if(type
== ALCbackend_Playback
)
559 static void ALCjackBackendFactory_probe(ALCjackBackendFactory
* UNUSED(self
), enum DevProbe type
)
563 case ALL_DEVICE_PROBE
:
564 AppendAllDevicesList(jackDevice
);
567 case CAPTURE_DEVICE_PROBE
:
572 static ALCbackend
* ALCjackBackendFactory_createBackend(ALCjackBackendFactory
* UNUSED(self
), ALCdevice
*device
, ALCbackend_Type type
)
574 if(type
== ALCbackend_Playback
)
576 ALCjackPlayback
*backend
;
578 backend
= ALCjackPlayback_New(sizeof(*backend
));
579 if(!backend
) return NULL
;
580 memset(backend
, 0, sizeof(*backend
));
582 ALCjackPlayback_Construct(backend
, device
);
584 return STATIC_CAST(ALCbackend
, backend
);
590 DEFINE_ALCBACKENDFACTORY_VTABLE(ALCjackBackendFactory
);
593 ALCbackendFactory
*ALCjackBackendFactory_getFactory(void)
595 static ALCjackBackendFactory factory
= ALCJACKBACKENDFACTORY_INITIALIZER
;
596 return STATIC_CAST(ALCbackendFactory
, &factory
);