1 /* runtime/weak dynamic JACK linking
3 * (C) 2014 Robin Gareus <robin@gareus.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "weak_libjack.h"
24 int have_libjack (void) {
34 #ifdef PLATFORM_WINDOWS
40 static void* lib_open(const char* const so) {
41 #ifdef PLATFORM_WINDOWS
42 return (void*) LoadLibraryA(so);
44 return dlopen(so, RTLD_NOW|RTLD_LOCAL);
48 static void* lib_symbol(void* const lib, const char* const sym) {
49 #ifdef PLATFORM_WINDOWS
50 return (void*) GetProcAddress((HMODULE)lib, sym);
52 return dlsym(lib, sym);
57 typedef void * pvoid_t;
58 #define MAPSYM(SYM, FAIL) _j._ ## SYM = (func_t)lib_symbol(lib, "jack_" # SYM); \
59 if (!_j._ ## SYM) err |= FAIL;
61 typedef void * __attribute__ ((__may_alias__)) pvoid_t;
62 #define MAPSYM(SYM, FAIL) *(pvoid_t *)(&_j._ ## SYM) = lib_symbol(lib, "jack_" # SYM); \
63 if (!_j._ ## SYM) err |= FAIL;
65 typedef void * __attribute__ ((__may_alias__)) pvoid_t;
66 #define MAPSYM(SYM, FAIL) *(pvoid_t *)(&_j._ ## SYM) = lib_symbol(lib, "jack_" # SYM); \
69 fprintf(stderr, "*** WEAK-JACK: required symbol 'jack_%s' was not found\n", "" # SYM); \
75 typedef void (* func_t) (void);
77 /* function pointers to the real jack API */
78 static struct WeakJack {
79 func_t _client_open; // special case due to varargs
81 #define JCFUN(ERR, RTYPE, NAME, RVAL) func_t _ ## NAME ;
82 #define JPFUN(ERR, RTYPE, NAME, DEF, ARGS, RVAL) func_t _ ## NAME ;
83 #define JXFUN(ERR, RTYPE, NAME, DEF, ARGS, CODE) func_t _ ## NAME ;
84 #define JVFUN(ERR, NAME, DEF, ARGS, CODE) func_t _ ## NAME ;
86 #include "weak_libjack.def"
94 static int _status = -1;
96 __attribute__((constructor))
97 static void init_weak_jack(void)
102 fprintf(stderr, "*** WEAK-JACK: initializing\n");
105 memset(&_j, 0, sizeof(_j));
108 lib = lib_open("libjack.dylib");
110 lib = lib_open("/usr/local/lib/libjack.dylib");
112 #elif (defined PLATFORM_WINDOWS)
113 # if ( defined(__x86_64__) || defined(_M_X64) )
114 lib = lib_open("libjack64.dll");
116 lib = lib_open("libjack.dll");
119 lib = lib_open("libjack.so.0");
123 fprintf(stderr, "*** WEAK-JACK: libjack was not found\n");
129 /* found library, now lookup functions */
130 MAPSYM(client_open, 2)
132 #define JCFUN(ERR, RTYPE, NAME, RVAL) MAPSYM(NAME, ERR)
133 #define JPFUN(ERR, RTYPE, NAME, DEF, ARGS, RVAL) MAPSYM(NAME, ERR)
134 #define JXFUN(ERR, RTYPE, NAME, DEF, ARGS, CODE) MAPSYM(NAME, ERR)
135 #define JVFUN(ERR, NAME, DEF, ARGS, CODE) MAPSYM(NAME, ERR)
137 #include "weak_libjack.def"
144 /* if a required symbol is not found, disable JACK completly */
146 _j._client_open = NULL;
150 fprintf(stderr, "*** WEAK-JACK: %s. (%d)\n", err ? "jack is not available" : "OK", _status);
154 int have_libjack (void) {
161 /*******************************************************************************
165 #if defined(__GNUC__) && (__GNUC__ > 2) && !defined(NDEBUG)
166 #define likely(expr) (__builtin_expect (!!(expr), 1))
168 #define likely(expr) (expr)
172 # define WJACK_WARNING(NAME) \
173 fprintf(stderr, "*** WEAK-JACK: function 'jack_%s' ignored\n", "" # NAME);
175 # define WJACK_WARNING(NAME) ;
178 /******************************************************************************
179 * JACK API wrapper functions.
181 * if a function pointer is set in the static struct WeakJack _j,
182 * the function is called directly.
183 * Otherwise a dummy NOOP implementation is provided.
184 * The latter is mainly for compile-time warnings.
186 * If libjack is not found, jack_client_open() will fail.
187 * In that case the application should not call any other libjack
188 * functions. Hence a real implementation is not needed.
189 * (jack ringbuffer may be an exception for some apps)
192 /* dedicated support for jack_client_open(,..) variable arg function macro */
193 func_t WJACK_get_client_open(void) {
197 return _j._client_open;
200 /* callback to set status */
201 jack_client_t * WJACK_no_client_open (const char *client_name, jack_options_t options, jack_status_t *status, ...) {
202 WJACK_WARNING(client_open);
203 if (status) { *status = JackFailure; }
207 /*******************************************************************************
208 * Macros to wrap jack API
211 /* abstraction for jack_client functions
212 * rtype jack_function_name (jack_client_t *client) { return rval; }
214 #define JCFUN(ERR, RTYPE, NAME, RVAL) \
215 RTYPE WJACK_ ## NAME (jack_client_t *client) { \
216 if likely(_j._ ## NAME) { \
217 return ((RTYPE (*)(jack_client_t *client)) _j._ ## NAME)(client); \
219 WJACK_WARNING(NAME) \
224 /* abstraction for NOOP functions with return value
225 * rtype jack_function_name (ARGS) { return rval; }
227 #define JPFUN(ERR, RTYPE, NAME, DEF, ARGS, RVAL) \
228 RTYPE WJACK_ ## NAME DEF { \
229 if likely(_j._ ## NAME) { \
230 return ((RTYPE (*)DEF) _j._ ## NAME) ARGS; \
232 WJACK_WARNING(NAME) \
237 /* abstraction for functions that need custom code.
238 * e.g. functions with return-value-pointer args,
239 * use CODE to initialize value
241 * rtype jack_function_name (ARGS) { CODE }
243 #define JXFUN(ERR, RTYPE, NAME, DEF, ARGS, CODE) \
244 RTYPE WJACK_ ## NAME DEF { \
245 if likely(_j._ ## NAME) { \
246 return ((RTYPE (*)DEF) _j._ ## NAME) ARGS; \
248 WJACK_WARNING(NAME) \
253 /* abstraction for void functions with return-value-pointer args
254 * void jack_function_name (ARGS) { CODE }
256 #define JVFUN(ERR, NAME, DEF, ARGS, CODE) \
257 void WJACK_ ## NAME DEF { \
258 if likely(_j._ ## NAME) { \
259 ((void (*)DEF) _j._ ## NAME) ARGS; \
261 WJACK_WARNING(NAME) \
266 #include "weak_libjack.def"
273 #endif // end USE_WEAK_JACK