Mercurial > hg > svapp
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()) { |