Mercurial > hg > sonic-visualiser
comparison main/OSCHandler.cpp @ 246:ddbde90773b0 spectrogram-cache-rejig
* Merge from trunk
author | Chris Cannam |
---|---|
date | Wed, 27 Feb 2008 11:59:42 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
214:37847fc0b381 | 246:ddbde90773b0 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006-2007 Chris Cannam and QMUL. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "MainWindow.h" | |
17 #include "data/osc/OSCQueue.h" | |
18 | |
19 #include "layer/WaveformLayer.h" | |
20 #include "view/ViewManager.h" | |
21 #include "view/Pane.h" | |
22 #include "view/PaneStack.h" | |
23 #include "data/model/WaveFileModel.h" | |
24 #include "base/CommandHistory.h" | |
25 #include "audioio/AudioCallbackPlaySource.h" | |
26 #include "audioio/AudioCallbackPlayTarget.h" | |
27 #include "framework/Document.h" | |
28 #include "data/fileio/WavFileWriter.h" | |
29 #include "plugin/transform/TransformFactory.h" | |
30 #include "widgets/Fader.h" | |
31 #include "widgets/AudioDial.h" | |
32 | |
33 #include <QFileInfo> | |
34 | |
35 void | |
36 MainWindow::handleOSCMessage(const OSCMessage &message) | |
37 { | |
38 std::cerr << "MainWindow::handleOSCMessage: thread id = " | |
39 << QThread::currentThreadId() << std::endl; | |
40 | |
41 // This large function should really be abstracted out. | |
42 | |
43 if (message.getMethod() == "open") { | |
44 | |
45 if (message.getArgCount() == 1 && | |
46 message.getArg(0).canConvert(QVariant::String)) { | |
47 QString path = message.getArg(0).toString(); | |
48 if (open(path, ReplaceMainModel) != FileOpenSucceeded) { | |
49 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" | |
50 << path.toStdString() << "\"" << std::endl; | |
51 } | |
52 //!!! we really need to spin here and not return until the | |
53 // file has been completely decoded... | |
54 } | |
55 | |
56 } else if (message.getMethod() == "openadditional") { | |
57 | |
58 if (message.getArgCount() == 1 && | |
59 message.getArg(0).canConvert(QVariant::String)) { | |
60 QString path = message.getArg(0).toString(); | |
61 if (open(path, CreateAdditionalModel) != FileOpenSucceeded) { | |
62 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" | |
63 << path.toStdString() << "\"" << std::endl; | |
64 } | |
65 } | |
66 | |
67 } else if (message.getMethod() == "recent" || | |
68 message.getMethod() == "last") { | |
69 | |
70 int n = 0; | |
71 if (message.getMethod() == "recent" && | |
72 message.getArgCount() == 1 && | |
73 message.getArg(0).canConvert(QVariant::Int)) { | |
74 n = message.getArg(0).toInt() - 1; | |
75 } | |
76 std::vector<QString> recent = m_recentFiles.getRecent(); | |
77 if (n >= 0 && n < int(recent.size())) { | |
78 if (open(recent[n], ReplaceMainModel) != FileOpenSucceeded) { | |
79 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \"" | |
80 << recent[n].toStdString() << "\"" << std::endl; | |
81 } | |
82 } | |
83 | |
84 } else if (message.getMethod() == "save") { | |
85 | |
86 QString path; | |
87 if (message.getArgCount() == 1 && | |
88 message.getArg(0).canConvert(QVariant::String)) { | |
89 path = message.getArg(0).toString(); | |
90 if (QFileInfo(path).exists()) { | |
91 std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in save" << std::endl; | |
92 } else { | |
93 saveSessionFile(path); | |
94 } | |
95 } | |
96 | |
97 } else if (message.getMethod() == "export") { | |
98 | |
99 QString path; | |
100 if (getMainModel()) { | |
101 if (message.getArgCount() == 1 && | |
102 message.getArg(0).canConvert(QVariant::String)) { | |
103 path = message.getArg(0).toString(); | |
104 if (QFileInfo(path).exists()) { | |
105 std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in export" << std::endl; | |
106 } else { | |
107 WavFileWriter writer(path, | |
108 getMainModel()->getSampleRate(), | |
109 getMainModel()->getChannelCount()); | |
110 MultiSelection ms = m_viewManager->getSelection(); | |
111 if (!ms.getSelections().empty()) { | |
112 writer.writeModel(getMainModel(), &ms); | |
113 } else { | |
114 writer.writeModel(getMainModel()); | |
115 } | |
116 } | |
117 } | |
118 } | |
119 | |
120 } else if (message.getMethod() == "jump" || | |
121 message.getMethod() == "play") { | |
122 | |
123 if (getMainModel()) { | |
124 | |
125 unsigned long frame = m_viewManager->getPlaybackFrame(); | |
126 bool selection = false; | |
127 bool play = (message.getMethod() == "play"); | |
128 | |
129 if (message.getArgCount() == 1) { | |
130 | |
131 if (message.getArg(0).canConvert(QVariant::String) && | |
132 message.getArg(0).toString() == "selection") { | |
133 | |
134 selection = true; | |
135 | |
136 } else if (message.getArg(0).canConvert(QVariant::String) && | |
137 message.getArg(0).toString() == "end") { | |
138 | |
139 frame = getMainModel()->getEndFrame(); | |
140 | |
141 } else if (message.getArg(0).canConvert(QVariant::Double)) { | |
142 | |
143 double time = message.getArg(0).toDouble(); | |
144 if (time < 0.0) time = 0.0; | |
145 | |
146 frame = lrint(time * getMainModel()->getSampleRate()); | |
147 } | |
148 } | |
149 | |
150 if (frame > getMainModel()->getEndFrame()) { | |
151 frame = getMainModel()->getEndFrame(); | |
152 } | |
153 | |
154 if (play) { | |
155 m_viewManager->setPlaySelectionMode(selection); | |
156 } | |
157 | |
158 if (selection) { | |
159 MultiSelection::SelectionList sl = m_viewManager->getSelections(); | |
160 if (!sl.empty()) { | |
161 frame = sl.begin()->getStartFrame(); | |
162 } | |
163 } | |
164 | |
165 m_viewManager->setPlaybackFrame(frame); | |
166 | |
167 if (play && !m_playSource->isPlaying()) { | |
168 m_playSource->play(frame); | |
169 } | |
170 } | |
171 | |
172 } else if (message.getMethod() == "stop") { | |
173 | |
174 if (m_playSource->isPlaying()) m_playSource->stop(); | |
175 | |
176 } else if (message.getMethod() == "loop") { | |
177 | |
178 if (message.getArgCount() == 1 && | |
179 message.getArg(0).canConvert(QVariant::String)) { | |
180 | |
181 QString str = message.getArg(0).toString(); | |
182 if (str == "on") { | |
183 m_viewManager->setPlayLoopMode(true); | |
184 } else if (str == "off") { | |
185 m_viewManager->setPlayLoopMode(false); | |
186 } | |
187 } | |
188 | |
189 } else if (message.getMethod() == "solo") { | |
190 | |
191 if (message.getArgCount() == 1 && | |
192 message.getArg(0).canConvert(QVariant::String)) { | |
193 | |
194 QString str = message.getArg(0).toString(); | |
195 if (str == "on") { | |
196 m_viewManager->setPlaySoloMode(true); | |
197 } else if (str == "off") { | |
198 m_viewManager->setPlaySoloMode(false); | |
199 } | |
200 } | |
201 | |
202 } else if (message.getMethod() == "select" || | |
203 message.getMethod() == "addselect") { | |
204 | |
205 if (getMainModel()) { | |
206 | |
207 int f0 = getMainModel()->getStartFrame(); | |
208 int f1 = getMainModel()->getEndFrame(); | |
209 | |
210 bool done = false; | |
211 | |
212 if (message.getArgCount() == 2 && | |
213 message.getArg(0).canConvert(QVariant::Double) && | |
214 message.getArg(1).canConvert(QVariant::Double)) { | |
215 | |
216 double t0 = message.getArg(0).toDouble(); | |
217 double t1 = message.getArg(1).toDouble(); | |
218 if (t1 < t0) { double temp = t0; t0 = t1; t1 = temp; } | |
219 if (t0 < 0.0) t0 = 0.0; | |
220 if (t1 < 0.0) t1 = 0.0; | |
221 | |
222 f0 = lrint(t0 * getMainModel()->getSampleRate()); | |
223 f1 = lrint(t1 * getMainModel()->getSampleRate()); | |
224 | |
225 Pane *pane = m_paneStack->getCurrentPane(); | |
226 Layer *layer = 0; | |
227 if (pane) layer = pane->getSelectedLayer(); | |
228 if (layer) { | |
229 size_t resolution; | |
230 layer->snapToFeatureFrame(pane, f0, resolution, | |
231 Layer::SnapLeft); | |
232 layer->snapToFeatureFrame(pane, f1, resolution, | |
233 Layer::SnapRight); | |
234 } | |
235 | |
236 } else if (message.getArgCount() == 1 && | |
237 message.getArg(0).canConvert(QVariant::String)) { | |
238 | |
239 QString str = message.getArg(0).toString(); | |
240 if (str == "none") { | |
241 m_viewManager->clearSelections(); | |
242 done = true; | |
243 } | |
244 } | |
245 | |
246 if (!done) { | |
247 if (message.getMethod() == "select") { | |
248 m_viewManager->setSelection(Selection(f0, f1)); | |
249 } else { | |
250 m_viewManager->addSelection(Selection(f0, f1)); | |
251 } | |
252 } | |
253 } | |
254 | |
255 } else if (message.getMethod() == "add") { | |
256 | |
257 if (getMainModel()) { | |
258 | |
259 if (message.getArgCount() >= 1 && | |
260 message.getArg(0).canConvert(QVariant::String)) { | |
261 | |
262 int channel = -1; | |
263 if (message.getArgCount() == 2 && | |
264 message.getArg(0).canConvert(QVariant::Int)) { | |
265 channel = message.getArg(0).toInt(); | |
266 if (channel < -1 || | |
267 channel > int(getMainModel()->getChannelCount())) { | |
268 std::cerr << "WARNING: MainWindow::handleOSCMessage: channel " | |
269 << channel << " out of range" << std::endl; | |
270 channel = -1; | |
271 } | |
272 } | |
273 | |
274 QString str = message.getArg(0).toString(); | |
275 | |
276 LayerFactory::LayerType type = | |
277 LayerFactory::getInstance()->getLayerTypeForName(str); | |
278 | |
279 if (type == LayerFactory::UnknownLayer) { | |
280 std::cerr << "WARNING: MainWindow::handleOSCMessage: unknown layer " | |
281 << "type " << str.toStdString() << std::endl; | |
282 } else { | |
283 | |
284 LayerConfiguration configuration(type, | |
285 getMainModel(), | |
286 channel); | |
287 | |
288 addPane(configuration, | |
289 tr("Add %1 Pane") | |
290 .arg(LayerFactory::getInstance()-> | |
291 getLayerPresentationName(type))); | |
292 } | |
293 } | |
294 } | |
295 | |
296 } else if (message.getMethod() == "undo") { | |
297 | |
298 CommandHistory::getInstance()->undo(); | |
299 | |
300 } else if (message.getMethod() == "redo") { | |
301 | |
302 CommandHistory::getInstance()->redo(); | |
303 | |
304 } else if (message.getMethod() == "set") { | |
305 | |
306 if (message.getArgCount() == 2 && | |
307 message.getArg(0).canConvert(QVariant::String) && | |
308 message.getArg(1).canConvert(QVariant::Double)) { | |
309 | |
310 QString property = message.getArg(0).toString(); | |
311 float value = (float)message.getArg(1).toDouble(); | |
312 | |
313 if (property == "gain") { | |
314 if (value < 0.0) value = 0.0; | |
315 m_fader->setValue(value); | |
316 if (m_playTarget) m_playTarget->setOutputGain(value); | |
317 } else if (property == "speedup") { | |
318 m_playSpeed->setMappedValue(value); | |
319 } else if (property == "overlays") { | |
320 if (value < 0.5) { | |
321 m_viewManager->setOverlayMode(ViewManager::NoOverlays); | |
322 } else if (value < 1.5) { | |
323 m_viewManager->setOverlayMode(ViewManager::MinimalOverlays); | |
324 } else if (value < 2.5) { | |
325 m_viewManager->setOverlayMode(ViewManager::StandardOverlays); | |
326 } else { | |
327 m_viewManager->setOverlayMode(ViewManager::AllOverlays); | |
328 } | |
329 } else if (property == "zoomwheels") { | |
330 m_viewManager->setZoomWheelsEnabled(value > 0.5); | |
331 } else if (property == "propertyboxes") { | |
332 bool toggle = ((value < 0.5) != | |
333 (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks)); | |
334 if (toggle) togglePropertyBoxes(); | |
335 } | |
336 | |
337 } else { | |
338 PropertyContainer *container = 0; | |
339 Pane *pane = m_paneStack->getCurrentPane(); | |
340 if (pane && | |
341 message.getArgCount() == 3 && | |
342 message.getArg(0).canConvert(QVariant::String) && | |
343 message.getArg(1).canConvert(QVariant::String) && | |
344 message.getArg(2).canConvert(QVariant::String)) { | |
345 if (message.getArg(0).toString() == "pane") { | |
346 container = pane->getPropertyContainer(0); | |
347 } else if (message.getArg(0).toString() == "layer") { | |
348 container = pane->getSelectedLayer(); | |
349 } | |
350 } | |
351 if (container) { | |
352 QString nameString = message.getArg(1).toString(); | |
353 QString valueString = message.getArg(2).toString(); | |
354 container->setPropertyWithCommand(nameString, valueString); | |
355 } | |
356 } | |
357 | |
358 } else if (message.getMethod() == "setcurrent") { | |
359 | |
360 int paneIndex = -1, layerIndex = -1; | |
361 bool wantLayer = false; | |
362 | |
363 if (message.getArgCount() >= 1 && | |
364 message.getArg(0).canConvert(QVariant::Int)) { | |
365 | |
366 paneIndex = message.getArg(0).toInt() - 1; | |
367 | |
368 if (message.getArgCount() >= 2 && | |
369 message.getArg(1).canConvert(QVariant::Int)) { | |
370 wantLayer = true; | |
371 layerIndex = message.getArg(1).toInt() - 1; | |
372 } | |
373 } | |
374 | |
375 if (paneIndex >= 0 && paneIndex < m_paneStack->getPaneCount()) { | |
376 Pane *pane = m_paneStack->getPane(paneIndex); | |
377 m_paneStack->setCurrentPane(pane); | |
378 if (layerIndex >= 0 && layerIndex < pane->getLayerCount()) { | |
379 Layer *layer = pane->getLayer(layerIndex); | |
380 m_paneStack->setCurrentLayer(pane, layer); | |
381 } else if (wantLayer && layerIndex == -1) { | |
382 m_paneStack->setCurrentLayer(pane, 0); | |
383 } | |
384 } | |
385 | |
386 } else if (message.getMethod() == "delete") { | |
387 | |
388 if (message.getArgCount() == 1 && | |
389 message.getArg(0).canConvert(QVariant::String)) { | |
390 | |
391 QString target = message.getArg(0).toString(); | |
392 | |
393 if (target == "pane") { | |
394 | |
395 deleteCurrentPane(); | |
396 | |
397 } else if (target == "layer") { | |
398 | |
399 deleteCurrentLayer(); | |
400 | |
401 } else { | |
402 | |
403 std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown delete target " << target.toStdString() << std::endl; | |
404 } | |
405 } | |
406 | |
407 } else if (message.getMethod() == "zoom") { | |
408 | |
409 if (message.getArgCount() == 1) { | |
410 if (message.getArg(0).canConvert(QVariant::String) && | |
411 message.getArg(0).toString() == "in") { | |
412 zoomIn(); | |
413 } else if (message.getArg(0).canConvert(QVariant::String) && | |
414 message.getArg(0).toString() == "out") { | |
415 zoomOut(); | |
416 } else if (message.getArg(0).canConvert(QVariant::String) && | |
417 message.getArg(0).toString() == "default") { | |
418 zoomDefault(); | |
419 } else if (message.getArg(0).canConvert(QVariant::Double)) { | |
420 double level = message.getArg(0).toDouble(); | |
421 Pane *currentPane = m_paneStack->getCurrentPane(); | |
422 if (level < 1.0) level = 1.0; | |
423 if (currentPane) currentPane->setZoomLevel(lrint(level)); | |
424 } | |
425 } | |
426 | |
427 } else if (message.getMethod() == "zoomvertical") { | |
428 | |
429 Pane *pane = m_paneStack->getCurrentPane(); | |
430 Layer *layer = 0; | |
431 if (pane && pane->getLayerCount() > 0) { | |
432 layer = pane->getLayer(pane->getLayerCount() - 1); | |
433 } | |
434 int defaultStep = 0; | |
435 int steps = 0; | |
436 if (layer) { | |
437 steps = layer->getVerticalZoomSteps(defaultStep); | |
438 if (message.getArgCount() == 1 && steps > 0) { | |
439 if (message.getArg(0).canConvert(QVariant::String) && | |
440 message.getArg(0).toString() == "in") { | |
441 int step = layer->getCurrentVerticalZoomStep() + 1; | |
442 if (step < steps) layer->setVerticalZoomStep(step); | |
443 } else if (message.getArg(0).canConvert(QVariant::String) && | |
444 message.getArg(0).toString() == "out") { | |
445 int step = layer->getCurrentVerticalZoomStep() - 1; | |
446 if (step >= 0) layer->setVerticalZoomStep(step); | |
447 } else if (message.getArg(0).canConvert(QVariant::String) && | |
448 message.getArg(0).toString() == "default") { | |
449 layer->setVerticalZoomStep(defaultStep); | |
450 } | |
451 } else if (message.getArgCount() == 2) { | |
452 if (message.getArg(0).canConvert(QVariant::Double) && | |
453 message.getArg(1).canConvert(QVariant::Double)) { | |
454 double min = message.getArg(0).toDouble(); | |
455 double max = message.getArg(1).toDouble(); | |
456 layer->setDisplayExtents(min, max); | |
457 } | |
458 } | |
459 } | |
460 | |
461 } else if (message.getMethod() == "quit") { | |
462 | |
463 m_abandoning = true; | |
464 close(); | |
465 | |
466 } else if (message.getMethod() == "resize") { | |
467 | |
468 if (message.getArgCount() == 2) { | |
469 | |
470 int width = 0, height = 0; | |
471 | |
472 if (message.getArg(1).canConvert(QVariant::Int)) { | |
473 | |
474 height = message.getArg(1).toInt(); | |
475 | |
476 if (message.getArg(0).canConvert(QVariant::String) && | |
477 message.getArg(0).toString() == "pane") { | |
478 | |
479 Pane *pane = m_paneStack->getCurrentPane(); | |
480 if (pane) pane->resize(pane->width(), height); | |
481 | |
482 } else if (message.getArg(0).canConvert(QVariant::Int)) { | |
483 | |
484 width = message.getArg(0).toInt(); | |
485 resize(width, height); | |
486 } | |
487 } | |
488 } | |
489 | |
490 } else if (message.getMethod() == "transform") { | |
491 | |
492 Pane *pane = m_paneStack->getCurrentPane(); | |
493 | |
494 if (getMainModel() && | |
495 pane && | |
496 message.getArgCount() == 1 && | |
497 message.getArg(0).canConvert(QVariant::String)) { | |
498 | |
499 TransformId transformId = message.getArg(0).toString(); | |
500 | |
501 Transform transform = TransformFactory::getInstance()-> | |
502 getDefaultTransformFor(transformId); | |
503 | |
504 Layer *newLayer = m_document->createDerivedLayer | |
505 (transform, getMainModel()); | |
506 | |
507 if (newLayer) { | |
508 m_document->addLayerToView(pane, newLayer); | |
509 m_recentTransforms.add(transformId); | |
510 m_paneStack->setCurrentLayer(pane, newLayer); | |
511 } | |
512 } | |
513 | |
514 } else { | |
515 std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown or unsupported " | |
516 << "method \"" << message.getMethod().toStdString() | |
517 << "\"" << std::endl; | |
518 } | |
519 | |
520 } |