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 }