comparison audioio/AudioJACKTarget.cpp @ 101:89a689720ee9 spectrogram-cache-rejig

* Merge from trunk
author Chris Cannam
date Wed, 27 Feb 2008 11:59:42 +0000
parents eb596ef12041
children
comparison
equal deleted inserted replaced
59:bf1a53489ccc 101:89a689720ee9
67 67
68 static jack_client_t *dynamic_jack_client_open(const char *client_name, 68 static jack_client_t *dynamic_jack_client_open(const char *client_name,
69 jack_options_t options, 69 jack_options_t options,
70 jack_status_t *status, ...) 70 jack_status_t *status, ...)
71 { 71 {
72 typedef jack_client_t (*func)(const char *client_name, 72 typedef jack_client_t *(*func)(const char *client_name,
73 jack_options_t options, 73 jack_options_t options,
74 jack_status_t *status, ...); 74 jack_status_t *status, ...);
75 void *s = symbol("jack_client_open"); 75 void *s = symbol("jack_client_open");
76 if (!s) return 0; 76 if (!s) return 0;
77 func f = (func)s; 77 func f = (func)s;
78 return f(client_name, options, status); // varargs not supported here 78 return f(client_name, options, status); // varargs not supported here
79 } 79 }
182 dynamic1(jack_nframes_t, jack_get_buffer_size, jack_client_t *, 0); 182 dynamic1(jack_nframes_t, jack_get_buffer_size, jack_client_t *, 0);
183 dynamic1(jack_nframes_t, jack_get_sample_rate, jack_client_t *, 0); 183 dynamic1(jack_nframes_t, jack_get_sample_rate, jack_client_t *, 0);
184 dynamic1(int, jack_activate, jack_client_t *, 1); 184 dynamic1(int, jack_activate, jack_client_t *, 1);
185 dynamic1(int, jack_deactivate, jack_client_t *, 1); 185 dynamic1(int, jack_deactivate, jack_client_t *, 1);
186 dynamic1(int, jack_client_close, jack_client_t *, 1); 186 dynamic1(int, jack_client_close, jack_client_t *, 1);
187 dynamic1(jack_nframes_t, jack_frame_time, jack_client_t *, 0);
187 dynamic1(jack_nframes_t, jack_port_get_latency, jack_port_t *, 0); 188 dynamic1(jack_nframes_t, jack_port_get_latency, jack_port_t *, 0);
188 dynamic1(const char *, jack_port_name, const jack_port_t *, 0); 189 dynamic1(const char *, jack_port_name, const jack_port_t *, 0);
189 190
190 #define jack_client_new dynamic_jack_client_new 191 #define jack_client_new dynamic_jack_client_new
191 #define jack_client_open dynamic_jack_client_open 192 #define jack_client_open dynamic_jack_client_open
194 #define jack_set_process_callback dynamic_jack_set_process_callback 195 #define jack_set_process_callback dynamic_jack_set_process_callback
195 #define jack_set_xrun_callback dynamic_jack_set_xrun_callback 196 #define jack_set_xrun_callback dynamic_jack_set_xrun_callback
196 #define jack_activate dynamic_jack_activate 197 #define jack_activate dynamic_jack_activate
197 #define jack_deactivate dynamic_jack_deactivate 198 #define jack_deactivate dynamic_jack_deactivate
198 #define jack_client_close dynamic_jack_client_close 199 #define jack_client_close dynamic_jack_client_close
200 #define jack_frame_time dynamic_jack_frame_time
199 #define jack_get_ports dynamic_jack_get_ports 201 #define jack_get_ports dynamic_jack_get_ports
200 #define jack_port_register dynamic_jack_port_register 202 #define jack_port_register dynamic_jack_port_register
201 #define jack_port_unregister dynamic_jack_port_unregister 203 #define jack_port_unregister dynamic_jack_port_unregister
202 #define jack_port_get_latency dynamic_jack_port_get_latency 204 #define jack_port_get_latency dynamic_jack_port_get_latency
203 #define jack_port_name dynamic_jack_port_name 205 #define jack_port_name dynamic_jack_port_name
209 211
210 AudioJACKTarget::AudioJACKTarget(AudioCallbackPlaySource *source) : 212 AudioJACKTarget::AudioJACKTarget(AudioCallbackPlaySource *source) :
211 AudioCallbackPlayTarget(source), 213 AudioCallbackPlayTarget(source),
212 m_client(0), 214 m_client(0),
213 m_bufferSize(0), 215 m_bufferSize(0),
214 m_sampleRate(0) 216 m_sampleRate(0),
217 m_done(false)
215 { 218 {
216 JackOptions options = JackNullOption; 219 JackOptions options = JackNullOption;
217 #ifdef HAVE_PORTAUDIO 220 #ifdef HAVE_PORTAUDIO
218 options = JackNoStartServer; 221 options = JackNoStartServer;
219 #endif 222 #endif
240 } 243 }
241 244
242 if (m_source) { 245 if (m_source) {
243 sourceModelReplaced(); 246 sourceModelReplaced();
244 } 247 }
248
249 // Mainstream JACK (though not jackdmp) calls mlockall() to lock
250 // down all memory for real-time operation. That isn't a terribly
251 // good idea in an application like this that may have very high
252 // dynamic memory usage in other threads, as mlockall() applies
253 // across all threads. We're far better off undoing it here and
254 // accepting the possible loss of true RT capability.
255 MUNLOCKALL();
245 } 256 }
246 257
247 AudioJACKTarget::~AudioJACKTarget() 258 AudioJACKTarget::~AudioJACKTarget()
248 { 259 {
249 std::cerr << "AudioJACKTarget::~AudioJACKTarget()" << std::endl; 260 std::cerr << "AudioJACKTarget::~AudioJACKTarget()" << std::endl;
261
262 if (m_source) {
263 m_source->setTarget(0, m_bufferSize);
264 }
265
266 shutdown();
267
250 if (m_client) { 268 if (m_client) {
269
270 while (m_outputs.size() > 0) {
271 std::vector<jack_port_t *>::iterator itr = m_outputs.end();
272 --itr;
273 jack_port_t *port = *itr;
274 std::cerr << "unregister " << m_outputs.size() << std::endl;
275 if (port) jack_port_unregister(m_client, port);
276 m_outputs.erase(itr);
277 }
278 std::cerr << "Deactivating... ";
251 jack_deactivate(m_client); 279 jack_deactivate(m_client);
280 std::cerr << "done\nClosing... ";
252 jack_client_close(m_client); 281 jack_client_close(m_client);
253 } 282 std::cerr << "done" << std::endl;
283 }
284
285 m_client = 0;
286
254 std::cerr << "AudioJACKTarget::~AudioJACKTarget() done" << std::endl; 287 std::cerr << "AudioJACKTarget::~AudioJACKTarget() done" << std::endl;
288 }
289
290 void
291 AudioJACKTarget::shutdown()
292 {
293 m_done = true;
255 } 294 }
256 295
257 bool 296 bool
258 AudioJACKTarget::isOK() const 297 AudioJACKTarget::isOK() const
259 { 298 {
260 return (m_client != 0); 299 return (m_client != 0);
261 } 300 }
262 301
302 double
303 AudioJACKTarget::getCurrentTime() const
304 {
305 if (m_client && m_sampleRate) {
306 return double(jack_frame_time(m_client)) / double(m_sampleRate);
307 } else {
308 return 0.0;
309 }
310 }
311
263 int 312 int
264 AudioJACKTarget::processStatic(jack_nframes_t nframes, void *arg) 313 AudioJACKTarget::processStatic(jack_nframes_t nframes, void *arg)
265 { 314 {
266 return ((AudioJACKTarget *)arg)->process(nframes); 315 return ((AudioJACKTarget *)arg)->process(nframes);
267 } 316 }
275 void 324 void
276 AudioJACKTarget::sourceModelReplaced() 325 AudioJACKTarget::sourceModelReplaced()
277 { 326 {
278 m_mutex.lock(); 327 m_mutex.lock();
279 328
280 m_source->setTargetBlockSize(m_bufferSize); 329 m_source->setTarget(this, m_bufferSize);
281 m_source->setTargetSampleRate(m_sampleRate); 330 m_source->setTargetSampleRate(m_sampleRate);
282 331
283 size_t channels = m_source->getSourceChannelCount(); 332 size_t channels = m_source->getSourceChannelCount();
284 333
285 // Because we offer pan, we always want at least 2 channels 334 // Because we offer pan, we always want at least 2 channels
340 } 389 }
341 390
342 int 391 int
343 AudioJACKTarget::process(jack_nframes_t nframes) 392 AudioJACKTarget::process(jack_nframes_t nframes)
344 { 393 {
394 if (m_done) return 0;
395
345 if (!m_mutex.tryLock()) { 396 if (!m_mutex.tryLock()) {
346 return 0; 397 return 0;
347 } 398 }
348 399
349 if (m_outputs.empty()) { 400 if (m_outputs.empty()) {