Mercurial > hg > sonic-visualiser
comparison audioio/AudioJACKTarget.cpp @ 2:42a78f0e8fe2
* Use pkgconfig to look up Vamp library and header details if possible
* Use runtime dlopen for JACK library when JACK support is enabled in a static
build on Linux
author | Chris Cannam |
---|---|
date | Mon, 31 Jul 2006 16:15:45 +0000 |
parents | cd5d7ff8ef38 |
children | fbd7a497fd89 |
comparison
equal
deleted
inserted
replaced
1:40116f709d3b | 2:42a78f0e8fe2 |
---|---|
21 #include <iostream> | 21 #include <iostream> |
22 #include <cmath> | 22 #include <cmath> |
23 | 23 |
24 //#define DEBUG_AUDIO_JACK_TARGET 1 | 24 //#define DEBUG_AUDIO_JACK_TARGET 1 |
25 | 25 |
26 #ifdef BUILD_STATIC | |
27 #ifdef Q_OS_LINUX | |
28 | |
29 // Some lunacy to enable JACK support in static builds. JACK isn't | |
30 // supposed to be linked statically, because it depends on a | |
31 // consistent shared memory layout between client library and daemon, | |
32 // so it's very fragile in the face of version mismatches. | |
33 // | |
34 // Therefore for static builds on Linux we avoid linking against JACK | |
35 // at all during the build, instead using dlopen and runtime symbol | |
36 // lookup to switch on JACK support at runtime. The following big | |
37 // mess (down to the #endifs) is the code that implements this. | |
38 | |
39 static void *symbol(const char *name) | |
40 { | |
41 static bool attempted = false; | |
42 static void *library = 0; | |
43 static std::map<const char *, void *> symbols; | |
44 if (symbols.find(name) != symbols.end()) return symbols[name]; | |
45 if (!library) { | |
46 if (!attempted) { | |
47 library = ::dlopen("libjack.so.1", RTLD_NOW); | |
48 if (!library) library = ::dlopen("libjack.so.0", RTLD_NOW); | |
49 if (!library) library = ::dlopen("libjack.so", RTLD_NOW); | |
50 if (!library) { | |
51 std::cerr << "WARNING: AudioJACKTarget: Failed to load JACK library: " | |
52 << ::dlerror() << " (tried .so, .so.0, .so.1)" | |
53 << std::endl; | |
54 } | |
55 attempted = true; | |
56 } | |
57 if (!library) return 0; | |
58 } | |
59 void *symbol = ::dlsym(library, name); | |
60 if (!symbol) { | |
61 std::cerr << "WARNING: AudioJACKTarget: Failed to locate symbol " | |
62 << name << ": " << ::dlerror() << std::endl; | |
63 } | |
64 symbols[name] = symbol; | |
65 return symbol; | |
66 } | |
67 | |
68 static int dynamic_jack_set_process_callback(jack_client_t *client, | |
69 JackProcessCallback process_callback, | |
70 void *arg) | |
71 { | |
72 typedef int (*func)(jack_client_t *client, | |
73 JackProcessCallback process_callback, | |
74 void *arg); | |
75 void *s = symbol("jack_set_process_callback"); | |
76 if (!s) return 1; | |
77 func f = (func)s; | |
78 return f(client, process_callback, arg); | |
79 } | |
80 | |
81 static const char **dynamic_jack_get_ports(jack_client_t *client, | |
82 const char *port_name_pattern, | |
83 const char *type_name_pattern, | |
84 unsigned long flags) | |
85 { | |
86 typedef const char **(*func)(jack_client_t *client, | |
87 const char *port_name_pattern, | |
88 const char *type_name_pattern, | |
89 unsigned long flags); | |
90 void *s = symbol("jack_get_ports"); | |
91 if (!s) return 0; | |
92 func f = (func)s; | |
93 return f(client, port_name_pattern, type_name_pattern, flags); | |
94 } | |
95 | |
96 static jack_port_t *dynamic_jack_port_register(jack_client_t *client, | |
97 const char *port_name, | |
98 const char *port_type, | |
99 unsigned long flags, | |
100 unsigned long buffer_size) | |
101 { | |
102 typedef jack_port_t *(*func)(jack_client_t *client, | |
103 const char *port_name, | |
104 const char *port_type, | |
105 unsigned long flags, | |
106 unsigned long buffer_size); | |
107 void *s = symbol("jack_port_register"); | |
108 if (!s) return 0; | |
109 func f = (func)s; | |
110 return f(client, port_name, port_type, flags, buffer_size); | |
111 } | |
112 | |
113 static int dynamic_jack_connect(jack_client_t *client, | |
114 const char *source, | |
115 const char *dest) | |
116 { | |
117 typedef int (*func)(jack_client_t *client, | |
118 const char *source, | |
119 const char *dest); | |
120 void *s = symbol("jack_connect"); | |
121 if (!s) return 1; | |
122 func f = (func)s; | |
123 return f(client, source, dest); | |
124 } | |
125 | |
126 static void *dynamic_jack_port_get_buffer(jack_port_t *port, | |
127 jack_nframes_t sz) | |
128 { | |
129 typedef void *(*func)(jack_port_t *, jack_nframes_t); | |
130 void *s = symbol("jack_port_get_buffer"); | |
131 if (!s) return 0; | |
132 func f = (func)s; | |
133 return f(port, sz); | |
134 } | |
135 | |
136 static int dynamic_jack_port_unregister(jack_client_t *client, | |
137 jack_port_t *port) | |
138 { | |
139 typedef int(*func)(jack_client_t *, jack_port_t *); | |
140 void *s = symbol("jack_port_unregister"); | |
141 if (!s) return 0; | |
142 func f = (func)s; | |
143 return f(client, port); | |
144 } | |
145 | |
146 #define dynamic1(rv, name, argtype, failval) \ | |
147 static rv dynamic_##name(argtype arg) { \ | |
148 typedef rv (*func) (argtype); \ | |
149 void *s = symbol(#name); \ | |
150 if (!s) return failval; \ | |
151 func f = (func) s; \ | |
152 return f(arg); \ | |
153 } | |
154 | |
155 dynamic1(jack_client_t *, jack_client_new, const char *, 0); | |
156 dynamic1(jack_nframes_t, jack_get_buffer_size, jack_client_t *, 0); | |
157 dynamic1(jack_nframes_t, jack_get_sample_rate, jack_client_t *, 0); | |
158 dynamic1(int, jack_activate, jack_client_t *, 1); | |
159 dynamic1(int, jack_deactivate, jack_client_t *, 1); | |
160 dynamic1(int, jack_client_close, jack_client_t *, 1); | |
161 dynamic1(jack_nframes_t, jack_port_get_latency, jack_port_t *, 0); | |
162 dynamic1(const char *, jack_port_name, const jack_port_t *, 0); | |
163 | |
164 #define jack_client_new dynamic_jack_client_new | |
165 #define jack_get_buffer_size dynamic_jack_get_buffer_size | |
166 #define jack_get_sample_rate dynamic_jack_get_sample_rate | |
167 #define jack_set_process_callback dynamic_jack_set_process_callback | |
168 #define jack_activate dynamic_jack_activate | |
169 #define jack_deactivate dynamic_jack_deactivate | |
170 #define jack_client_close dynamic_jack_client_close | |
171 #define jack_get_ports dynamic_jack_get_ports | |
172 #define jack_port_register dynamic_jack_port_register | |
173 #define jack_port_unregister dynamic_jack_port_unregister | |
174 #define jack_port_get_latency dynamic_jack_port_get_latency | |
175 #define jack_port_name dynamic_jack_port_name | |
176 #define jack_connect dynamic_jack_connect | |
177 #define jack_port_get_buffer dynamic_jack_port_get_buffer | |
178 | |
179 #endif | |
180 #endif | |
181 | |
26 AudioJACKTarget::AudioJACKTarget(AudioCallbackPlaySource *source) : | 182 AudioJACKTarget::AudioJACKTarget(AudioCallbackPlaySource *source) : |
27 AudioCallbackPlayTarget(source), | 183 AudioCallbackPlayTarget(source), |
28 m_client(0), | 184 m_client(0), |
29 m_bufferSize(0), | 185 m_bufferSize(0), |
30 m_sampleRate(0) | 186 m_sampleRate(0) |