comparison main/MainWindow.cpp @ 180:98ba77e0d897

* Merge from sv-match-alignment branch (excluding alignment-specific document). - add aggregate wave model (not yet complete enough to be added as a true model in a layer, but there's potential) - add play solo mode - add alignment model -- unused in plain SV - fix two plugin leaks - add m3u playlist support (opens all files at once, potentially hazardous) - fix retrieval of pre-encoded URLs - add ability to resample audio files on import, so as to match rates with other files previously loaded; add preference for same - add preliminary support in transform code for range and rate of transform input - reorganise preferences dialog, move dark-background option to preferences, add option for temporary directory location
author Chris Cannam
date Fri, 28 Sep 2007 13:56:38 +0000
parents 5bde373ad5ca
children ebd906049fb6
comparison
equal deleted inserted replaced
179:dab257bd9d2d 180:98ba77e0d897
45 #include "widgets/KeyReference.h" 45 #include "widgets/KeyReference.h"
46 #include "audioio/AudioCallbackPlaySource.h" 46 #include "audioio/AudioCallbackPlaySource.h"
47 #include "audioio/AudioCallbackPlayTarget.h" 47 #include "audioio/AudioCallbackPlayTarget.h"
48 #include "audioio/AudioTargetFactory.h" 48 #include "audioio/AudioTargetFactory.h"
49 #include "audioio/PlaySpeedRangeMapper.h" 49 #include "audioio/PlaySpeedRangeMapper.h"
50 #include "data/fileio/AudioFileReaderFactory.h"
51 #include "data/fileio/DataFileReaderFactory.h" 50 #include "data/fileio/DataFileReaderFactory.h"
51 #include "data/fileio/PlaylistFileReader.h"
52 #include "data/fileio/WavFileWriter.h" 52 #include "data/fileio/WavFileWriter.h"
53 #include "data/fileio/CSVFileWriter.h" 53 #include "data/fileio/CSVFileWriter.h"
54 #include "data/fileio/BZipFileDevice.h" 54 #include "data/fileio/BZipFileDevice.h"
55 #include "data/fileio/RemoteFile.h" 55 #include "data/fileio/RemoteFile.h"
56 #include "data/fft/FFTDataServer.h" 56 #include "data/fft/FFTDataServer.h"
62 #include "base/Profiler.h" 62 #include "base/Profiler.h"
63 #include "base/Clipboard.h" 63 #include "base/Clipboard.h"
64 #include "base/UnitDatabase.h" 64 #include "base/UnitDatabase.h"
65 #include "base/ColourDatabase.h" 65 #include "base/ColourDatabase.h"
66 #include "osc/OSCQueue.h" 66 #include "osc/OSCQueue.h"
67
68 //!!!
69 #include "data/model/AggregateWaveModel.h"
67 70
68 // For version information 71 // For version information
69 #include "vamp/vamp.h" 72 #include "vamp/vamp.h"
70 #include "vamp-sdk/PluginBase.h" 73 #include "vamp-sdk/PluginBase.h"
71 #include "plugin/api/ladspa.h" 74 #include "plugin/api/ladspa.h"
174 m_viewManager = new ViewManager(); 177 m_viewManager = new ViewManager();
175 connect(m_viewManager, SIGNAL(selectionChanged()), 178 connect(m_viewManager, SIGNAL(selectionChanged()),
176 this, SLOT(updateMenuStates())); 179 this, SLOT(updateMenuStates()));
177 connect(m_viewManager, SIGNAL(inProgressSelectionChanged()), 180 connect(m_viewManager, SIGNAL(inProgressSelectionChanged()),
178 this, SLOT(inProgressSelectionChanged())); 181 this, SLOT(inProgressSelectionChanged()));
182
183 Preferences::BackgroundMode mode =
184 Preferences::getInstance()->getBackgroundMode();
185 m_initialDarkBackground = m_viewManager->getGlobalDarkBackground();
186 if (mode != Preferences::BackgroundFromTheme) {
187 m_viewManager->setGlobalDarkBackground
188 (mode == Preferences::DarkBackground);
189 }
179 190
180 m_descriptionLabel = new QLabel; 191 m_descriptionLabel = new QLabel;
181 192
182 QScrollArea *scroll = new QScrollArea(frame); 193 QScrollArea *scroll = new QScrollArea(frame);
183 scroll->setWidgetResizable(true); 194 scroll->setWidgetResizable(true);
846 action->setChecked(false); 857 action->setChecked(false);
847 overlayGroup->addAction(action); 858 overlayGroup->addAction(action);
848 m_keyReference->registerShortcut(action); 859 m_keyReference->registerShortcut(action);
849 menu->addAction(action); 860 menu->addAction(action);
850 861
851 menu->addSeparator();
852
853 action = new QAction(tr("Use Dar&k Background"), this);
854 action->setStatusTip(tr("Switch between light and dark background colour schemes"));
855 connect(action, SIGNAL(triggered()), this, SLOT(toggleDarkBackground()));
856 action->setCheckable(true);
857 action->setChecked(m_viewManager->getGlobalDarkBackground());
858 menu->addAction(action);
859
860 menu->addSeparator(); 862 menu->addSeparator();
861 863
862 action = new QAction(tr("Show &Zoom Wheels"), this); 864 action = new QAction(tr("Show &Zoom Wheels"), this);
863 action->setShortcut(tr("Z")); 865 action->setShortcut(tr("Z"));
864 action->setStatusTip(tr("Show thumbwheels for zooming horizontally and vertically")); 866 action->setStatusTip(tr("Show thumbwheels for zooming horizontally and vertically"));
1682 connect(m_viewManager, SIGNAL(playLoopModeChanged(bool)), 1684 connect(m_viewManager, SIGNAL(playLoopModeChanged(bool)),
1683 plAction, SLOT(setChecked(bool))); 1685 plAction, SLOT(setChecked(bool)));
1684 connect(plAction, SIGNAL(triggered()), this, SLOT(playLoopToggled())); 1686 connect(plAction, SIGNAL(triggered()), this, SLOT(playLoopToggled()));
1685 connect(this, SIGNAL(canPlay(bool)), plAction, SLOT(setEnabled(bool))); 1687 connect(this, SIGNAL(canPlay(bool)), plAction, SLOT(setEnabled(bool)));
1686 1688
1689 QAction *soAction = toolbar->addAction(il.load("solo"),
1690 tr("Solo Current Pane"));
1691 soAction->setCheckable(true);
1692 soAction->setChecked(m_viewManager->getPlaySoloMode());
1693 soAction->setShortcut(tr("o"));
1694 soAction->setStatusTip(tr("Solo the current pane during playback"));
1695 connect(m_viewManager, SIGNAL(playSoloModeChanged(bool)),
1696 soAction, SLOT(setChecked(bool)));
1697 connect(soAction, SIGNAL(triggered()), this, SLOT(playSoloToggled()));
1698 connect(this, SIGNAL(canPlay(bool)), soAction, SLOT(setEnabled(bool)));
1699
1687 m_keyReference->registerShortcut(playAction); 1700 m_keyReference->registerShortcut(playAction);
1688 m_keyReference->registerShortcut(psAction); 1701 m_keyReference->registerShortcut(psAction);
1689 m_keyReference->registerShortcut(plAction); 1702 m_keyReference->registerShortcut(plAction);
1703 m_keyReference->registerShortcut(soAction);
1690 m_keyReference->registerShortcut(m_rwdAction); 1704 m_keyReference->registerShortcut(m_rwdAction);
1691 m_keyReference->registerShortcut(m_ffwdAction); 1705 m_keyReference->registerShortcut(m_ffwdAction);
1692 m_keyReference->registerShortcut(rwdStartAction); 1706 m_keyReference->registerShortcut(rwdStartAction);
1693 m_keyReference->registerShortcut(ffwdEndAction); 1707 m_keyReference->registerShortcut(ffwdEndAction);
1694 1708
1695 menu->addAction(playAction); 1709 menu->addAction(playAction);
1696 menu->addAction(psAction); 1710 menu->addAction(psAction);
1697 menu->addAction(plAction); 1711 menu->addAction(plAction);
1712 menu->addAction(soAction);
1698 menu->addSeparator(); 1713 menu->addSeparator();
1699 menu->addAction(m_rwdAction); 1714 menu->addAction(m_rwdAction);
1700 menu->addAction(m_ffwdAction); 1715 menu->addAction(m_ffwdAction);
1701 menu->addSeparator(); 1716 menu->addSeparator();
1702 menu->addAction(rwdStartAction); 1717 menu->addAction(rwdStartAction);
1704 menu->addSeparator(); 1719 menu->addSeparator();
1705 1720
1706 m_rightButtonPlaybackMenu->addAction(playAction); 1721 m_rightButtonPlaybackMenu->addAction(playAction);
1707 m_rightButtonPlaybackMenu->addAction(psAction); 1722 m_rightButtonPlaybackMenu->addAction(psAction);
1708 m_rightButtonPlaybackMenu->addAction(plAction); 1723 m_rightButtonPlaybackMenu->addAction(plAction);
1724 m_rightButtonPlaybackMenu->addAction(soAction);
1709 m_rightButtonPlaybackMenu->addSeparator(); 1725 m_rightButtonPlaybackMenu->addSeparator();
1710 m_rightButtonPlaybackMenu->addAction(m_rwdAction); 1726 m_rightButtonPlaybackMenu->addAction(m_rwdAction);
1711 m_rightButtonPlaybackMenu->addAction(m_ffwdAction); 1727 m_rightButtonPlaybackMenu->addAction(m_ffwdAction);
1712 m_rightButtonPlaybackMenu->addSeparator(); 1728 m_rightButtonPlaybackMenu->addSeparator();
1713 m_rightButtonPlaybackMenu->addAction(rwdStartAction); 1729 m_rightButtonPlaybackMenu->addAction(rwdStartAction);
1994 m_viewManager->setPlaySelectionMode(!m_viewManager->getPlaySelectionMode()); 2010 m_viewManager->setPlaySelectionMode(!m_viewManager->getPlaySelectionMode());
1995 } 2011 }
1996 } 2012 }
1997 2013
1998 void 2014 void
2015 MainWindow::playSoloToggled()
2016 {
2017 QAction *action = dynamic_cast<QAction *>(sender());
2018
2019 if (action) {
2020 m_viewManager->setPlaySoloMode(action->isChecked());
2021 } else {
2022 m_viewManager->setPlaySoloMode(!m_viewManager->getPlaySoloMode());
2023 }
2024
2025 if (!m_viewManager->getPlaySoloMode()) {
2026 m_viewManager->setPlaybackModel(0);
2027 if (m_playSource) {
2028 m_playSource->clearSoloModelSet();
2029 }
2030 }
2031 }
2032
2033 void
1999 MainWindow::currentPaneChanged(Pane *p) 2034 MainWindow::currentPaneChanged(Pane *p)
2000 { 2035 {
2001 updateMenuStates(); 2036 updateMenuStates();
2002 updateVisibleRangeDisplay(p); 2037 updateVisibleRangeDisplay(p);
2038
2039 if (!p) return;
2040
2041 if (!(m_viewManager &&
2042 m_playSource &&
2043 m_viewManager->getPlaySoloMode())) {
2044 if (m_viewManager) m_viewManager->setPlaybackModel(0);
2045 return;
2046 }
2047
2048 Model *prevPlaybackModel = m_viewManager->getPlaybackModel();
2049
2050 std::set<Model *> soloModels;
2051
2052 for (int i = 0; i < p->getLayerCount(); ++i) {
2053 Layer *layer = p->getLayer(i);
2054 if (dynamic_cast<TimeRulerLayer *>(layer)) {
2055 continue;
2056 }
2057 if (layer && layer->getModel()) {
2058 Model *model = layer->getModel();
2059 if (dynamic_cast<RangeSummarisableTimeValueModel *>(model)) {
2060 m_viewManager->setPlaybackModel(model);
2061 }
2062 soloModels.insert(model);
2063 }
2064 }
2065
2066 RangeSummarisableTimeValueModel *a =
2067 dynamic_cast<RangeSummarisableTimeValueModel *>(prevPlaybackModel);
2068 RangeSummarisableTimeValueModel *b =
2069 dynamic_cast<RangeSummarisableTimeValueModel *>(m_viewManager->
2070 getPlaybackModel());
2071
2072 m_playSource->setSoloModelSet(soloModels);
2073
2074 if (a && b && (a != b)) {
2075 int frame = m_playSource->getCurrentPlayingFrame();
2076 //!!! I don't really believe that these functions are the right way around
2077 int rframe = a->alignFromReference(frame);
2078 int bframe = b->alignToReference(rframe);
2079 if (m_playSource->isPlaying()) m_playSource->play(bframe);
2080 }
2003 } 2081 }
2004 2082
2005 void 2083 void
2006 MainWindow::currentLayerChanged(Pane *p, Layer *) 2084 MainWindow::currentLayerChanged(Pane *p, Layer *)
2007 { 2085 {
2678 return FileOpenFailed; 2756 return FileOpenFailed;
2679 } 2757 }
2680 2758
2681 m_openingAudioFile = true; 2759 m_openingAudioFile = true;
2682 2760
2683 WaveFileModel *newModel = new WaveFileModel(path, location); 2761 size_t rate = 0;
2762
2763 if (Preferences::getInstance()->getResampleOnLoad()) {
2764 rate = m_playSource->getSourceSampleRate();
2765 }
2766
2767 WaveFileModel *newModel = new WaveFileModel(path, location, rate);
2684 2768
2685 if (!newModel->isOK()) { 2769 if (!newModel->isOK()) {
2686 delete newModel; 2770 delete newModel;
2687 m_openingAudioFile = false; 2771 m_openingAudioFile = false;
2688 return FileOpenFailed; 2772 return FileOpenFailed;
2782 if (realFile) { 2866 if (realFile) {
2783 registerLastOpenedFilePath(FileFinder::AudioFile, path); // for file dialog 2867 registerLastOpenedFilePath(FileFinder::AudioFile, path); // for file dialog
2784 } 2868 }
2785 m_openingAudioFile = false; 2869 m_openingAudioFile = false;
2786 2870
2871 currentPaneChanged(m_paneStack->getCurrentPane());
2872
2787 return FileOpenSucceeded; 2873 return FileOpenSucceeded;
2874 }
2875
2876 MainWindow::FileOpenStatus
2877 MainWindow::openPlaylistFile(QString path, AudioFileOpenMode mode)
2878 {
2879 return openPlaylistFile(path, path, mode);
2880 }
2881
2882 MainWindow::FileOpenStatus
2883 MainWindow::openPlaylistFile(QString path, QString location, AudioFileOpenMode mode)
2884 {
2885 if (!(QFileInfo(path).exists() &&
2886 QFileInfo(path).isFile() &&
2887 QFileInfo(path).isReadable())) {
2888 return FileOpenFailed;
2889 }
2890
2891 std::set<QString> extensions;
2892 PlaylistFileReader::getSupportedExtensions(extensions);
2893 QString extension = QFileInfo(path).suffix();
2894 if (extensions.find(extension) == extensions.end()) return FileOpenFailed;
2895
2896 PlaylistFileReader reader(path);
2897 if (!reader.isOK()) return FileOpenFailed;
2898
2899 PlaylistFileReader::Playlist playlist = reader.load();
2900
2901 bool someSuccess = false;
2902
2903 for (PlaylistFileReader::Playlist::const_iterator i = playlist.begin();
2904 i != playlist.end(); ++i) {
2905
2906 FileOpenStatus status = openURL(*i, mode);
2907
2908 if (status == FileOpenCancelled) {
2909 return FileOpenCancelled;
2910 }
2911
2912 if (status == FileOpenSucceeded) {
2913 someSuccess = true;
2914 mode = CreateAdditionalModel;
2915 }
2916 }
2917
2918 if (someSuccess) return FileOpenSucceeded;
2919 else return FileOpenFailed;
2788 } 2920 }
2789 2921
2790 void 2922 void
2791 MainWindow::createPlayTarget() 2923 MainWindow::createPlayTarget()
2792 { 2924 {
2963 tr("Session file \"%1\" could not be opened").arg(path)); 3095 tr("Session file \"%1\" could not be opened").arg(path));
2964 } 3096 }
2965 3097
2966 } else { 3098 } else {
2967 3099
2968 if (openAudioFile(path, AskUser) == FileOpenFailed) { 3100 if (openPlaylistFile(path, AskUser) == FileOpenFailed) {
2969 3101
2970 if (!canImportLayer || (openLayerFile(path) == FileOpenFailed)) { 3102 if (openAudioFile(path, AskUser) == FileOpenFailed) {
2971 3103
2972 QMessageBox::critical(this, tr("Failed to open file"), 3104 if (!canImportLayer || (openLayerFile(path) == FileOpenFailed)) {
2973 tr("File \"%1\" could not be opened").arg(path)); 3105
3106 QMessageBox::critical(this, tr("Failed to open file"),
3107 tr("File \"%1\" could not be opened").arg(path));
3108 }
2974 } 3109 }
2975 } 3110 }
2976 } 3111 }
2977 } 3112 }
2978 3113
3031 tr("Session file \"%1\" could not be opened").arg(path)); 3166 tr("Session file \"%1\" could not be opened").arg(path));
3032 } 3167 }
3033 3168
3034 } else { 3169 } else {
3035 3170
3036 if (openAudioFile(path, AskUser) == FileOpenFailed) { 3171 if (openPlaylistFile(path, AskUser) == FileOpenFailed) {
3037 3172
3038 bool canImportLayer = (getMainModel() != 0 && 3173 if (openAudioFile(path, AskUser) == FileOpenFailed) {
3039 m_paneStack != 0 && 3174
3040 m_paneStack->getCurrentPane() != 0); 3175 bool canImportLayer = (getMainModel() != 0 &&
3041 3176 m_paneStack != 0 &&
3042 if (!canImportLayer || (openLayerFile(path) == FileOpenFailed)) { 3177 m_paneStack->getCurrentPane() != 0);
3043 3178
3044 QMessageBox::critical(this, tr("Failed to open file"), 3179 if (!canImportLayer || (openLayerFile(path) == FileOpenFailed)) {
3045 tr("File \"%1\" could not be opened").arg(path)); 3180
3181 QMessageBox::critical(this, tr("Failed to open file"),
3182 tr("File \"%1\" could not be opened").arg(path));
3183 }
3046 } 3184 }
3047 } 3185 }
3048 } 3186 }
3049 } 3187 }
3050 3188
3051 MainWindow::FileOpenStatus 3189 MainWindow::FileOpenStatus
3052 MainWindow::openURL(QUrl url) 3190 MainWindow::openURL(QUrl url, AudioFileOpenMode mode)
3053 { 3191 {
3054 if (url.scheme().toLower() == "file") { 3192 if (url.scheme().toLower() == "file") {
3055 return openSomeFile(url.toLocalFile()); 3193
3194 return openSomeFile(url.toLocalFile(), mode);
3195
3056 } else if (!RemoteFile::canHandleScheme(url)) { 3196 } else if (!RemoteFile::canHandleScheme(url)) {
3197
3057 QMessageBox::critical(this, tr("Unsupported scheme in URL"), 3198 QMessageBox::critical(this, tr("Unsupported scheme in URL"),
3058 tr("The URL scheme \"%1\" is not supported") 3199 tr("The URL scheme \"%1\" is not supported")
3059 .arg(url.scheme())); 3200 .arg(url.scheme()));
3060 return FileOpenFailed; 3201 return FileOpenFailed;
3202
3061 } else { 3203 } else {
3062 RemoteFile rf(url); 3204 RemoteFile rf(url);
3063 rf.wait(); 3205 rf.wait();
3064 if (!rf.isOK()) { 3206 if (!rf.isOK()) {
3065 QMessageBox::critical(this, tr("File download failed"), 3207 QMessageBox::critical(this, tr("File download failed"),
3066 tr("Failed to download URL \"%1\": %2") 3208 tr("Failed to download URL \"%1\": %2")
3067 .arg(url.toString()).arg(rf.getErrorString())); 3209 .arg(url.toString()).arg(rf.getErrorString()));
3068 return FileOpenFailed; 3210 return FileOpenFailed;
3069 } 3211 }
3070 FileOpenStatus status; 3212 FileOpenStatus status;
3071 if ((status = openSomeFile(rf.getLocalFilename(), url.toString())) != 3213 if ((status = openSomeFile(rf.getLocalFilename(), url.toString(),
3214 mode)) !=
3215 FileOpenSucceeded) {
3216 rf.deleteLocalFile();
3217 }
3218 return status;
3219 }
3220 }
3221
3222 MainWindow::FileOpenStatus
3223 MainWindow::openURL(QString ustr, AudioFileOpenMode mode)
3224 {
3225 // This function is used when we don't know whether the string is
3226 // an encoded or human-readable url
3227
3228 QUrl url(ustr);
3229
3230 if (url.scheme().toLower() == "file") {
3231
3232 return openSomeFile(url.toLocalFile(), mode);
3233
3234 } else if (!RemoteFile::canHandleScheme(url)) {
3235
3236 QMessageBox::critical(this, tr("Unsupported scheme in URL"),
3237 tr("The URL scheme \"%1\" is not supported")
3238 .arg(url.scheme()));
3239 return FileOpenFailed;
3240
3241 } else {
3242 RemoteFile rf(url);
3243 rf.wait();
3244 if (!rf.isOK()) {
3245 // rf was created on the assumption that ustr was
3246 // human-readable. Let's try again, this time assuming it
3247 // was already encoded.
3248 std::cerr << "MainWindow::openURL: Failed to retrieve URL \""
3249 << ustr.toStdString() << "\" as human-readable URL; "
3250 << "trying again treating it as encoded URL"
3251 << std::endl;
3252 url.setEncodedUrl(ustr.toAscii());
3253 return openURL(url, mode);
3254 }
3255
3256 FileOpenStatus status;
3257 if ((status = openSomeFile(rf.getLocalFilename(), ustr, mode)) !=
3072 FileOpenSucceeded) { 3258 FileOpenSucceeded) {
3073 rf.deleteLocalFile(); 3259 rf.deleteLocalFile();
3074 } 3260 }
3075 return status; 3261 return status;
3076 } 3262 }
3090 3276
3091 bool canImportLayer = (getMainModel() != 0 && 3277 bool canImportLayer = (getMainModel() != 0 &&
3092 m_paneStack != 0 && 3278 m_paneStack != 0 &&
3093 m_paneStack->getCurrentPane() != 0); 3279 m_paneStack->getCurrentPane() != 0);
3094 3280
3095 if ((status = openAudioFile(path, location, mode)) != FileOpenFailed) { 3281 if ((status = openPlaylistFile(path, location, mode)) != FileOpenFailed) {
3282 return status;
3283 } else if ((status = openAudioFile(path, location, mode)) != FileOpenFailed) {
3096 return status; 3284 return status;
3097 } else if ((status = openSessionFile(path, location)) != FileOpenFailed) { 3285 } else if ((status = openSessionFile(path, location)) != FileOpenFailed) {
3098 return status; 3286 return status;
3099 } else if (!canImportLayer) { 3287 } else if (!canImportLayer) {
3100 return FileOpenFailed; 3288 return FileOpenFailed;
3544 3732
3545 settings.endGroup(); 3733 settings.endGroup();
3546 } 3734 }
3547 3735
3548 void 3736 void
3549 MainWindow::toggleDarkBackground()
3550 {
3551 if (!m_viewManager) return;
3552
3553 m_viewManager->setGlobalDarkBackground
3554 (!m_viewManager->getGlobalDarkBackground());
3555
3556 if (m_viewManager->getGlobalDarkBackground()) {
3557 m_panLayer->setBaseColour
3558 (ColourDatabase::getInstance()->getColourIndex(tr("Bright Green")));
3559 } else {
3560 m_panLayer->setBaseColour
3561 (ColourDatabase::getInstance()->getColourIndex(tr("Green")));
3562 }
3563 }
3564
3565 void
3566 MainWindow::preferenceChanged(PropertyContainer::PropertyName name) 3737 MainWindow::preferenceChanged(PropertyContainer::PropertyName name)
3567 { 3738 {
3568 if (name == "Property Box Layout") { 3739 if (name == "Property Box Layout") {
3569 if (m_paneStack->getLayoutStyle() != PaneStack::NoPropertyStacks) { 3740 if (m_paneStack->getLayoutStyle() != PaneStack::NoPropertyStacks) {
3570 if (Preferences::getInstance()->getPropertyBoxLayout() == 3741 if (Preferences::getInstance()->getPropertyBoxLayout() ==
3572 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout); 3743 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout);
3573 } else { 3744 } else {
3574 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout); 3745 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout);
3575 } 3746 }
3576 } 3747 }
3577 } 3748 } else if (name == "Background Mode" && m_viewManager) {
3749 Preferences::BackgroundMode mode =
3750 Preferences::getInstance()->getBackgroundMode();
3751 if (mode == Preferences::BackgroundFromTheme) {
3752 m_viewManager->setGlobalDarkBackground(m_initialDarkBackground);
3753 } else if (mode == Preferences::DarkBackground) {
3754 m_viewManager->setGlobalDarkBackground(true);
3755 } else {
3756 m_viewManager->setGlobalDarkBackground(false);
3757 }
3758 if (m_viewManager->getGlobalDarkBackground()) {
3759 m_panLayer->setBaseColour
3760 (ColourDatabase::getInstance()->getColourIndex(tr("Bright Green")));
3761 } else {
3762 m_panLayer->setBaseColour
3763 (ColourDatabase::getInstance()->getColourIndex(tr("Green")));
3764 }
3765 }
3578 } 3766 }
3579 3767
3580 void 3768 void
3581 MainWindow::play() 3769 MainWindow::play()
3582 { 3770 {
4411 4599
4412 void 4600 void
4413 MainWindow::modelAboutToBeDeleted(Model *model) 4601 MainWindow::modelAboutToBeDeleted(Model *model)
4414 { 4602 {
4415 // std::cerr << "MainWindow::modelAboutToBeDeleted(" << model << ")" << std::endl; 4603 // std::cerr << "MainWindow::modelAboutToBeDeleted(" << model << ")" << std::endl;
4604 if (model == m_viewManager->getPlaybackModel()) {
4605 m_viewManager->setPlaybackModel(0);
4606 }
4416 m_playSource->removeModel(model); 4607 m_playSource->removeModel(model);
4417 FFTDataServer::modelAboutToBeDeleted(model); 4608 FFTDataServer::modelAboutToBeDeleted(model);
4418 } 4609 }
4419 4610
4420 void 4611 void
4645 QString str = message.getArg(0).toString(); 4836 QString str = message.getArg(0).toString();
4646 if (str == "on") { 4837 if (str == "on") {
4647 m_viewManager->setPlayLoopMode(true); 4838 m_viewManager->setPlayLoopMode(true);
4648 } else if (str == "off") { 4839 } else if (str == "off") {
4649 m_viewManager->setPlayLoopMode(false); 4840 m_viewManager->setPlayLoopMode(false);
4841 }
4842 }
4843
4844 } else if (message.getMethod() == "solo") {
4845
4846 if (message.getArgCount() == 1 &&
4847 message.getArg(0).canConvert(QVariant::String)) {
4848
4849 QString str = message.getArg(0).toString();
4850 if (str == "on") {
4851 m_viewManager->setPlaySoloMode(true);
4852 } else if (str == "off") {
4853 m_viewManager->setPlaySoloMode(false);
4650 } 4854 }
4651 } 4855 }
4652 4856
4653 } else if (message.getMethod() == "select" || 4857 } else if (message.getMethod() == "select" ||
4654 message.getMethod() == "addselect") { 4858 message.getMethod() == "addselect") {