00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifdef HAVE_JACK
00017
00018 #include "AudioJACKTarget.h"
00019 #include "AudioCallbackPlaySource.h"
00020
00021 #include <iostream>
00022 #include <cmath>
00023
00024
00025
00026 #ifdef BUILD_STATIC
00027 #ifdef Q_OS_LINUX
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 static void *symbol(const char *name)
00040 {
00041 static bool attempted = false;
00042 static void *library = 0;
00043 static std::map<const char *, void *> symbols;
00044 if (symbols.find(name) != symbols.end()) return symbols[name];
00045 if (!library) {
00046 if (!attempted) {
00047 library = ::dlopen("libjack.so.1", RTLD_NOW);
00048 if (!library) library = ::dlopen("libjack.so.0", RTLD_NOW);
00049 if (!library) library = ::dlopen("libjack.so", RTLD_NOW);
00050 if (!library) {
00051 std::cerr << "WARNING: AudioJACKTarget: Failed to load JACK library: "
00052 << ::dlerror() << " (tried .so, .so.0, .so.1)"
00053 << std::endl;
00054 }
00055 attempted = true;
00056 }
00057 if (!library) return 0;
00058 }
00059 void *symbol = ::dlsym(library, name);
00060 if (!symbol) {
00061 std::cerr << "WARNING: AudioJACKTarget: Failed to locate symbol "
00062 << name << ": " << ::dlerror() << std::endl;
00063 }
00064 symbols[name] = symbol;
00065 return symbol;
00066 }
00067
00068 static jack_client_t *dynamic_jack_client_open(const char *client_name,
00069 jack_options_t options,
00070 jack_status_t *status, ...)
00071 {
00072 typedef jack_client_t *(*func)(const char *client_name,
00073 jack_options_t options,
00074 jack_status_t *status, ...);
00075 void *s = symbol("jack_client_open");
00076 if (!s) return 0;
00077 func f = (func)s;
00078 return f(client_name, options, status);
00079 }
00080
00081 static int dynamic_jack_set_process_callback(jack_client_t *client,
00082 JackProcessCallback process_callback,
00083 void *arg)
00084 {
00085 typedef int (*func)(jack_client_t *client,
00086 JackProcessCallback process_callback,
00087 void *arg);
00088 void *s = symbol("jack_set_process_callback");
00089 if (!s) return 1;
00090 func f = (func)s;
00091 return f(client, process_callback, arg);
00092 }
00093
00094 static int dynamic_jack_set_xrun_callback(jack_client_t *client,
00095 JackXRunCallback xrun_callback,
00096 void *arg)
00097 {
00098 typedef int (*func)(jack_client_t *client,
00099 JackXRunCallback xrun_callback,
00100 void *arg);
00101 void *s = symbol("jack_set_xrun_callback");
00102 if (!s) return 1;
00103 func f = (func)s;
00104 return f(client, xrun_callback, arg);
00105 }
00106
00107 static const char **dynamic_jack_get_ports(jack_client_t *client,
00108 const char *port_name_pattern,
00109 const char *type_name_pattern,
00110 unsigned long flags)
00111 {
00112 typedef const char **(*func)(jack_client_t *client,
00113 const char *port_name_pattern,
00114 const char *type_name_pattern,
00115 unsigned long flags);
00116 void *s = symbol("jack_get_ports");
00117 if (!s) return 0;
00118 func f = (func)s;
00119 return f(client, port_name_pattern, type_name_pattern, flags);
00120 }
00121
00122 static jack_port_t *dynamic_jack_port_register(jack_client_t *client,
00123 const char *port_name,
00124 const char *port_type,
00125 unsigned long flags,
00126 unsigned long buffer_size)
00127 {
00128 typedef jack_port_t *(*func)(jack_client_t *client,
00129 const char *port_name,
00130 const char *port_type,
00131 unsigned long flags,
00132 unsigned long buffer_size);
00133 void *s = symbol("jack_port_register");
00134 if (!s) return 0;
00135 func f = (func)s;
00136 return f(client, port_name, port_type, flags, buffer_size);
00137 }
00138
00139 static int dynamic_jack_connect(jack_client_t *client,
00140 const char *source,
00141 const char *dest)
00142 {
00143 typedef int (*func)(jack_client_t *client,
00144 const char *source,
00145 const char *dest);
00146 void *s = symbol("jack_connect");
00147 if (!s) return 1;
00148 func f = (func)s;
00149 return f(client, source, dest);
00150 }
00151
00152 static void *dynamic_jack_port_get_buffer(jack_port_t *port,
00153 jack_nframes_t sz)
00154 {
00155 typedef void *(*func)(jack_port_t *, jack_nframes_t);
00156 void *s = symbol("jack_port_get_buffer");
00157 if (!s) return 0;
00158 func f = (func)s;
00159 return f(port, sz);
00160 }
00161
00162 static int dynamic_jack_port_unregister(jack_client_t *client,
00163 jack_port_t *port)
00164 {
00165 typedef int(*func)(jack_client_t *, jack_port_t *);
00166 void *s = symbol("jack_port_unregister");
00167 if (!s) return 0;
00168 func f = (func)s;
00169 return f(client, port);
00170 }
00171
00172 #define dynamic1(rv, name, argtype, failval) \
00173 static rv dynamic_##name(argtype arg) { \
00174 typedef rv (*func) (argtype); \
00175 void *s = symbol(#name); \
00176 if (!s) return failval; \
00177 func f = (func) s; \
00178 return f(arg); \
00179 }
00180
00181 dynamic1(jack_client_t *, jack_client_new, const char *, 0);
00182 dynamic1(jack_nframes_t, jack_get_buffer_size, jack_client_t *, 0);
00183 dynamic1(jack_nframes_t, jack_get_sample_rate, jack_client_t *, 0);
00184 dynamic1(int, jack_activate, jack_client_t *, 1);
00185 dynamic1(int, jack_deactivate, jack_client_t *, 1);
00186 dynamic1(int, jack_client_close, jack_client_t *, 1);
00187 dynamic1(jack_nframes_t, jack_frame_time, jack_client_t *, 0);
00188 dynamic1(jack_nframes_t, jack_port_get_latency, jack_port_t *, 0);
00189 dynamic1(const char *, jack_port_name, const jack_port_t *, 0);
00190
00191 #define jack_client_new dynamic_jack_client_new
00192 #define jack_client_open dynamic_jack_client_open
00193 #define jack_get_buffer_size dynamic_jack_get_buffer_size
00194 #define jack_get_sample_rate dynamic_jack_get_sample_rate
00195 #define jack_set_process_callback dynamic_jack_set_process_callback
00196 #define jack_set_xrun_callback dynamic_jack_set_xrun_callback
00197 #define jack_activate dynamic_jack_activate
00198 #define jack_deactivate dynamic_jack_deactivate
00199 #define jack_client_close dynamic_jack_client_close
00200 #define jack_frame_time dynamic_jack_frame_time
00201 #define jack_get_ports dynamic_jack_get_ports
00202 #define jack_port_register dynamic_jack_port_register
00203 #define jack_port_unregister dynamic_jack_port_unregister
00204 #define jack_port_get_latency dynamic_jack_port_get_latency
00205 #define jack_port_name dynamic_jack_port_name
00206 #define jack_connect dynamic_jack_connect
00207 #define jack_port_get_buffer dynamic_jack_port_get_buffer
00208
00209 #endif
00210 #endif
00211
00212 AudioJACKTarget::AudioJACKTarget(AudioCallbackPlaySource *source) :
00213 AudioCallbackPlayTarget(source),
00214 m_client(0),
00215 m_bufferSize(0),
00216 m_sampleRate(0),
00217 m_done(false)
00218 {
00219 JackOptions options = JackNullOption;
00220 #ifdef HAVE_PORTAUDIO
00221 options = JackNoStartServer;
00222 #endif
00223
00224 JackStatus status = JackStatus(0);
00225 m_client = jack_client_open(source->getClientName().toLocal8Bit().data(),
00226 options, &status);
00227
00228 if (!m_client) {
00229 std::cerr << "AudioJACKTarget: Failed to connect to JACK server: status code "
00230 << status << std::endl;
00231 return;
00232 }
00233
00234 m_bufferSize = jack_get_buffer_size(m_client);
00235 m_sampleRate = jack_get_sample_rate(m_client);
00236
00237 jack_set_xrun_callback(m_client, xrunStatic, this);
00238 jack_set_process_callback(m_client, processStatic, this);
00239
00240 if (jack_activate(m_client)) {
00241 std::cerr << "ERROR: AudioJACKTarget: Failed to activate JACK client"
00242 << std::endl;
00243 }
00244
00245 if (m_source) {
00246 sourceModelReplaced();
00247 }
00248
00249
00250
00251
00252
00253
00254
00255 MUNLOCKALL();
00256 }
00257
00258 AudioJACKTarget::~AudioJACKTarget()
00259 {
00260 std::cerr << "AudioJACKTarget::~AudioJACKTarget()" << std::endl;
00261
00262 if (m_source) {
00263 m_source->setTarget(0, m_bufferSize);
00264 }
00265
00266 shutdown();
00267
00268 if (m_client) {
00269
00270 while (m_outputs.size() > 0) {
00271 std::vector<jack_port_t *>::iterator itr = m_outputs.end();
00272 --itr;
00273 jack_port_t *port = *itr;
00274 std::cerr << "unregister " << m_outputs.size() << std::endl;
00275 if (port) jack_port_unregister(m_client, port);
00276 m_outputs.erase(itr);
00277 }
00278 std::cerr << "Deactivating... ";
00279 jack_deactivate(m_client);
00280 std::cerr << "done\nClosing... ";
00281 jack_client_close(m_client);
00282 std::cerr << "done" << std::endl;
00283 }
00284
00285 m_client = 0;
00286
00287 std::cerr << "AudioJACKTarget::~AudioJACKTarget() done" << std::endl;
00288 }
00289
00290 void
00291 AudioJACKTarget::shutdown()
00292 {
00293 m_done = true;
00294 }
00295
00296 bool
00297 AudioJACKTarget::isOK() const
00298 {
00299 return (m_client != 0);
00300 }
00301
00302 double
00303 AudioJACKTarget::getCurrentTime() const
00304 {
00305 if (m_client && m_sampleRate) {
00306 return double(jack_frame_time(m_client)) / double(m_sampleRate);
00307 } else {
00308 return 0.0;
00309 }
00310 }
00311
00312 int
00313 AudioJACKTarget::processStatic(jack_nframes_t nframes, void *arg)
00314 {
00315 return ((AudioJACKTarget *)arg)->process(nframes);
00316 }
00317
00318 int
00319 AudioJACKTarget::xrunStatic(void *arg)
00320 {
00321 return ((AudioJACKTarget *)arg)->xrun();
00322 }
00323
00324 void
00325 AudioJACKTarget::sourceModelReplaced()
00326 {
00327 m_mutex.lock();
00328
00329 m_source->setTarget(this, m_bufferSize);
00330 m_source->setTargetSampleRate(m_sampleRate);
00331
00332 size_t channels = m_source->getSourceChannelCount();
00333
00334
00335 if (channels < 2) channels = 2;
00336
00337 if (channels == m_outputs.size() || !m_client) {
00338 m_mutex.unlock();
00339 return;
00340 }
00341
00342 const char **ports =
00343 jack_get_ports(m_client, NULL, NULL,
00344 JackPortIsPhysical | JackPortIsInput);
00345 size_t physicalPortCount = 0;
00346 while (ports[physicalPortCount]) ++physicalPortCount;
00347
00348 #ifdef DEBUG_AUDIO_JACK_TARGET
00349 std::cerr << "AudioJACKTarget::sourceModelReplaced: have " << channels << " channels and " << physicalPortCount << " physical ports" << std::endl;
00350 #endif
00351
00352 while (m_outputs.size() < channels) {
00353
00354 char name[20];
00355 jack_port_t *port;
00356
00357 sprintf(name, "out %d", m_outputs.size() + 1);
00358
00359 port = jack_port_register(m_client,
00360 name,
00361 JACK_DEFAULT_AUDIO_TYPE,
00362 JackPortIsOutput,
00363 0);
00364
00365 if (!port) {
00366 std::cerr
00367 << "ERROR: AudioJACKTarget: Failed to create JACK output port "
00368 << m_outputs.size() << std::endl;
00369 } else {
00370 m_source->setTargetPlayLatency(jack_port_get_latency(port));
00371 }
00372
00373 if (m_outputs.size() < physicalPortCount) {
00374 jack_connect(m_client, jack_port_name(port), ports[m_outputs.size()]);
00375 }
00376
00377 m_outputs.push_back(port);
00378 }
00379
00380 while (m_outputs.size() > channels) {
00381 std::vector<jack_port_t *>::iterator itr = m_outputs.end();
00382 --itr;
00383 jack_port_t *port = *itr;
00384 if (port) jack_port_unregister(m_client, port);
00385 m_outputs.erase(itr);
00386 }
00387
00388 m_mutex.unlock();
00389 }
00390
00391 int
00392 AudioJACKTarget::process(jack_nframes_t nframes)
00393 {
00394 if (m_done) return 0;
00395
00396 if (!m_mutex.tryLock()) {
00397 return 0;
00398 }
00399
00400 if (m_outputs.empty()) {
00401 m_mutex.unlock();
00402 return 0;
00403 }
00404
00405 #ifdef DEBUG_AUDIO_JACK_TARGET
00406 std::cout << "AudioJACKTarget::process(" << nframes << "): have a source" << std::endl;
00407 #endif
00408
00409 #ifdef DEBUG_AUDIO_JACK_TARGET
00410 if (m_bufferSize != nframes) {
00411 std::cerr << "WARNING: m_bufferSize != nframes (" << m_bufferSize << " != " << nframes << ")" << std::endl;
00412 }
00413 #endif
00414
00415 float **buffers = (float **)alloca(m_outputs.size() * sizeof(float *));
00416
00417 for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
00418 buffers[ch] = (float *)jack_port_get_buffer(m_outputs[ch], nframes);
00419 }
00420
00421 size_t received = 0;
00422
00423 if (m_source) {
00424 received = m_source->getSourceSamples(nframes, buffers);
00425 }
00426
00427 for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
00428 for (size_t i = received; i < nframes; ++i) {
00429 buffers[ch][i] = 0.0;
00430 }
00431 }
00432
00433 float peakLeft = 0.0, peakRight = 0.0;
00434
00435 for (size_t ch = 0; ch < m_outputs.size(); ++ch) {
00436
00437 float peak = 0.0;
00438
00439 for (size_t i = 0; i < nframes; ++i) {
00440 buffers[ch][i] *= m_outputGain;
00441 float sample = fabsf(buffers[ch][i]);
00442 if (sample > peak) peak = sample;
00443 }
00444
00445 if (ch == 0) peakLeft = peak;
00446 if (ch > 0 || m_outputs.size() == 1) peakRight = peak;
00447 }
00448
00449 if (m_source) {
00450 m_source->setOutputLevels(peakLeft, peakRight);
00451 }
00452
00453 m_mutex.unlock();
00454 return 0;
00455 }
00456
00457 int
00458 AudioJACKTarget::xrun()
00459 {
00460 std::cerr << "AudioJACKTarget: xrun!" << std::endl;
00461 if (m_source) m_source->audioProcessingOverload();
00462 return 0;
00463 }
00464
00465 #endif
00466