comparison main/MainWindow.cpp @ 246:ddbde90773b0 spectrogram-cache-rejig

* Merge from trunk
author Chris Cannam
date Wed, 27 Feb 2008 11:59:42 +0000
parents 11ca12902c6a
children
comparison
equal deleted inserted replaced
214:37847fc0b381 246:ddbde90773b0
14 */ 14 */
15 15
16 #include "../version.h" 16 #include "../version.h"
17 17
18 #include "MainWindow.h" 18 #include "MainWindow.h"
19 #include "framework/Document.h"
20 #include "PreferencesDialog.h" 19 #include "PreferencesDialog.h"
21 20
22 #include "view/Pane.h" 21 #include "view/Pane.h"
23 #include "view/PaneStack.h" 22 #include "view/PaneStack.h"
24 #include "data/model/WaveFileModel.h" 23 #include "data/model/WaveFileModel.h"
25 #include "data/model/SparseOneDimensionalModel.h" 24 #include "data/model/SparseOneDimensionalModel.h"
26 #include "data/model/NoteModel.h" 25 #include "data/model/NoteModel.h"
27 #include "data/model/Labeller.h" 26 #include "data/model/Labeller.h"
27 #include "data/osc/OSCQueue.h"
28 #include "framework/Document.h"
28 #include "view/ViewManager.h" 29 #include "view/ViewManager.h"
29 #include "base/Preferences.h" 30 #include "base/Preferences.h"
30 #include "layer/WaveformLayer.h" 31 #include "layer/WaveformLayer.h"
31 #include "layer/TimeRulerLayer.h" 32 #include "layer/TimeRulerLayer.h"
32 #include "layer/TimeInstantLayer.h" 33 #include "layer/TimeInstantLayer.h"
39 #include "view/Overview.h" 40 #include "view/Overview.h"
40 #include "widgets/PropertyBox.h" 41 #include "widgets/PropertyBox.h"
41 #include "widgets/PropertyStack.h" 42 #include "widgets/PropertyStack.h"
42 #include "widgets/AudioDial.h" 43 #include "widgets/AudioDial.h"
43 #include "widgets/IconLoader.h" 44 #include "widgets/IconLoader.h"
44 #include "widgets/LayerTree.h" 45 #include "widgets/LayerTreeDialog.h"
45 #include "widgets/ListInputDialog.h" 46 #include "widgets/ListInputDialog.h"
46 #include "widgets/SubdividingMenu.h" 47 #include "widgets/SubdividingMenu.h"
47 #include "widgets/NotifyingPushButton.h" 48 #include "widgets/NotifyingPushButton.h"
48 #include "widgets/KeyReference.h" 49 #include "widgets/KeyReference.h"
49 #include "widgets/LabelCounterInputDialog.h" 50 #include "widgets/LabelCounterInputDialog.h"
67 #include "base/CommandHistory.h" 68 #include "base/CommandHistory.h"
68 #include "base/Profiler.h" 69 #include "base/Profiler.h"
69 #include "base/Clipboard.h" 70 #include "base/Clipboard.h"
70 #include "base/UnitDatabase.h" 71 #include "base/UnitDatabase.h"
71 #include "base/ColourDatabase.h" 72 #include "base/ColourDatabase.h"
72 #include "data/osc/OSCQueue.h"
73 73
74 // For version information 74 // For version information
75 #include "vamp/vamp.h" 75 #include "vamp/vamp.h"
76 #include "vamp-sdk/PluginBase.h" 76 #include "vamp-sdk/PluginBase.h"
77 #include "plugin/api/ladspa.h" 77 #include "plugin/api/ladspa.h"
131 m_soloAction(0), 131 m_soloAction(0),
132 m_soloModified(false), 132 m_soloModified(false),
133 m_prevSolo(false), 133 m_prevSolo(false),
134 m_ffwdAction(0), 134 m_ffwdAction(0),
135 m_rwdAction(0), 135 m_rwdAction(0),
136 m_playControlsSpacer(0),
137 m_playControlsWidth(0),
136 m_preferencesDialog(0), 138 m_preferencesDialog(0),
137 m_layerTreeView(0), 139 m_layerTreeDialog(0),
138 m_keyReference(new KeyReference()) 140 m_keyReference(new KeyReference())
139 { 141 {
140 setWindowTitle(tr("Sonic Visualiser")); 142 setWindowTitle(tr("Sonic Visualiser"));
141 143
142 UnitDatabase *udb = UnitDatabase::getInstance(); 144 UnitDatabase *udb = UnitDatabase::getInstance();
218 connect(m_playSpeed, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); 220 connect(m_playSpeed, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
219 connect(m_playSpeed, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); 221 connect(m_playSpeed, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
220 222
221 IconLoader il; 223 IconLoader il;
222 224
223 m_playSharpen = new NotifyingPushButton(frame);
224 m_playSharpen->setToolTip(tr("Sharpen percussive transients"));
225 m_playSharpen->setFixedSize(20, 20);
226 m_playSharpen->setEnabled(false);
227 m_playSharpen->setCheckable(true);
228 m_playSharpen->setChecked(false);
229 m_playSharpen->setIcon(il.load("sharpen"));
230 connect(m_playSharpen, SIGNAL(clicked()), this, SLOT(playSharpenToggled()));
231 connect(m_playSharpen, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
232 connect(m_playSharpen, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
233
234 m_playMono = new NotifyingPushButton(frame);
235 m_playMono->setToolTip(tr("Run time stretcher in mono only"));
236 m_playMono->setFixedSize(20, 20);
237 m_playMono->setEnabled(false);
238 m_playMono->setCheckable(true);
239 m_playMono->setChecked(false);
240 m_playMono->setIcon(il.load("mono"));
241 connect(m_playMono, SIGNAL(clicked()), this, SLOT(playMonoToggled()));
242 connect(m_playMono, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
243 connect(m_playMono, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
244
245 QSettings settings; 225 QSettings settings;
246 settings.beginGroup("MainWindow"); 226 settings.beginGroup("MainWindow");
247 m_playSharpen->setChecked(settings.value("playsharpen", true).toBool());
248 m_playMono->setChecked(settings.value("playmono", false).toBool());
249 settings.endGroup(); 227 settings.endGroup();
228
229 m_playControlsSpacer = new QFrame;
250 230
251 layout->setSpacing(4); 231 layout->setSpacing(4);
252 layout->addWidget(scroll, 0, 0, 1, 5); 232 layout->addWidget(scroll, 0, 0, 1, 5);
253 layout->addWidget(m_overview, 1, 0); 233 layout->addWidget(m_overview, 1, 1);
254 layout->addWidget(m_fader, 1, 1); 234 layout->addWidget(m_playControlsSpacer, 1, 2);
255 layout->addWidget(m_playSpeed, 1, 2); 235 layout->addWidget(m_playSpeed, 1, 3);
256 layout->addWidget(m_playSharpen, 1, 3); 236 layout->addWidget(m_fader, 1, 4);
257 layout->addWidget(m_playMono, 1, 4); 237
258 238 m_playControlsWidth =
259 m_paneStack->setPropertyStackMinWidth 239 m_fader->width() + m_playSpeed->width() + layout->spacing() * 2;
260 (m_fader->width() + m_playSpeed->width() + m_playSharpen->width() + 240
261 m_playMono->width() + layout->spacing() * 4); 241 layout->setColumnMinimumWidth(0, 14);
262 242 layout->setColumnStretch(0, 0);
263 layout->setColumnStretch(0, 10); 243
244 m_paneStack->setPropertyStackMinWidth(m_playControlsWidth
245 + 2 + layout->spacing());
246 m_playControlsSpacer->setFixedSize(QSize(2, 2));
247
248 layout->setColumnStretch(1, 10);
249
250 connect(m_paneStack, SIGNAL(propertyStacksResized(int)),
251 this, SLOT(propertyStacksResized(int)));
264 252
265 frame->setLayout(layout); 253 frame->setLayout(layout);
266 254
267 setupMenus(); 255 setupMenus();
268 setupToolbars(); 256 setupToolbars();
275 263
276 MainWindow::~MainWindow() 264 MainWindow::~MainWindow()
277 { 265 {
278 delete m_keyReference; 266 delete m_keyReference;
279 delete m_preferencesDialog; 267 delete m_preferencesDialog;
280 delete m_layerTreeView; 268 delete m_layerTreeDialog;
281 Profiles::getInstance()->dump(); 269 Profiles::getInstance()->dump();
282 } 270 }
283 271
284 void 272 void
285 MainWindow::setupMenus() 273 MainWindow::setupMenus()
591 connect(this, SIGNAL(canInsertInstantsAtBoundaries(bool)), action, SLOT(setEnabled(bool))); 579 connect(this, SIGNAL(canInsertInstantsAtBoundaries(bool)), action, SLOT(setEnabled(bool)));
592 m_keyReference->registerShortcut(action); 580 m_keyReference->registerShortcut(action);
593 menu->addAction(action); 581 menu->addAction(action);
594 582
595 QMenu *numberingMenu = menu->addMenu(tr("Number New Instants with")); 583 QMenu *numberingMenu = menu->addMenu(tr("Number New Instants with"));
584 numberingMenu->setTearOffEnabled(true);
596 QActionGroup *numberingGroup = new QActionGroup(this); 585 QActionGroup *numberingGroup = new QActionGroup(this);
597 586
598 Labeller::TypeNameMap types = m_labeller->getTypeNames(); 587 Labeller::TypeNameMap types = m_labeller->getTypeNames();
599 for (Labeller::TypeNameMap::iterator i = types.begin(); i != types.end(); ++i) { 588 for (Labeller::TypeNameMap::iterator i = types.begin(); i != types.end(); ++i) {
600 589
612 if (i->first == Labeller::ValueFromTwoLevelCounter) { 601 if (i->first == Labeller::ValueFromTwoLevelCounter) {
613 602
614 QMenu *cycleMenu = numberingMenu->addMenu(tr("Cycle size")); 603 QMenu *cycleMenu = numberingMenu->addMenu(tr("Cycle size"));
615 QActionGroup *cycleGroup = new QActionGroup(this); 604 QActionGroup *cycleGroup = new QActionGroup(this);
616 605
617 int cycles[] = { 2, 3, 4, 5, 6, 7, 8, 10, 12, 16 }; 606 int cycles[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 16 };
618 for (int i = 0; i < int(sizeof(cycles)/sizeof(cycles[0])); ++i) { 607 for (int i = 0; i < int(sizeof(cycles)/sizeof(cycles[0])); ++i) {
619 action = new QAction(QString("%1").arg(cycles[i]), this); 608 action = new QAction(QString("%1").arg(cycles[i]), this);
620 connect(action, SIGNAL(triggered()), this, SLOT(setInstantsCounterCycle())); 609 connect(action, SIGNAL(triggered()), this, SLOT(setInstantsCounterCycle()));
621 action->setCheckable(true); 610 action->setCheckable(true);
622 action->setChecked(cycles[i] == m_labeller->getCounterCycleSize()); 611 action->setChecked(cycles[i] == m_labeller->getCounterCycleSize());
623 cycleGroup->addAction(action); 612 cycleGroup->addAction(action);
624 cycleMenu->addAction(action); 613 cycleMenu->addAction(action);
625 } 614 }
626
627 action = new QAction(tr("Reset Counters..."), this);
628 connect(action, SIGNAL(triggered()), this, SLOT(resetInstantsCounters()));
629 numberingMenu->addAction(action);
630 } 615 }
631 616
632 if (i->first == Labeller::ValueNone || 617 if (i->first == Labeller::ValueNone ||
633 i->first == Labeller::ValueFromTwoLevelCounter || 618 i->first == Labeller::ValueFromTwoLevelCounter ||
634 i->first == Labeller::ValueFromRealTime) { 619 i->first == Labeller::ValueFromRealTime) {
635 numberingMenu->addSeparator(); 620 numberingMenu->addSeparator();
636 } 621 }
637 } 622 }
638 623
639 action = new QAction(tr("Re-Number Selected Instants"), this); 624 action = new QAction(tr("Set Numbering Counters..."), this);
640 action->setStatusTip(tr("Re-number the selected instants using the current labelling scheme")); 625 action->setStatusTip(tr("Set the counters used for counter-based labelling"));
626 connect(action, SIGNAL(triggered()), this, SLOT(resetInstantsCounters()));
627 menu->addAction(action);
628
629 action = new QAction(tr("Renumber Selected Instants"), this);
630 action->setStatusTip(tr("Renumber the selected instants using the current labelling scheme"));
641 connect(action, SIGNAL(triggered()), this, SLOT(renumberInstants())); 631 connect(action, SIGNAL(triggered()), this, SLOT(renumberInstants()));
642 connect(this, SIGNAL(canRenumberInstants(bool)), action, SLOT(setEnabled(bool))); 632 connect(this, SIGNAL(canRenumberInstants(bool)), action, SLOT(setEnabled(bool)));
643 // m_keyReference->registerShortcut(action); 633 // m_keyReference->registerShortcut(action);
644 menu->addAction(action); 634 menu->addAction(action);
645 } 635 }
808 } 798 }
809 settings.endGroup(); 799 settings.endGroup();
810 800
811 menu->addSeparator(); 801 menu->addSeparator();
812 802
813 action = new QAction(tr("Show La&yer Hierarchy"), this); 803 action = new QAction(tr("Show La&yer Summary"), this);
814 action->setShortcut(tr("H")); 804 action->setShortcut(tr("Y"));
815 action->setStatusTip(tr("Open a window displaying the hierarchy of panes and layers in this session")); 805 action->setStatusTip(tr("Open a window displaying the hierarchy of panes and layers in this session"));
816 connect(action, SIGNAL(triggered()), this, SLOT(showLayerTree())); 806 connect(action, SIGNAL(triggered()), this, SLOT(showLayerTree()));
817 m_keyReference->registerShortcut(action); 807 m_keyReference->registerShortcut(action);
818 menu->addAction(action); 808 menu->addAction(action);
819 } 809 }
846 QAction *action = new QAction(il.load("pane"), tr("Add &New Pane"), this); 836 QAction *action = new QAction(il.load("pane"), tr("Add &New Pane"), this);
847 action->setShortcut(tr("N")); 837 action->setShortcut(tr("N"));
848 action->setStatusTip(tr("Add a new pane containing only a time ruler")); 838 action->setStatusTip(tr("Add a new pane containing only a time ruler"));
849 connect(action, SIGNAL(triggered()), this, SLOT(addPane())); 839 connect(action, SIGNAL(triggered()), this, SLOT(addPane()));
850 connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool))); 840 connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool)));
851 m_paneActions[action] = PaneConfiguration(LayerFactory::TimeRuler); 841 m_paneActions[action] = LayerConfiguration(LayerFactory::TimeRuler);
852 m_keyReference->registerShortcut(action); 842 m_keyReference->registerShortcut(action);
853 menu->addAction(action); 843 menu->addAction(action);
854 844
855 menu->addSeparator(); 845 menu->addSeparator();
856 846
882 m_keyReference->registerShortcut(action); 872 m_keyReference->registerShortcut(action);
883 } 873 }
884 874
885 connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); 875 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
886 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); 876 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
887 m_layerActions[action] = type; 877 m_layerActions[action] = LayerConfiguration(type);
888 menu->addAction(action); 878 menu->addAction(action);
889 m_rightButtonLayerMenu->addAction(action); 879 m_rightButtonLayerMenu->addAction(action);
890 } 880 }
891 881
892 m_rightButtonLayerMenu->addSeparator(); 882 m_rightButtonLayerMenu->addSeparator();
899 LayerFactory::PeakFrequencySpectrogram, 889 LayerFactory::PeakFrequencySpectrogram,
900 LayerFactory::Spectrum 890 LayerFactory::Spectrum
901 }; 891 };
902 892
903 std::vector<Model *> models; 893 std::vector<Model *> models;
904 if (m_document) models = m_document->getTransformerInputModels(); //!!! not well named for this! 894 if (m_document) models = m_document->getTransformInputModels();
905 bool plural = (models.size() > 1); 895 bool plural = (models.size() > 1);
906 if (models.empty()) { 896 if (models.empty()) {
907 models.push_back(getMainModel()); // probably 0 897 models.push_back(getMainModel()); // probably 0
908 } 898 }
909 899
910 for (unsigned int i = 0; 900 for (unsigned int i = 0;
911 i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) { 901 i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) {
912 902
913 for (int menuType = 0; menuType <= 1; ++menuType) { // pane, layer 903 const int paneMenuType = 0, layerMenuType = 1;
914 904
915 if (menuType == 0) menu = m_paneMenu; 905 for (int menuType = paneMenuType; menuType <= layerMenuType; ++menuType) {
906
907 if (menuType == paneMenuType) menu = m_paneMenu;
916 else menu = m_layerMenu; 908 else menu = m_layerMenu;
917 909
918 QMenu *submenu = 0; 910 QMenu *submenu = 0;
919 911
920 QIcon icon; 912 QIcon icon;
925 switch (type) { 917 switch (type) {
926 918
927 case LayerFactory::Waveform: 919 case LayerFactory::Waveform:
928 icon = il.load("waveform"); 920 icon = il.load("waveform");
929 mainText = tr("Add &Waveform"); 921 mainText = tr("Add &Waveform");
930 if (menuType == 0) { 922 if (menuType == paneMenuType) {
931 shortcutText = tr("W"); 923 shortcutText = tr("W");
932 tipText = tr("Add a new pane showing a waveform view"); 924 tipText = tr("Add a new pane showing a waveform view");
933 } else { 925 } else {
934 tipText = tr("Add a new layer showing a waveform view"); 926 tipText = tr("Add a new layer showing a waveform view");
935 } 927 }
937 break; 929 break;
938 930
939 case LayerFactory::Spectrogram: 931 case LayerFactory::Spectrogram:
940 icon = il.load("spectrogram"); 932 icon = il.load("spectrogram");
941 mainText = tr("Add Spectro&gram"); 933 mainText = tr("Add Spectro&gram");
942 if (menuType == 0) { 934 if (menuType == paneMenuType) {
943 shortcutText = tr("G"); 935 shortcutText = tr("G");
944 tipText = tr("Add a new pane showing a spectrogram"); 936 tipText = tr("Add a new pane showing a spectrogram");
945 } else { 937 } else {
946 tipText = tr("Add a new layer showing a spectrogram"); 938 tipText = tr("Add a new layer showing a spectrogram");
947 } 939 }
948 break; 940 break;
949 941
950 case LayerFactory::MelodicRangeSpectrogram: 942 case LayerFactory::MelodicRangeSpectrogram:
951 icon = il.load("spectrogram"); 943 icon = il.load("spectrogram");
952 mainText = tr("Add &Melodic Range Spectrogram"); 944 mainText = tr("Add &Melodic Range Spectrogram");
953 if (menuType == 0) { 945 if (menuType == paneMenuType) {
954 shortcutText = tr("M"); 946 shortcutText = tr("M");
955 tipText = tr("Add a new pane showing a spectrogram set up for an overview of note pitches"); 947 tipText = tr("Add a new pane showing a spectrogram set up for an overview of note pitches");
956 } else { 948 } else {
957 tipText = tr("Add a new layer showing a spectrogram set up for an overview of note pitches"); 949 tipText = tr("Add a new layer showing a spectrogram set up for an overview of note pitches");
958 } 950 }
959 break; 951 break;
960 952
961 case LayerFactory::PeakFrequencySpectrogram: 953 case LayerFactory::PeakFrequencySpectrogram:
962 icon = il.load("spectrogram"); 954 icon = il.load("spectrogram");
963 mainText = tr("Add Pea&k Frequency Spectrogram"); 955 mainText = tr("Add Pea&k Frequency Spectrogram");
964 if (menuType == 0) { 956 if (menuType == paneMenuType) {
965 shortcutText = tr("K"); 957 shortcutText = tr("K");
966 tipText = tr("Add a new pane showing a spectrogram set up for tracking frequencies"); 958 tipText = tr("Add a new pane showing a spectrogram set up for tracking frequencies");
967 } else { 959 } else {
968 tipText = tr("Add a new layer showing a spectrogram set up for tracking frequencies"); 960 tipText = tr("Add a new layer showing a spectrogram set up for tracking frequencies");
969 } 961 }
970 break; 962 break;
971 963
972 case LayerFactory::Spectrum: 964 case LayerFactory::Spectrum:
973 icon = il.load("spectrum"); 965 icon = il.load("spectrum");
974 mainText = tr("Add Spectr&um"); 966 mainText = tr("Add Spectr&um");
975 if (menuType == 0) { 967 if (menuType == paneMenuType) {
976 shortcutText = tr("U"); 968 shortcutText = tr("U");
977 tipText = tr("Add a new pane showing a frequency spectrum"); 969 tipText = tr("Add a new pane showing a frequency spectrum");
978 } else { 970 } else {
979 tipText = tr("Add a new layer showing a frequency spectrum"); 971 tipText = tr("Add a new layer showing a frequency spectrum");
980 } 972 }
982 974
983 default: break; 975 default: break;
984 } 976 }
985 977
986 std::vector<Model *> candidateModels; 978 std::vector<Model *> candidateModels;
987 if (menuType == 0) { 979 // if (menuType == paneMenuType) {
988 candidateModels = models; 980 candidateModels = models;
989 } else { 981 // } else {
990 candidateModels.push_back(0); 982 // candidateModels.push_back(0);
991 } 983 // }
992 984
993 for (std::vector<Model *>::iterator mi = 985 for (std::vector<Model *>::iterator mi =
994 candidateModels.begin(); 986 candidateModels.begin();
995 mi != candidateModels.end(); ++mi) { 987 mi != candidateModels.end(); ++mi) {
996 988
1011 1003
1012 if (c == 1 && channels == 1) continue; 1004 if (c == 1 && channels == 1) continue;
1013 bool isDefault = (c == 0); 1005 bool isDefault = (c == 0);
1014 bool isOnly = (isDefault && (channels == 1)); 1006 bool isOnly = (isDefault && (channels == 1));
1015 1007
1016 if (menuType == 1) { 1008 // if (menuType == layerMenuType) {
1017 if (isDefault) isOnly = true; 1009 // if (isDefault) isOnly = true;
1018 else continue; 1010 // else continue;
1019 } 1011 // }
1020 1012
1021 if (isOnly && (!plural || menuType == 1)) { 1013 if (isOnly && (!plural /*|| menuType == layerMenuType*/)) {
1022 1014
1023 if (menuType == 1 && type != LayerFactory::Waveform) { 1015 // if (menuType == layerMenuType && type != LayerFactory::Waveform) {
1024 action = new QAction(mainText, this); 1016 // action = new QAction(mainText, this);
1025 } else { 1017 // } else {
1026 action = new QAction(icon, mainText, this); 1018 action = new QAction(icon, mainText, this);
1027 } 1019 // }
1028 1020
1029 action->setShortcut(shortcutText); 1021 action->setShortcut(shortcutText);
1030 action->setStatusTip(tipText); 1022 action->setStatusTip(tipText);
1031 if (menuType == 0) { 1023 if (menuType == paneMenuType) {
1032 connect(action, SIGNAL(triggered()), 1024 connect(action, SIGNAL(triggered()),
1033 this, SLOT(addPane())); 1025 this, SLOT(addPane()));
1034 connect(this, SIGNAL(canAddPane(bool)), 1026 connect(this, SIGNAL(canAddPane(bool)),
1035 action, SLOT(setEnabled(bool))); 1027 action, SLOT(setEnabled(bool)));
1036 m_paneActions[action] = PaneConfiguration(type); 1028 m_paneActions[action] = LayerConfiguration(type);
1037 } else { 1029 } else {
1038 connect(action, SIGNAL(triggered()), 1030 connect(action, SIGNAL(triggered()),
1039 this, SLOT(addLayer())); 1031 this, SLOT(addLayer()));
1040 connect(this, SIGNAL(canAddLayer(bool)), 1032 connect(this, SIGNAL(canAddLayer(bool)),
1041 action, SLOT(setEnabled(bool))); 1033 action, SLOT(setEnabled(bool)));
1042 m_layerActions[action] = type; 1034 m_layerActions[action] = LayerConfiguration(type);
1043 } 1035 }
1044 if (shortcutText != "") { 1036 if (shortcutText != "") {
1045 m_keyReference->registerShortcut(action); 1037 m_keyReference->registerShortcut(action);
1046 } 1038 }
1047 menu->addAction(action); 1039 menu->addAction(action);
1081 action = new QAction(actionText, this); 1073 action = new QAction(actionText, this);
1082 } 1074 }
1083 1075
1084 action->setStatusTip(tipText); 1076 action->setStatusTip(tipText);
1085 1077
1086 if (menuType == 0) { 1078 if (menuType == paneMenuType) {
1087 connect(action, SIGNAL(triggered()), 1079 connect(action, SIGNAL(triggered()),
1088 this, SLOT(addPane())); 1080 this, SLOT(addPane()));
1089 connect(this, SIGNAL(canAddPane(bool)), 1081 connect(this, SIGNAL(canAddPane(bool)),
1090 action, SLOT(setEnabled(bool))); 1082 action, SLOT(setEnabled(bool)));
1091 m_paneActions[action] = 1083 m_paneActions[action] =
1092 PaneConfiguration(type, model, c - 1); 1084 LayerConfiguration(type, model, c - 1);
1093 } else { 1085 } else {
1094 connect(action, SIGNAL(triggered()), 1086 connect(action, SIGNAL(triggered()),
1095 this, SLOT(addLayer())); 1087 this, SLOT(addLayer()));
1096 connect(this, SIGNAL(canAddLayer(bool)), 1088 connect(this, SIGNAL(canAddLayer(bool)),
1097 action, SLOT(setEnabled(bool))); 1089 action, SLOT(setEnabled(bool)));
1098 m_layerActions[action] = type; 1090 m_layerActions[action] =
1091 LayerConfiguration(type, model, c - 1);
1099 } 1092 }
1100 1093
1101 submenu->addAction(action); 1094 submenu->addAction(action);
1102 } 1095 }
1103 } 1096 }
1104 } 1097 }
1105 } 1098 }
1106 } 1099 }
1107 1100
1108 menu = m_paneMenu; 1101 menu = m_paneMenu;
1102 menu->addSeparator();
1103
1104 action = new QAction(tr("Switch to Previous Pane"), this);
1105 action->setShortcut(tr("["));
1106 action->setStatusTip(tr("Make the next pane up in the pane stack current"));
1107 connect(action, SIGNAL(triggered()), this, SLOT(previousPane()));
1108 connect(this, SIGNAL(canSelectPreviousPane(bool)), action, SLOT(setEnabled(bool)));
1109 m_keyReference->registerShortcut(action);
1110 menu->addAction(action);
1111
1112 action = new QAction(tr("Switch to Next Pane"), this);
1113 action->setShortcut(tr("]"));
1114 action->setStatusTip(tr("Make the next pane down in the pane stack current"));
1115 connect(action, SIGNAL(triggered()), this, SLOT(nextPane()));
1116 connect(this, SIGNAL(canSelectNextPane(bool)), action, SLOT(setEnabled(bool)));
1117 m_keyReference->registerShortcut(action);
1118 menu->addAction(action);
1109 1119
1110 menu->addSeparator(); 1120 menu->addSeparator();
1111 1121
1112 action = new QAction(il.load("editdelete"), tr("&Delete Pane"), this); 1122 action = new QAction(il.load("editdelete"), tr("&Delete Pane"), this);
1113 action->setShortcut(tr("Ctrl+Shift+D")); 1123 action->setShortcut(tr("Ctrl+Shift+D"));
1121 1131
1122 action = new QAction(il.load("timeruler"), tr("Add &Time Ruler"), this); 1132 action = new QAction(il.load("timeruler"), tr("Add &Time Ruler"), this);
1123 action->setStatusTip(tr("Add a new layer showing a time ruler")); 1133 action->setStatusTip(tr("Add a new layer showing a time ruler"));
1124 connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); 1134 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
1125 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); 1135 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
1126 m_layerActions[action] = LayerFactory::TimeRuler; 1136 m_layerActions[action] = LayerConfiguration(LayerFactory::TimeRuler);
1127 menu->addAction(action); 1137 menu->addAction(action);
1128 1138
1129 menu->addSeparator(); 1139 menu->addSeparator();
1130 1140
1131 m_existingLayersMenu = menu->addMenu(tr("Add &Existing Layer")); 1141 m_existingLayersMenu = menu->addMenu(tr("Add &Existing Layer"));
1136 m_sliceMenu->setTearOffEnabled(true); 1146 m_sliceMenu->setTearOffEnabled(true);
1137 m_rightButtonLayerMenu->addMenu(m_sliceMenu); 1147 m_rightButtonLayerMenu->addMenu(m_sliceMenu);
1138 1148
1139 setupExistingLayersMenus(); 1149 setupExistingLayersMenus();
1140 1150
1151 /*!!! These don't work correctly -- fix or omit
1152 menu->addSeparator();
1153
1154 action = new QAction(tr("Switch to Previous Layer"), this);
1155 action->setShortcut(tr("{"));
1156 action->setStatusTip(tr("Make the previous layer in the pane current"));
1157 connect(action, SIGNAL(triggered()), this, SLOT(previousLayer()));
1158 connect(this, SIGNAL(canSelectPreviousLayer(bool)), action, SLOT(setEnabled(bool)));
1159 m_keyReference->registerShortcut(action);
1160 menu->addAction(action);
1161
1162 action = new QAction(tr("Switch to Next Layer"), this);
1163 action->setShortcut(tr("}"));
1164 action->setStatusTip(tr("Make the next layer in the pane current"));
1165 connect(action, SIGNAL(triggered()), this, SLOT(nextLayer()));
1166 connect(this, SIGNAL(canSelectNextLayer(bool)), action, SLOT(setEnabled(bool)));
1167 m_keyReference->registerShortcut(action);
1168 menu->addAction(action);
1169 */
1141 m_rightButtonLayerMenu->addSeparator(); 1170 m_rightButtonLayerMenu->addSeparator();
1142 menu->addSeparator(); 1171 menu->addSeparator();
1143 1172
1144 QAction *raction = new QAction(tr("&Rename Layer..."), this); 1173 QAction *raction = new QAction(tr("&Rename Layer..."), this);
1145 raction->setShortcut(tr("R")); 1174 raction->setShortcut(tr("R"));
1172 m_transformsMenu = menuBar()->addMenu(tr("&Transform")); 1201 m_transformsMenu = menuBar()->addMenu(tr("&Transform"));
1173 m_transformsMenu->setTearOffEnabled(true); 1202 m_transformsMenu->setTearOffEnabled(true);
1174 } 1203 }
1175 1204
1176 TransformList transforms = 1205 TransformList transforms =
1177 TransformFactory::getInstance()->getAllTransforms(); 1206 TransformFactory::getInstance()->getAllTransformDescriptions();
1178 1207
1179 vector<QString> types = 1208 vector<QString> types =
1180 TransformFactory::getInstance()->getAllTransformTypes(); 1209 TransformFactory::getInstance()->getAllTransformTypes();
1181 1210
1182 map<QString, map<QString, SubdividingMenu *> > categoryMenus; 1211 map<QString, map<QString, SubdividingMenu *> > categoryMenus;
1278 byMakerMenu->addMenu(makerMenus[*i][maker]); 1307 byMakerMenu->addMenu(makerMenus[*i][maker]);
1279 pendingMenus.insert(makerMenus[*i][maker]); 1308 pendingMenus.insert(makerMenus[*i][maker]);
1280 } 1309 }
1281 } 1310 }
1282 1311
1312 // Names should only be duplicated here if they have the same
1313 // plugin name, output name and maker but are in different library
1314 // .so names -- that won't happen often I hope
1315 std::map<QString, QString> idNameSonameMap;
1316 std::set<QString> seenNames, duplicateNames;
1317 for (unsigned int i = 0; i < transforms.size(); ++i) {
1318 QString name = transforms[i].name;
1319 if (seenNames.find(name) != seenNames.end()) {
1320 duplicateNames.insert(name);
1321 } else {
1322 seenNames.insert(name);
1323 }
1324 }
1325
1283 for (unsigned int i = 0; i < transforms.size(); ++i) { 1326 for (unsigned int i = 0; i < transforms.size(); ++i) {
1284 1327
1285 QString name = transforms[i].name; 1328 QString name = transforms[i].name;
1286 if (name == "") name = transforms[i].identifier; 1329 if (name == "") name = transforms[i].identifier;
1287 1330
1296 if (maker == "") maker = tr("Unknown"); 1339 if (maker == "") maker = tr("Unknown");
1297 maker.replace(QRegExp(tr(" [\\(<].*$")), ""); 1340 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
1298 1341
1299 QString pluginName = name.section(": ", 0, 0); 1342 QString pluginName = name.section(": ", 0, 0);
1300 QString output = name.section(": ", 1); 1343 QString output = name.section(": ", 1);
1344
1345 if (duplicateNames.find(pluginName) != duplicateNames.end()) {
1346 pluginName = QString("%1 <%2>")
1347 .arg(pluginName)
1348 .arg(transforms[i].identifier.section(':', 1, 1));
1349 if (output == "") name = pluginName;
1350 else name = QString("%1: %2")
1351 .arg(pluginName)
1352 .arg(output);
1353 }
1301 1354
1302 QAction *action = new QAction(tr("%1...").arg(name), this); 1355 QAction *action = new QAction(tr("%1...").arg(name), this);
1303 connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); 1356 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
1304 m_transformActions[action] = transforms[i].identifier; 1357 m_transformActions[action] = transforms[i].identifier;
1305 m_transformActionsReverse[transforms[i].identifier] = action; 1358 m_transformActionsReverse[transforms[i].identifier] = action;
1437 ti->second->setShortcut(tr("Ctrl+T")); 1490 ti->second->setShortcut(tr("Ctrl+T"));
1438 m_keyReference->registerShortcut 1491 m_keyReference->registerShortcut
1439 (tr("Repeat Transform"), 1492 (tr("Repeat Transform"),
1440 ti->second->shortcut(), 1493 ti->second->shortcut(),
1441 tr("Re-select the most recently run transform")); 1494 tr("Re-select the most recently run transform"));
1495 } else {
1496 ti->second->setShortcut(QString(""));
1442 } 1497 }
1443 m_recentTransformsMenu->addAction(ti->second); 1498 m_recentTransformsMenu->addAction(ti->second);
1444 } 1499 }
1445 } 1500 }
1446 1501
1735 connect(this, SIGNAL(canEditLayer(bool)), action, SLOT(setEnabled(bool))); 1790 connect(this, SIGNAL(canEditLayer(bool)), action, SLOT(setEnabled(bool)));
1736 group->addAction(action); 1791 group->addAction(action);
1737 m_keyReference->registerShortcut(action); 1792 m_keyReference->registerShortcut(action);
1738 m_toolActions[ViewManager::DrawMode] = action; 1793 m_toolActions[ViewManager::DrawMode] = action;
1739 1794
1795 action = toolbar->addAction(il.load("erase"),
1796 tr("Erase"));
1797 action->setCheckable(true);
1798 action->setShortcut(tr("5"));
1799 action->setStatusTip(tr("Erase items from layer"));
1800 connect(action, SIGNAL(triggered()), this, SLOT(toolEraseSelected()));
1801 connect(this, SIGNAL(canEditLayer(bool)), action, SLOT(setEnabled(bool)));
1802 group->addAction(action);
1803 m_keyReference->registerShortcut(action);
1804 m_toolActions[ViewManager::EraseMode] = action;
1805
1740 action = toolbar->addAction(il.load("measure"), 1806 action = toolbar->addAction(il.load("measure"),
1741 tr("Measure")); 1807 tr("Measure"));
1742 action->setCheckable(true); 1808 action->setCheckable(true);
1743 action->setShortcut(tr("5")); 1809 action->setShortcut(tr("6"));
1744 action->setStatusTip(tr("Make measurements in layer")); 1810 action->setStatusTip(tr("Make measurements in layer"));
1745 connect(action, SIGNAL(triggered()), this, SLOT(toolMeasureSelected())); 1811 connect(action, SIGNAL(triggered()), this, SLOT(toolMeasureSelected()));
1746 connect(this, SIGNAL(canMeasureLayer(bool)), action, SLOT(setEnabled(bool))); 1812 connect(this, SIGNAL(canMeasureLayer(bool)), action, SLOT(setEnabled(bool)));
1747 group->addAction(action); 1813 group->addAction(action);
1748 m_keyReference->registerShortcut(action); 1814 m_keyReference->registerShortcut(action);
1749 m_toolActions[ViewManager::MeasureMode] = action; 1815 m_toolActions[ViewManager::MeasureMode] = action;
1750
1751 // action = toolbar->addAction(il.load("text"),
1752 // tr("Text"));
1753 // action->setCheckable(true);
1754 // action->setShortcut(tr("5"));
1755 // connect(action, SIGNAL(triggered()), this, SLOT(toolTextSelected()));
1756 // group->addAction(action);
1757 // m_toolActions[ViewManager::TextMode] = action;
1758 1816
1759 toolNavigateSelected(); 1817 toolNavigateSelected();
1760 1818
1761 Pane::registerShortcuts(*m_keyReference); 1819 Pane::registerShortcuts(*m_keyReference);
1762 } 1820 }
1896 { 1954 {
1897 m_viewManager->setToolMode(ViewManager::DrawMode); 1955 m_viewManager->setToolMode(ViewManager::DrawMode);
1898 } 1956 }
1899 1957
1900 void 1958 void
1959 MainWindow::toolEraseSelected()
1960 {
1961 m_viewManager->setToolMode(ViewManager::EraseMode);
1962 }
1963
1964 void
1901 MainWindow::toolMeasureSelected() 1965 MainWindow::toolMeasureSelected()
1902 { 1966 {
1903 m_viewManager->setToolMode(ViewManager::MeasureMode); 1967 m_viewManager->setToolMode(ViewManager::MeasureMode);
1904 } 1968 }
1905
1906 //void
1907 //MainWindow::toolTextSelected()
1908 //{
1909 // m_viewManager->setToolMode(ViewManager::TextMode);
1910 //}
1911 1969
1912 void 1970 void
1913 MainWindow::importAudio() 1971 MainWindow::importAudio()
1914 { 1972 {
1915 QString path = getOpenFileName(FileFinder::AudioFile); 1973 QString path = getOpenFileName(FileFinder::AudioFile);
2504 2562
2505 if (m_preferencesDialog && 2563 if (m_preferencesDialog &&
2506 m_preferencesDialog->isVisible()) { 2564 m_preferencesDialog->isVisible()) {
2507 closeSession(); // otherwise we'll have to wait for prefs changes 2565 closeSession(); // otherwise we'll have to wait for prefs changes
2508 m_preferencesDialog->applicationClosing(false); 2566 m_preferencesDialog->applicationClosing(false);
2509 }
2510
2511 if (m_layerTreeView &&
2512 m_layerTreeView->isVisible()) {
2513 delete m_layerTreeView;
2514 } 2567 }
2515 2568
2516 closeSession(); 2569 closeSession();
2517 2570
2518 e->accept(); 2571 e->accept();
2657 } 2710 }
2658 } 2711 }
2659 } 2712 }
2660 2713
2661 void 2714 void
2715 MainWindow::propertyStacksResized(int width)
2716 {
2717 std::cerr << "MainWindow::propertyStacksResized(" << width << ")" << std::endl;
2718
2719 if (!m_playControlsSpacer) return;
2720
2721 int spacerWidth = width - m_playControlsWidth - 4;
2722
2723 std::cerr << "resizing spacer from " << m_playControlsSpacer->width() << " to " << spacerWidth << std::endl;
2724
2725 m_playControlsSpacer->setFixedSize(QSize(spacerWidth, 2));
2726 }
2727
2728 void
2662 MainWindow::addPane() 2729 MainWindow::addPane()
2663 { 2730 {
2664 QObject *s = sender(); 2731 QObject *s = sender();
2665 QAction *action = dynamic_cast<QAction *>(s); 2732 QAction *action = dynamic_cast<QAction *>(s);
2666 2733
2680 2747
2681 addPane(i->second, action->text()); 2748 addPane(i->second, action->text());
2682 } 2749 }
2683 2750
2684 void 2751 void
2685 MainWindow::addPane(const PaneConfiguration &configuration, QString text) 2752 MainWindow::addPane(const LayerConfiguration &configuration, QString text)
2686 { 2753 {
2687 CommandHistory::getInstance()->startCompoundOperation(text, true); 2754 CommandHistory::getInstance()->startCompoundOperation(text, true);
2688 2755
2689 AddPaneCommand *command = new AddPaneCommand(this); 2756 AddPaneCommand *command = new AddPaneCommand(this);
2690 CommandHistory::getInstance()->addCommand(command); 2757 CommandHistory::getInstance()->addCommand(command);
2717 Model *model = 0; 2784 Model *model = 0;
2718 2785
2719 if (suggestedModel) { 2786 if (suggestedModel) {
2720 2787
2721 // check its validity 2788 // check its validity
2722 std::vector<Model *> inputModels = m_document->getTransformerInputModels(); 2789 std::vector<Model *> inputModels = m_document->getTransformInputModels();
2723 for (size_t j = 0; j < inputModels.size(); ++j) { 2790 for (size_t j = 0; j < inputModels.size(); ++j) {
2724 if (inputModels[j] == suggestedModel) { 2791 if (inputModels[j] == suggestedModel) {
2725 model = suggestedModel; 2792 model = suggestedModel;
2726 break; 2793 break;
2727 } 2794 }
2811 std::cerr << "WARNING: MainWindow::addLayer: unknown action " 2878 std::cerr << "WARNING: MainWindow::addLayer: unknown action "
2812 << action->objectName().toStdString() << std::endl; 2879 << action->objectName().toStdString() << std::endl;
2813 return; 2880 return;
2814 } 2881 }
2815 2882
2816 LayerFactory::LayerType type = i->second; 2883 LayerFactory::LayerType type = i->second.layer;
2817 2884
2818 LayerFactory::LayerTypeSet emptyTypes = 2885 LayerFactory::LayerTypeSet emptyTypes =
2819 LayerFactory::getInstance()->getValidEmptyLayerTypes(); 2886 LayerFactory::getInstance()->getValidEmptyLayerTypes();
2820 2887
2821 Layer *newLayer; 2888 Layer *newLayer;
2822 2889
2823 if (emptyTypes.find(type) != emptyTypes.end()) { 2890 if (emptyTypes.find(type) != emptyTypes.end()) {
2824 2891
2825 newLayer = m_document->createEmptyLayer(type); 2892 newLayer = m_document->createEmptyLayer(type);
2826 m_toolActions[ViewManager::DrawMode]->trigger(); 2893 if (newLayer) {
2894 m_toolActions[ViewManager::DrawMode]->trigger();
2895 }
2827 2896
2828 } else { 2897 } else {
2829 2898
2830 newLayer = m_document->createMainModelLayer(type); 2899 if (!i->second.sourceModel) {
2831 } 2900 // e.g. time ruler
2832 2901 newLayer = m_document->createMainModelLayer(type);
2833 m_document->addLayerToView(pane, newLayer); 2902 } else {
2834 m_paneStack->setCurrentLayer(pane, newLayer); 2903 newLayer = m_document->createLayer(type);
2904 if (m_document->isKnownModel(i->second.sourceModel)) {
2905 m_document->setChannel(newLayer, i->second.channel);
2906 m_document->setModel(newLayer, i->second.sourceModel);
2907 } else {
2908 std::cerr << "WARNING: MainWindow::addLayer: unknown model "
2909 << i->second.sourceModel
2910 << " (\""
2911 << (i->second.sourceModel ? i->second.sourceModel->objectName().toStdString() : "")
2912 << "\") in layer action map"
2913 << std::endl;
2914 }
2915 }
2916 }
2917
2918 if (newLayer) {
2919 m_document->addLayerToView(pane, newLayer);
2920 m_paneStack->setCurrentLayer(pane, newLayer);
2921 }
2835 2922
2836 return; 2923 return;
2837 } 2924 }
2838 2925
2839 TransformId transform = i->second; 2926 //!!! want to do something like this, but it's not supported in
2840 ModelTransformerFactory *factory = ModelTransformerFactory::getInstance(); 2927 //ModelTransformerFactory yet
2841 2928 /*
2842 QString configurationXml;
2843
2844 int channel = -1; 2929 int channel = -1;
2845 // pick up the default channel from any existing layers on the same pane 2930 // pick up the default channel from any existing layers on the same pane
2846 for (int j = 0; j < pane->getLayerCount(); ++j) { 2931 for (int j = 0; j < pane->getLayerCount(); ++j) {
2847 int c = LayerFactory::getInstance()->getChannel(pane->getLayer(j)); 2932 int c = LayerFactory::getInstance()->getChannel(pane->getLayer(j));
2848 if (c != -1) { 2933 if (c != -1) {
2849 channel = c; 2934 channel = c;
2850 break; 2935 break;
2851 } 2936 }
2852 } 2937 }
2938 */
2853 2939
2854 // We always ask for configuration, even if the plugin isn't 2940 // We always ask for configuration, even if the plugin isn't
2855 // supposed to be configurable, because we need to let the user 2941 // supposed to be configurable, because we need to let the user
2856 // change the execution context (block size etc). 2942 // change the execution context (block size etc).
2857 2943
2858 PluginTransformer::ExecutionContext context(channel); 2944 QString transformId = i->second;
2945 Transform transform = TransformFactory::getInstance()->
2946 getDefaultTransformFor(transformId);
2859 2947
2860 std::vector<Model *> candidateInputModels = 2948 std::vector<Model *> candidateInputModels =
2861 m_document->getTransformerInputModels(); 2949 m_document->getTransformInputModels();
2862 2950
2951 Model *defaultInputModel = 0;
2952 for (int j = 0; j < pane->getLayerCount(); ++j) {
2953 Layer *layer = pane->getLayer(j);
2954 if (!layer) continue;
2955 if (LayerFactory::getInstance()->getLayerType(layer) !=
2956 LayerFactory::Waveform &&
2957 !layer->isLayerOpaque()) continue;
2958 Model *model = layer->getModel();
2959 if (!model) continue;
2960 for (size_t k = 0; k < candidateInputModels.size(); ++k) {
2961 if (candidateInputModels[k] == model) {
2962 defaultInputModel = model;
2963 break;
2964 }
2965 }
2966 if (defaultInputModel) break;
2967 }
2968
2863 size_t startFrame = 0, duration = 0; 2969 size_t startFrame = 0, duration = 0;
2864 size_t endFrame = 0; 2970 size_t endFrame = 0;
2865 m_viewManager->getSelection().getExtents(startFrame, endFrame); 2971 m_viewManager->getSelection().getExtents(startFrame, endFrame);
2866 if (endFrame > startFrame) duration = endFrame - startFrame; 2972 if (endFrame > startFrame) duration = endFrame - startFrame;
2867 else startFrame = 0; 2973 else startFrame = 0;
2868 2974
2869 Model *inputModel = factory->getConfigurationForTransformer 2975 ModelTransformer::Input input = ModelTransformerFactory::getInstance()->
2976 getConfigurationForTransform
2870 (transform, 2977 (transform,
2871 candidateInputModels, 2978 candidateInputModels,
2872 context, 2979 defaultInputModel,
2873 configurationXml,
2874 m_playSource, 2980 m_playSource,
2875 startFrame, 2981 startFrame,
2876 duration); 2982 duration);
2877 2983
2878 if (!inputModel) return; 2984 if (!input.getModel()) return;
2879 2985
2880 // std::cerr << "MainWindow::addLayer: Input model is " << inputModel << " \"" << inputModel->objectName().toStdString() << "\"" << std::endl; 2986 // std::cerr << "MainWindow::addLayer: Input model is " << input.getModel() << " \"" << input.getModel()->objectName().toStdString() << "\"" << std::endl;
2881 2987
2882 Layer *newLayer = m_document->createDerivedLayer(transform, 2988 Layer *newLayer = m_document->createDerivedLayer(transform, input);
2883 inputModel,
2884 context,
2885 configurationXml);
2886 2989
2887 if (newLayer) { 2990 if (newLayer) {
2888 m_document->addLayerToView(pane, newLayer); 2991 m_document->addLayerToView(pane, newLayer);
2889 m_document->setChannel(newLayer, context.channel); 2992 m_document->setChannel(newLayer, input.getChannel());
2890 m_recentTransforms.add(transform); 2993 m_recentTransforms.add(transformId);
2891 m_paneStack->setCurrentLayer(pane, newLayer); 2994 m_paneStack->setCurrentLayer(pane, newLayer);
2892 } 2995 }
2893 2996
2894 updateMenuStates(); 2997 updateMenuStates();
2895 } 2998 }
2905 QString newName = QInputDialog::getText 3008 QString newName = QInputDialog::getText
2906 (this, tr("Rename Layer"), 3009 (this, tr("Rename Layer"),
2907 tr("New name for this layer:"), 3010 tr("New name for this layer:"),
2908 QLineEdit::Normal, layer->objectName(), &ok); 3011 QLineEdit::Normal, layer->objectName(), &ok);
2909 if (ok) { 3012 if (ok) {
2910 layer->setObjectName(newName); 3013 layer->setPresentationName(newName);
2911 setupExistingLayersMenus(); 3014 setupExistingLayersMenus();
2912 } 3015 }
2913 } 3016 }
2914 } 3017 }
2915 } 3018 }
2984 contextHelpChanged(tr("Playback speed: %1%2%") 3087 contextHelpChanged(tr("Playback speed: %1%2%")
2985 .arg(position > 100 ? "+" : "") 3088 .arg(position > 100 ? "+" : "")
2986 .arg(pc)); 3089 .arg(pc));
2987 } 3090 }
2988 3091
2989 m_playSharpen->setEnabled(something); 3092 m_playSource->setTimeStretch(factor);
2990 m_playMono->setEnabled(something);
2991 bool sharpen = (something && m_playSharpen->isChecked());
2992 bool mono = (something && m_playMono->isChecked());
2993 m_playSource->setTimeStretch(factor, sharpen, mono);
2994 3093
2995 updateMenuStates(); 3094 updateMenuStates();
2996 } 3095 }
2997
2998 void
2999 MainWindow::playSharpenToggled()
3000 {
3001 QSettings settings;
3002 settings.beginGroup("MainWindow");
3003 settings.setValue("playsharpen", m_playSharpen->isChecked());
3004 settings.endGroup();
3005
3006 playSpeedChanged(m_playSpeed->value());
3007 }
3008
3009 void
3010 MainWindow::playMonoToggled()
3011 {
3012 QSettings settings;
3013 settings.beginGroup("MainWindow");
3014 settings.setValue("playmono", m_playMono->isChecked());
3015 settings.endGroup();
3016
3017 playSpeedChanged(m_playSpeed->value());
3018 }
3019 3096
3020 void 3097 void
3021 MainWindow::speedUpPlayback() 3098 MainWindow::speedUpPlayback()
3022 { 3099 {
3023 int value = m_playSpeed->value(); 3100 int value = m_playSpeed->value();
3037 3114
3038 void 3115 void
3039 MainWindow::restoreNormalPlayback() 3116 MainWindow::restoreNormalPlayback()
3040 { 3117 {
3041 m_playSpeed->setValue(m_playSpeed->defaultValue()); 3118 m_playSpeed->setValue(m_playSpeed->defaultValue());
3119 }
3120
3121 void
3122 MainWindow::currentPaneChanged(Pane *pane)
3123 {
3124 MainWindowBase::currentPaneChanged(pane);
3125
3126 if (!pane || !m_panLayer) return;
3127 for (int i = pane->getLayerCount(); i > 0; ) {
3128 --i;
3129 Layer *layer = pane->getLayer(i);
3130 if (LayerFactory::getInstance()->getLayerType(layer) ==
3131 LayerFactory::Waveform) {
3132 RangeSummarisableTimeValueModel *tvm =
3133 dynamic_cast<RangeSummarisableTimeValueModel *>(layer->getModel());
3134 if (tvm) {
3135 m_panLayer->setModel(tvm);
3136 return;
3137 }
3138 }
3139 }
3042 } 3140 }
3043 3141
3044 void 3142 void
3045 MainWindow::updateVisibleRangeDisplay(Pane *p) const 3143 MainWindow::updateVisibleRangeDisplay(Pane *p) const
3046 { 3144 {
3192 3290
3193 void 3291 void
3194 MainWindow::resetInstantsCounters() 3292 MainWindow::resetInstantsCounters()
3195 { 3293 {
3196 LabelCounterInputDialog dialog(m_labeller, this); 3294 LabelCounterInputDialog dialog(m_labeller, this);
3295 dialog.setWindowTitle(tr("Reset Counters"));
3197 dialog.exec(); 3296 dialog.exec();
3198 } 3297 }
3199 3298
3200 void 3299 void
3201 MainWindow::modelGenerationFailed(QString transformName) 3300 MainWindow::modelGenerationFailed(QString transformName, QString message)
3301 {
3302 if (message != "") {
3303
3304 QMessageBox::warning
3305 (this,
3306 tr("Failed to generate layer"),
3307 tr("<b>Layer generation failed</b><p>Failed to generate derived layer.<p>The layer transform \"%1\" failed:<p>%2")
3308 .arg(transformName).arg(message),
3309 QMessageBox::Ok);
3310 } else {
3311 QMessageBox::warning
3312 (this,
3313 tr("Failed to generate layer"),
3314 tr("<b>Layer generation failed</b><p>Failed to generate a derived layer.<p>The layer transform \"%1\" failed.<p>No error information is available.")
3315 .arg(transformName),
3316 QMessageBox::Ok);
3317 }
3318 }
3319
3320 void
3321 MainWindow::modelGenerationWarning(QString transformName, QString message)
3322 {
3323 QMessageBox::warning
3324 (this, tr("Warning"), message, QMessageBox::Ok);
3325 }
3326
3327 void
3328 MainWindow::modelRegenerationFailed(QString layerName,
3329 QString transformName, QString message)
3330 {
3331 if (message != "") {
3332
3333 QMessageBox::warning
3334 (this,
3335 tr("Failed to regenerate layer"),
3336 tr("<b>Layer generation failed</b><p>Failed to regenerate derived layer \"%1\" using new data model as input.<p>The layer transform \"%2\" failed:<p>%3")
3337 .arg(layerName).arg(transformName).arg(message),
3338 QMessageBox::Ok);
3339 } else {
3340 QMessageBox::warning
3341 (this,
3342 tr("Failed to regenerate layer"),
3343 tr("<b>Layer generation failed</b><p>Failed to regenerate derived layer \"%1\" using new data model as input.<p>The layer transform \"%2\" failed.<p>No error information is available.")
3344 .arg(layerName).arg(transformName),
3345 QMessageBox::Ok);
3346 }
3347 }
3348
3349 void
3350 MainWindow::modelRegenerationWarning(QString layerName,
3351 QString transformName, QString message)
3352 {
3353 QMessageBox::warning
3354 (this, tr("Warning"), tr("<b>Warning when regenerating layer</b><p>When regenerating the derived layer \"%1\" using new data model as input:<p>%2").arg(layerName).arg(message), QMessageBox::Ok);
3355 }
3356
3357 void
3358 MainWindow::alignmentFailed(QString transformName, QString message)
3202 { 3359 {
3203 QMessageBox::warning 3360 QMessageBox::warning
3204 (this, 3361 (this,
3205 tr("Failed to generate layer"), 3362 tr("Failed to calculate alignment"),
3206 tr("<b>Layer generation failed</b><p>Failed to generate a derived layer.<p>The layer transform \"%1\" failed.<p>This may mean that a plugin failed to initialise, perhaps because it rejected the processing block size that was requested.") 3363 tr("<b>Alignment calculation failed</b><p>Failed to calculate an audio alignment using transform \"%1\":<p>%2")
3207 .arg(transformName), 3364 .arg(transformName).arg(message),
3208 QMessageBox::Ok);
3209 }
3210
3211 void
3212 MainWindow::modelRegenerationFailed(QString layerName, QString transformName)
3213 {
3214 QMessageBox::warning
3215 (this,
3216 tr("Failed to regenerate layer"),
3217 tr("<b>Layer generation failed</b><p>Failed to regenerate derived layer \"%1\".<p>The layer transform \"%2\" failed to run.<p>This may mean that the layer used a plugin that is not currently available.")
3218 .arg(layerName).arg(transformName),
3219 QMessageBox::Ok); 3365 QMessageBox::Ok);
3220 } 3366 }
3221 3367
3222 void 3368 void
3223 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position) 3369 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position)
3228 } 3374 }
3229 3375
3230 void 3376 void
3231 MainWindow::showLayerTree() 3377 MainWindow::showLayerTree()
3232 { 3378 {
3233 if (!m_layerTreeView.isNull()) { 3379 if (!m_layerTreeDialog.isNull()) {
3234 m_layerTreeView->show(); 3380 m_layerTreeDialog->show();
3235 m_layerTreeView->raise(); 3381 m_layerTreeDialog->raise();
3236 return; 3382 return;
3237 } 3383 }
3238 3384
3239 //!!! should use an actual dialog class 3385 m_layerTreeDialog = new LayerTreeDialog(m_paneStack);
3240 3386 m_layerTreeDialog->setAttribute(Qt::WA_DeleteOnClose); // see below
3241 m_layerTreeView = new QTreeView(); 3387 m_layerTreeDialog->show();
3242 LayerTreeModel *tree = new LayerTreeModel(m_paneStack);
3243 m_layerTreeView->resize(500, 300); //!!!
3244 m_layerTreeView->setModel(tree);
3245 m_layerTreeView->expandAll();
3246 m_layerTreeView->show();
3247 }
3248
3249 void
3250 MainWindow::handleOSCMessage(const OSCMessage &message)
3251 {
3252 std::cerr << "MainWindow::handleOSCMessage: thread id = "
3253 << QThread::currentThreadId() << std::endl;
3254
3255 // This large function should really be abstracted out.
3256
3257 if (message.getMethod() == "open") {
3258
3259 if (message.getArgCount() == 1 &&
3260 message.getArg(0).canConvert(QVariant::String)) {
3261 QString path = message.getArg(0).toString();
3262 if (open(path, ReplaceMainModel) != FileOpenSucceeded) {
3263 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \""
3264 << path.toStdString() << "\"" << std::endl;
3265 }
3266 //!!! we really need to spin here and not return until the
3267 // file has been completely decoded...
3268 }
3269
3270 } else if (message.getMethod() == "openadditional") {
3271
3272 if (message.getArgCount() == 1 &&
3273 message.getArg(0).canConvert(QVariant::String)) {
3274 QString path = message.getArg(0).toString();
3275 if (open(path, CreateAdditionalModel) != FileOpenSucceeded) {
3276 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \""
3277 << path.toStdString() << "\"" << std::endl;
3278 }
3279 }
3280
3281 } else if (message.getMethod() == "recent" ||
3282 message.getMethod() == "last") {
3283
3284 int n = 0;
3285 if (message.getMethod() == "recent" &&
3286 message.getArgCount() == 1 &&
3287 message.getArg(0).canConvert(QVariant::Int)) {
3288 n = message.getArg(0).toInt() - 1;
3289 }
3290 std::vector<QString> recent = m_recentFiles.getRecent();
3291 if (n >= 0 && n < int(recent.size())) {
3292 if (open(recent[n], ReplaceMainModel) != FileOpenSucceeded) {
3293 std::cerr << "MainWindow::handleOSCMessage: File open failed for path \""
3294 << recent[n].toStdString() << "\"" << std::endl;
3295 }
3296 }
3297
3298 } else if (message.getMethod() == "save") {
3299
3300 QString path;
3301 if (message.getArgCount() == 1 &&
3302 message.getArg(0).canConvert(QVariant::String)) {
3303 path = message.getArg(0).toString();
3304 if (QFileInfo(path).exists()) {
3305 std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in save" << std::endl;
3306 } else {
3307 saveSessionFile(path);
3308 }
3309 }
3310
3311 } else if (message.getMethod() == "export") {
3312
3313 QString path;
3314 if (getMainModel()) {
3315 if (message.getArgCount() == 1 &&
3316 message.getArg(0).canConvert(QVariant::String)) {
3317 path = message.getArg(0).toString();
3318 if (QFileInfo(path).exists()) {
3319 std::cerr << "MainWindow::handleOSCMessage: Refusing to overwrite existing file in export" << std::endl;
3320 } else {
3321 WavFileWriter writer(path,
3322 getMainModel()->getSampleRate(),
3323 getMainModel()->getChannelCount());
3324 MultiSelection ms = m_viewManager->getSelection();
3325 if (!ms.getSelections().empty()) {
3326 writer.writeModel(getMainModel(), &ms);
3327 } else {
3328 writer.writeModel(getMainModel());
3329 }
3330 }
3331 }
3332 }
3333
3334 } else if (message.getMethod() == "jump" ||
3335 message.getMethod() == "play") {
3336
3337 if (getMainModel()) {
3338
3339 unsigned long frame = m_viewManager->getPlaybackFrame();
3340 bool selection = false;
3341 bool play = (message.getMethod() == "play");
3342
3343 if (message.getArgCount() == 1) {
3344
3345 if (message.getArg(0).canConvert(QVariant::String) &&
3346 message.getArg(0).toString() == "selection") {
3347
3348 selection = true;
3349
3350 } else if (message.getArg(0).canConvert(QVariant::String) &&
3351 message.getArg(0).toString() == "end") {
3352
3353 frame = getMainModel()->getEndFrame();
3354
3355 } else if (message.getArg(0).canConvert(QVariant::Double)) {
3356
3357 double time = message.getArg(0).toDouble();
3358 if (time < 0.0) time = 0.0;
3359
3360 frame = lrint(time * getMainModel()->getSampleRate());
3361 }
3362 }
3363
3364 if (frame > getMainModel()->getEndFrame()) {
3365 frame = getMainModel()->getEndFrame();
3366 }
3367
3368 if (play) {
3369 m_viewManager->setPlaySelectionMode(selection);
3370 }
3371
3372 if (selection) {
3373 MultiSelection::SelectionList sl = m_viewManager->getSelections();
3374 if (!sl.empty()) {
3375 frame = sl.begin()->getStartFrame();
3376 }
3377 }
3378
3379 m_viewManager->setPlaybackFrame(frame);
3380
3381 if (play && !m_playSource->isPlaying()) {
3382 m_playSource->play(frame);
3383 }
3384 }
3385
3386 } else if (message.getMethod() == "stop") {
3387
3388 if (m_playSource->isPlaying()) m_playSource->stop();
3389
3390 } else if (message.getMethod() == "loop") {
3391
3392 if (message.getArgCount() == 1 &&
3393 message.getArg(0).canConvert(QVariant::String)) {
3394
3395 QString str = message.getArg(0).toString();
3396 if (str == "on") {
3397 m_viewManager->setPlayLoopMode(true);
3398 } else if (str == "off") {
3399 m_viewManager->setPlayLoopMode(false);
3400 }
3401 }
3402
3403 } else if (message.getMethod() == "solo") {
3404
3405 if (message.getArgCount() == 1 &&
3406 message.getArg(0).canConvert(QVariant::String)) {
3407
3408 QString str = message.getArg(0).toString();
3409 if (str == "on") {
3410 m_viewManager->setPlaySoloMode(true);
3411 } else if (str == "off") {
3412 m_viewManager->setPlaySoloMode(false);
3413 }
3414 }
3415
3416 } else if (message.getMethod() == "select" ||
3417 message.getMethod() == "addselect") {
3418
3419 if (getMainModel()) {
3420
3421 int f0 = getMainModel()->getStartFrame();
3422 int f1 = getMainModel()->getEndFrame();
3423
3424 bool done = false;
3425
3426 if (message.getArgCount() == 2 &&
3427 message.getArg(0).canConvert(QVariant::Double) &&
3428 message.getArg(1).canConvert(QVariant::Double)) {
3429
3430 double t0 = message.getArg(0).toDouble();
3431 double t1 = message.getArg(1).toDouble();
3432 if (t1 < t0) { double temp = t0; t0 = t1; t1 = temp; }
3433 if (t0 < 0.0) t0 = 0.0;
3434 if (t1 < 0.0) t1 = 0.0;
3435
3436 f0 = lrint(t0 * getMainModel()->getSampleRate());
3437 f1 = lrint(t1 * getMainModel()->getSampleRate());
3438
3439 Pane *pane = m_paneStack->getCurrentPane();
3440 Layer *layer = 0;
3441 if (pane) layer = pane->getSelectedLayer();
3442 if (layer) {
3443 size_t resolution;
3444 layer->snapToFeatureFrame(pane, f0, resolution,
3445 Layer::SnapLeft);
3446 layer->snapToFeatureFrame(pane, f1, resolution,
3447 Layer::SnapRight);
3448 }
3449
3450 } else if (message.getArgCount() == 1 &&
3451 message.getArg(0).canConvert(QVariant::String)) {
3452
3453 QString str = message.getArg(0).toString();
3454 if (str == "none") {
3455 m_viewManager->clearSelections();
3456 done = true;
3457 }
3458 }
3459
3460 if (!done) {
3461 if (message.getMethod() == "select") {
3462 m_viewManager->setSelection(Selection(f0, f1));
3463 } else {
3464 m_viewManager->addSelection(Selection(f0, f1));
3465 }
3466 }
3467 }
3468
3469 } else if (message.getMethod() == "add") {
3470
3471 if (getMainModel()) {
3472
3473 if (message.getArgCount() >= 1 &&
3474 message.getArg(0).canConvert(QVariant::String)) {
3475
3476 int channel = -1;
3477 if (message.getArgCount() == 2 &&
3478 message.getArg(0).canConvert(QVariant::Int)) {
3479 channel = message.getArg(0).toInt();
3480 if (channel < -1 ||
3481 channel > int(getMainModel()->getChannelCount())) {
3482 std::cerr << "WARNING: MainWindow::handleOSCMessage: channel "
3483 << channel << " out of range" << std::endl;
3484 channel = -1;
3485 }
3486 }
3487
3488 QString str = message.getArg(0).toString();
3489
3490 LayerFactory::LayerType type =
3491 LayerFactory::getInstance()->getLayerTypeForName(str);
3492
3493 if (type == LayerFactory::UnknownLayer) {
3494 std::cerr << "WARNING: MainWindow::handleOSCMessage: unknown layer "
3495 << "type " << str.toStdString() << std::endl;
3496 } else {
3497
3498 PaneConfiguration configuration(type,
3499 getMainModel(),
3500 channel);
3501
3502 addPane(configuration,
3503 tr("Add %1 Pane")
3504 .arg(LayerFactory::getInstance()->
3505 getLayerPresentationName(type)));
3506 }
3507 }
3508 }
3509
3510 } else if (message.getMethod() == "undo") {
3511
3512 CommandHistory::getInstance()->undo();
3513
3514 } else if (message.getMethod() == "redo") {
3515
3516 CommandHistory::getInstance()->redo();
3517
3518 } else if (message.getMethod() == "set") {
3519
3520 if (message.getArgCount() == 2 &&
3521 message.getArg(0).canConvert(QVariant::String) &&
3522 message.getArg(1).canConvert(QVariant::Double)) {
3523
3524 QString property = message.getArg(0).toString();
3525 float value = (float)message.getArg(1).toDouble();
3526
3527 if (property == "gain") {
3528 if (value < 0.0) value = 0.0;
3529 m_fader->setValue(value);
3530 if (m_playTarget) m_playTarget->setOutputGain(value);
3531 } else if (property == "speedup") {
3532 m_playSpeed->setMappedValue(value);
3533 } else if (property == "overlays") {
3534 if (value < 0.5) {
3535 m_viewManager->setOverlayMode(ViewManager::NoOverlays);
3536 } else if (value < 1.5) {
3537 m_viewManager->setOverlayMode(ViewManager::MinimalOverlays);
3538 } else if (value < 2.5) {
3539 m_viewManager->setOverlayMode(ViewManager::StandardOverlays);
3540 } else {
3541 m_viewManager->setOverlayMode(ViewManager::AllOverlays);
3542 }
3543 } else if (property == "zoomwheels") {
3544 m_viewManager->setZoomWheelsEnabled(value > 0.5);
3545 } else if (property == "propertyboxes") {
3546 bool toggle = ((value < 0.5) !=
3547 (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks));
3548 if (toggle) togglePropertyBoxes();
3549 }
3550
3551 } else {
3552 PropertyContainer *container = 0;
3553 Pane *pane = m_paneStack->getCurrentPane();
3554 if (pane &&
3555 message.getArgCount() == 3 &&
3556 message.getArg(0).canConvert(QVariant::String) &&
3557 message.getArg(1).canConvert(QVariant::String) &&
3558 message.getArg(2).canConvert(QVariant::String)) {
3559 if (message.getArg(0).toString() == "pane") {
3560 container = pane->getPropertyContainer(0);
3561 } else if (message.getArg(0).toString() == "layer") {
3562 container = pane->getSelectedLayer();
3563 }
3564 }
3565 if (container) {
3566 QString nameString = message.getArg(1).toString();
3567 QString valueString = message.getArg(2).toString();
3568 container->setPropertyWithCommand(nameString, valueString);
3569 }
3570 }
3571
3572 } else if (message.getMethod() == "setcurrent") {
3573
3574 int paneIndex = -1, layerIndex = -1;
3575 bool wantLayer = false;
3576
3577 if (message.getArgCount() >= 1 &&
3578 message.getArg(0).canConvert(QVariant::Int)) {
3579
3580 paneIndex = message.getArg(0).toInt() - 1;
3581
3582 if (message.getArgCount() >= 2 &&
3583 message.getArg(1).canConvert(QVariant::Int)) {
3584 wantLayer = true;
3585 layerIndex = message.getArg(1).toInt() - 1;
3586 }
3587 }
3588
3589 if (paneIndex >= 0 && paneIndex < m_paneStack->getPaneCount()) {
3590 Pane *pane = m_paneStack->getPane(paneIndex);
3591 m_paneStack->setCurrentPane(pane);
3592 if (layerIndex >= 0 && layerIndex < pane->getLayerCount()) {
3593 Layer *layer = pane->getLayer(layerIndex);
3594 m_paneStack->setCurrentLayer(pane, layer);
3595 } else if (wantLayer && layerIndex == -1) {
3596 m_paneStack->setCurrentLayer(pane, 0);
3597 }
3598 }
3599
3600 } else if (message.getMethod() == "delete") {
3601
3602 if (message.getArgCount() == 1 &&
3603 message.getArg(0).canConvert(QVariant::String)) {
3604
3605 QString target = message.getArg(0).toString();
3606
3607 if (target == "pane") {
3608
3609 deleteCurrentPane();
3610
3611 } else if (target == "layer") {
3612
3613 deleteCurrentLayer();
3614
3615 } else {
3616
3617 std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown delete target " << target.toStdString() << std::endl;
3618 }
3619 }
3620
3621 } else if (message.getMethod() == "zoom") {
3622
3623 if (message.getArgCount() == 1) {
3624 if (message.getArg(0).canConvert(QVariant::String) &&
3625 message.getArg(0).toString() == "in") {
3626 zoomIn();
3627 } else if (message.getArg(0).canConvert(QVariant::String) &&
3628 message.getArg(0).toString() == "out") {
3629 zoomOut();
3630 } else if (message.getArg(0).canConvert(QVariant::String) &&
3631 message.getArg(0).toString() == "default") {
3632 zoomDefault();
3633 } else if (message.getArg(0).canConvert(QVariant::Double)) {
3634 double level = message.getArg(0).toDouble();
3635 Pane *currentPane = m_paneStack->getCurrentPane();
3636 if (level < 1.0) level = 1.0;
3637 if (currentPane) currentPane->setZoomLevel(lrint(level));
3638 }
3639 }
3640
3641 } else if (message.getMethod() == "zoomvertical") {
3642
3643 Pane *pane = m_paneStack->getCurrentPane();
3644 Layer *layer = 0;
3645 if (pane && pane->getLayerCount() > 0) {
3646 layer = pane->getLayer(pane->getLayerCount() - 1);
3647 }
3648 int defaultStep = 0;
3649 int steps = 0;
3650 if (layer) {
3651 steps = layer->getVerticalZoomSteps(defaultStep);
3652 if (message.getArgCount() == 1 && steps > 0) {
3653 if (message.getArg(0).canConvert(QVariant::String) &&
3654 message.getArg(0).toString() == "in") {
3655 int step = layer->getCurrentVerticalZoomStep() + 1;
3656 if (step < steps) layer->setVerticalZoomStep(step);
3657 } else if (message.getArg(0).canConvert(QVariant::String) &&
3658 message.getArg(0).toString() == "out") {
3659 int step = layer->getCurrentVerticalZoomStep() - 1;
3660 if (step >= 0) layer->setVerticalZoomStep(step);
3661 } else if (message.getArg(0).canConvert(QVariant::String) &&
3662 message.getArg(0).toString() == "default") {
3663 layer->setVerticalZoomStep(defaultStep);
3664 }
3665 } else if (message.getArgCount() == 2) {
3666 if (message.getArg(0).canConvert(QVariant::Double) &&
3667 message.getArg(1).canConvert(QVariant::Double)) {
3668 double min = message.getArg(0).toDouble();
3669 double max = message.getArg(1).toDouble();
3670 layer->setDisplayExtents(min, max);
3671 }
3672 }
3673 }
3674
3675 } else if (message.getMethod() == "quit") {
3676
3677 m_abandoning = true;
3678 close();
3679
3680 } else if (message.getMethod() == "resize") {
3681
3682 if (message.getArgCount() == 2) {
3683
3684 int width = 0, height = 0;
3685
3686 if (message.getArg(1).canConvert(QVariant::Int)) {
3687
3688 height = message.getArg(1).toInt();
3689
3690 if (message.getArg(0).canConvert(QVariant::String) &&
3691 message.getArg(0).toString() == "pane") {
3692
3693 Pane *pane = m_paneStack->getCurrentPane();
3694 if (pane) pane->resize(pane->width(), height);
3695
3696 } else if (message.getArg(0).canConvert(QVariant::Int)) {
3697
3698 width = message.getArg(0).toInt();
3699 resize(width, height);
3700 }
3701 }
3702 }
3703
3704 } else if (message.getMethod() == "transform") {
3705
3706 Pane *pane = m_paneStack->getCurrentPane();
3707
3708 if (getMainModel() &&
3709 pane &&
3710 message.getArgCount() == 1 &&
3711 message.getArg(0).canConvert(QVariant::String)) {
3712
3713 TransformId transform = message.getArg(0).toString();
3714
3715 Layer *newLayer = m_document->createDerivedLayer
3716 (transform,
3717 getMainModel(),
3718 ModelTransformerFactory::getInstance()->getDefaultContextForTransformer
3719 (transform, getMainModel()),
3720 "");
3721
3722 if (newLayer) {
3723 m_document->addLayerToView(pane, newLayer);
3724 m_recentTransforms.add(transform);
3725 m_paneStack->setCurrentLayer(pane, newLayer);
3726 }
3727 }
3728
3729 } else {
3730 std::cerr << "WARNING: MainWindow::handleOSCMessage: Unknown or unsupported "
3731 << "method \"" << message.getMethod().toStdString()
3732 << "\"" << std::endl;
3733 }
3734
3735 } 3388 }
3736 3389
3737 void 3390 void
3738 MainWindow::preferences() 3391 MainWindow::preferences()
3739 { 3392 {
3764 3417
3765 if (w == m_fader) { 3418 if (w == m_fader) {
3766 contextHelpChanged(tr("Adjust the master playback level")); 3419 contextHelpChanged(tr("Adjust the master playback level"));
3767 } else if (w == m_playSpeed) { 3420 } else if (w == m_playSpeed) {
3768 contextHelpChanged(tr("Adjust the master playback speed")); 3421 contextHelpChanged(tr("Adjust the master playback speed"));
3769 } else if (w == m_playSharpen && w->isEnabled()) {
3770 contextHelpChanged(tr("Toggle transient sharpening for playback time scaling"));
3771 } else if (w == m_playMono && w->isEnabled()) {
3772 contextHelpChanged(tr("Toggle mono mode for playback time scaling"));
3773 } 3422 }
3774 } 3423 }
3775 3424
3776 void 3425 void
3777 MainWindow::mouseLeftWidget() 3426 MainWindow::mouseLeftWidget()
3786 } 3435 }
3787 3436
3788 void 3437 void
3789 MainWindow::help() 3438 MainWindow::help()
3790 { 3439 {
3791 openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/1.0/en/")); 3440 openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/1.2/en/"));
3792 } 3441 }
3793 3442
3794 void 3443 void
3795 MainWindow::about() 3444 MainWindow::about()
3796 { 3445 {
3813 #endif 3462 #endif
3814 3463
3815 QString aboutText; 3464 QString aboutText;
3816 3465
3817 aboutText += tr("<h3>About Sonic Visualiser</h3>"); 3466 aboutText += tr("<h3>About Sonic Visualiser</h3>");
3818 aboutText += tr("<p>Sonic Visualiser is a program for viewing and exploring audio data for<br>semantic music analysis and annotation.</p>"); 3467 aboutText += tr("<p>Sonic Visualiser is a program for viewing and exploring audio data for semantic music analysis and annotation.</p>");
3819 aboutText += tr("<p>%1 : %2 configuration</p>") 3468 aboutText += tr("<p>%1 : %2 configuration</p>")
3820 .arg(version) 3469 .arg(version)
3821 .arg(debug ? tr("Debug") : tr("Release")); 3470 .arg(debug ? tr("Debug") : tr("Release"));
3822 3471
3823 #ifndef BUILD_STATIC 3472 #ifndef BUILD_STATIC
3895 #endif 3544 #endif
3896 aboutText += "</p>"; 3545 aboutText += "</p>";
3897 #endif 3546 #endif
3898 3547
3899 aboutText += 3548 aboutText +=
3900 "<p>Sonic Visualiser Copyright &copy; 2005 - 2007 Chris Cannam and<br>" 3549 "<p>Sonic Visualiser Copyright &copy; 2005 - 2008 Chris Cannam and "
3901 "Queen Mary, University of London.</p>" 3550 "Queen Mary, University of London.</p>"
3902 "<p>This program is free software; you can redistribute it and/or<br>" 3551 "<p>This program is free software; you can redistribute it and/or "
3903 "modify it under the terms of the GNU General Public License as<br>" 3552 "modify it under the terms of the GNU General Public License as "
3904 "published by the Free Software Foundation; either version 2 of the<br>" 3553 "published by the Free Software Foundation; either version 2 of the "
3905 "License, or (at your option) any later version.<br>See the file " 3554 "License, or (at your option) any later version.<br>See the file "
3906 "COPYING included with this distribution for more information.</p>"; 3555 "COPYING included with this distribution for more information.</p>";
3907 3556
3908 QMessageBox::about(this, tr("About Sonic Visualiser"), aboutText); 3557 QMessageBox::about(this, tr("About Sonic Visualiser"), aboutText);
3909 } 3558 }