annotate main/OSCHandler.cpp @ 2442:b3330c31ea0e spectrogram-export

Add layer export of selected region as well as whole layer
author Chris Cannam
date Wed, 08 Jan 2020 15:41:46 +0000
parents 3612bfc24950
children e9506f77388d
rev   line source
Chris@224 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@224 2
Chris@224 3 /*
Chris@224 4 Sonic Visualiser
Chris@224 5 An audio file viewer and annotation editor.
Chris@224 6 Centre for Digital Music, Queen Mary, University of London.
Chris@224 7 This file copyright 2006-2007 Chris Cannam and QMUL.
Chris@224 8
Chris@224 9 This program is free software; you can redistribute it and/or
Chris@224 10 modify it under the terms of the GNU General Public License as
Chris@224 11 published by the Free Software Foundation; either version 2 of the
Chris@224 12 License, or (at your option) any later version. See the file
Chris@224 13 COPYING included with this distribution for more information.
Chris@224 14 */
Chris@216 15
Chris@216 16 #include "MainWindow.h"
Chris@216 17 #include "data/osc/OSCQueue.h"
Chris@216 18
Chris@216 19 #include "layer/WaveformLayer.h"
Chris@216 20 #include "view/ViewManager.h"
Chris@216 21 #include "view/Pane.h"
Chris@216 22 #include "view/PaneStack.h"
Chris@216 23 #include "data/model/WaveFileModel.h"
Chris@248 24 #include "widgets/CommandHistory.h"
Chris@1035 25 #include "audio/AudioCallbackPlaySource.h"
Chris@216 26 #include "framework/Document.h"
Chris@216 27 #include "data/fileio/WavFileWriter.h"
Chris@249 28 #include "transform/TransformFactory.h"
Chris@1386 29 #include "widgets/LevelPanWidget.h"
Chris@1431 30 #include "widgets/LevelPanToolButton.h"
Chris@216 31 #include "widgets/AudioDial.h"
Chris@216 32
Chris@1035 33 #include <bqaudioio/SystemPlaybackTarget.h>
Chris@1035 34
Chris@216 35 #include <QFileInfo>
Chris@2441 36 #include <QTime>
Chris@2441 37 #include <QElapsedTimer>
Chris@2441 38
Chris@2441 39 #define NOW (QTime::currentTime().toString(Qt::ISODateWithMs))
Chris@216 40
Chris@216 41 void
Chris@216 42 MainWindow::handleOSCMessage(const OSCMessage &message)
Chris@216 43 {
Chris@2441 44 QElapsedTimer timer;
Chris@2441 45 timer.start();
Chris@2441 46
Chris@2441 47 SVDEBUG << "OSCHandler at " << NOW << ": handling message: "
Chris@2441 48 << message.toString() << endl;
Chris@216 49
Chris@216 50 if (message.getMethod() == "open") {
Chris@216 51
Chris@216 52 if (message.getArgCount() == 1 &&
Chris@216 53 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 54 QString path = message.getArg(0).toString();
Chris@2441 55 if (open(path, ReplaceMainModel) == FileOpenSucceeded) {
Chris@2441 56 SVDEBUG << "OSCHandler: Opened path \""
Chris@2441 57 << path << "\"" << endl;
Chris@2441 58 } else {
Chris@2441 59 SVCERR << "OSCHandler: File open failed for path \""
Chris@2441 60 << path << "\"" << endl;
Chris@216 61 }
Chris@216 62 //!!! we really need to spin here and not return until the
Chris@216 63 // file has been completely decoded...
Chris@216 64 }
Chris@216 65
Chris@216 66 } else if (message.getMethod() == "openadditional") {
Chris@216 67
Chris@216 68 if (message.getArgCount() == 1 &&
Chris@216 69 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 70 QString path = message.getArg(0).toString();
Chris@2441 71 if (open(path, CreateAdditionalModel) == FileOpenSucceeded) {
Chris@2441 72 SVDEBUG << "OSCHandler: Opened additional path \""
Chris@2441 73 << path << "\"" << endl;
Chris@2441 74 } else {
Chris@2441 75 SVCERR << "OSCHandler: File open failed for path \""
Chris@665 76 << path << "\"" << endl;
Chris@216 77 }
Chris@216 78 }
Chris@216 79
Chris@216 80 } else if (message.getMethod() == "recent" ||
Chris@216 81 message.getMethod() == "last") {
Chris@216 82
Chris@216 83 int n = 0;
Chris@216 84 if (message.getMethod() == "recent" &&
Chris@216 85 message.getArgCount() == 1 &&
Chris@216 86 message.getArg(0).canConvert(QVariant::Int)) {
Chris@216 87 n = message.getArg(0).toInt() - 1;
Chris@216 88 }
Chris@216 89 std::vector<QString> recent = m_recentFiles.getRecent();
Chris@216 90 if (n >= 0 && n < int(recent.size())) {
Chris@2441 91 QString path = recent[n];
Chris@2441 92 if (open(path, ReplaceMainModel) == FileOpenSucceeded) {
Chris@2441 93 SVDEBUG << "OSCHandler: Opened recent path \""
Chris@2441 94 << path << "\"" << endl;
Chris@2441 95 } else {
Chris@2441 96 SVCERR << "OSCHandler: File open failed for path \""
Chris@2441 97 << path << "\"" << endl;
Chris@216 98 }
Chris@216 99 }
Chris@216 100
Chris@216 101 } else if (message.getMethod() == "save") {
Chris@216 102
Chris@216 103 QString path;
Chris@216 104 if (message.getArgCount() == 1 &&
Chris@216 105 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 106 path = message.getArg(0).toString();
Chris@216 107 if (QFileInfo(path).exists()) {
Chris@2441 108 SVCERR << "OSCHandler: Refusing to overwrite existing file in save" << endl;
Chris@2441 109 } else if (saveSessionFile(path)) {
Chris@2441 110 SVDEBUG << "OSCHandler: Saved session to path \""
Chris@2441 111 << path << "\"" << endl;
Chris@216 112 } else {
Chris@2441 113 SVCERR << "OSCHandler: Save failed to path \""
Chris@2441 114 << path << "\"" << endl;
Chris@216 115 }
Chris@216 116 }
Chris@216 117
Chris@216 118 } else if (message.getMethod() == "export") {
Chris@216 119
Chris@216 120 QString path;
Chris@216 121 if (getMainModel()) {
Chris@216 122 if (message.getArgCount() == 1 &&
Chris@216 123 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 124 path = message.getArg(0).toString();
Chris@216 125 if (QFileInfo(path).exists()) {
Chris@2441 126 SVCERR << "OSCHandler: Refusing to overwrite existing file in export" << endl;
Chris@216 127 } else {
Chris@216 128 WavFileWriter writer(path,
Chris@216 129 getMainModel()->getSampleRate(),
Chris@428 130 getMainModel()->getChannelCount(),
Chris@428 131 WavFileWriter::WriteToTemporary);
Chris@216 132 MultiSelection ms = m_viewManager->getSelection();
Chris@2441 133 if (writer.writeModel
Chris@2441 134 (getMainModel().get(),
Chris@2441 135 ms.getSelections().empty() ? nullptr : &ms)) {
Chris@2441 136 SVDEBUG << "OSCHandler: Exported audio to path \""
Chris@2441 137 << path << "\"" << endl;
Chris@216 138 } else {
Chris@2441 139 SVCERR << "OSCHandler: Export failed to path \""
Chris@2441 140 << path << "\"" << endl;
Chris@216 141 }
Chris@216 142 }
Chris@216 143 }
Chris@216 144 }
Chris@216 145
Chris@2242 146 } else if (message.getMethod() == "exportlayer") {
Chris@2242 147
Chris@2242 148 QString path;
Chris@2242 149 if (message.getArgCount() == 1 &&
Chris@2242 150 message.getArg(0).canConvert(QVariant::String)) {
Chris@2242 151 path = message.getArg(0).toString();
Chris@2242 152 if (QFileInfo(path).exists()) {
Chris@2242 153 SVDEBUG << "OSCHandler: Refusing to overwrite existing file in layer export" << endl;
Chris@2242 154 } else {
Chris@2242 155 Pane *currentPane = nullptr;
Chris@2242 156 Layer *currentLayer = nullptr;
Chris@2242 157 if (m_paneStack) currentPane = m_paneStack->getCurrentPane();
Chris@2242 158 if (currentPane) currentLayer = currentPane->getSelectedLayer();
Chris@2442 159 MultiSelection ms = m_viewManager->getSelection();
Chris@2242 160 if (currentLayer) {
Chris@2242 161 QString error;
Chris@2442 162 if (exportLayerTo
Chris@2442 163 (currentLayer, currentPane,
Chris@2442 164 ms.getSelections().empty() ? nullptr : &ms,
Chris@2442 165 path, error)) {
Chris@2442 166 SVDEBUG << "OSCHandler: Exported layer \""
Chris@2442 167 << currentLayer->getLayerPresentationName()
Chris@2442 168 << "\" to path \"" << path << "\"" << endl;
Chris@2442 169 } else {
Chris@2442 170 SVCERR << "OSCHandler: Export failed to path \""
Chris@2442 171 << path << "\"" << endl;
Chris@2242 172 }
Chris@2242 173 } else {
Chris@2242 174 SVCERR << "OSCHandler: No current layer to export" << endl;
Chris@2242 175 }
Chris@2242 176 }
Chris@2242 177 }
Chris@2242 178
Chris@216 179 } else if (message.getMethod() == "jump" ||
Chris@216 180 message.getMethod() == "play") {
Chris@216 181
Chris@216 182 if (getMainModel()) {
Chris@216 183
Chris@922 184 sv_frame_t frame = m_viewManager->getPlaybackFrame();
Chris@216 185 bool selection = false;
Chris@216 186 bool play = (message.getMethod() == "play");
Chris@216 187
Chris@216 188 if (message.getArgCount() == 1) {
Chris@216 189
Chris@216 190 if (message.getArg(0).canConvert(QVariant::String) &&
Chris@216 191 message.getArg(0).toString() == "selection") {
Chris@216 192
Chris@216 193 selection = true;
Chris@216 194
Chris@216 195 } else if (message.getArg(0).canConvert(QVariant::String) &&
Chris@216 196 message.getArg(0).toString() == "end") {
Chris@216 197
Chris@216 198 frame = getMainModel()->getEndFrame();
Chris@216 199
Chris@216 200 } else if (message.getArg(0).canConvert(QVariant::Double)) {
Chris@216 201
Chris@216 202 double time = message.getArg(0).toDouble();
Chris@216 203 if (time < 0.0) time = 0.0;
Chris@216 204
Chris@216 205 frame = lrint(time * getMainModel()->getSampleRate());
Chris@216 206 }
Chris@216 207 }
Chris@216 208
Chris@216 209 if (frame > getMainModel()->getEndFrame()) {
Chris@216 210 frame = getMainModel()->getEndFrame();
Chris@216 211 }
Chris@216 212
Chris@216 213 if (play) {
Chris@216 214 m_viewManager->setPlaySelectionMode(selection);
Chris@216 215 }
Chris@216 216
Chris@216 217 if (selection) {
Chris@216 218 MultiSelection::SelectionList sl = m_viewManager->getSelections();
Chris@216 219 if (!sl.empty()) {
Chris@216 220 frame = sl.begin()->getStartFrame();
Chris@216 221 }
Chris@216 222 }
Chris@216 223
Chris@1617 224 SVDEBUG << "OSCHandler: Setting playback frame to " << frame << endl;
Chris@1617 225
Chris@216 226 m_viewManager->setPlaybackFrame(frame);
Chris@216 227
Chris@1617 228 if (play) {
Chris@1617 229 if (!m_playSource->isPlaying()) {
Chris@1617 230 SVDEBUG << "OSCHandler: Play source is not yet playing, calling play()" << endl;
Chris@1617 231 // handles audio device suspend/resume etc, as
Chris@1617 232 // well as calling m_playSource->play(frame)
Chris@1617 233 MainWindow::play();
Chris@1617 234 } else {
Chris@1617 235 SVDEBUG << "OSCHandler: Play source is already playing, not starting it" << endl;
Chris@1617 236 }
Chris@1617 237 } else {
Chris@1617 238 SVDEBUG << "OSCHandler: Jump only requested, not starting playback" << endl;
Chris@216 239 }
Chris@216 240 }
Chris@216 241
Chris@313 242 } else if (message.getMethod() == "ffwd") {
Chris@313 243
Chris@313 244 if (message.getArgCount() == 1) {
Chris@313 245
Chris@313 246 if (message.getArg(0).canConvert(QVariant::String) &&
Chris@313 247 message.getArg(0).toString() == "similar") {
Chris@313 248
Chris@2441 249 SVDEBUG << "OSCHandler: Calling ffwdSimilar" << endl;
Chris@313 250 ffwdSimilar();
Chris@313 251 }
Chris@313 252 } else {
Chris@313 253
Chris@2441 254 SVDEBUG << "OSCHandler: Calling ffwd" << endl;
Chris@313 255 ffwd();
Chris@313 256 }
Chris@313 257
Chris@313 258 } else if (message.getMethod() == "rewind") {
Chris@313 259
Chris@313 260 if (message.getArgCount() == 1) {
Chris@313 261
Chris@313 262 if (message.getArg(0).canConvert(QVariant::String) &&
Chris@313 263 message.getArg(0).toString() == "similar") {
Chris@313 264
Chris@2441 265 SVDEBUG << "OSCHandler: Calling rewindSimilar" << endl;
Chris@313 266 rewindSimilar();
Chris@313 267 }
Chris@313 268 } else {
Chris@313 269
Chris@2441 270 SVDEBUG << "OSCHandler: Calling rewind" << endl;
Chris@313 271 rewind();
Chris@313 272 }
Chris@313 273
Chris@216 274 } else if (message.getMethod() == "stop") {
Chris@216 275
Chris@2441 276 if (m_playSource->isPlaying()) {
Chris@2441 277 // As with play, we want to use the MainWindow function
Chris@2441 278 // rather than call m_playSource directly because that way
Chris@2441 279 // the audio driver suspend/resume etc is handled properly
Chris@2441 280 SVDEBUG << "OSCHandler: Calling stop" << endl;
Chris@2441 281 MainWindow::stop();
Chris@2441 282 } else {
Chris@2441 283 SVDEBUG << "OSCHandler: Not playing, doing nothing" << endl;
Chris@2441 284 }
Chris@216 285
Chris@216 286 } else if (message.getMethod() == "loop") {
Chris@216 287
Chris@216 288 if (message.getArgCount() == 1 &&
Chris@216 289 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 290
Chris@216 291 QString str = message.getArg(0).toString();
Chris@216 292 if (str == "on") {
Chris@2441 293 SVDEBUG << "OSCHandler: Enabling loop mode" << endl;
Chris@216 294 m_viewManager->setPlayLoopMode(true);
Chris@216 295 } else if (str == "off") {
Chris@2441 296 SVDEBUG << "OSCHandler: Disabling loop mode" << endl;
Chris@216 297 m_viewManager->setPlayLoopMode(false);
Chris@216 298 }
Chris@216 299 }
Chris@216 300
Chris@216 301 } else if (message.getMethod() == "solo") {
Chris@216 302
Chris@216 303 if (message.getArgCount() == 1 &&
Chris@216 304 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 305
Chris@216 306 QString str = message.getArg(0).toString();
Chris@216 307 if (str == "on") {
Chris@2441 308 SVDEBUG << "OSCHandler: Enabling solo mode" << endl;
Chris@216 309 m_viewManager->setPlaySoloMode(true);
Chris@216 310 } else if (str == "off") {
Chris@2441 311 SVDEBUG << "OSCHandler: Disabling solo mode" << endl;
Chris@216 312 m_viewManager->setPlaySoloMode(false);
Chris@216 313 }
Chris@216 314 }
Chris@216 315
Chris@216 316 } else if (message.getMethod() == "select" ||
Chris@216 317 message.getMethod() == "addselect") {
Chris@216 318
Chris@216 319 if (getMainModel()) {
Chris@216 320
Chris@920 321 sv_frame_t f0 = getMainModel()->getStartFrame();
Chris@920 322 sv_frame_t f1 = getMainModel()->getEndFrame();
Chris@216 323
Chris@216 324 bool done = false;
Chris@216 325
Chris@216 326 if (message.getArgCount() == 2 &&
Chris@216 327 message.getArg(0).canConvert(QVariant::Double) &&
Chris@216 328 message.getArg(1).canConvert(QVariant::Double)) {
Chris@216 329
Chris@216 330 double t0 = message.getArg(0).toDouble();
Chris@216 331 double t1 = message.getArg(1).toDouble();
Chris@216 332 if (t1 < t0) { double temp = t0; t0 = t1; t1 = temp; }
Chris@216 333 if (t0 < 0.0) t0 = 0.0;
Chris@216 334 if (t1 < 0.0) t1 = 0.0;
Chris@216 335
Chris@216 336 f0 = lrint(t0 * getMainModel()->getSampleRate());
Chris@216 337 f1 = lrint(t1 * getMainModel()->getSampleRate());
Chris@2441 338
Chris@2441 339 SVDEBUG << "OSCHandler: Converted selection extents to frames "
Chris@2441 340 << f0 << " and " << f1 << endl;
Chris@216 341
Chris@216 342 Pane *pane = m_paneStack->getCurrentPane();
Chris@2126 343 Layer *layer = nullptr;
Chris@216 344 if (pane) layer = pane->getSelectedLayer();
Chris@216 345 if (layer) {
Chris@730 346 int resolution;
Chris@216 347 layer->snapToFeatureFrame(pane, f0, resolution,
Chris@2380 348 Layer::SnapLeft, -1);
Chris@216 349 layer->snapToFeatureFrame(pane, f1, resolution,
Chris@2380 350 Layer::SnapRight, -1);
Chris@2441 351
Chris@2441 352 SVDEBUG << "OSCHandler: Snapped selection extents to "
Chris@2441 353 << f0 << " and " << f1 << " for current layer \""
Chris@2441 354 << layer->getLayerPresentationName() << "\""
Chris@2441 355 << endl;
Chris@216 356 }
Chris@216 357
Chris@216 358 } else if (message.getArgCount() == 1 &&
Chris@216 359 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 360
Chris@216 361 QString str = message.getArg(0).toString();
Chris@216 362 if (str == "none") {
Chris@2441 363 SVDEBUG << "OSCHandler: Clearing selection" << endl;
Chris@216 364 m_viewManager->clearSelections();
Chris@216 365 done = true;
Chris@2441 366 } else if (str == "all") {
Chris@2441 367 SVDEBUG << "OSCHandler: Selecting all" << endl;
Chris@2441 368 f0 = getModelsStartFrame();
Chris@2441 369 f0 = getModelsEndFrame();
Chris@216 370 }
Chris@216 371 }
Chris@216 372
Chris@216 373 if (!done) {
Chris@216 374 if (message.getMethod() == "select") {
Chris@216 375 m_viewManager->setSelection(Selection(f0, f1));
Chris@216 376 } else {
Chris@216 377 m_viewManager->addSelection(Selection(f0, f1));
Chris@216 378 }
Chris@216 379 }
Chris@2441 380
Chris@2441 381 SVDEBUG << "OSCHandler: Selection now is "
Chris@2441 382 << m_viewManager->getSelection().toString() << endl;
Chris@2441 383
Chris@2441 384 } else {
Chris@2441 385 SVCERR << "OSCHandler: No main model, can't modify selection"
Chris@2441 386 << endl;
Chris@216 387 }
Chris@216 388
Chris@216 389 } else if (message.getMethod() == "add") {
Chris@216 390
Chris@216 391 if (getMainModel()) {
Chris@216 392
Chris@216 393 if (message.getArgCount() >= 1 &&
Chris@216 394 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 395
Chris@216 396 int channel = -1;
Chris@216 397 if (message.getArgCount() == 2 &&
Chris@216 398 message.getArg(0).canConvert(QVariant::Int)) {
Chris@216 399 channel = message.getArg(0).toInt();
Chris@216 400 if (channel < -1 ||
Chris@216 401 channel > int(getMainModel()->getChannelCount())) {
Chris@2441 402 SVCERR << "WARNING: OSCHandler: channel "
Chris@665 403 << channel << " out of range" << endl;
Chris@216 404 channel = -1;
Chris@216 405 }
Chris@216 406 }
Chris@216 407
Chris@216 408 QString str = message.getArg(0).toString();
Chris@216 409
Chris@216 410 LayerFactory::LayerType type =
Chris@216 411 LayerFactory::getInstance()->getLayerTypeForName(str);
Chris@216 412
Chris@216 413 if (type == LayerFactory::UnknownLayer) {
Chris@2441 414 SVCERR << "WARNING: OSCHandler: unknown layer "
Chris@2441 415 << "type " << str << endl;
Chris@216 416 } else {
Chris@216 417
Chris@232 418 LayerConfiguration configuration(type,
Chris@2300 419 getMainModelId(),
Chris@232 420 channel);
Chris@2441 421
Chris@2441 422 QString pname = LayerFactory::getInstance()->
Chris@2441 423 getLayerPresentationName(type);
Chris@216 424
Chris@2441 425 addPane(configuration, tr("Add %1 Pane") .arg(pname));
Chris@2441 426
Chris@2441 427 SVDEBUG << "OSCHandler: Added pane \"" << pname
Chris@2441 428 << "\"" << endl;
Chris@216 429 }
Chris@216 430 }
Chris@216 431 }
Chris@216 432
Chris@216 433 } else if (message.getMethod() == "undo") {
Chris@216 434
Chris@2441 435 SVDEBUG << "OSCHandler: Calling undo" << endl;
Chris@216 436 CommandHistory::getInstance()->undo();
Chris@216 437
Chris@216 438 } else if (message.getMethod() == "redo") {
Chris@216 439
Chris@2441 440 SVDEBUG << "OSCHandler: Calling redo" << endl;
Chris@216 441 CommandHistory::getInstance()->redo();
Chris@216 442
Chris@216 443 } else if (message.getMethod() == "set") {
Chris@216 444
Chris@216 445 if (message.getArgCount() == 2 &&
Chris@216 446 message.getArg(0).canConvert(QVariant::String) &&
Chris@216 447 message.getArg(1).canConvert(QVariant::Double)) {
Chris@216 448
Chris@216 449 QString property = message.getArg(0).toString();
Chris@216 450 float value = (float)message.getArg(1).toDouble();
Chris@216 451
Chris@216 452 if (property == "gain") {
Chris@216 453 if (value < 0.0) value = 0.0;
Chris@1386 454 m_mainLevelPan->setLevel(value);
Chris@216 455 if (m_playTarget) m_playTarget->setOutputGain(value);
Chris@1617 456 } else if (property == "speed") {
Chris@1617 457 m_playSpeed->setMappedValue(value);
Chris@216 458 } else if (property == "speedup") {
Chris@1617 459
Chris@1617 460 // The speedup method existed before the speed method
Chris@1617 461 // and is a bit weirder.
Chris@1617 462 //
Chris@1617 463 // For speed(x), x is a percentage of normal speed, so
Chris@1617 464 // x=100 means play at the normal speed, x=50 means
Chris@1617 465 // half speed, x=200 double speed etc.
Chris@1617 466 //
Chris@1617 467 // For speedup(x), x was some sort of modifier of
Chris@1617 468 // percentage thing, so x=0 meant play at the normal
Chris@1617 469 // speed, x=50 meant play at 150% of normal speed,
Chris@1617 470 // x=100 meant play at double speed, and x=-100 rather
Chris@1617 471 // bizarrely meant play at half speed. We handle this
Chris@1617 472 // now by converting to speed percentage as follows:
Chris@1617 473
Chris@1617 474 double percentage = 100.0;
Chris@1617 475 if (value > 0.f) {
Chris@1617 476 percentage = percentage + value;
Chris@1617 477 } else {
Chris@1617 478 percentage = 10000.0 / (percentage - value);
Chris@1617 479 }
Chris@1617 480 SVDEBUG << "OSCHandler: converted speedup(" << value
Chris@1617 481 << ") into speed(" << percentage << ")" << endl;
Chris@1617 482
Chris@1617 483 m_playSpeed->setMappedValue(percentage);
Chris@1617 484
Chris@216 485 } else if (property == "overlays") {
Chris@216 486 if (value < 0.5) {
Chris@216 487 m_viewManager->setOverlayMode(ViewManager::NoOverlays);
Chris@216 488 } else if (value < 1.5) {
Chris@701 489 m_viewManager->setOverlayMode(ViewManager::StandardOverlays);
Chris@216 490 } else {
Chris@216 491 m_viewManager->setOverlayMode(ViewManager::AllOverlays);
Chris@216 492 }
Chris@216 493 } else if (property == "zoomwheels") {
Chris@216 494 m_viewManager->setZoomWheelsEnabled(value > 0.5);
Chris@216 495 } else if (property == "propertyboxes") {
Chris@216 496 bool toggle = ((value < 0.5) !=
Chris@2339 497 (m_paneStack->getLayoutStyle() ==
Chris@2339 498 PaneStack::HiddenPropertyStacksLayout));
Chris@216 499 if (toggle) togglePropertyBoxes();
Chris@216 500 }
Chris@216 501
Chris@216 502 } else {
Chris@2126 503 PropertyContainer *container = nullptr;
Chris@216 504 Pane *pane = m_paneStack->getCurrentPane();
Chris@216 505 if (pane &&
Chris@216 506 message.getArgCount() == 3 &&
Chris@216 507 message.getArg(0).canConvert(QVariant::String) &&
Chris@216 508 message.getArg(1).canConvert(QVariant::String) &&
Chris@216 509 message.getArg(2).canConvert(QVariant::String)) {
Chris@216 510 if (message.getArg(0).toString() == "pane") {
Chris@216 511 container = pane->getPropertyContainer(0);
Chris@216 512 } else if (message.getArg(0).toString() == "layer") {
Chris@216 513 container = pane->getSelectedLayer();
Chris@216 514 }
Chris@216 515 }
Chris@216 516 if (container) {
Chris@216 517 QString nameString = message.getArg(1).toString();
Chris@216 518 QString valueString = message.getArg(2).toString();
Chris@248 519 Command *c = container->getSetPropertyCommand
Chris@248 520 (nameString, valueString);
Chris@248 521 if (c) CommandHistory::getInstance()->addCommand(c, true, true);
Chris@216 522 }
Chris@216 523 }
Chris@216 524
Chris@216 525 } else if (message.getMethod() == "setcurrent") {
Chris@216 526
Chris@216 527 int paneIndex = -1, layerIndex = -1;
Chris@216 528 bool wantLayer = false;
Chris@216 529
Chris@216 530 if (message.getArgCount() >= 1 &&
Chris@216 531 message.getArg(0).canConvert(QVariant::Int)) {
Chris@216 532
Chris@216 533 paneIndex = message.getArg(0).toInt() - 1;
Chris@216 534
Chris@216 535 if (message.getArgCount() >= 2 &&
Chris@216 536 message.getArg(1).canConvert(QVariant::Int)) {
Chris@216 537 wantLayer = true;
Chris@216 538 layerIndex = message.getArg(1).toInt() - 1;
Chris@216 539 }
Chris@216 540 }
Chris@216 541
Chris@216 542 if (paneIndex >= 0 && paneIndex < m_paneStack->getPaneCount()) {
Chris@216 543 Pane *pane = m_paneStack->getPane(paneIndex);
Chris@216 544 m_paneStack->setCurrentPane(pane);
Chris@2441 545 SVDEBUG << "OSCHandler: Set current pane to index "
Chris@2441 546 << paneIndex << " (pane id " << pane->getId()
Chris@2441 547 << ")" << endl;
Chris@216 548 if (layerIndex >= 0 && layerIndex < pane->getLayerCount()) {
Chris@2437 549 Layer *layer = pane->getFixedOrderLayer(layerIndex);
Chris@216 550 m_paneStack->setCurrentLayer(pane, layer);
Chris@2441 551 SVDEBUG << "OSCHandler: Set current layer to index "
Chris@2441 552 << layerIndex << " (layer \""
Chris@2441 553 << layer->getLayerPresentationName() << "\")" << endl;
Chris@216 554 } else if (wantLayer && layerIndex == -1) {
Chris@2126 555 m_paneStack->setCurrentLayer(pane, nullptr);
Chris@2441 556 } else if (wantLayer) {
Chris@2441 557 SVCERR << "OSCHandler: Layer index "
Chris@2441 558 << layerIndex << " out of range for pane" << endl;
Chris@2441 559 }
Chris@216 560 }
Chris@216 561
Chris@216 562 } else if (message.getMethod() == "delete") {
Chris@216 563
Chris@216 564 if (message.getArgCount() == 1 &&
Chris@216 565 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 566
Chris@216 567 QString target = message.getArg(0).toString();
Chris@216 568
Chris@216 569 if (target == "pane") {
Chris@216 570
Chris@2441 571 SVDEBUG << "OSCHandler: Calling deleteCurrentPane" << endl;
Chris@216 572 deleteCurrentPane();
Chris@216 573
Chris@216 574 } else if (target == "layer") {
Chris@216 575
Chris@2441 576 SVDEBUG << "OSCHandler: Calling deleteCurrentLayer" << endl;
Chris@216 577 deleteCurrentLayer();
Chris@216 578
Chris@216 579 } else {
Chris@216 580
Chris@2441 581 SVCERR << "WARNING: OSCHandler: Unknown delete target \""
Chris@2441 582 << target << "\"" << endl;
Chris@216 583 }
Chris@216 584 }
Chris@216 585
Chris@216 586 } else if (message.getMethod() == "zoom") {
Chris@216 587
Chris@216 588 if (message.getArgCount() == 1) {
Chris@216 589 if (message.getArg(0).canConvert(QVariant::String) &&
Chris@216 590 message.getArg(0).toString() == "in") {
Chris@216 591 zoomIn();
Chris@216 592 } else if (message.getArg(0).canConvert(QVariant::String) &&
Chris@216 593 message.getArg(0).toString() == "out") {
Chris@216 594 zoomOut();
Chris@216 595 } else if (message.getArg(0).canConvert(QVariant::String) &&
Chris@216 596 message.getArg(0).toString() == "default") {
Chris@216 597 zoomDefault();
Chris@312 598 } else if (message.getArg(0).canConvert(QVariant::String) &&
Chris@312 599 message.getArg(0).toString() == "fit") {
Chris@312 600 zoomToFit();
Chris@216 601 } else if (message.getArg(0).canConvert(QVariant::Double)) {
Chris@216 602 double level = message.getArg(0).toDouble();
Chris@216 603 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@2011 604 ZoomLevel zoomLevel;
Chris@2011 605 if (level >= 0.66) {
Chris@2011 606 zoomLevel = ZoomLevel(ZoomLevel::FramesPerPixel,
Chris@2011 607 int(round(level)));
Chris@2011 608 } else {
Chris@2011 609 zoomLevel = ZoomLevel(ZoomLevel::PixelsPerFrame,
Chris@2011 610 int(round(1.0 / level)));
Chris@2011 611 }
Chris@2011 612 if (currentPane) {
Chris@2441 613 SVDEBUG << "OSCHandler: Setting zoom level to "
Chris@2441 614 << zoomLevel << endl;
Chris@2011 615 currentPane->setZoomLevel(zoomLevel);
Chris@2441 616 } else {
Chris@2441 617 SVCERR << "OSCHandler: No current pane, can't set zoom"
Chris@2441 618 << endl;
Chris@2011 619 }
Chris@216 620 }
Chris@216 621 }
Chris@216 622
Chris@216 623 } else if (message.getMethod() == "zoomvertical") {
Chris@216 624
Chris@216 625 Pane *pane = m_paneStack->getCurrentPane();
Chris@2126 626 Layer *layer = nullptr;
Chris@216 627 if (pane && pane->getLayerCount() > 0) {
Chris@216 628 layer = pane->getLayer(pane->getLayerCount() - 1);
Chris@216 629 }
Chris@216 630 int defaultStep = 0;
Chris@216 631 int steps = 0;
Chris@216 632 if (layer) {
Chris@216 633 steps = layer->getVerticalZoomSteps(defaultStep);
Chris@216 634 if (message.getArgCount() == 1 && steps > 0) {
Chris@216 635 if (message.getArg(0).canConvert(QVariant::String) &&
Chris@216 636 message.getArg(0).toString() == "in") {
Chris@216 637 int step = layer->getCurrentVerticalZoomStep() + 1;
Chris@216 638 if (step < steps) layer->setVerticalZoomStep(step);
Chris@216 639 } else if (message.getArg(0).canConvert(QVariant::String) &&
Chris@216 640 message.getArg(0).toString() == "out") {
Chris@216 641 int step = layer->getCurrentVerticalZoomStep() - 1;
Chris@216 642 if (step >= 0) layer->setVerticalZoomStep(step);
Chris@216 643 } else if (message.getArg(0).canConvert(QVariant::String) &&
Chris@216 644 message.getArg(0).toString() == "default") {
Chris@216 645 layer->setVerticalZoomStep(defaultStep);
Chris@216 646 }
Chris@216 647 } else if (message.getArgCount() == 2) {
Chris@216 648 if (message.getArg(0).canConvert(QVariant::Double) &&
Chris@216 649 message.getArg(1).canConvert(QVariant::Double)) {
Chris@216 650 double min = message.getArg(0).toDouble();
Chris@216 651 double max = message.getArg(1).toDouble();
Chris@216 652 layer->setDisplayExtents(min, max);
Chris@216 653 }
Chris@216 654 }
Chris@216 655 }
Chris@216 656
Chris@216 657 } else if (message.getMethod() == "quit") {
Chris@2440 658
Chris@2440 659 SVDEBUG << "OSCHandler: Exiting abruptly" << endl;
Chris@2440 660 m_documentModified = false; // so we don't ask to save
Chris@216 661 close();
Chris@216 662
Chris@216 663 } else if (message.getMethod() == "resize") {
Chris@216 664
Chris@216 665 if (message.getArgCount() == 2) {
Chris@216 666
Chris@216 667 int width = 0, height = 0;
Chris@216 668
Chris@216 669 if (message.getArg(1).canConvert(QVariant::Int)) {
Chris@216 670
Chris@216 671 height = message.getArg(1).toInt();
Chris@216 672
Chris@216 673 if (message.getArg(0).canConvert(QVariant::String) &&
Chris@216 674 message.getArg(0).toString() == "pane") {
Chris@216 675
Chris@216 676 Pane *pane = m_paneStack->getCurrentPane();
Chris@216 677 if (pane) pane->resize(pane->width(), height);
Chris@216 678
Chris@216 679 } else if (message.getArg(0).canConvert(QVariant::Int)) {
Chris@216 680
Chris@216 681 width = message.getArg(0).toInt();
Chris@216 682 resize(width, height);
Chris@216 683 }
Chris@216 684 }
Chris@216 685 }
Chris@216 686
Chris@216 687 } else if (message.getMethod() == "transform") {
Chris@216 688
Chris@2441 689 if (message.getArgCount() == 1 &&
Chris@216 690 message.getArg(0).canConvert(QVariant::String)) {
Chris@216 691
Chris@2441 692 Pane *pane = m_paneStack->getCurrentPane();
Chris@2441 693
Chris@2441 694 if (getMainModel() && pane) {
Chris@216 695
Chris@2441 696 TransformId transformId = message.getArg(0).toString();
Chris@2441 697
Chris@2441 698 Transform transform = TransformFactory::getInstance()->
Chris@2441 699 getDefaultTransformFor(transformId);
Chris@2441 700
Chris@2441 701 SVDEBUG << "OSCHandler: Running transform on main model:"
Chris@2441 702 << transform.toXmlString() << endl;
Chris@1770 703
Chris@2441 704 Layer *newLayer = m_document->createDerivedLayer
Chris@2441 705 (transform, getMainModelId());
Chris@2441 706
Chris@2441 707 if (newLayer) {
Chris@2441 708 m_document->addLayerToView(pane, newLayer);
Chris@2441 709 m_recentTransforms.add(transformId);
Chris@2441 710 m_paneStack->setCurrentLayer(pane, newLayer);
Chris@2441 711 } else {
Chris@2441 712 SVCERR << "OSCHandler: Transform failed to run" << endl;
Chris@2441 713 }
Chris@2441 714 } else {
Chris@2441 715 SVCERR << "OSCHandler: Lack main model or pane, "
Chris@2441 716 << "can't run transform" << endl;
Chris@216 717 }
Chris@2441 718 }
Chris@216 719
Chris@216 720 } else {
Chris@2441 721 SVCERR << "WARNING: OSCHandler: Unknown or unsupported "
Chris@665 722 << "method \"" << message.getMethod()
Chris@665 723 << "\"" << endl;
Chris@216 724 }
Chris@2441 725
Chris@2441 726 SVDEBUG << "OSCHandler at " << NOW << ": finished message: "
Chris@2441 727 << message.toString() << " in " << timer.elapsed() << "ms" << endl;
Chris@216 728 }