Mercurial > hg > sonic-visualiser
comparison main/OSCHandler.cpp @ 1617:afe620d017d7
Update OSC handler: fix play (which wasn't working because it didn't resume audio driver) and speedup (wrong mapping for the new speed controls), and add more sensible new speed method
author | Chris Cannam |
---|---|
date | Mon, 27 Feb 2017 15:07:27 +0000 |
parents | f013210eeceb |
children | 893f556cd5c9 |
comparison
equal
deleted
inserted
replaced
1616:e86e23110e42 | 1617:afe620d017d7 |
---|---|
35 #include <QFileInfo> | 35 #include <QFileInfo> |
36 | 36 |
37 void | 37 void |
38 MainWindow::handleOSCMessage(const OSCMessage &message) | 38 MainWindow::handleOSCMessage(const OSCMessage &message) |
39 { | 39 { |
40 SVDEBUG << "MainWindow::handleOSCMessage: thread id = " | 40 SVDEBUG << "OSCHandler: method = \"" |
41 << QThread::currentThreadId() << endl; | 41 << message.getMethod() << "\"" << endl; |
42 | 42 |
43 // This large function should really be abstracted out. | 43 // This large function should really be abstracted out. |
44 | 44 |
45 if (message.getMethod() == "open") { | 45 if (message.getMethod() == "open") { |
46 | 46 |
47 if (message.getArgCount() == 1 && | 47 if (message.getArgCount() == 1 && |
48 message.getArg(0).canConvert(QVariant::String)) { | 48 message.getArg(0).canConvert(QVariant::String)) { |
49 QString path = message.getArg(0).toString(); | 49 QString path = message.getArg(0).toString(); |
50 if (open(path, ReplaceMainModel) != FileOpenSucceeded) { | 50 if (open(path, ReplaceMainModel) != FileOpenSucceeded) { |
51 cerr << "MainWindow::handleOSCMessage: File open failed for path \"" | 51 cerr << "OSCHandler: File open failed for path \"" |
52 << path << "\"" << endl; | 52 << path << "\"" << endl; |
53 } | 53 } |
54 //!!! we really need to spin here and not return until the | 54 //!!! we really need to spin here and not return until the |
55 // file has been completely decoded... | 55 // file has been completely decoded... |
56 } | 56 } |
59 | 59 |
60 if (message.getArgCount() == 1 && | 60 if (message.getArgCount() == 1 && |
61 message.getArg(0).canConvert(QVariant::String)) { | 61 message.getArg(0).canConvert(QVariant::String)) { |
62 QString path = message.getArg(0).toString(); | 62 QString path = message.getArg(0).toString(); |
63 if (open(path, CreateAdditionalModel) != FileOpenSucceeded) { | 63 if (open(path, CreateAdditionalModel) != FileOpenSucceeded) { |
64 cerr << "MainWindow::handleOSCMessage: File open failed for path \"" | 64 cerr << "OSCHandler: File open failed for path \"" |
65 << path << "\"" << endl; | 65 << path << "\"" << endl; |
66 } | 66 } |
67 } | 67 } |
68 | 68 |
69 } else if (message.getMethod() == "recent" || | 69 } else if (message.getMethod() == "recent" || |
76 n = message.getArg(0).toInt() - 1; | 76 n = message.getArg(0).toInt() - 1; |
77 } | 77 } |
78 std::vector<QString> recent = m_recentFiles.getRecent(); | 78 std::vector<QString> recent = m_recentFiles.getRecent(); |
79 if (n >= 0 && n < int(recent.size())) { | 79 if (n >= 0 && n < int(recent.size())) { |
80 if (open(recent[n], ReplaceMainModel) != FileOpenSucceeded) { | 80 if (open(recent[n], ReplaceMainModel) != FileOpenSucceeded) { |
81 cerr << "MainWindow::handleOSCMessage: File open failed for path \"" | 81 cerr << "OSCHandler: File open failed for path \"" |
82 << recent[n] << "\"" << endl; | 82 << recent[n] << "\"" << endl; |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 } else if (message.getMethod() == "save") { | 86 } else if (message.getMethod() == "save") { |
88 QString path; | 88 QString path; |
89 if (message.getArgCount() == 1 && | 89 if (message.getArgCount() == 1 && |
90 message.getArg(0).canConvert(QVariant::String)) { | 90 message.getArg(0).canConvert(QVariant::String)) { |
91 path = message.getArg(0).toString(); | 91 path = message.getArg(0).toString(); |
92 if (QFileInfo(path).exists()) { | 92 if (QFileInfo(path).exists()) { |
93 SVDEBUG << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in save" << endl; | 93 SVDEBUG << "OSCHandler: Refusing to overwrite existing file in save" << endl; |
94 } else { | 94 } else { |
95 saveSessionFile(path); | 95 saveSessionFile(path); |
96 } | 96 } |
97 } | 97 } |
98 | 98 |
102 if (getMainModel()) { | 102 if (getMainModel()) { |
103 if (message.getArgCount() == 1 && | 103 if (message.getArgCount() == 1 && |
104 message.getArg(0).canConvert(QVariant::String)) { | 104 message.getArg(0).canConvert(QVariant::String)) { |
105 path = message.getArg(0).toString(); | 105 path = message.getArg(0).toString(); |
106 if (QFileInfo(path).exists()) { | 106 if (QFileInfo(path).exists()) { |
107 SVDEBUG << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in export" << endl; | 107 SVDEBUG << "OSCHandler: Refusing to overwrite existing file in export" << endl; |
108 } else { | 108 } else { |
109 WavFileWriter writer(path, | 109 WavFileWriter writer(path, |
110 getMainModel()->getSampleRate(), | 110 getMainModel()->getSampleRate(), |
111 getMainModel()->getChannelCount(), | 111 getMainModel()->getChannelCount(), |
112 WavFileWriter::WriteToTemporary); | 112 WavFileWriter::WriteToTemporary); |
163 if (!sl.empty()) { | 163 if (!sl.empty()) { |
164 frame = sl.begin()->getStartFrame(); | 164 frame = sl.begin()->getStartFrame(); |
165 } | 165 } |
166 } | 166 } |
167 | 167 |
168 SVDEBUG << "OSCHandler: Setting playback frame to " << frame << endl; | |
169 | |
168 m_viewManager->setPlaybackFrame(frame); | 170 m_viewManager->setPlaybackFrame(frame); |
169 | 171 |
170 if (play && !m_playSource->isPlaying()) { | 172 if (play) { |
171 m_playSource->play(frame); | 173 if (!m_playSource->isPlaying()) { |
174 SVDEBUG << "OSCHandler: Play source is not yet playing, calling play()" << endl; | |
175 // handles audio device suspend/resume etc, as | |
176 // well as calling m_playSource->play(frame) | |
177 MainWindow::play(); | |
178 } else { | |
179 SVDEBUG << "OSCHandler: Play source is already playing, not starting it" << endl; | |
180 } | |
181 } else { | |
182 SVDEBUG << "OSCHandler: Jump only requested, not starting playback" << endl; | |
172 } | 183 } |
173 } | 184 } |
174 | 185 |
175 } else if (message.getMethod() == "ffwd") { | 186 } else if (message.getMethod() == "ffwd") { |
176 | 187 |
200 rewind(); | 211 rewind(); |
201 } | 212 } |
202 | 213 |
203 } else if (message.getMethod() == "stop") { | 214 } else if (message.getMethod() == "stop") { |
204 | 215 |
205 if (m_playSource->isPlaying()) m_playSource->stop(); | 216 if (m_playSource->isPlaying()) { |
217 // As with play, we want to use the MainWindow | |
218 // function rather than call m_playSource directly | |
219 // because that way the audio driver suspend/resume | |
220 // etc is handled properly | |
221 MainWindow::stop(); | |
222 } | |
206 | 223 |
207 } else if (message.getMethod() == "loop") { | 224 } else if (message.getMethod() == "loop") { |
208 | 225 |
209 if (message.getArgCount() == 1 && | 226 if (message.getArgCount() == 1 && |
210 message.getArg(0).canConvert(QVariant::String)) { | 227 message.getArg(0).canConvert(QVariant::String)) { |
294 if (message.getArgCount() == 2 && | 311 if (message.getArgCount() == 2 && |
295 message.getArg(0).canConvert(QVariant::Int)) { | 312 message.getArg(0).canConvert(QVariant::Int)) { |
296 channel = message.getArg(0).toInt(); | 313 channel = message.getArg(0).toInt(); |
297 if (channel < -1 || | 314 if (channel < -1 || |
298 channel > int(getMainModel()->getChannelCount())) { | 315 channel > int(getMainModel()->getChannelCount())) { |
299 cerr << "WARNING: MainWindow::handleOSCMessage: channel " | 316 cerr << "WARNING: OSCHandler: channel " |
300 << channel << " out of range" << endl; | 317 << channel << " out of range" << endl; |
301 channel = -1; | 318 channel = -1; |
302 } | 319 } |
303 } | 320 } |
304 | 321 |
306 | 323 |
307 LayerFactory::LayerType type = | 324 LayerFactory::LayerType type = |
308 LayerFactory::getInstance()->getLayerTypeForName(str); | 325 LayerFactory::getInstance()->getLayerTypeForName(str); |
309 | 326 |
310 if (type == LayerFactory::UnknownLayer) { | 327 if (type == LayerFactory::UnknownLayer) { |
311 cerr << "WARNING: MainWindow::handleOSCMessage: unknown layer " | 328 cerr << "WARNING: OSCHandler: unknown layer " |
312 << "type " << str << endl; | 329 << "type " << str << endl; |
313 } else { | 330 } else { |
314 | 331 |
315 LayerConfiguration configuration(type, | 332 LayerConfiguration configuration(type, |
316 getMainModel(), | 333 getMainModel(), |
343 | 360 |
344 if (property == "gain") { | 361 if (property == "gain") { |
345 if (value < 0.0) value = 0.0; | 362 if (value < 0.0) value = 0.0; |
346 m_mainLevelPan->setLevel(value); | 363 m_mainLevelPan->setLevel(value); |
347 if (m_playTarget) m_playTarget->setOutputGain(value); | 364 if (m_playTarget) m_playTarget->setOutputGain(value); |
365 } else if (property == "speed") { | |
366 m_playSpeed->setMappedValue(value); | |
348 } else if (property == "speedup") { | 367 } else if (property == "speedup") { |
349 m_playSpeed->setMappedValue(value); | 368 |
369 // The speedup method existed before the speed method | |
370 // and is a bit weirder. | |
371 // | |
372 // For speed(x), x is a percentage of normal speed, so | |
373 // x=100 means play at the normal speed, x=50 means | |
374 // half speed, x=200 double speed etc. | |
375 // | |
376 // For speedup(x), x was some sort of modifier of | |
377 // percentage thing, so x=0 meant play at the normal | |
378 // speed, x=50 meant play at 150% of normal speed, | |
379 // x=100 meant play at double speed, and x=-100 rather | |
380 // bizarrely meant play at half speed. We handle this | |
381 // now by converting to speed percentage as follows: | |
382 | |
383 double percentage = 100.0; | |
384 if (value > 0.f) { | |
385 percentage = percentage + value; | |
386 } else { | |
387 percentage = 10000.0 / (percentage - value); | |
388 } | |
389 SVDEBUG << "OSCHandler: converted speedup(" << value | |
390 << ") into speed(" << percentage << ")" << endl; | |
391 | |
392 m_playSpeed->setMappedValue(percentage); | |
393 | |
350 } else if (property == "overlays") { | 394 } else if (property == "overlays") { |
351 if (value < 0.5) { | 395 if (value < 0.5) { |
352 m_viewManager->setOverlayMode(ViewManager::NoOverlays); | 396 m_viewManager->setOverlayMode(ViewManager::NoOverlays); |
353 } else if (value < 1.5) { | 397 } else if (value < 1.5) { |
354 m_viewManager->setOverlayMode(ViewManager::StandardOverlays); | 398 m_viewManager->setOverlayMode(ViewManager::StandardOverlays); |
429 | 473 |
430 deleteCurrentLayer(); | 474 deleteCurrentLayer(); |
431 | 475 |
432 } else { | 476 } else { |
433 | 477 |
434 cerr << "WARNING: MainWindow::handleOSCMessage: Unknown delete target " << target << endl; | 478 cerr << "WARNING: OSCHandler: Unknown delete target " << target << endl; |
435 } | 479 } |
436 } | 480 } |
437 | 481 |
438 } else if (message.getMethod() == "zoom") { | 482 } else if (message.getMethod() == "zoom") { |
439 | 483 |
544 m_paneStack->setCurrentLayer(pane, newLayer); | 588 m_paneStack->setCurrentLayer(pane, newLayer); |
545 } | 589 } |
546 } | 590 } |
547 | 591 |
548 } else { | 592 } else { |
549 cerr << "WARNING: MainWindow::handleOSCMessage: Unknown or unsupported " | 593 cerr << "WARNING: OSCHandler: Unknown or unsupported " |
550 << "method \"" << message.getMethod() | 594 << "method \"" << message.getMethod() |
551 << "\"" << endl; | 595 << "\"" << endl; |
552 } | 596 } |
553 | |
554 } | 597 } |