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 }