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)