00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "MainWindowBase.h"
00017 #include "Document.h"
00018
00019
00020 #include "view/Pane.h"
00021 #include "view/PaneStack.h"
00022 #include "data/model/WaveFileModel.h"
00023 #include "data/model/SparseOneDimensionalModel.h"
00024 #include "data/model/NoteModel.h"
00025 #include "data/model/Labeller.h"
00026 #include "view/ViewManager.h"
00027
00028 #include "layer/WaveformLayer.h"
00029 #include "layer/TimeRulerLayer.h"
00030 #include "layer/TimeInstantLayer.h"
00031 #include "layer/TimeValueLayer.h"
00032 #include "layer/Colour3DPlotLayer.h"
00033 #include "layer/SliceLayer.h"
00034 #include "layer/SliceableLayer.h"
00035 #include "layer/ImageLayer.h"
00036
00037 #include "widgets/ListInputDialog.h"
00038
00039 #include "audioio/AudioCallbackPlaySource.h"
00040 #include "audioio/AudioCallbackPlayTarget.h"
00041 #include "audioio/AudioTargetFactory.h"
00042 #include "audioio/PlaySpeedRangeMapper.h"
00043 #include "data/fileio/DataFileReaderFactory.h"
00044 #include "data/fileio/PlaylistFileReader.h"
00045 #include "data/fileio/WavFileWriter.h"
00046 #include "data/fileio/CSVFileWriter.h"
00047 #include "data/fileio/MIDIFileWriter.h"
00048 #include "data/fileio/BZipFileDevice.h"
00049 #include "data/fileio/FileSource.h"
00050
00051 #include "data/fft/FFTDataServer.h"
00052
00053 #include "base/RecentFiles.h"
00054
00055 #include "base/PlayParameterRepository.h"
00056 #include "base/XmlExportable.h"
00057 #include "base/CommandHistory.h"
00058 #include "base/Profiler.h"
00059 #include "base/Preferences.h"
00060
00061 #include "data/osc/OSCQueue.h"
00062
00063 #include <QApplication>
00064 #include <QMessageBox>
00065 #include <QGridLayout>
00066 #include <QLabel>
00067 #include <QAction>
00068 #include <QMenuBar>
00069 #include <QToolBar>
00070 #include <QInputDialog>
00071 #include <QStatusBar>
00072 #include <QTreeView>
00073 #include <QFile>
00074 #include <QFileInfo>
00075 #include <QDir>
00076 #include <QTextStream>
00077 #include <QProcess>
00078 #include <QShortcut>
00079 #include <QSettings>
00080 #include <QDateTime>
00081 #include <QProcess>
00082 #include <QCheckBox>
00083 #include <QRegExp>
00084 #include <QScrollArea>
00085
00086 #include <iostream>
00087 #include <cstdio>
00088 #include <errno.h>
00089
00090 using std::cerr;
00091 using std::endl;
00092
00093 using std::vector;
00094 using std::map;
00095 using std::set;
00096
00097
00098 MainWindowBase::MainWindowBase(bool withAudioOutput, bool withOSCSupport) :
00099 m_document(0),
00100 m_paneStack(0),
00101 m_viewManager(0),
00102 m_timeRulerLayer(0),
00103 m_audioOutput(withAudioOutput),
00104 m_playSource(0),
00105 m_playTarget(0),
00106 m_oscQueue(withOSCSupport ? new OSCQueue() : 0),
00107 m_recentFiles("RecentFiles", 20),
00108 m_recentTransforms("RecentTransforms", 20),
00109 m_documentModified(false),
00110 m_openingAudioFile(false),
00111 m_abandoning(false),
00112 m_labeller(0)
00113 {
00114 connect(CommandHistory::getInstance(), SIGNAL(commandExecuted()),
00115 this, SLOT(documentModified()));
00116 connect(CommandHistory::getInstance(), SIGNAL(documentRestored()),
00117 this, SLOT(documentRestored()));
00118
00119 m_viewManager = new ViewManager();
00120 connect(m_viewManager, SIGNAL(selectionChanged()),
00121 this, SLOT(updateMenuStates()));
00122 connect(m_viewManager, SIGNAL(inProgressSelectionChanged()),
00123 this, SLOT(inProgressSelectionChanged()));
00124
00125 Preferences::BackgroundMode mode =
00126 Preferences::getInstance()->getBackgroundMode();
00127 m_initialDarkBackground = m_viewManager->getGlobalDarkBackground();
00128 if (mode != Preferences::BackgroundFromTheme) {
00129 m_viewManager->setGlobalDarkBackground
00130 (mode == Preferences::DarkBackground);
00131 }
00132
00133 m_paneStack = new PaneStack(0, m_viewManager);
00134 connect(m_paneStack, SIGNAL(currentPaneChanged(Pane *)),
00135 this, SLOT(currentPaneChanged(Pane *)));
00136 connect(m_paneStack, SIGNAL(currentLayerChanged(Pane *, Layer *)),
00137 this, SLOT(currentLayerChanged(Pane *, Layer *)));
00138 connect(m_paneStack, SIGNAL(rightButtonMenuRequested(Pane *, QPoint)),
00139 this, SLOT(rightButtonMenuRequested(Pane *, QPoint)));
00140 connect(m_paneStack, SIGNAL(contextHelpChanged(const QString &)),
00141 this, SLOT(contextHelpChanged(const QString &)));
00142 connect(m_paneStack, SIGNAL(paneAdded(Pane *)),
00143 this, SLOT(paneAdded(Pane *)));
00144 connect(m_paneStack, SIGNAL(paneHidden(Pane *)),
00145 this, SLOT(paneHidden(Pane *)));
00146 connect(m_paneStack, SIGNAL(paneAboutToBeDeleted(Pane *)),
00147 this, SLOT(paneAboutToBeDeleted(Pane *)));
00148 connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QStringList)),
00149 this, SLOT(paneDropAccepted(Pane *, QStringList)));
00150 connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QString)),
00151 this, SLOT(paneDropAccepted(Pane *, QString)));
00152 connect(m_paneStack, SIGNAL(paneDeleteButtonClicked(Pane *)),
00153 this, SLOT(paneDeleteButtonClicked(Pane *)));
00154
00155 m_playSource = new AudioCallbackPlaySource(m_viewManager,
00156 QApplication::applicationName());
00157
00158 connect(m_playSource, SIGNAL(sampleRateMismatch(size_t, size_t, bool)),
00159 this, SLOT(sampleRateMismatch(size_t, size_t, bool)));
00160 connect(m_playSource, SIGNAL(audioOverloadPluginDisabled()),
00161 this, SLOT(audioOverloadPluginDisabled()));
00162
00163 connect(m_viewManager, SIGNAL(outputLevelsChanged(float, float)),
00164 this, SLOT(outputLevelsChanged(float, float)));
00165
00166 connect(m_viewManager, SIGNAL(playbackFrameChanged(unsigned long)),
00167 this, SLOT(playbackFrameChanged(unsigned long)));
00168
00169 connect(m_viewManager, SIGNAL(globalCentreFrameChanged(unsigned long)),
00170 this, SLOT(globalCentreFrameChanged(unsigned long)));
00171
00172 connect(m_viewManager, SIGNAL(viewCentreFrameChanged(View *, unsigned long)),
00173 this, SLOT(viewCentreFrameChanged(View *, unsigned long)));
00174
00175 connect(m_viewManager, SIGNAL(viewZoomLevelChanged(View *, unsigned long, bool)),
00176 this, SLOT(viewZoomLevelChanged(View *, unsigned long, bool)));
00177
00178 connect(Preferences::getInstance(),
00179 SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
00180 this,
00181 SLOT(preferenceChanged(PropertyContainer::PropertyName)));
00182
00183 if (m_oscQueue && m_oscQueue->isOK()) {
00184 connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC()));
00185 QTimer *oscTimer = new QTimer(this);
00186 connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC()));
00187 oscTimer->start(1000);
00188 }
00189
00190 Labeller::ValueType labellerType = Labeller::ValueFromTwoLevelCounter;
00191 QSettings settings;
00192 settings.beginGroup("MainWindow");
00193 labellerType = (Labeller::ValueType)
00194 settings.value("labellertype", (int)labellerType).toInt();
00195 int cycle = settings.value("labellercycle", 4).toInt();
00196 settings.endGroup();
00197
00198 m_labeller = new Labeller(labellerType);
00199 m_labeller->setCounterCycleSize(cycle);
00200 }
00201
00202 MainWindowBase::~MainWindowBase()
00203 {
00204 if (m_playTarget) m_playTarget->shutdown();
00205
00206 delete m_playSource;
00207 delete m_viewManager;
00208 delete m_oscQueue;
00209 Profiles::getInstance()->dump();
00210 }
00211
00212 QString
00213 MainWindowBase::getOpenFileName(FileFinder::FileType type)
00214 {
00215 FileFinder *ff = FileFinder::getInstance();
00216 switch (type) {
00217 case FileFinder::SessionFile:
00218 return ff->getOpenFileName(type, m_sessionFile);
00219 case FileFinder::AudioFile:
00220 return ff->getOpenFileName(type, m_audioFile);
00221 case FileFinder::LayerFile:
00222 return ff->getOpenFileName(type, m_sessionFile);
00223 case FileFinder::LayerFileNoMidi:
00224 return ff->getOpenFileName(type, m_sessionFile);
00225 case FileFinder::SessionOrAudioFile:
00226 return ff->getOpenFileName(type, m_sessionFile);
00227 case FileFinder::ImageFile:
00228 return ff->getOpenFileName(type, m_sessionFile);
00229 case FileFinder::AnyFile:
00230 if (getMainModel() != 0 &&
00231 m_paneStack != 0 &&
00232 m_paneStack->getCurrentPane() != 0) {
00233 return ff->getOpenFileName(FileFinder::AnyFile, m_sessionFile);
00234 } else {
00235 return ff->getOpenFileName(FileFinder::SessionOrAudioFile,
00236 m_sessionFile);
00237 }
00238 }
00239 return "";
00240 }
00241
00242 QString
00243 MainWindowBase::getSaveFileName(FileFinder::FileType type)
00244 {
00245 FileFinder *ff = FileFinder::getInstance();
00246 switch (type) {
00247 case FileFinder::SessionFile:
00248 return ff->getSaveFileName(type, m_sessionFile);
00249 case FileFinder::AudioFile:
00250 return ff->getSaveFileName(type, m_audioFile);
00251 case FileFinder::LayerFile:
00252 return ff->getSaveFileName(type, m_sessionFile);
00253 case FileFinder::LayerFileNoMidi:
00254 return ff->getSaveFileName(type, m_sessionFile);
00255 case FileFinder::SessionOrAudioFile:
00256 return ff->getSaveFileName(type, m_sessionFile);
00257 case FileFinder::ImageFile:
00258 return ff->getSaveFileName(type, m_sessionFile);
00259 case FileFinder::AnyFile:
00260 return ff->getSaveFileName(type, m_sessionFile);
00261 }
00262 return "";
00263 }
00264
00265 void
00266 MainWindowBase::registerLastOpenedFilePath(FileFinder::FileType type, QString path)
00267 {
00268 FileFinder *ff = FileFinder::getInstance();
00269 ff->registerLastOpenedFilePath(type, path);
00270 }
00271
00272 void
00273 MainWindowBase::updateMenuStates()
00274 {
00275 Pane *currentPane = 0;
00276 Layer *currentLayer = 0;
00277
00278 if (m_paneStack) currentPane = m_paneStack->getCurrentPane();
00279 if (currentPane) currentLayer = currentPane->getSelectedLayer();
00280
00281 bool havePrevPane = false, haveNextPane = false;
00282 bool havePrevLayer = false, haveNextLayer = false;
00283
00284 if (currentPane) {
00285 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
00286 if (m_paneStack->getPane(i) == currentPane) {
00287 if (i > 0) havePrevPane = true;
00288 if (i < m_paneStack->getPaneCount()-1) haveNextPane = true;
00289 break;
00290 }
00291 }
00292 if (currentLayer) {
00293 for (int i = 0; i < currentPane->getLayerCount(); ++i) {
00294 if (currentPane->getLayer(i) == currentLayer) {
00295 if (i > 0) havePrevLayer = true;
00296 if (i < currentPane->getLayerCount()-1) haveNextLayer = true;
00297 break;
00298 }
00299 }
00300 }
00301 }
00302
00303 bool haveCurrentPane =
00304 (currentPane != 0);
00305 bool haveCurrentLayer =
00306 (haveCurrentPane &&
00307 (currentLayer != 0));
00308 bool haveMainModel =
00309 (getMainModel() != 0);
00310 bool havePlayTarget =
00311 (m_playTarget != 0);
00312 bool haveSelection =
00313 (m_viewManager &&
00314 !m_viewManager->getSelections().empty());
00315 bool haveCurrentEditableLayer =
00316 (haveCurrentLayer &&
00317 currentLayer->isLayerEditable());
00318 bool haveCurrentTimeInstantsLayer =
00319 (haveCurrentLayer &&
00320 dynamic_cast<TimeInstantLayer *>(currentLayer));
00321 bool haveCurrentColour3DPlot =
00322 (haveCurrentLayer &&
00323 dynamic_cast<Colour3DPlotLayer *>(currentLayer));
00324 bool haveClipboardContents =
00325 (m_viewManager &&
00326 !m_viewManager->getClipboard().empty());
00327
00328 emit canAddPane(haveMainModel);
00329 emit canDeleteCurrentPane(haveCurrentPane);
00330 emit canZoom(haveMainModel && haveCurrentPane);
00331 emit canScroll(haveMainModel && haveCurrentPane);
00332 emit canAddLayer(haveMainModel && haveCurrentPane);
00333 emit canImportMoreAudio(haveMainModel);
00334 emit canImportLayer(haveMainModel && haveCurrentPane);
00335 emit canExportAudio(haveMainModel);
00336 emit canExportLayer(haveMainModel &&
00337 (haveCurrentEditableLayer || haveCurrentColour3DPlot));
00338 emit canExportImage(haveMainModel && haveCurrentPane);
00339 emit canDeleteCurrentLayer(haveCurrentLayer);
00340 emit canRenameLayer(haveCurrentLayer);
00341 emit canEditLayer(haveCurrentEditableLayer);
00342 emit canMeasureLayer(haveCurrentLayer);
00343 emit canSelect(haveMainModel && haveCurrentPane);
00344 emit canPlay(havePlayTarget);
00345 emit canFfwd(true);
00346 emit canRewind(true);
00347 emit canPaste(haveClipboardContents);
00348 emit canInsertInstant(haveCurrentPane);
00349 emit canInsertInstantsAtBoundaries(haveCurrentPane && haveSelection);
00350 emit canRenumberInstants(haveCurrentTimeInstantsLayer && haveSelection);
00351 emit canPlaySelection(haveMainModel && havePlayTarget && haveSelection);
00352 emit canClearSelection(haveSelection);
00353 emit canEditSelection(haveSelection && haveCurrentEditableLayer);
00354 emit canSave(m_sessionFile != "" && m_documentModified);
00355 emit canSelectPreviousPane(havePrevPane);
00356 emit canSelectNextPane(haveNextPane);
00357 emit canSelectPreviousLayer(havePrevLayer);
00358 emit canSelectNextLayer(haveNextLayer);
00359 }
00360
00361 void
00362 MainWindowBase::documentModified()
00363 {
00364
00365
00366 if (!m_documentModified) {
00368 setWindowTitle(tr("%1 (modified)").arg(windowTitle()));
00369 }
00370
00371 m_documentModified = true;
00372 updateMenuStates();
00373 }
00374
00375 void
00376 MainWindowBase::documentRestored()
00377 {
00378
00379
00380 if (m_documentModified) {
00382 QString wt(windowTitle());
00383 wt.replace(tr(" (modified)"), "");
00384 setWindowTitle(wt);
00385 }
00386
00387 m_documentModified = false;
00388 updateMenuStates();
00389 }
00390
00391 void
00392 MainWindowBase::playLoopToggled()
00393 {
00394 QAction *action = dynamic_cast<QAction *>(sender());
00395
00396 if (action) {
00397 m_viewManager->setPlayLoopMode(action->isChecked());
00398 } else {
00399 m_viewManager->setPlayLoopMode(!m_viewManager->getPlayLoopMode());
00400 }
00401 }
00402
00403 void
00404 MainWindowBase::playSelectionToggled()
00405 {
00406 QAction *action = dynamic_cast<QAction *>(sender());
00407
00408 if (action) {
00409 m_viewManager->setPlaySelectionMode(action->isChecked());
00410 } else {
00411 m_viewManager->setPlaySelectionMode(!m_viewManager->getPlaySelectionMode());
00412 }
00413 }
00414
00415 void
00416 MainWindowBase::playSoloToggled()
00417 {
00418 QAction *action = dynamic_cast<QAction *>(sender());
00419
00420 if (action) {
00421 m_viewManager->setPlaySoloMode(action->isChecked());
00422 } else {
00423 m_viewManager->setPlaySoloMode(!m_viewManager->getPlaySoloMode());
00424 }
00425
00426 if (m_viewManager->getPlaySoloMode()) {
00427 currentPaneChanged(m_paneStack->getCurrentPane());
00428 } else {
00429 m_viewManager->setPlaybackModel(0);
00430 if (m_playSource) {
00431 m_playSource->clearSoloModelSet();
00432 }
00433 }
00434 }
00435
00436 void
00437 MainWindowBase::currentPaneChanged(Pane *p)
00438 {
00439 updateMenuStates();
00440 updateVisibleRangeDisplay(p);
00441
00442 if (!p) return;
00443
00444 if (!(m_viewManager &&
00445 m_playSource &&
00446 m_viewManager->getPlaySoloMode())) {
00447 if (m_viewManager) m_viewManager->setPlaybackModel(0);
00448 return;
00449 }
00450
00451 Model *prevPlaybackModel = m_viewManager->getPlaybackModel();
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 int frame = m_playSource->getCurrentBufferedFrame();
00462
00463
00464
00465 View::ModelSet soloModels = p->getModels();
00466
00467 View::ModelSet sources;
00468 for (View::ModelSet::iterator mi = soloModels.begin();
00469 mi != soloModels.end(); ++mi) {
00470 if (*mi && (*mi)->getSourceModel()) {
00471 sources.insert((*mi)->getSourceModel());
00472 }
00473 }
00474 for (View::ModelSet::iterator mi = sources.begin();
00475 mi != sources.end(); ++mi) {
00476 soloModels.insert(*mi);
00477 }
00478
00480
00481
00482
00483
00484 for (View::ModelSet::iterator mi = soloModels.begin();
00485 mi != soloModels.end(); ++mi) {
00486 if (dynamic_cast<RangeSummarisableTimeValueModel *>(*mi)) {
00487 m_viewManager->setPlaybackModel(*mi);
00488 }
00489 }
00490
00491 RangeSummarisableTimeValueModel *a =
00492 dynamic_cast<RangeSummarisableTimeValueModel *>(prevPlaybackModel);
00493 RangeSummarisableTimeValueModel *b =
00494 dynamic_cast<RangeSummarisableTimeValueModel *>(m_viewManager->
00495 getPlaybackModel());
00496
00497 m_playSource->setSoloModelSet(soloModels);
00498
00499 if (a && b && (a != b)) {
00500 if (m_playSource->isPlaying()) m_playSource->play(frame);
00501 }
00502 }
00503
00504 void
00505 MainWindowBase::currentLayerChanged(Pane *p, Layer *)
00506 {
00507 updateMenuStates();
00508 updateVisibleRangeDisplay(p);
00509 }
00510
00511 void
00512 MainWindowBase::selectAll()
00513 {
00514 if (!getMainModel()) return;
00515 m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(),
00516 getMainModel()->getEndFrame()));
00517 }
00518
00519 void
00520 MainWindowBase::selectToStart()
00521 {
00522 if (!getMainModel()) return;
00523 m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(),
00524 m_viewManager->getGlobalCentreFrame()));
00525 }
00526
00527 void
00528 MainWindowBase::selectToEnd()
00529 {
00530 if (!getMainModel()) return;
00531 m_viewManager->setSelection(Selection(m_viewManager->getGlobalCentreFrame(),
00532 getMainModel()->getEndFrame()));
00533 }
00534
00535 void
00536 MainWindowBase::selectVisible()
00537 {
00538 Model *model = getMainModel();
00539 if (!model) return;
00540
00541 Pane *currentPane = m_paneStack->getCurrentPane();
00542 if (!currentPane) return;
00543
00544 size_t startFrame, endFrame;
00545
00546 if (currentPane->getStartFrame() < 0) startFrame = 0;
00547 else startFrame = currentPane->getStartFrame();
00548
00549 if (currentPane->getEndFrame() > model->getEndFrame()) endFrame = model->getEndFrame();
00550 else endFrame = currentPane->getEndFrame();
00551
00552 m_viewManager->setSelection(Selection(startFrame, endFrame));
00553 }
00554
00555 void
00556 MainWindowBase::clearSelection()
00557 {
00558 m_viewManager->clearSelections();
00559 }
00560
00561 void
00562 MainWindowBase::cut()
00563 {
00564 Pane *currentPane = m_paneStack->getCurrentPane();
00565 if (!currentPane) return;
00566
00567 Layer *layer = currentPane->getSelectedLayer();
00568 if (!layer) return;
00569
00570 Clipboard &clipboard = m_viewManager->getClipboard();
00571 clipboard.clear();
00572
00573 MultiSelection::SelectionList selections = m_viewManager->getSelections();
00574
00575 CommandHistory::getInstance()->startCompoundOperation(tr("Cut"), true);
00576
00577 for (MultiSelection::SelectionList::iterator i = selections.begin();
00578 i != selections.end(); ++i) {
00579 layer->copy(currentPane, *i, clipboard);
00580 layer->deleteSelection(*i);
00581 }
00582
00583 CommandHistory::getInstance()->endCompoundOperation();
00584 }
00585
00586 void
00587 MainWindowBase::copy()
00588 {
00589 Pane *currentPane = m_paneStack->getCurrentPane();
00590 if (!currentPane) return;
00591
00592 Layer *layer = currentPane->getSelectedLayer();
00593 if (!layer) return;
00594
00595 Clipboard &clipboard = m_viewManager->getClipboard();
00596 clipboard.clear();
00597
00598 MultiSelection::SelectionList selections = m_viewManager->getSelections();
00599
00600 for (MultiSelection::SelectionList::iterator i = selections.begin();
00601 i != selections.end(); ++i) {
00602 layer->copy(currentPane, *i, clipboard);
00603 }
00604 }
00605
00606 void
00607 MainWindowBase::paste()
00608 {
00609 Pane *currentPane = m_paneStack->getCurrentPane();
00610 if (!currentPane) return;
00611
00612 Layer *layer = currentPane->getSelectedLayer();
00613
00614 Clipboard &clipboard = m_viewManager->getClipboard();
00615
00616
00617 bool inCompound = false;
00618
00619 if (!layer || !layer->isLayerEditable()) {
00620
00621 CommandHistory::getInstance()->startCompoundOperation
00622 (tr("Paste"), true);
00623
00624
00625
00626 LayerFactory::LayerType type =
00627 LayerFactory::getInstance()->getLayerTypeForClipboardContents(clipboard);
00628 layer = m_document->createEmptyLayer(type);
00629
00630 if (!layer) {
00631 CommandHistory::getInstance()->endCompoundOperation();
00632 return;
00633 }
00634
00635 m_document->addLayerToView(currentPane, layer);
00636 m_paneStack->setCurrentLayer(currentPane, layer);
00637
00638 inCompound = true;
00639 }
00640
00641 layer->paste(currentPane, clipboard, 0, true);
00642
00643 if (inCompound) CommandHistory::getInstance()->endCompoundOperation();
00644 }
00645
00646 void
00647 MainWindowBase::deleteSelected()
00648 {
00649 if (m_paneStack->getCurrentPane() &&
00650 m_paneStack->getCurrentPane()->getSelectedLayer()) {
00651
00652 Layer *layer = m_paneStack->getCurrentPane()->getSelectedLayer();
00653
00654 if (m_viewManager &&
00655 (m_viewManager->getToolMode() == ViewManager::MeasureMode)) {
00656
00657 layer->deleteCurrentMeasureRect();
00658
00659 } else {
00660
00661 MultiSelection::SelectionList selections =
00662 m_viewManager->getSelections();
00663
00664 for (MultiSelection::SelectionList::iterator i = selections.begin();
00665 i != selections.end(); ++i) {
00666 layer->deleteSelection(*i);
00667 }
00668 }
00669 }
00670 }
00671
00672 void
00673 MainWindowBase::insertInstant()
00674 {
00675 int frame = m_viewManager->getPlaybackFrame();
00676 insertInstantAt(frame);
00677 }
00678
00679 void
00680 MainWindowBase::insertInstantsAtBoundaries()
00681 {
00682 MultiSelection::SelectionList selections = m_viewManager->getSelections();
00683 for (MultiSelection::SelectionList::iterator i = selections.begin();
00684 i != selections.end(); ++i) {
00685 size_t start = i->getStartFrame();
00686 size_t end = i->getEndFrame();
00687 if (start != end) {
00688 insertInstantAt(i->getStartFrame());
00689 insertInstantAt(i->getEndFrame());
00690 }
00691 }
00692 }
00693
00694 void
00695 MainWindowBase::insertInstantAt(size_t frame)
00696 {
00697 Pane *pane = m_paneStack->getCurrentPane();
00698 if (!pane) {
00699 return;
00700 }
00701
00702 frame = pane->alignFromReference(frame);
00703
00704 Layer *layer = dynamic_cast<TimeInstantLayer *>
00705 (pane->getSelectedLayer());
00706
00707 if (!layer) {
00708 for (int i = pane->getLayerCount(); i > 0; --i) {
00709 layer = dynamic_cast<TimeInstantLayer *>(pane->getLayer(i - 1));
00710 if (layer) break;
00711 }
00712
00713 if (!layer) {
00714 CommandHistory::getInstance()->startCompoundOperation
00715 (tr("Add Point"), true);
00716 layer = m_document->createEmptyLayer(LayerFactory::TimeInstants);
00717 if (layer) {
00718 m_document->addLayerToView(pane, layer);
00719 m_paneStack->setCurrentLayer(pane, layer);
00720 }
00721 CommandHistory::getInstance()->endCompoundOperation();
00722 }
00723 }
00724
00725 if (layer) {
00726
00727 Model *model = layer->getModel();
00728 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
00729 (model);
00730
00731 if (sodm) {
00732 SparseOneDimensionalModel::Point point(frame, "");
00733
00734 SparseOneDimensionalModel::Point prevPoint(0);
00735 bool havePrevPoint = false;
00736
00737 SparseOneDimensionalModel::EditCommand *command =
00738 new SparseOneDimensionalModel::EditCommand(sodm, tr("Add Point"));
00739
00740 if (m_labeller->requiresPrevPoint()) {
00741
00742 SparseOneDimensionalModel::PointList prevPoints =
00743 sodm->getPreviousPoints(frame);
00744
00745 if (!prevPoints.empty()) {
00746 prevPoint = *prevPoints.begin();
00747 havePrevPoint = true;
00748 }
00749 }
00750
00751 if (m_labeller) {
00752
00753 m_labeller->setSampleRate(sodm->getSampleRate());
00754
00755 if (m_labeller->actingOnPrevPoint()) {
00756 command->deletePoint(prevPoint);
00757 }
00758
00759 m_labeller->label<SparseOneDimensionalModel::Point>
00760 (point, havePrevPoint ? &prevPoint : 0);
00761
00762 if (m_labeller->actingOnPrevPoint()) {
00763 command->addPoint(prevPoint);
00764 }
00765 }
00766
00767 command->addPoint(point);
00768
00769 command->setName(tr("Add Point at %1 s")
00770 .arg(RealTime::frame2RealTime
00771 (frame,
00772 sodm->getSampleRate())
00773 .toText(false).c_str()));
00774
00775 command->finish();
00776 }
00777 }
00778 }
00779
00780 void
00781 MainWindowBase::renumberInstants()
00782 {
00783 Pane *pane = m_paneStack->getCurrentPane();
00784 if (!pane) return;
00785
00786 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer());
00787 if (!layer) return;
00788
00789 MultiSelection ms(m_viewManager->getSelection());
00790
00791 Model *model = layer->getModel();
00792 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
00793 (model);
00794 if (!sodm) return;
00795
00796 if (!m_labeller) return;
00797
00798 Labeller labeller(*m_labeller);
00799 labeller.setSampleRate(sodm->getSampleRate());
00800
00801
00802
00803 labeller.labelAll<SparseOneDimensionalModel::Point>(*sodm, &ms);
00804 }
00805
00806 MainWindowBase::FileOpenStatus
00807 MainWindowBase::open(QString fileOrUrl, AudioFileOpenMode mode)
00808 {
00809 return open(FileSource(fileOrUrl, FileSource::ProgressDialog), mode);
00810 }
00811
00812 MainWindowBase::FileOpenStatus
00813 MainWindowBase::open(FileSource source, AudioFileOpenMode mode)
00814 {
00815 FileOpenStatus status;
00816
00817 if (!source.isAvailable()) return FileOpenFailed;
00818 source.waitForData();
00819
00820 bool canImportLayer = (getMainModel() != 0 &&
00821 m_paneStack != 0 &&
00822 m_paneStack->getCurrentPane() != 0);
00823
00824 if ((status = openAudio(source, mode)) != FileOpenFailed) {
00825 return status;
00826 } else if ((status = openSession(source)) != FileOpenFailed) {
00827 return status;
00828 } else if ((status = openPlaylist(source, mode)) != FileOpenFailed) {
00829 return status;
00830 } else if (!canImportLayer) {
00831 return FileOpenWrongMode;
00832 } else if ((status = openImage(source)) != FileOpenFailed) {
00833 return status;
00834 } else if ((status = openLayer(source)) != FileOpenFailed) {
00835 return status;
00836 } else {
00837 return FileOpenFailed;
00838 }
00839 }
00840
00841 MainWindowBase::FileOpenStatus
00842 MainWindowBase::openAudio(FileSource source, AudioFileOpenMode mode)
00843 {
00844 std::cerr << "MainWindowBase::openAudio(" << source.getLocation().toStdString() << ")" << std::endl;
00845
00846 if (!source.isAvailable()) return FileOpenFailed;
00847 source.waitForData();
00848
00849 m_openingAudioFile = true;
00850
00851 size_t rate = 0;
00852
00853 if (Preferences::getInstance()->getResampleOnLoad()) {
00854 rate = m_playSource->getSourceSampleRate();
00855 }
00856
00857 WaveFileModel *newModel = new WaveFileModel(source, rate);
00858
00859 if (!newModel->isOK()) {
00860 delete newModel;
00861 m_openingAudioFile = false;
00862 return FileOpenFailed;
00863 }
00864
00865 std::cerr << "mode = " << mode << std::endl;
00866
00867 if (mode == AskUser) {
00868 if (getMainModel()) {
00869
00870 static bool prevSetAsMain = true;
00871 bool setAsMain = true;
00872
00873 QStringList items;
00874 items << tr("Replace the existing main waveform")
00875 << tr("Load this file into a new waveform pane");
00876
00877 bool ok = false;
00878 QString item = ListInputDialog::getItem
00879 (this, tr("Select target for import"),
00880 tr("You already have an audio waveform loaded.\nWhat would you like to do with the new audio file?"),
00881 items, prevSetAsMain ? 0 : 1, &ok);
00882
00883 if (!ok || item.isEmpty()) {
00884 delete newModel;
00885 m_openingAudioFile = false;
00886 return FileOpenCancelled;
00887 }
00888
00889 setAsMain = (item == items[0]);
00890 prevSetAsMain = setAsMain;
00891
00892 if (setAsMain) mode = ReplaceMainModel;
00893 else mode = CreateAdditionalModel;
00894
00895 } else {
00896 mode = ReplaceMainModel;
00897 }
00898 }
00899
00900 if (mode == ReplaceCurrentPane) {
00901
00902 Pane *pane = m_paneStack->getCurrentPane();
00903 if (pane) {
00904 if (getMainModel()) {
00905 View::ModelSet models(pane->getModels());
00906 if (models.find(getMainModel()) != models.end()) {
00907 mode = ReplaceMainModel;
00908 }
00909 } else {
00910 mode = ReplaceMainModel;
00911 }
00912 } else {
00913 mode = CreateAdditionalModel;
00914 }
00915 }
00916
00917 if (mode == CreateAdditionalModel && !getMainModel()) {
00918 mode = ReplaceMainModel;
00919 }
00920
00921 if (mode == ReplaceMainModel) {
00922
00923 Model *prevMain = getMainModel();
00924 if (prevMain) {
00925 m_playSource->removeModel(prevMain);
00926 PlayParameterRepository::getInstance()->removeModel(prevMain);
00927 }
00928 PlayParameterRepository::getInstance()->addModel(newModel);
00929
00930 m_document->setMainModel(newModel);
00931
00932 setupMenus();
00933
00934 if (m_sessionFile == "") {
00936 setWindowTitle(tr("%1: %2")
00937 .arg(QApplication::applicationName())
00938 .arg(source.getLocation()));
00939 CommandHistory::getInstance()->clear();
00940 CommandHistory::getInstance()->documentSaved();
00941 m_documentModified = false;
00942 } else {
00943 setWindowTitle(tr("%1: %2 [%3]")
00944 .arg(QApplication::applicationName())
00945 .arg(QFileInfo(m_sessionFile).fileName())
00946 .arg(source.getLocation()));
00947 if (m_documentModified) {
00948 m_documentModified = false;
00949 documentModified();
00950 }
00951 }
00952
00953 if (!source.isRemote()) m_audioFile = source.getLocalFilename();
00954
00955 } else if (mode == CreateAdditionalModel) {
00956
00957 CommandHistory::getInstance()->startCompoundOperation
00958 (tr("Import \"%1\"").arg(source.getLocation()), true);
00959
00960 m_document->addImportedModel(newModel);
00961
00962 AddPaneCommand *command = new AddPaneCommand(this);
00963 CommandHistory::getInstance()->addCommand(command);
00964
00965 Pane *pane = command->getPane();
00966
00967 if (m_timeRulerLayer) {
00968 m_document->addLayerToView(pane, m_timeRulerLayer);
00969 }
00970
00971 Layer *newLayer = m_document->createImportedLayer(newModel);
00972
00973 if (newLayer) {
00974 m_document->addLayerToView(pane, newLayer);
00975 }
00976
00977 CommandHistory::getInstance()->endCompoundOperation();
00978
00979 } else if (mode == ReplaceCurrentPane) {
00980
00981
00982
00983
00984
00985
00986
00987 Pane *pane = m_paneStack->getCurrentPane();
00988 Layer *replace = 0;
00989
00990 for (int i = 0; i < pane->getLayerCount(); ++i) {
00991 Layer *layer = pane->getLayer(i);
00992 if (dynamic_cast<WaveformLayer *>(layer)) {
00993 replace = layer;
00994 break;
00995 }
00996 }
00997
00998 CommandHistory::getInstance()->startCompoundOperation
00999 (tr("Import \"%1\"").arg(source.getLocation()), true);
01000
01001 m_document->addImportedModel(newModel);
01002
01003 if (replace) {
01004 m_document->removeLayerFromView(pane, replace);
01005 }
01006
01007 Layer *newLayer = m_document->createImportedLayer(newModel);
01008
01009 if (newLayer) {
01010 m_document->addLayerToView(pane, newLayer);
01011 }
01012
01013 CommandHistory::getInstance()->endCompoundOperation();
01014 }
01015
01016 updateMenuStates();
01017 m_recentFiles.addFile(source.getLocation());
01018 if (!source.isRemote()) {
01019
01020 registerLastOpenedFilePath(FileFinder::AudioFile,
01021 source.getLocalFilename());
01022 }
01023 m_openingAudioFile = false;
01024
01025 currentPaneChanged(m_paneStack->getCurrentPane());
01026
01027 return FileOpenSucceeded;
01028 }
01029
01030 MainWindowBase::FileOpenStatus
01031 MainWindowBase::openPlaylist(FileSource source, AudioFileOpenMode mode)
01032 {
01033 std::set<QString> extensions;
01034 PlaylistFileReader::getSupportedExtensions(extensions);
01035 QString extension = source.getExtension();
01036 if (extensions.find(extension) == extensions.end()) return FileOpenFailed;
01037
01038 if (!source.isAvailable()) return FileOpenFailed;
01039 source.waitForData();
01040
01041 PlaylistFileReader reader(source.getLocalFilename());
01042 if (!reader.isOK()) return FileOpenFailed;
01043
01044 PlaylistFileReader::Playlist playlist = reader.load();
01045
01046 bool someSuccess = false;
01047
01048 for (PlaylistFileReader::Playlist::const_iterator i = playlist.begin();
01049 i != playlist.end(); ++i) {
01050
01051 FileOpenStatus status = openAudio
01052 (FileSource(*i, FileSource::ProgressDialog), mode);
01053
01054 if (status == FileOpenCancelled) {
01055 return FileOpenCancelled;
01056 }
01057
01058 if (status == FileOpenSucceeded) {
01059 someSuccess = true;
01060 mode = CreateAdditionalModel;
01061 }
01062 }
01063
01064 if (someSuccess) return FileOpenSucceeded;
01065 else return FileOpenFailed;
01066 }
01067
01068 MainWindowBase::FileOpenStatus
01069 MainWindowBase::openLayer(FileSource source)
01070 {
01071 Pane *pane = m_paneStack->getCurrentPane();
01072
01073 if (!pane) {
01074
01075 std::cerr << "WARNING: MainWindowBase::openLayer: no current pane" << std::endl;
01076 return FileOpenWrongMode;
01077 }
01078
01079 if (!getMainModel()) {
01080
01081 std::cerr << "WARNING: MainWindowBase::openLayer: No main model -- hence no default sample rate available" << std::endl;
01082 return FileOpenWrongMode;
01083 }
01084
01085 if (!source.isAvailable()) return FileOpenFailed;
01086 source.waitForData();
01087
01088 QString path = source.getLocalFilename();
01089
01090 if (source.getExtension() == "svl" || source.getExtension() == "xml") {
01091
01092 PaneCallback callback(this);
01093 QFile file(path);
01094
01095 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
01096 std::cerr << "ERROR: MainWindowBase::openLayer("
01097 << source.getLocation().toStdString()
01098 << "): Failed to open file for reading" << std::endl;
01099 return FileOpenFailed;
01100 }
01101
01102 SVFileReader reader(m_document, callback, source.getLocation());
01103 connect
01104 (&reader, SIGNAL(modelRegenerationFailed(QString, QString, QString)),
01105 this, SLOT(modelRegenerationFailed(QString, QString, QString)));
01106 connect
01107 (&reader, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
01108 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
01109 reader.setCurrentPane(pane);
01110
01111 QXmlInputSource inputSource(&file);
01112 reader.parse(inputSource);
01113
01114 if (!reader.isOK()) {
01115 std::cerr << "ERROR: MainWindowBase::openLayer("
01116 << source.getLocation().toStdString()
01117 << "): Failed to read XML file: "
01118 << reader.getErrorString().toStdString() << std::endl;
01119 return FileOpenFailed;
01120 }
01121
01122 m_recentFiles.addFile(source.getLocation());
01123
01124 if (!source.isRemote()) {
01125 registerLastOpenedFilePath(FileFinder::LayerFile, path);
01126 }
01127
01128 return FileOpenSucceeded;
01129
01130 } else {
01131
01132 try {
01133
01134 Model *model = DataFileReaderFactory::load
01135 (path, getMainModel()->getSampleRate());
01136
01137 if (model) {
01138
01139 std::cerr << "MainWindowBase::openLayer: Have model" << std::endl;
01140
01141 Layer *newLayer = m_document->createImportedLayer(model);
01142
01143 if (newLayer) {
01144
01145 m_document->addLayerToView(pane, newLayer);
01146 m_paneStack->setCurrentLayer(pane, newLayer);
01147
01148 m_recentFiles.addFile(source.getLocation());
01149
01150 if (!source.isRemote()) {
01151 registerLastOpenedFilePath
01152 (FileFinder::LayerFile,
01153 path);
01154 }
01155
01156 return FileOpenSucceeded;
01157 }
01158 }
01159 } catch (DataFileReaderFactory::Exception e) {
01160 if (e == DataFileReaderFactory::ImportCancelled) {
01161 return FileOpenCancelled;
01162 }
01163 }
01164 }
01165
01166 return FileOpenFailed;
01167 }
01168
01169 MainWindowBase::FileOpenStatus
01170 MainWindowBase::openImage(FileSource source)
01171 {
01172 Pane *pane = m_paneStack->getCurrentPane();
01173
01174 if (!pane) {
01175
01176 std::cerr << "WARNING: MainWindowBase::openImage: no current pane" << std::endl;
01177 return FileOpenWrongMode;
01178 }
01179
01180 if (!m_document->getMainModel()) {
01181 return FileOpenWrongMode;
01182 }
01183
01184 bool newLayer = false;
01185
01186 ImageLayer *il = dynamic_cast<ImageLayer *>(pane->getSelectedLayer());
01187 if (!il) {
01188 for (int i = pane->getLayerCount()-1; i >= 0; --i) {
01189 il = dynamic_cast<ImageLayer *>(pane->getLayer(i));
01190 if (il) break;
01191 }
01192 }
01193 if (!il) {
01194 il = dynamic_cast<ImageLayer *>
01195 (m_document->createEmptyLayer(LayerFactory::Image));
01196 if (!il) return FileOpenFailed;
01197 newLayer = true;
01198 }
01199
01200
01201
01202 std::cerr << "openImage: trying location \"" << source.getLocation().toStdString() << "\" in image layer" << std::endl;
01203
01204 if (!il->addImage(m_viewManager->getGlobalCentreFrame(), source.getLocation())) {
01205 if (newLayer) {
01206 m_document->deleteLayer(il);
01207 }
01208 return FileOpenFailed;
01209 } else {
01210 if (newLayer) {
01211 m_document->addLayerToView(pane, il);
01212 }
01213 m_paneStack->setCurrentLayer(pane, il);
01214 }
01215
01216 return FileOpenSucceeded;
01217 }
01218
01219 MainWindowBase::FileOpenStatus
01220 MainWindowBase::openSessionFile(QString fileOrUrl)
01221 {
01222 return openSession(FileSource(fileOrUrl, FileSource::ProgressDialog));
01223 }
01224
01225 MainWindowBase::FileOpenStatus
01226 MainWindowBase::openSession(FileSource source)
01227 {
01228 if (!source.isAvailable()) return FileOpenFailed;
01229 if (source.getExtension() != "sv") return FileOpenFailed;
01230 source.waitForData();
01231
01232 BZipFileDevice bzFile(source.getLocalFilename());
01233 if (!bzFile.open(QIODevice::ReadOnly)) return FileOpenFailed;
01234
01235 if (!checkSaveModified()) return FileOpenCancelled;
01236
01237 QString error;
01238 closeSession();
01239 createDocument();
01240
01241 PaneCallback callback(this);
01242 m_viewManager->clearSelections();
01243
01244 SVFileReader reader(m_document, callback, source.getLocation());
01245 connect
01246 (&reader, SIGNAL(modelRegenerationFailed(QString, QString, QString)),
01247 this, SLOT(modelRegenerationFailed(QString, QString, QString)));
01248 connect
01249 (&reader, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
01250 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
01251 QXmlInputSource inputSource(&bzFile);
01252 reader.parse(inputSource);
01253
01254 if (!reader.isOK()) {
01255 error = tr("SV XML file read error:\n%1").arg(reader.getErrorString());
01256 }
01257
01258 bzFile.close();
01259
01260 bool ok = (error == "");
01261
01262 if (ok) {
01263
01264 setWindowTitle(tr("%1: %2")
01265 .arg(QApplication::applicationName())
01266 .arg(source.getLocation()));
01267
01268 if (!source.isRemote()) m_sessionFile = source.getLocalFilename();
01269
01270 setupMenus();
01271
01272 CommandHistory::getInstance()->clear();
01273 CommandHistory::getInstance()->documentSaved();
01274 m_documentModified = false;
01275 updateMenuStates();
01276
01277 m_recentFiles.addFile(source.getLocation());
01278
01279 if (!source.isRemote()) {
01280
01281 registerLastOpenedFilePath(FileFinder::SessionFile,
01282 source.getLocalFilename());
01283 }
01284
01285 } else {
01286 setWindowTitle(QApplication::applicationName());
01287 }
01288
01289 return ok ? FileOpenSucceeded : FileOpenFailed;
01290 }
01291
01292 void
01293 MainWindowBase::createPlayTarget()
01294 {
01295 if (m_playTarget) return;
01296
01297 m_playTarget = AudioTargetFactory::createCallbackTarget(m_playSource);
01298 if (!m_playTarget) {
01299 QMessageBox::warning
01300 (this, tr("Couldn't open audio device"),
01301 tr("<b>No audio available</b><p>Could not open an audio device for playback.<p>Audio playback will not be available during this session."),
01302 QMessageBox::Ok);
01303 }
01304 }
01305
01306 WaveFileModel *
01307 MainWindowBase::getMainModel()
01308 {
01309 if (!m_document) return 0;
01310 return m_document->getMainModel();
01311 }
01312
01313 const WaveFileModel *
01314 MainWindowBase::getMainModel() const
01315 {
01316 if (!m_document) return 0;
01317 return m_document->getMainModel();
01318 }
01319
01320 void
01321 MainWindowBase::createDocument()
01322 {
01323 m_document = new Document;
01324
01325 connect(m_document, SIGNAL(layerAdded(Layer *)),
01326 this, SLOT(layerAdded(Layer *)));
01327 connect(m_document, SIGNAL(layerRemoved(Layer *)),
01328 this, SLOT(layerRemoved(Layer *)));
01329 connect(m_document, SIGNAL(layerAboutToBeDeleted(Layer *)),
01330 this, SLOT(layerAboutToBeDeleted(Layer *)));
01331 connect(m_document, SIGNAL(layerInAView(Layer *, bool)),
01332 this, SLOT(layerInAView(Layer *, bool)));
01333
01334 connect(m_document, SIGNAL(modelAdded(Model *)),
01335 this, SLOT(modelAdded(Model *)));
01336 connect(m_document, SIGNAL(mainModelChanged(WaveFileModel *)),
01337 this, SLOT(mainModelChanged(WaveFileModel *)));
01338 connect(m_document, SIGNAL(modelAboutToBeDeleted(Model *)),
01339 this, SLOT(modelAboutToBeDeleted(Model *)));
01340
01341 connect(m_document, SIGNAL(modelGenerationFailed(QString, QString)),
01342 this, SLOT(modelGenerationFailed(QString, QString)));
01343 connect(m_document, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
01344 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
01345 connect(m_document, SIGNAL(modelGenerationFailed(QString, QString)),
01346 this, SLOT(modelGenerationFailed(QString, QString)));
01347 connect(m_document, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
01348 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
01349 connect(m_document, SIGNAL(alignmentFailed(QString, QString)),
01350 this, SLOT(alignmentFailed(QString, QString)));
01351 }
01352
01353 bool
01354 MainWindowBase::saveSessionFile(QString path)
01355 {
01356 BZipFileDevice bzFile(path);
01357 if (!bzFile.open(QIODevice::WriteOnly)) {
01358 std::cerr << "Failed to open session file \"" << path.toStdString()
01359 << "\" for writing: "
01360 << bzFile.errorString().toStdString() << std::endl;
01361 return false;
01362 }
01363
01364 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
01365
01366 QTextStream out(&bzFile);
01367 toXml(out);
01368 out.flush();
01369
01370 QApplication::restoreOverrideCursor();
01371
01372 if (!bzFile.isOK()) {
01373 QMessageBox::critical(this, tr("Failed to write file"),
01374 tr("<b>Save failed</b><p>Failed to write to file \"%1\": %2")
01375 .arg(path).arg(bzFile.errorString()));
01376 bzFile.close();
01377 return false;
01378 }
01379
01380 bzFile.close();
01381 return true;
01382 }
01383
01384 void
01385 MainWindowBase::toXml(QTextStream &out)
01386 {
01387 QString indent(" ");
01388
01389 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
01390 out << "<!DOCTYPE sonic-visualiser>\n";
01391 out << "<sv>\n";
01392
01393 m_document->toXml(out, "", "");
01394
01395 out << "<display>\n";
01396
01397 out << QString(" <window width=\"%1\" height=\"%2\"/>\n")
01398 .arg(width()).arg(height());
01399
01400 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
01401
01402 Pane *pane = m_paneStack->getPane(i);
01403
01404 if (pane) {
01405 pane->toXml(out, indent);
01406 }
01407 }
01408
01409 out << "</display>\n";
01410
01411 m_viewManager->getSelection().toXml(out);
01412
01413 out << "</sv>\n";
01414 }
01415
01416 Pane *
01417 MainWindowBase::addPaneToStack()
01418 {
01419 AddPaneCommand *command = new AddPaneCommand(this);
01420 CommandHistory::getInstance()->addCommand(command);
01421 Pane *pane = command->getPane();
01422 return pane;
01423 }
01424
01425 void
01426 MainWindowBase::zoomIn()
01427 {
01428 Pane *currentPane = m_paneStack->getCurrentPane();
01429 if (currentPane) currentPane->zoom(true);
01430 }
01431
01432 void
01433 MainWindowBase::zoomOut()
01434 {
01435 Pane *currentPane = m_paneStack->getCurrentPane();
01436 if (currentPane) currentPane->zoom(false);
01437 }
01438
01439 void
01440 MainWindowBase::zoomToFit()
01441 {
01442 Pane *currentPane = m_paneStack->getCurrentPane();
01443 if (!currentPane) return;
01444
01445 Model *model = getMainModel();
01446 if (!model) return;
01447
01448 size_t start = model->getStartFrame();
01449 size_t end = model->getEndFrame();
01450 if (m_playSource) end = std::max(end, m_playSource->getPlayEndFrame());
01451 size_t pixels = currentPane->width();
01452
01453 size_t sw = currentPane->getVerticalScaleWidth();
01454 if (pixels > sw * 2) pixels -= sw * 2;
01455 else pixels = 1;
01456 if (pixels > 4) pixels -= 4;
01457
01458 size_t zoomLevel = (end - start) / pixels;
01459
01460 currentPane->setZoomLevel(zoomLevel);
01461 currentPane->setCentreFrame((start + end) / 2);
01462 }
01463
01464 void
01465 MainWindowBase::zoomDefault()
01466 {
01467 Pane *currentPane = m_paneStack->getCurrentPane();
01468 if (currentPane) currentPane->setZoomLevel(1024);
01469 }
01470
01471 void
01472 MainWindowBase::scrollLeft()
01473 {
01474 Pane *currentPane = m_paneStack->getCurrentPane();
01475 if (currentPane) currentPane->scroll(false, false);
01476 }
01477
01478 void
01479 MainWindowBase::jumpLeft()
01480 {
01481 Pane *currentPane = m_paneStack->getCurrentPane();
01482 if (currentPane) currentPane->scroll(false, true);
01483 }
01484
01485 void
01486 MainWindowBase::scrollRight()
01487 {
01488 Pane *currentPane = m_paneStack->getCurrentPane();
01489 if (currentPane) currentPane->scroll(true, false);
01490 }
01491
01492 void
01493 MainWindowBase::jumpRight()
01494 {
01495 Pane *currentPane = m_paneStack->getCurrentPane();
01496 if (currentPane) currentPane->scroll(true, true);
01497 }
01498
01499 void
01500 MainWindowBase::showNoOverlays()
01501 {
01502 m_viewManager->setOverlayMode(ViewManager::NoOverlays);
01503 }
01504
01505 void
01506 MainWindowBase::showMinimalOverlays()
01507 {
01508 m_viewManager->setOverlayMode(ViewManager::MinimalOverlays);
01509 }
01510
01511 void
01512 MainWindowBase::showStandardOverlays()
01513 {
01514 m_viewManager->setOverlayMode(ViewManager::StandardOverlays);
01515 }
01516
01517 void
01518 MainWindowBase::showAllOverlays()
01519 {
01520 m_viewManager->setOverlayMode(ViewManager::AllOverlays);
01521 }
01522
01523 void
01524 MainWindowBase::toggleZoomWheels()
01525 {
01526 if (m_viewManager->getZoomWheelsEnabled()) {
01527 m_viewManager->setZoomWheelsEnabled(false);
01528 } else {
01529 m_viewManager->setZoomWheelsEnabled(true);
01530 }
01531 }
01532
01533 void
01534 MainWindowBase::togglePropertyBoxes()
01535 {
01536 if (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks) {
01537 if (Preferences::getInstance()->getPropertyBoxLayout() ==
01538 Preferences::VerticallyStacked) {
01539 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout);
01540 } else {
01541 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout);
01542 }
01543 } else {
01544 m_paneStack->setLayoutStyle(PaneStack::NoPropertyStacks);
01545 }
01546 }
01547
01548 void
01549 MainWindowBase::toggleStatusBar()
01550 {
01551 QSettings settings;
01552 settings.beginGroup("MainWindow");
01553 bool sb = settings.value("showstatusbar", true).toBool();
01554
01555 if (sb) {
01556 statusBar()->hide();
01557 } else {
01558 statusBar()->show();
01559 }
01560
01561 settings.setValue("showstatusbar", !sb);
01562
01563 settings.endGroup();
01564 }
01565
01566 void
01567 MainWindowBase::preferenceChanged(PropertyContainer::PropertyName name)
01568 {
01569 if (name == "Property Box Layout") {
01570 if (m_paneStack->getLayoutStyle() != PaneStack::NoPropertyStacks) {
01571 if (Preferences::getInstance()->getPropertyBoxLayout() ==
01572 Preferences::VerticallyStacked) {
01573 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout);
01574 } else {
01575 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout);
01576 }
01577 }
01578 } else if (name == "Background Mode" && m_viewManager) {
01579 Preferences::BackgroundMode mode =
01580 Preferences::getInstance()->getBackgroundMode();
01581 if (mode == Preferences::BackgroundFromTheme) {
01582 m_viewManager->setGlobalDarkBackground(m_initialDarkBackground);
01583 } else if (mode == Preferences::DarkBackground) {
01584 m_viewManager->setGlobalDarkBackground(true);
01585 } else {
01586 m_viewManager->setGlobalDarkBackground(false);
01587 }
01588 }
01589 }
01590
01591 void
01592 MainWindowBase::play()
01593 {
01594 if (m_playSource->isPlaying()) {
01595 stop();
01596 } else {
01597 playbackFrameChanged(m_viewManager->getPlaybackFrame());
01598 m_playSource->play(m_viewManager->getPlaybackFrame());
01599 }
01600 }
01601
01602 void
01603 MainWindowBase::ffwd()
01604 {
01605 if (!getMainModel()) return;
01606
01607 int frame = m_viewManager->getPlaybackFrame();
01608 ++frame;
01609
01610 Pane *pane = m_paneStack->getCurrentPane();
01611 Layer *layer = getSnapLayer();
01612 size_t sr = getMainModel()->getSampleRate();
01613
01614 if (!layer) {
01615
01616 frame = RealTime::realTime2Frame
01617 (RealTime::frame2RealTime(frame, sr) + RealTime(2, 0), sr);
01618 if (frame > int(getMainModel()->getEndFrame())) {
01619 frame = getMainModel()->getEndFrame();
01620 }
01621
01622 } else {
01623
01624 size_t resolution = 0;
01625 if (layer->snapToFeatureFrame(m_paneStack->getCurrentPane(),
01626 frame, resolution, Layer::SnapRight)) {
01627 if (pane) frame = pane->alignToReference(frame);
01628 } else {
01629 frame = getMainModel()->getEndFrame();
01630 }
01631 }
01632
01633 if (frame < 0) frame = 0;
01634
01635 if (m_viewManager->getPlaySelectionMode()) {
01636 frame = m_viewManager->constrainFrameToSelection(size_t(frame));
01637 }
01638
01639 m_viewManager->setPlaybackFrame(frame);
01640 }
01641
01642 void
01643 MainWindowBase::ffwdEnd()
01644 {
01645 if (!getMainModel()) return;
01646
01647 size_t frame = getMainModel()->getEndFrame();
01648
01649 if (m_viewManager->getPlaySelectionMode()) {
01650 frame = m_viewManager->constrainFrameToSelection(frame);
01651 }
01652
01653 m_viewManager->setPlaybackFrame(frame);
01654 }
01655
01656 void
01657 MainWindowBase::rewind()
01658 {
01659 if (!getMainModel()) return;
01660
01661 int frame = m_viewManager->getPlaybackFrame();
01662 if (frame > 0) --frame;
01663
01664 Pane *pane = m_paneStack->getCurrentPane();
01665 Layer *layer = getSnapLayer();
01666 size_t sr = getMainModel()->getSampleRate();
01667
01668
01669
01670
01671 if (m_playSource && m_playSource->isPlaying()) {
01672 RealTime ct = RealTime::frame2RealTime(frame, sr);
01673 ct = ct - RealTime::fromSeconds(0.25);
01674 if (ct < RealTime::zeroTime) ct = RealTime::zeroTime;
01675
01676 frame = RealTime::realTime2Frame(ct, sr);
01677
01678 }
01679
01680 if (!layer) {
01681
01682 frame = RealTime::realTime2Frame
01683 (RealTime::frame2RealTime(frame, sr) - RealTime(2, 0), sr);
01684 if (frame < int(getMainModel()->getStartFrame())) {
01685 frame = getMainModel()->getStartFrame();
01686 }
01687
01688 } else {
01689
01690 size_t resolution = 0;
01691 if (layer->snapToFeatureFrame(m_paneStack->getCurrentPane(),
01692 frame, resolution, Layer::SnapLeft)) {
01693
01694 if (pane) frame = pane->alignToReference(frame);
01695 } else {
01696 frame = getMainModel()->getStartFrame();
01697 }
01698 }
01699
01700 if (frame < 0) frame = 0;
01701
01702 if (m_viewManager->getPlaySelectionMode()) {
01703 frame = m_viewManager->constrainFrameToSelection(size_t(frame));
01704 }
01705
01706 m_viewManager->setPlaybackFrame(frame);
01707 }
01708
01709 void
01710 MainWindowBase::rewindStart()
01711 {
01712 if (!getMainModel()) return;
01713
01714 size_t frame = getMainModel()->getStartFrame();
01715
01716 if (m_viewManager->getPlaySelectionMode()) {
01717 frame = m_viewManager->constrainFrameToSelection(frame);
01718 }
01719
01720 m_viewManager->setPlaybackFrame(frame);
01721 }
01722
01723 Layer *
01724 MainWindowBase::getSnapLayer() const
01725 {
01726 Pane *pane = m_paneStack->getCurrentPane();
01727 if (!pane) return 0;
01728
01729 Layer *layer = pane->getSelectedLayer();
01730
01731 if (!dynamic_cast<TimeInstantLayer *>(layer) &&
01732 !dynamic_cast<TimeValueLayer *>(layer) &&
01733 !dynamic_cast<TimeRulerLayer *>(layer)) {
01734
01735 layer = 0;
01736
01737 for (int i = pane->getLayerCount(); i > 0; --i) {
01738 Layer *l = pane->getLayer(i-1);
01739 if (dynamic_cast<TimeRulerLayer *>(l)) {
01740 layer = l;
01741 break;
01742 }
01743 }
01744 }
01745
01746 return layer;
01747 }
01748
01749 void
01750 MainWindowBase::stop()
01751 {
01752 m_playSource->stop();
01753
01754 if (m_paneStack && m_paneStack->getCurrentPane()) {
01755 updateVisibleRangeDisplay(m_paneStack->getCurrentPane());
01756 } else {
01757 m_myStatusMessage = "";
01758 statusBar()->showMessage("");
01759 }
01760 }
01761
01762 MainWindowBase::AddPaneCommand::AddPaneCommand(MainWindowBase *mw) :
01763 m_mw(mw),
01764 m_pane(0),
01765 m_prevCurrentPane(0),
01766 m_added(false)
01767 {
01768 }
01769
01770 MainWindowBase::AddPaneCommand::~AddPaneCommand()
01771 {
01772 if (m_pane && !m_added) {
01773 m_mw->m_paneStack->deletePane(m_pane);
01774 }
01775 }
01776
01777 QString
01778 MainWindowBase::AddPaneCommand::getName() const
01779 {
01780 return tr("Add Pane");
01781 }
01782
01783 void
01784 MainWindowBase::AddPaneCommand::execute()
01785 {
01786 if (!m_pane) {
01787 m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane();
01788 m_pane = m_mw->m_paneStack->addPane();
01789
01790 connect(m_pane, SIGNAL(contextHelpChanged(const QString &)),
01791 m_mw, SLOT(contextHelpChanged(const QString &)));
01792 } else {
01793 m_mw->m_paneStack->showPane(m_pane);
01794 }
01795
01796 m_mw->m_paneStack->setCurrentPane(m_pane);
01797 m_added = true;
01798 }
01799
01800 void
01801 MainWindowBase::AddPaneCommand::unexecute()
01802 {
01803 m_mw->m_paneStack->hidePane(m_pane);
01804 m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane);
01805 m_added = false;
01806 }
01807
01808 MainWindowBase::RemovePaneCommand::RemovePaneCommand(MainWindowBase *mw, Pane *pane) :
01809 m_mw(mw),
01810 m_pane(pane),
01811 m_added(true)
01812 {
01813 }
01814
01815 MainWindowBase::RemovePaneCommand::~RemovePaneCommand()
01816 {
01817 if (m_pane && !m_added) {
01818 m_mw->m_paneStack->deletePane(m_pane);
01819 }
01820 }
01821
01822 QString
01823 MainWindowBase::RemovePaneCommand::getName() const
01824 {
01825 return tr("Remove Pane");
01826 }
01827
01828 void
01829 MainWindowBase::RemovePaneCommand::execute()
01830 {
01831 m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane();
01832 m_mw->m_paneStack->hidePane(m_pane);
01833 m_added = false;
01834 }
01835
01836 void
01837 MainWindowBase::RemovePaneCommand::unexecute()
01838 {
01839 m_mw->m_paneStack->showPane(m_pane);
01840 m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane);
01841 m_added = true;
01842 }
01843
01844 void
01845 MainWindowBase::deleteCurrentPane()
01846 {
01847 CommandHistory::getInstance()->startCompoundOperation
01848 (tr("Delete Pane"), true);
01849
01850 Pane *pane = m_paneStack->getCurrentPane();
01851 if (pane) {
01852 while (pane->getLayerCount() > 0) {
01853 Layer *layer = pane->getLayer(0);
01854 if (layer) {
01855 m_document->removeLayerFromView(pane, layer);
01856 } else {
01857 break;
01858 }
01859 }
01860
01861 RemovePaneCommand *command = new RemovePaneCommand(this, pane);
01862 CommandHistory::getInstance()->addCommand(command);
01863 }
01864
01865 CommandHistory::getInstance()->endCompoundOperation();
01866
01867 updateMenuStates();
01868 }
01869
01870 void
01871 MainWindowBase::deleteCurrentLayer()
01872 {
01873 Pane *pane = m_paneStack->getCurrentPane();
01874 if (pane) {
01875 Layer *layer = pane->getSelectedLayer();
01876 if (layer) {
01877 m_document->removeLayerFromView(pane, layer);
01878 }
01879 }
01880 updateMenuStates();
01881 }
01882
01883 void
01884 MainWindowBase::previousPane()
01885 {
01886 if (!m_paneStack) return;
01887
01888 Pane *currentPane = m_paneStack->getCurrentPane();
01889 if (!currentPane) return;
01890
01891 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
01892 if (m_paneStack->getPane(i) == currentPane) {
01893 if (i == 0) return;
01894 m_paneStack->setCurrentPane(m_paneStack->getPane(i-1));
01895 updateMenuStates();
01896 return;
01897 }
01898 }
01899 }
01900
01901 void
01902 MainWindowBase::nextPane()
01903 {
01904 if (!m_paneStack) return;
01905
01906 Pane *currentPane = m_paneStack->getCurrentPane();
01907 if (!currentPane) return;
01908
01909 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
01910 if (m_paneStack->getPane(i) == currentPane) {
01911 if (i == m_paneStack->getPaneCount()-1) return;
01912 m_paneStack->setCurrentPane(m_paneStack->getPane(i+1));
01913 updateMenuStates();
01914 return;
01915 }
01916 }
01917 }
01918
01919 void
01920 MainWindowBase::previousLayer()
01921 {
01923
01924 if (!m_paneStack) return;
01925
01926 Pane *currentPane = m_paneStack->getCurrentPane();
01927 if (!currentPane) return;
01928
01929 Layer *currentLayer = currentPane->getSelectedLayer();
01930 if (!currentLayer) return;
01931
01932 for (int i = 0; i < currentPane->getLayerCount(); ++i) {
01933 if (currentPane->getLayer(i) == currentLayer) {
01934 if (i == 0) return;
01935 m_paneStack->setCurrentLayer(currentPane,
01936 currentPane->getLayer(i-1));
01937 updateMenuStates();
01938 return;
01939 }
01940 }
01941 }
01942
01943 void
01944 MainWindowBase::nextLayer()
01945 {
01947
01948 if (!m_paneStack) return;
01949
01950 Pane *currentPane = m_paneStack->getCurrentPane();
01951 if (!currentPane) return;
01952
01953 Layer *currentLayer = currentPane->getSelectedLayer();
01954 if (!currentLayer) return;
01955
01956 for (int i = 0; i < currentPane->getLayerCount(); ++i) {
01957 if (currentPane->getLayer(i) == currentLayer) {
01958 if (i == currentPane->getLayerCount()-1) return;
01959 m_paneStack->setCurrentLayer(currentPane,
01960 currentPane->getLayer(i+1));
01961 updateMenuStates();
01962 return;
01963 }
01964 }
01965 }
01966
01967 void
01968 MainWindowBase::playbackFrameChanged(unsigned long frame)
01969 {
01970 if (!(m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
01971
01972 RealTime now = RealTime::frame2RealTime
01973 (frame, getMainModel()->getSampleRate());
01974
01975 if (now.sec == m_lastPlayStatusSec) return;
01976
01977 RealTime then = RealTime::frame2RealTime
01978 (m_playSource->getPlayEndFrame(), getMainModel()->getSampleRate());
01979
01980 QString nowStr;
01981 QString thenStr;
01982 QString remainingStr;
01983
01984 if (then.sec > 10) {
01985 nowStr = now.toSecText().c_str();
01986 thenStr = then.toSecText().c_str();
01987 remainingStr = (then - now).toSecText().c_str();
01988 m_lastPlayStatusSec = now.sec;
01989 } else {
01990 nowStr = now.toText(true).c_str();
01991 thenStr = then.toText(true).c_str();
01992 remainingStr = (then - now).toText(true).c_str();
01993 }
01994
01995 m_myStatusMessage = tr("Playing: %1 of %2 (%3 remaining)")
01996 .arg(nowStr).arg(thenStr).arg(remainingStr);
01997
01998 statusBar()->showMessage(m_myStatusMessage);
01999 }
02000
02001 void
02002 MainWindowBase::globalCentreFrameChanged(unsigned long )
02003 {
02004 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
02005 Pane *p = 0;
02006 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return;
02007 if (!p->getFollowGlobalPan()) return;
02008 updateVisibleRangeDisplay(p);
02009 }
02010
02011 void
02012 MainWindowBase::viewCentreFrameChanged(View *v, unsigned long )
02013 {
02014 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
02015 Pane *p = 0;
02016 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return;
02017 if (v == p) updateVisibleRangeDisplay(p);
02018 }
02019
02020 void
02021 MainWindowBase::viewZoomLevelChanged(View *v, unsigned long , bool )
02022 {
02023 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
02024 Pane *p = 0;
02025 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return;
02026 if (v == p) updateVisibleRangeDisplay(p);
02027 }
02028
02029 void
02030 MainWindowBase::layerAdded(Layer *)
02031 {
02032
02033 updateMenuStates();
02034 }
02035
02036 void
02037 MainWindowBase::layerRemoved(Layer *)
02038 {
02039
02040 updateMenuStates();
02041 }
02042
02043 void
02044 MainWindowBase::layerAboutToBeDeleted(Layer *layer)
02045 {
02046
02047 if (m_timeRulerLayer && (layer == m_timeRulerLayer)) {
02048
02049 m_timeRulerLayer = 0;
02050 }
02051 }
02052
02053 void
02054 MainWindowBase::layerInAView(Layer *layer, bool inAView)
02055 {
02056
02057
02058
02059 Model *model = layer->getModel();
02060 if (model) {
02061 if (inAView) {
02062 m_playSource->addModel(model);
02063 } else {
02064 bool found = false;
02065 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
02066 Pane *pane = m_paneStack->getPane(i);
02067 if (!pane) continue;
02068 for (int j = 0; j < pane->getLayerCount(); ++j) {
02069 Layer *pl = pane->getLayer(j);
02070 if (pl && pl->getModel() == model) {
02071 found = true;
02072 break;
02073 }
02074 }
02075 if (found) break;
02076 }
02077 if (!found) m_playSource->removeModel(model);
02078 }
02079 }
02080
02081 updateMenuStates();
02082 }
02083
02084 void
02085 MainWindowBase::modelAdded(Model *model)
02086 {
02087
02088 m_playSource->addModel(model);
02089 }
02090
02091 void
02092 MainWindowBase::mainModelChanged(WaveFileModel *model)
02093 {
02094
02095 updateDescriptionLabel();
02096 if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate());
02097 if (model && !m_playTarget && m_audioOutput) createPlayTarget();
02098 }
02099
02100 void
02101 MainWindowBase::modelAboutToBeDeleted(Model *model)
02102 {
02103
02104 if (model == m_viewManager->getPlaybackModel()) {
02105 m_viewManager->setPlaybackModel(0);
02106 }
02107 m_playSource->removeModel(model);
02108 FFTDataServer::modelAboutToBeDeleted(model);
02109 }
02110
02111 void
02112 MainWindowBase::paneDeleteButtonClicked(Pane *pane)
02113 {
02114 bool found = false;
02115 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
02116 if (m_paneStack->getPane(i) == pane) {
02117 found = true;
02118 break;
02119 }
02120 }
02121 if (!found) {
02122 std::cerr << "MainWindowBase::paneDeleteButtonClicked: Unknown pane "
02123 << pane << std::endl;
02124 return;
02125 }
02126
02127 CommandHistory::getInstance()->startCompoundOperation
02128 (tr("Delete Pane"), true);
02129
02130 while (pane->getLayerCount() > 0) {
02131 Layer *layer = pane->getLayer(0);
02132 if (layer) {
02133 m_document->removeLayerFromView(pane, layer);
02134 } else {
02135 break;
02136 }
02137 }
02138
02139 RemovePaneCommand *command = new RemovePaneCommand(this, pane);
02140 CommandHistory::getInstance()->addCommand(command);
02141
02142 CommandHistory::getInstance()->endCompoundOperation();
02143
02144 updateMenuStates();
02145 }
02146
02147 void
02148 MainWindowBase::pollOSC()
02149 {
02150 if (!m_oscQueue || m_oscQueue->isEmpty()) return;
02151 std::cerr << "MainWindowBase::pollOSC: have " << m_oscQueue->getMessagesAvailable() << " messages" << std::endl;
02152
02153 if (m_openingAudioFile) return;
02154
02155 OSCMessage message = m_oscQueue->readMessage();
02156
02157 if (message.getTarget() != 0) {
02158 return;
02159 }
02160
02161 handleOSCMessage(message);
02162 }
02163
02164 void
02165 MainWindowBase::inProgressSelectionChanged()
02166 {
02167 Pane *currentPane = 0;
02168 if (m_paneStack) currentPane = m_paneStack->getCurrentPane();
02169 if (currentPane) updateVisibleRangeDisplay(currentPane);
02170 }
02171
02172 void
02173 MainWindowBase::contextHelpChanged(const QString &s)
02174 {
02175 if (s == "" && m_myStatusMessage != "") {
02176 statusBar()->showMessage(m_myStatusMessage);
02177 return;
02178 }
02179 statusBar()->showMessage(s);
02180 }
02181
02182 void
02183 MainWindowBase::openHelpUrl(QString url)
02184 {
02185
02186
02187 QProcess *process = new QProcess(this);
02188 connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater()));
02189
02190 QStringList args;
02191
02192 #ifdef Q_OS_MAC
02193 args.append(url);
02194 process->start("open", args);
02195 #else
02196 #ifdef Q_OS_WIN32
02197
02198 QString pf(getenv("ProgramFiles"));
02199 QString command = pf + QString("\\Internet Explorer\\IEXPLORE.EXE");
02200
02201 args.append(url);
02202 process->start(command, args);
02203
02204 #else
02205 #ifdef Q_WS_X11
02206 if (!qgetenv("KDE_FULL_SESSION").isEmpty()) {
02207 args.append("exec");
02208 args.append(url);
02209 process->start("kfmclient", args);
02210 } else if (!qgetenv("BROWSER").isEmpty()) {
02211 args.append(url);
02212 process->start(qgetenv("BROWSER"), args);
02213 } else {
02214 args.append(url);
02215 process->start("firefox", args);
02216 }
02217 #endif
02218 #endif
02219 #endif
02220 }
02221