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);
48 static void *jack_handle
;
49 #define MAKE_FUNC(f) static __typeof(f) * p##f
50 JACK_FUNCS(MAKE_FUNC
);
53 #define jack_client_open pjack_client_open
54 #define jack_client_close pjack_client_close
55 #define jack_client_name_size pjack_client_name_size
56 #define jack_get_client_name pjack_get_client_name
60 static ALCboolean
jack_load(void)
62 ALCboolean error
= ALC_FALSE
;
67 jack_handle
= LoadLib("libjack.so.0");
72 #define LOAD_FUNC(f) do { \
73 p##f = GetSymbol(jack_handle, #f); \
78 JACK_FUNCS(LOAD_FUNC
);
83 CloseLib(jack_handle
);
94 typedef struct ALCjackPlayback
{
95 DERIVE_FROM_TYPE(ALCbackend
);
97 jack_client_t
*Client
;
103 static void ALCjackPlayback_Construct(ALCjackPlayback
*self
, ALCdevice
*device
);
104 static void ALCjackPlayback_Destruct(ALCjackPlayback
*self
);
105 static ALCenum
ALCjackPlayback_open(ALCjackPlayback
*self
, const ALCchar
*name
);
106 static void ALCjackPlayback_close(ALCjackPlayback
*self
);
107 static ALCboolean
ALCjackPlayback_reset(ALCjackPlayback
*self
);
108 static ALCboolean
ALCjackPlayback_start(ALCjackPlayback
*self
);
109 static void ALCjackPlayback_stop(ALCjackPlayback
*self
);
110 static DECLARE_FORWARD2(ALCjackPlayback
, ALCbackend
, ALCenum
, captureSamples
, void*, ALCuint
)
111 static DECLARE_FORWARD(ALCjackPlayback
, ALCbackend
, ALCuint
, availableSamples
)
112 static DECLARE_FORWARD(ALCjackPlayback
, ALCbackend
, ALint64
, getLatency
)
113 static DECLARE_FORWARD(ALCjackPlayback
, ALCbackend
, void, lock
)
114 static DECLARE_FORWARD(ALCjackPlayback
, ALCbackend
, void, unlock
)
115 DECLARE_DEFAULT_ALLOCATORS(ALCjackPlayback
)
117 DEFINE_ALCBACKEND_VTABLE(ALCjackPlayback
);
120 static void ALCjackPlayback_Construct(ALCjackPlayback
*self
, ALCdevice
*device
)
122 ALCbackend_Construct(STATIC_CAST(ALCbackend
, self
), device
);
123 SET_VTABLE2(ALCjackPlayback
, ALCbackend
, self
);
129 static void ALCjackPlayback_Destruct(ALCjackPlayback
*self
)
132 jack_client_close(self
->Client
);
135 ALCbackend_Destruct(STATIC_CAST(ALCbackend
, self
));
139 static ALCenum
ALCjackPlayback_open(ALCjackPlayback
*self
, const ALCchar
*name
)
141 ALCdevice
*device
= STATIC_CAST(ALCbackend
, self
)->mDevice
;
145 else if(strcmp(name
, jackDevice
) != 0)
146 return ALC_INVALID_VALUE
;
149 al_string_copy_cstr(&device
->DeviceName
, name
);
151 return ALC_INVALID_VALUE
;
154 static void ALCjackPlayback_close(ALCjackPlayback
*UNUSED(self
))
158 static ALCboolean
ALCjackPlayback_reset(ALCjackPlayback
*UNUSED(self
))
160 //jack_set_process_callback (client, process, &data);
164 static ALCboolean
ALCjackPlayback_start(ALCjackPlayback
*UNUSED(self
))
169 static void ALCjackPlayback_stop(ALCjackPlayback
*self
)
177 althrd_join(self
->thread
, &res
);
181 typedef struct ALCjackBackendFactory
{
182 DERIVE_FROM_TYPE(ALCbackendFactory
);
183 } ALCjackBackendFactory
;
184 #define ALCJACKBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCjackBackendFactory, ALCbackendFactory) } }
186 static ALCboolean
ALCjackBackendFactory_init(ALCjackBackendFactory
* UNUSED(self
))
188 jack_client_t
*client
;
189 jack_status_t status
;
194 client
= jack_client_open("alsoft", 0, &status
, NULL
);
197 WARN("jack_client_open() failed, 0x%02x\n", status
);
198 if((status
&JackServerFailed
))
199 ERR("Unable to connect to JACK server\n");
203 jack_client_close(client
);
207 static void ALCjackBackendFactory_deinit(ALCjackBackendFactory
* UNUSED(self
))
211 CloseLib(jack_handle
);
216 static ALCboolean
ALCjackBackendFactory_querySupport(ALCjackBackendFactory
* UNUSED(self
), ALCbackend_Type type
)
218 if(type
== ALCbackend_Playback
)
223 static void ALCjackBackendFactory_probe(ALCjackBackendFactory
* UNUSED(self
), enum DevProbe type
)
227 case ALL_DEVICE_PROBE
:
228 AppendAllDevicesList(jackDevice
);
231 case CAPTURE_DEVICE_PROBE
:
236 static ALCbackend
* ALCjackBackendFactory_createBackend(ALCjackBackendFactory
* UNUSED(self
), ALCdevice
*device
, ALCbackend_Type type
)
238 if(type
== ALCbackend_Playback
)
240 ALCjackPlayback
*backend
;
242 backend
= ALCjackPlayback_New(sizeof(*backend
));
243 if(!backend
) return NULL
;
244 memset(backend
, 0, sizeof(*backend
));
246 ALCjackPlayback_Construct(backend
, device
);
248 return STATIC_CAST(ALCbackend
, backend
);
254 DEFINE_ALCBACKENDFACTORY_VTABLE(ALCjackBackendFactory
);
257 ALCbackendFactory
*ALCjackBackendFactory_getFactory(void)
259 static ALCjackBackendFactory factory
= ALCJACKBACKENDFACTORY_INITIALIZER
;
260 return STATIC_CAST(ALCbackendFactory
, &factory
);