Mercurial > hg > sonic-visualiser
comparison main/MainWindow.cpp @ 2306:a1c14880404b
Merge from branch by-id
author | Chris Cannam |
---|---|
date | Wed, 17 Jul 2019 14:28:24 +0100 |
parents | a54082a29106 1bf8b93dc006 |
children | 186a452dddd3 |
comparison
equal
deleted
inserted
replaced
2296:a54082a29106 | 2306:a1c14880404b |
---|---|
74 #include "data/midi/MIDIInput.h" | 74 #include "data/midi/MIDIInput.h" |
75 #include "base/RecentFiles.h" | 75 #include "base/RecentFiles.h" |
76 #include "plugin/PluginScan.h" | 76 #include "plugin/PluginScan.h" |
77 #include "transform/TransformFactory.h" | 77 #include "transform/TransformFactory.h" |
78 #include "transform/ModelTransformerFactory.h" | 78 #include "transform/ModelTransformerFactory.h" |
79 #include "base/PlayParameterRepository.h" | |
80 #include "base/XmlExportable.h" | 79 #include "base/XmlExportable.h" |
81 #include "widgets/CommandHistory.h" | 80 #include "widgets/CommandHistory.h" |
82 #include "base/Profiler.h" | 81 #include "base/Profiler.h" |
83 #include "base/Clipboard.h" | 82 #include "base/Clipboard.h" |
84 #include "base/UnitDatabase.h" | 83 #include "base/UnitDatabase.h" |
1292 LayerFactory::Spectrum | 1291 LayerFactory::Spectrum |
1293 }; | 1292 }; |
1294 int backgroundTypeCount = int(sizeof(backgroundTypes) / | 1293 int backgroundTypeCount = int(sizeof(backgroundTypes) / |
1295 sizeof(backgroundTypes[0])); | 1294 sizeof(backgroundTypes[0])); |
1296 | 1295 |
1297 std::vector<Model *> models; | 1296 std::vector<ModelId> models; |
1298 if (m_document) models = m_document->getTransformInputModels(); | 1297 if (m_document) models = m_document->getTransformInputModels(); |
1299 bool plural = (models.size() > 1); | 1298 bool plural = (models.size() > 1); |
1300 if (models.empty()) { | 1299 if (models.empty()) { |
1301 models.push_back(getMainModel()); // probably 0 | 1300 models.push_back(getMainModelId()); // probably None at this point |
1302 } | 1301 } |
1303 | 1302 |
1304 for (int i = 0; i < backgroundTypeCount; ++i) { | 1303 for (int i = 0; i < backgroundTypeCount; ++i) { |
1305 | 1304 |
1306 const int paneMenuType = 0, layerMenuType = 1; | 1305 const int paneMenuType = 0, layerMenuType = 1; |
1380 break; | 1379 break; |
1381 | 1380 |
1382 default: break; | 1381 default: break; |
1383 } | 1382 } |
1384 | 1383 |
1385 std::vector<Model *> candidateModels = models; | 1384 std::vector<ModelId> candidateModels = models; |
1385 if (candidateModels.empty()) { | |
1386 throw std::logic_error("candidateModels should not be empty"); | |
1387 } | |
1386 | 1388 |
1387 for (std::vector<Model *>::iterator mi = | 1389 for (auto modelId: candidateModels) { |
1388 candidateModels.begin(); | 1390 |
1389 mi != candidateModels.end(); ++mi) { | 1391 auto model = ModelById::get(modelId); |
1390 | 1392 |
1391 Model *model = *mi; | |
1392 | |
1393 int channels = 0; | 1393 int channels = 0; |
1394 if (model) { | 1394 if (model) { |
1395 DenseTimeValueModel *dtvm = | 1395 if (auto dtvm = ModelById::getAs<DenseTimeValueModel> |
1396 dynamic_cast<DenseTimeValueModel *>(model); | 1396 (modelId)) { |
1397 if (dtvm) channels = dtvm->getChannelCount(); | 1397 channels = dtvm->getChannelCount(); |
1398 } | |
1398 } | 1399 } |
1399 if (channels < 1 && getMainModel()) { | 1400 if (channels < 1 && getMainModel()) { |
1400 channels = getMainModel()->getChannelCount(); | 1401 channels = getMainModel()->getChannelCount(); |
1401 } | 1402 } |
1402 if (channels < 1) channels = 1; | 1403 if (channels < 1) channels = 1; |
1417 connect(action, SIGNAL(triggered()), | 1418 connect(action, SIGNAL(triggered()), |
1418 this, SLOT(addPane())); | 1419 this, SLOT(addPane())); |
1419 connect(this, SIGNAL(canAddPane(bool)), | 1420 connect(this, SIGNAL(canAddPane(bool)), |
1420 action, SLOT(setEnabled(bool))); | 1421 action, SLOT(setEnabled(bool))); |
1421 m_paneActions.push_back | 1422 m_paneActions.push_back |
1422 ({ action, LayerConfiguration(type, model) }); | 1423 ({ action, LayerConfiguration(type, modelId) }); |
1423 } else { | 1424 } else { |
1424 connect(action, SIGNAL(triggered()), | 1425 connect(action, SIGNAL(triggered()), |
1425 this, SLOT(addLayer())); | 1426 this, SLOT(addLayer())); |
1426 connect(this, SIGNAL(canAddLayer(bool)), | 1427 connect(this, SIGNAL(canAddLayer(bool)), |
1427 action, SLOT(setEnabled(bool))); | 1428 action, SLOT(setEnabled(bool))); |
1428 m_layerActions.push_back | 1429 m_layerActions.push_back |
1429 ({ action, LayerConfiguration(type, model) }); | 1430 ({ action, LayerConfiguration(type, modelId) }); |
1430 } | 1431 } |
1431 if (shortcutText != "") { | 1432 if (shortcutText != "") { |
1432 m_keyReference->registerShortcut(action); | 1433 m_keyReference->registerShortcut(action); |
1433 } | 1434 } |
1434 menu->addAction(action); | 1435 menu->addAction(action); |
1459 .arg(actionText); | 1460 .arg(actionText); |
1460 } | 1461 } |
1461 | 1462 |
1462 if (isDefault) { | 1463 if (isDefault) { |
1463 action = new QAction(icon, actionText, this); | 1464 action = new QAction(icon, actionText, this); |
1464 if (!model || model == getMainModel()) { | 1465 if (!model || modelId == getMainModelId()) { |
1465 // Default for the shortcut is to | 1466 // Default for the shortcut is to |
1466 // attach to an action that uses the | 1467 // attach to an action that uses the |
1467 // main model as input. But this may | 1468 // main model as input. But this may |
1468 // change when the user selects a | 1469 // change when the user selects a |
1469 // different pane - see | 1470 // different pane - see |
1480 connect(action, SIGNAL(triggered()), | 1481 connect(action, SIGNAL(triggered()), |
1481 this, SLOT(addPane())); | 1482 this, SLOT(addPane())); |
1482 connect(this, SIGNAL(canAddPane(bool)), | 1483 connect(this, SIGNAL(canAddPane(bool)), |
1483 action, SLOT(setEnabled(bool))); | 1484 action, SLOT(setEnabled(bool))); |
1484 m_paneActions.push_back | 1485 m_paneActions.push_back |
1485 ({ action, LayerConfiguration(type, model, c - 1) }); | 1486 ({ action, LayerConfiguration(type, modelId, c - 1) }); |
1486 } else { | 1487 } else { |
1487 connect(action, SIGNAL(triggered()), | 1488 connect(action, SIGNAL(triggered()), |
1488 this, SLOT(addLayer())); | 1489 this, SLOT(addLayer())); |
1489 connect(this, SIGNAL(canAddLayer(bool)), | 1490 connect(this, SIGNAL(canAddLayer(bool)), |
1490 action, SLOT(setEnabled(bool))); | 1491 action, SLOT(setEnabled(bool))); |
1491 m_layerActions.push_back | 1492 m_layerActions.push_back |
1492 ({ action, LayerConfiguration(type, model, c - 1) }); | 1493 ({ action, LayerConfiguration(type, modelId, c - 1) }); |
1493 } | 1494 } |
1494 | 1495 |
1495 submenu->addAction(action); | 1496 submenu->addAction(action); |
1496 } | 1497 } |
1497 | 1498 |
1498 if (isDefault && menuType == layerMenuType && | 1499 if (isDefault && menuType == layerMenuType && |
1499 mi == candidateModels.begin()) { | 1500 modelId == *candidateModels.begin()) { |
1500 // only add for one model, one channel, one menu on | 1501 // only add for one model, one channel, one menu on |
1501 // right button -- the action itself will discover | 1502 // right button -- the action itself will discover |
1502 // which model is the correct one (based on pane) | 1503 // which model is the correct one (based on pane) |
1503 action = new QAction(icon, mainText, this); | 1504 action = new QAction(icon, mainText, this); |
1504 action->setStatusTip(tipText); | 1505 action->setStatusTip(tipText); |
1505 connect(action, SIGNAL(triggered()), | 1506 connect(action, SIGNAL(triggered()), |
1506 this, SLOT(addLayer())); | 1507 this, SLOT(addLayer())); |
1507 connect(this, SIGNAL(canAddLayer(bool)), | 1508 connect(this, SIGNAL(canAddLayer(bool)), |
1508 action, SLOT(setEnabled(bool))); | 1509 action, SLOT(setEnabled(bool))); |
1509 m_layerActions.push_back | 1510 m_layerActions.push_back |
1510 ({ action, LayerConfiguration(type, nullptr, 0) }); | 1511 ({ action, LayerConfiguration(type, ModelId(), 0) }); |
1511 m_rightButtonLayerMenu->addAction(action); | 1512 m_rightButtonLayerMenu->addAction(action); |
1512 } | 1513 } |
1513 } | 1514 } |
1514 } | 1515 } |
1515 } | 1516 } |
1618 | 1619 |
1619 finaliseMenus(); | 1620 finaliseMenus(); |
1620 } | 1621 } |
1621 | 1622 |
1622 void | 1623 void |
1623 MainWindow::updateLayerShortcutsFor(Model *model) | 1624 MainWindow::updateLayerShortcutsFor(ModelId modelId) |
1624 { | 1625 { |
1625 // Called when e.g. the current pane has changed, to ensure the | 1626 // Called when e.g. the current pane has changed, to ensure the |
1626 // various layer shortcuts select an action whose input model is | 1627 // various layer shortcuts select an action whose input model is |
1627 // the active one in this pane | 1628 // the active one in this pane |
1628 | 1629 |
1629 set<LayerFactory::LayerType> seen; | 1630 set<LayerFactory::LayerType> seen; |
1630 | 1631 |
1631 for (auto &a : m_paneActions) { | 1632 for (auto &a : m_paneActions) { |
1632 if (!a.second.sourceModel) continue; // empty pane/layer shortcut | 1633 if (a.second.sourceModel.isNone()) { |
1634 continue; // empty pane/layer shortcut | |
1635 } | |
1633 auto type = a.second.layer; | 1636 auto type = a.second.layer; |
1634 if (a.second.sourceModel == model && seen.find(type) == seen.end()) { | 1637 if (a.second.sourceModel == modelId && seen.find(type) == seen.end()) { |
1635 a.first->setShortcut(shortcutFor(type, true)); | 1638 a.first->setShortcut(shortcutFor(type, true)); |
1636 seen.insert(type); | 1639 seen.insert(type); |
1637 } else { | 1640 } else { |
1638 a.first->setShortcut(QString()); | 1641 a.first->setShortcut(QString()); |
1639 } | 1642 } |
1640 } | 1643 } |
1641 | 1644 |
1642 seen.clear(); | 1645 seen.clear(); |
1643 | 1646 |
1644 for (auto &a : m_layerActions) { | 1647 for (auto &a : m_layerActions) { |
1645 if (!a.second.sourceModel) continue; // empty pane/layer shortcut | 1648 if (a.second.sourceModel.isNone()) { |
1649 continue; // empty pane/layer shortcut | |
1650 } | |
1646 auto type = a.second.layer; | 1651 auto type = a.second.layer; |
1647 if (a.second.sourceModel == model && seen.find(type) == seen.end()) { | 1652 if (a.second.sourceModel == modelId && seen.find(type) == seen.end()) { |
1648 a.first->setShortcut(shortcutFor(type, false)); | 1653 a.first->setShortcut(shortcutFor(type, false)); |
1649 seen.insert(type); | 1654 seen.insert(type); |
1650 } else { | 1655 } else { |
1651 a.first->setShortcut(QString()); | 1656 a.first->setShortcut(QString()); |
1652 } | 1657 } |
2688 } | 2693 } |
2689 | 2694 |
2690 void | 2695 void |
2691 MainWindow::exportAudio(bool asData) | 2696 MainWindow::exportAudio(bool asData) |
2692 { | 2697 { |
2693 if (!getMainModel()) return; | 2698 auto modelId = getMainModelId(); |
2694 | 2699 if (modelId.isNone()) return; |
2695 RangeSummarisableTimeValueModel *model = getMainModel(); | 2700 |
2696 std::set<RangeSummarisableTimeValueModel *> otherModels; | 2701 std::set<ModelId> otherModelIds; |
2697 RangeSummarisableTimeValueModel *current = model; | 2702 ModelId current = modelId; |
2703 | |
2698 if (m_paneStack) { | 2704 if (m_paneStack) { |
2699 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { | 2705 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { |
2700 Pane *pane = m_paneStack->getPane(i); | 2706 Pane *pane = m_paneStack->getPane(i); |
2701 if (!pane) continue; | 2707 if (!pane) continue; |
2702 for (int j = 0; j < pane->getLayerCount(); ++j) { | 2708 for (int j = 0; j < pane->getLayerCount(); ++j) { |
2703 Layer *layer = pane->getLayer(j); | 2709 Layer *layer = pane->getLayer(j); |
2704 if (!layer) continue; | 2710 if (!layer) continue; |
2705 cerr << "layer = " << layer->objectName() << endl; | 2711 cerr << "layer = " << layer->objectName() << endl; |
2706 Model *m = layer->getModel(); | 2712 ModelId m = layer->getModel(); |
2707 RangeSummarisableTimeValueModel *wm = | 2713 if (ModelById::isa<RangeSummarisableTimeValueModel>(m)) { |
2708 dynamic_cast<RangeSummarisableTimeValueModel *>(m); | 2714 otherModelIds.insert(m); |
2709 if (wm) { | |
2710 cerr << "found: " << wm->objectName() << endl; | |
2711 otherModels.insert(wm); | |
2712 if (pane == m_paneStack->getCurrentPane()) { | 2715 if (pane == m_paneStack->getCurrentPane()) { |
2713 current = wm; | 2716 current = m; |
2714 } | 2717 } |
2715 } | 2718 } |
2716 } | 2719 } |
2717 } | 2720 } |
2718 } | 2721 } |
2719 if (!otherModels.empty()) { | 2722 if (!otherModelIds.empty()) { |
2720 std::map<QString, RangeSummarisableTimeValueModel *> m; | 2723 std::map<QString, ModelId> m; |
2721 m[tr("1. %2").arg(model->objectName())] = model; | 2724 QString unnamed = tr("<unnamed>"); |
2725 QString oname = unnamed; | |
2726 if (auto mp = ModelById::get(modelId)) { | |
2727 oname = mp->objectName(); | |
2728 } | |
2729 m[tr("1. %2").arg(oname)] = modelId; | |
2722 int n = 2; | 2730 int n = 2; |
2723 int c = 0; | 2731 int c = 0; |
2724 for (std::set<RangeSummarisableTimeValueModel *>::const_iterator i | 2732 for (auto otherModelId: otherModelIds) { |
2725 = otherModels.begin(); | 2733 if (otherModelId == modelId) continue; |
2726 i != otherModels.end(); ++i) { | 2734 oname = unnamed; |
2727 if (*i == model) continue; | 2735 if (auto mp = ModelById::get(otherModelId)) { |
2728 m[tr("%1. %2").arg(n).arg((*i)->objectName())] = *i; | 2736 oname = mp->objectName(); |
2737 } | |
2738 m[tr("%1. %2").arg(n).arg(oname)] = otherModelId; | |
2729 ++n; | 2739 ++n; |
2730 if (*i == current) c = n-1; | 2740 if (otherModelId == current) c = n-1; |
2731 } | 2741 } |
2732 QStringList items; | 2742 QStringList items; |
2733 for (std::map<QString, RangeSummarisableTimeValueModel *> | 2743 for (auto i: m) { |
2734 ::const_iterator i = m.begin(); | 2744 items << i.first; |
2735 i != m.end(); ++i) { | |
2736 items << i->first; | |
2737 } | 2745 } |
2738 if (items.size() > 1) { | 2746 if (items.size() > 1) { |
2739 bool ok = false; | 2747 bool ok = false; |
2740 QString item = QInputDialog::getItem | 2748 QString item = QInputDialog::getItem |
2741 (this, tr("Select audio file to export"), | 2749 (this, tr("Select audio file to export"), |
2742 tr("Which audio file do you want to export from?"), | 2750 tr("Which audio file do you want to export from?"), |
2743 items, c, false, &ok); | 2751 items, c, false, &ok); |
2744 if (!ok || item.isEmpty()) return; | 2752 if (!ok || item.isEmpty()) return; |
2745 if (m.find(item) == m.end()) { | 2753 if (m.find(item) == m.end()) { |
2746 cerr << "WARNING: Model " << item | 2754 SVCERR << "WARNING: Model " << item |
2747 << " not found in list!" << endl; | 2755 << " not found in list!" << endl; |
2748 } else { | 2756 } else { |
2749 model = m[item]; | 2757 modelId = m[item]; |
2750 } | 2758 } |
2751 } | 2759 } |
2752 } | 2760 } |
2753 | 2761 |
2762 auto model = ModelById::getAs<DenseTimeValueModel>(modelId); | |
2763 if (!model) { | |
2764 SVCERR << "ERROR: Chosen model is not a DenseTimeValueModel!" << endl; | |
2765 return; | |
2766 } | |
2767 | |
2754 QString path; | 2768 QString path; |
2755 if (asData) { | 2769 if (asData) { |
2756 path = getSaveFileName(FileFinder::CSVFile); | 2770 path = getSaveFileName(FileFinder::CSVFile); |
2757 } else { | 2771 } else { |
2758 path = getSaveFileName(FileFinder::AudioFile); | 2772 path = getSaveFileName(FileFinder::AudioFile); |
2833 | 2847 |
2834 WavFileWriter subwriter(subpath, | 2848 WavFileWriter subwriter(subpath, |
2835 model->getSampleRate(), | 2849 model->getSampleRate(), |
2836 model->getChannelCount(), | 2850 model->getChannelCount(), |
2837 WavFileWriter::WriteToTemporary); | 2851 WavFileWriter::WriteToTemporary); |
2838 subwriter.writeModel(model, &subms); | 2852 subwriter.writeModel(model.get(), &subms); |
2839 ok = subwriter.isOK(); | 2853 ok = subwriter.isOK(); |
2840 | 2854 |
2841 if (!ok) { | 2855 if (!ok) { |
2842 error = subwriter.getError(); | 2856 error = subwriter.getError(); |
2843 break; | 2857 break; |
2854 true, | 2868 true, |
2855 0, | 2869 0, |
2856 this, | 2870 this, |
2857 Qt::ApplicationModal | 2871 Qt::ApplicationModal |
2858 }; | 2872 }; |
2859 CSVFileWriter writer(path, model, &dialog, | 2873 CSVFileWriter writer(path, model.get(), &dialog, |
2860 ((QFileInfo(path).suffix() == "csv") ? | 2874 ((QFileInfo(path).suffix() == "csv") ? |
2861 "," : "\t")); | 2875 "," : "\t")); |
2862 if (selectionToWrite) { | 2876 if (selectionToWrite) { |
2863 writer.writeSelection(*selectionToWrite); | 2877 writer.writeSelection(*selectionToWrite); |
2864 } else { | 2878 } else { |
2869 } else { | 2883 } else { |
2870 WavFileWriter writer(path, | 2884 WavFileWriter writer(path, |
2871 model->getSampleRate(), | 2885 model->getSampleRate(), |
2872 model->getChannelCount(), | 2886 model->getChannelCount(), |
2873 WavFileWriter::WriteToTemporary); | 2887 WavFileWriter::WriteToTemporary); |
2874 writer.writeModel(model, selectionToWrite); | 2888 writer.writeModel(model.get(), selectionToWrite); |
2875 ok = writer.isOK(); | 2889 ok = writer.isOK(); |
2876 error = writer.getError(); | 2890 error = writer.getError(); |
2877 } | 2891 } |
2878 } | 2892 } |
2879 | 2893 |
2934 delete model; | 2948 delete model; |
2935 status = FileOpenFailed; | 2949 status = FileOpenFailed; |
2936 | 2950 |
2937 } else { | 2951 } else { |
2938 | 2952 |
2953 auto modelId = ModelById::add(std::shared_ptr<Model>(model)); | |
2954 | |
2939 status = addOpenedAudioModel(path, | 2955 status = addOpenedAudioModel(path, |
2940 model, | 2956 modelId, |
2941 CreateAdditionalModel, | 2957 CreateAdditionalModel, |
2942 getDefaultSessionTemplate(), | 2958 getDefaultSessionTemplate(), |
2943 false); | 2959 false); |
2944 } | 2960 } |
2945 | 2961 |
2995 if (!pane) return; | 3011 if (!pane) return; |
2996 | 3012 |
2997 Layer *layer = pane->getSelectedLayer(); | 3013 Layer *layer = pane->getSelectedLayer(); |
2998 if (!layer) return; | 3014 if (!layer) return; |
2999 | 3015 |
3000 Model *model = layer->getModel(); | 3016 ModelId modelId = layer->getModel(); |
3001 if (!model) return; | 3017 if (modelId.isNone()) return; |
3002 | 3018 |
3003 FileFinder::FileType type = FileFinder::LayerFileNoMidi; | 3019 FileFinder::FileType type = FileFinder::LayerFileNoMidi; |
3004 if (dynamic_cast<NoteModel *>(model)) type = FileFinder::LayerFile; | 3020 if (ModelById::isa<NoteModel>(modelId)) type = FileFinder::LayerFile; |
3005 QString path = getSaveFileName(type); | 3021 QString path = getSaveFileName(type); |
3006 | 3022 |
3007 if (path == "") return; | 3023 if (path == "") return; |
3008 | 3024 |
3009 QString error; | 3025 QString error; |
3383 << endl; | 3399 << endl; |
3384 return; | 3400 return; |
3385 } | 3401 } |
3386 | 3402 |
3387 QString mainModelLocation; | 3403 QString mainModelLocation; |
3388 WaveFileModel *mm = getMainModel(); | 3404 auto mm = getMainModel(); |
3389 if (mm) mainModelLocation = mm->getLocation(); | 3405 if (mm) mainModelLocation = mm->getLocation(); |
3390 if (mainModelLocation != "") { | 3406 if (mainModelLocation != "") { |
3391 openAudio(mainModelLocation, ReplaceSession, n); | 3407 openAudio(mainModelLocation, ReplaceSession, n); |
3392 } else { | 3408 } else { |
3393 openSessionTemplate(n); | 3409 openSessionTemplate(n); |
3455 | 3471 |
3456 void | 3472 void |
3457 MainWindow::paneAdded(Pane *pane) | 3473 MainWindow::paneAdded(Pane *pane) |
3458 { | 3474 { |
3459 if (m_overview) m_overview->registerView(pane); | 3475 if (m_overview) m_overview->registerView(pane); |
3476 if (pane) { | |
3477 connect(pane, SIGNAL(cancelButtonPressed(Layer *)), | |
3478 this, SLOT(paneCancelButtonPressed(Layer *))); | |
3479 } | |
3460 } | 3480 } |
3461 | 3481 |
3462 void | 3482 void |
3463 MainWindow::paneHidden(Pane *pane) | 3483 MainWindow::paneHidden(Pane *pane) |
3464 { | 3484 { |
3468 void | 3488 void |
3469 MainWindow::paneAboutToBeDeleted(Pane *pane) | 3489 MainWindow::paneAboutToBeDeleted(Pane *pane) |
3470 { | 3490 { |
3471 if (m_overview) m_overview->unregisterView(pane); | 3491 if (m_overview) m_overview->unregisterView(pane); |
3472 } | 3492 } |
3493 | |
3494 void | |
3495 MainWindow::paneCancelButtonPressed(Layer *layer) | |
3496 { | |
3497 Pane *pane = qobject_cast<Pane *>(sender()); | |
3498 bool found = false; | |
3499 if (pane && layer) { | |
3500 for (int i = 0; i < pane->getLayerCount(); ++i) { | |
3501 if (pane->getLayer(i) == layer) { | |
3502 found = true; | |
3503 break; | |
3504 } | |
3505 } | |
3506 } | |
3507 if (!found) { | |
3508 SVDEBUG << "MainWindow::paneCancelButtonPressed: Unknown layer in pane" | |
3509 << endl; | |
3510 return; | |
3511 } | |
3512 | |
3513 SVDEBUG << "MainWindow::paneCancelButtonPressed: Layer " << layer << endl; | |
3514 | |
3515 // We need to ensure that the transform that is populating this | |
3516 // layer's model is stopped - that is the main reason to use | |
3517 // Cancel after all. It would also be a good idea to remove the | |
3518 // incomplete layer from both the view and the undo/redo stack. | |
3519 | |
3520 // Deleting the target model will ensure that the transform gets | |
3521 // stopped, but removing the layer from the view is not enough to | |
3522 // delete the model, because a reference to the layer remains on | |
3523 // the undo/redo stack. If we also replace the model id with None | |
3524 // in the layer, that does the trick. | |
3525 | |
3526 m_document->setModel(layer, {}); | |
3527 m_document->removeLayerFromView(pane, layer); | |
3528 | |
3529 // We still have a layer with no model on the undo/redo stack, | |
3530 // which is a pity. I'm not sure we can easily remove it, since | |
3531 // other commands may have been pushed on the stack since, so | |
3532 // let's just leave that for now. | |
3533 | |
3534 updateMenuStates(); | |
3535 } | |
3473 | 3536 |
3474 void | 3537 void |
3475 MainWindow::paneDropAccepted(Pane *pane, QStringList uriList) | 3538 MainWindow::paneDropAccepted(Pane *pane, QStringList uriList) |
3476 { | 3539 { |
3477 if (pane) m_paneStack->setCurrentPane(pane); | 3540 if (pane) m_paneStack->setCurrentPane(pane); |
3833 m_document->addLayerToView(pane, m_timeRulerLayer); | 3896 m_document->addLayerToView(pane, m_timeRulerLayer); |
3834 } | 3897 } |
3835 | 3898 |
3836 Layer *newLayer = m_document->createLayer(configuration.layer); | 3899 Layer *newLayer = m_document->createLayer(configuration.layer); |
3837 | 3900 |
3838 Model *suggestedModel = configuration.sourceModel; | 3901 ModelId suggestedModelId = configuration.sourceModel; |
3839 Model *model = nullptr; | 3902 ModelId modelId; |
3840 | 3903 |
3841 if (suggestedModel) { | 3904 if (!suggestedModelId.isNone()) { |
3842 | 3905 |
3843 // check its validity | 3906 // check its validity |
3844 std::vector<Model *> inputModels = m_document->getTransformInputModels(); | 3907 std::vector<ModelId> inputModels = m_document->getTransformInputModels(); |
3845 for (size_t j = 0; j < inputModels.size(); ++j) { | 3908 for (auto im: inputModels) { |
3846 if (inputModels[j] == suggestedModel) { | 3909 if (im == suggestedModelId) { |
3847 model = suggestedModel; | 3910 modelId = suggestedModelId; |
3848 break; | |
3849 } | 3911 } |
3850 } | 3912 } |
3851 | 3913 |
3852 if (!model) { | 3914 if (modelId.isNone()) { |
3853 cerr << "WARNING: Model " << (void *)suggestedModel | 3915 cerr << "WARNING: Model " << modelId |
3854 << " appears in pane action map, but is not reported " | 3916 << " appears in pane action map, but is not reported " |
3855 << "by document as a valid transform source" << endl; | 3917 << "by document as a valid transform source" << endl; |
3856 } | 3918 } |
3857 } | 3919 } |
3858 | 3920 |
3859 if (!model) { | 3921 if (modelId.isNone()) { |
3860 model = m_document->getMainModel(); | 3922 modelId = m_document->getMainModel(); |
3861 } | 3923 } |
3862 | 3924 |
3863 m_document->setModel(newLayer, model); | 3925 m_document->setModel(newLayer, modelId); |
3864 | 3926 |
3865 m_document->setChannel(newLayer, configuration.channel); | 3927 m_document->setChannel(newLayer, configuration.channel); |
3866 m_document->addLayerToView(pane, newLayer); | 3928 m_document->addLayerToView(pane, newLayer); |
3867 | 3929 |
3868 m_paneStack->setCurrentPane(pane); | 3930 m_paneStack->setCurrentPane(pane); |
3972 } | 4034 } |
3973 } | 4035 } |
3974 | 4036 |
3975 } else { | 4037 } else { |
3976 | 4038 |
3977 Model *model = i->second.sourceModel; | 4039 ModelId modelId = i->second.sourceModel; |
3978 | 4040 |
3979 cerr << "model = "<< model << endl; | 4041 if (modelId.isNone()) { |
3980 | |
3981 if (!model) { | |
3982 if (type == LayerFactory::TimeRuler) { | 4042 if (type == LayerFactory::TimeRuler) { |
3983 newLayer = m_document->createMainModelLayer(type); | 4043 newLayer = m_document->createMainModelLayer(type); |
3984 } else { | 4044 } else { |
3985 // if model is unspecified and this is not a | 4045 // if model is unspecified and this is not a |
3986 // time-ruler layer, use any plausible model from | 4046 // time-ruler layer, use any plausible model from |
3987 // the current pane -- this is the case for | 4047 // the current pane -- this is the case for |
3988 // right-button menu layer additions | 4048 // right-button menu layer additions |
3989 Pane::ModelSet ms = pane->getModels(); | 4049 Pane::ModelSet ms = pane->getModels(); |
3990 foreach (Model *m, ms) { | 4050 for (ModelId m: ms) { |
3991 RangeSummarisableTimeValueModel *r = | 4051 if (ModelById::isa<RangeSummarisableTimeValueModel>(m)) { |
3992 dynamic_cast<RangeSummarisableTimeValueModel *>(m); | 4052 modelId = m; |
3993 if (r) model = m; | 4053 } |
3994 } | 4054 } |
3995 if (!model) model = getMainModel(); | 4055 if (modelId.isNone()) { |
4056 modelId = getMainModelId(); | |
4057 } | |
3996 } | 4058 } |
3997 } | 4059 } |
3998 | 4060 |
3999 if (model) { | 4061 if (!modelId.isNone()) { |
4000 newLayer = m_document->createLayer(type); | 4062 newLayer = m_document->createLayer(type); |
4001 if (m_document->isKnownModel(model)) { | 4063 if (m_document->isKnownModel(modelId)) { |
4002 m_document->setChannel(newLayer, i->second.channel); | 4064 m_document->setChannel(newLayer, i->second.channel); |
4003 m_document->setModel(newLayer, model); | 4065 m_document->setModel(newLayer, modelId); |
4004 } else { | 4066 } else { |
4005 cerr << "WARNING: MainWindow::addLayer: unknown model " | 4067 SVCERR << "WARNING: MainWindow::addLayer: unknown model " |
4006 << model | 4068 << modelId << " in layer action map" << endl; |
4007 << " (\"" | |
4008 << model->objectName() | |
4009 << "\") in layer action map" | |
4010 << endl; | |
4011 } | 4069 } |
4012 } | 4070 } |
4013 } | 4071 } |
4014 | 4072 |
4015 if (newLayer) { | 4073 if (newLayer) { |
4062 tr("<b>Failed to query transform attributes</b><p>Plugin or server error: %1</p>") | 4120 tr("<b>Failed to query transform attributes</b><p>Plugin or server error: %1</p>") |
4063 .arg(e.what())); | 4121 .arg(e.what())); |
4064 return; | 4122 return; |
4065 } | 4123 } |
4066 | 4124 |
4067 std::vector<Model *> candidateInputModels = | 4125 std::vector<ModelId> candidateInputModels = |
4068 m_document->getTransformInputModels(); | 4126 m_document->getTransformInputModels(); |
4069 | 4127 |
4070 Model *defaultInputModel = nullptr; | 4128 ModelId defaultInputModelId; |
4071 | 4129 |
4072 for (int j = 0; j < pane->getLayerCount(); ++j) { | 4130 for (int j = 0; j < pane->getLayerCount(); ++j) { |
4073 | 4131 |
4074 Layer *layer = pane->getLayer(j); | 4132 Layer *layer = pane->getLayer(j); |
4075 if (!layer) continue; | 4133 if (!layer) continue; |
4076 | 4134 |
4077 if (LayerFactory::getInstance()->getLayerType(layer) != | 4135 if (LayerFactory::getInstance()->getLayerType(layer) != |
4078 LayerFactory::Waveform && | 4136 LayerFactory::Waveform && |
4079 !layer->isLayerOpaque()) continue; | 4137 !layer->isLayerOpaque()) { |
4080 | 4138 continue; |
4081 Model *model = layer->getModel(); | 4139 } |
4082 if (!model) continue; | 4140 |
4083 | 4141 ModelId modelId = layer->getModel(); |
4084 for (size_t k = 0; k < candidateInputModels.size(); ++k) { | 4142 if (modelId.isNone()) continue; |
4085 if (candidateInputModels[k] == model) { | 4143 |
4086 defaultInputModel = model; | 4144 for (ModelId candidateId: candidateInputModels) { |
4145 if (candidateId == modelId) { | |
4146 defaultInputModelId = modelId; | |
4087 break; | 4147 break; |
4088 } | 4148 } |
4089 } | 4149 } |
4090 | 4150 |
4091 if (defaultInputModel) break; | 4151 if (!defaultInputModelId.isNone()) break; |
4092 } | 4152 } |
4093 | 4153 |
4094 AggregateWaveModel *aggregate = nullptr; | 4154 ModelId aggregate; |
4095 | 4155 |
4096 if (candidateInputModels.size() > 1) { | 4156 if (candidateInputModels.size() > 1) { |
4097 // Add an aggregate model as another option | 4157 // Add an aggregate model as another option |
4098 AggregateWaveModel::ChannelSpecList sl; | 4158 AggregateWaveModel::ChannelSpecList sl; |
4099 foreach (Model *m, candidateInputModels) { | 4159 for (ModelId mid: candidateInputModels) { |
4100 RangeSummarisableTimeValueModel *r = | 4160 if (ModelById::isa<RangeSummarisableTimeValueModel>(mid)) { |
4101 qobject_cast<RangeSummarisableTimeValueModel *>(m); | 4161 sl.push_back(AggregateWaveModel::ModelChannelSpec(mid, -1)); |
4102 if (r) { | |
4103 sl.push_back(AggregateWaveModel::ModelChannelSpec(r, -1)); | |
4104 } | 4162 } |
4105 } | 4163 } |
4106 if (!sl.empty()) { | 4164 if (!sl.empty()) { |
4107 aggregate = new AggregateWaveModel(sl); | 4165 auto aggregate = std::make_shared<AggregateWaveModel>(sl); |
4108 aggregate->setObjectName(tr("Multiplex all of the above")); | 4166 aggregate->setObjectName(tr("Multiplex all of the above")); |
4109 candidateInputModels.push_back(aggregate); | 4167 candidateInputModels.push_back(ModelById::add(aggregate)); |
4110 } | 4168 } |
4111 } | 4169 } |
4112 | 4170 |
4113 sv_frame_t startFrame = 0, duration = 0; | 4171 sv_frame_t startFrame = 0, duration = 0; |
4114 sv_frame_t endFrame = 0; | 4172 sv_frame_t endFrame = 0; |
4120 | 4178 |
4121 ModelTransformer::Input input = ModelTransformerFactory::getInstance()-> | 4179 ModelTransformer::Input input = ModelTransformerFactory::getInstance()-> |
4122 getConfigurationForTransform | 4180 getConfigurationForTransform |
4123 (transform, | 4181 (transform, |
4124 candidateInputModels, | 4182 candidateInputModels, |
4125 defaultInputModel, | 4183 defaultInputModelId, |
4126 m_playSource, | 4184 m_playSource, |
4127 startFrame, | 4185 startFrame, |
4128 duration, | 4186 duration, |
4129 &configurator); | 4187 &configurator); |
4130 | 4188 |
4131 if (aggregate) { | 4189 if (!aggregate.isNone()) { |
4132 if (input.getModel() == aggregate) { | 4190 if (input.getModel() == aggregate) { |
4133 aggregate->setObjectName(tr("Multiplexed audio")); | 4191 if (auto aggregateModel = ModelById::get(aggregate)) { |
4134 m_document->addAggregateModel(aggregate); | 4192 aggregateModel->setObjectName(tr("Multiplexed audio")); |
4193 } | |
4194 m_document->addNonDerivedModel(aggregate); | |
4135 } else { | 4195 } else { |
4136 aggregate->aboutToDelete(); | 4196 ModelById::release(aggregate); |
4137 delete aggregate; | 4197 } |
4138 } | 4198 } |
4139 } | 4199 |
4140 | 4200 if (input.getModel().isNone()) return; |
4141 if (!input.getModel()) return; | |
4142 | 4201 |
4143 // SVDEBUG << "MainWindow::addLayer: Input model is " << input.getModel() << " \"" << input.getModel()->objectName() << "\"" << endl << "transform:" << endl << transform.toXmlString() << endl; | 4202 // SVDEBUG << "MainWindow::addLayer: Input model is " << input.getModel() << " \"" << input.getModel()->objectName() << "\"" << endl << "transform:" << endl << transform.toXmlString() << endl; |
4144 | 4203 |
4145 try { | 4204 try { |
4146 Layer *newLayer = m_document->createDerivedLayer(transform, input); | 4205 Layer *newLayer = m_document->createDerivedLayer(transform, input); |
4326 --i; | 4385 --i; |
4327 Layer *layer = pane->getLayer(i); | 4386 Layer *layer = pane->getLayer(i); |
4328 if (layer && | 4387 if (layer && |
4329 LayerFactory::getInstance()->getLayerType(layer) == | 4388 LayerFactory::getInstance()->getLayerType(layer) == |
4330 LayerFactory::Waveform && | 4389 LayerFactory::Waveform && |
4331 layer->getModel() == getMainModel()) { | 4390 layer->getModel() == getMainModelId()) { |
4332 containsMainModel = true; | 4391 containsMainModel = true; |
4333 break; | 4392 break; |
4334 } | 4393 } |
4335 } | 4394 } |
4336 | 4395 |
4337 bool panLayerSet = false; | 4396 bool panLayerSet = false; |
4338 | 4397 |
4339 for (int i = pane->getLayerCount(); i > 0; ) { | 4398 for (int i = pane->getLayerCount(); i > 0; ) { |
4340 --i; | 4399 --i; |
4341 Layer *layer = pane->getLayer(i); | 4400 Layer *layer = pane->getLayer(i); |
4342 RangeSummarisableTimeValueModel *tvm = | 4401 ModelId modelId = layer->getModel(); |
4343 qobject_cast<RangeSummarisableTimeValueModel *>(layer->getModel()); | 4402 if (ModelById::isa<RangeSummarisableTimeValueModel>(modelId)) { |
4344 if (tvm) { | |
4345 auto type = LayerFactory::getInstance()->getLayerType(layer); | 4403 auto type = LayerFactory::getInstance()->getLayerType(layer); |
4346 if (type != LayerFactory::TimeRuler) { | 4404 if (type != LayerFactory::TimeRuler) { |
4347 updateLayerShortcutsFor(tvm); | 4405 updateLayerShortcutsFor(modelId); |
4348 } | 4406 } |
4349 if (type == LayerFactory::Waveform) { | 4407 if (type == LayerFactory::Waveform) { |
4350 m_panLayer->setModel(tvm); | 4408 m_panLayer->setModel(modelId); |
4351 panLayerSet = true; | 4409 panLayerSet = true; |
4352 break; | 4410 break; |
4353 } | 4411 } |
4354 } | 4412 } |
4355 } | 4413 } |
4356 | 4414 |
4357 if (containsMainModel && !panLayerSet) { | 4415 if (containsMainModel && !panLayerSet) { |
4358 m_panLayer->setModel(getMainModel()); | 4416 m_panLayer->setModel(getMainModelId()); |
4359 } | 4417 } |
4360 } | 4418 } |
4361 | 4419 |
4362 void | 4420 void |
4363 MainWindow::updateVisibleRangeDisplay(Pane *p) const | 4421 MainWindow::updateVisibleRangeDisplay(Pane *p) const |
4364 { | 4422 { |
4365 if (!getMainModel() || !p) { | 4423 sv_samplerate_t sampleRate = 0; |
4424 if (auto mm = getMainModel()) { | |
4425 sampleRate = mm->getSampleRate(); | |
4426 } else { | |
4427 return; | |
4428 } | |
4429 if (!p) { | |
4366 return; | 4430 return; |
4367 } | 4431 } |
4368 | 4432 |
4369 bool haveSelection = false; | 4433 bool haveSelection = false; |
4370 sv_frame_t startFrame = 0, endFrame = 0; | 4434 sv_frame_t startFrame = 0, endFrame = 0; |
4384 if (!haveSelection) { | 4448 if (!haveSelection) { |
4385 startFrame = p->getFirstVisibleFrame(); | 4449 startFrame = p->getFirstVisibleFrame(); |
4386 endFrame = p->getLastVisibleFrame(); | 4450 endFrame = p->getLastVisibleFrame(); |
4387 } | 4451 } |
4388 | 4452 |
4389 RealTime start = RealTime::frame2RealTime | 4453 RealTime start = RealTime::frame2RealTime(startFrame, sampleRate); |
4390 (startFrame, getMainModel()->getSampleRate()); | 4454 RealTime end = RealTime::frame2RealTime(endFrame, sampleRate); |
4391 | |
4392 RealTime end = RealTime::frame2RealTime | |
4393 (endFrame, getMainModel()->getSampleRate()); | |
4394 | |
4395 RealTime duration = end - start; | 4455 RealTime duration = end - start; |
4396 | 4456 |
4397 QString startStr, endStr, durationStr; | 4457 QString startStr, endStr, durationStr; |
4398 startStr = start.toText(true).c_str(); | 4458 startStr = start.toText(true).c_str(); |
4399 endStr = end.toText(true).c_str(); | 4459 endStr = end.toText(true).c_str(); |
4582 | 4642 |
4583 if (!noteOn) continue; | 4643 if (!noteOn) continue; |
4584 | 4644 |
4585 if (!m_playSource || !m_playSource->isPlaying()) continue; | 4645 if (!m_playSource || !m_playSource->isPlaying()) continue; |
4586 | 4646 |
4587 Model *model = static_cast<Layer *>(currentTimeValueLayer)->getModel(); | 4647 ModelId modelId = currentTimeValueLayer->getModel(); |
4588 SparseTimeValueModel *tvm = | 4648 if (ModelById::isa<SparseTimeValueModel>(modelId)) { |
4589 dynamic_cast<SparseTimeValueModel *>(model); | |
4590 if (tvm) { | |
4591 Event point(frame, float(ev.getPitch() % 12), ""); | 4649 Event point(frame, float(ev.getPitch() % 12), ""); |
4592 AddEventCommand *command = new AddEventCommand | 4650 AddEventCommand *command = new AddEventCommand |
4593 (tvm, point, tr("Add Point")); | 4651 (modelId.untyped, point, tr("Add Point")); |
4594 CommandHistory::getInstance()->addCommand(command); | 4652 CommandHistory::getInstance()->addCommand(command); |
4595 } | 4653 } |
4596 | 4654 |
4597 continue; | 4655 continue; |
4598 } | 4656 } |
4635 setupExistingLayersMenus(); | 4693 setupExistingLayersMenus(); |
4636 MainWindowBase::layerInAView(layer, inAView); | 4694 MainWindowBase::layerInAView(layer, inAView); |
4637 } | 4695 } |
4638 | 4696 |
4639 void | 4697 void |
4640 MainWindow::modelAdded(Model *model) | 4698 MainWindow::modelAdded(ModelId modelId) |
4641 { | 4699 { |
4642 MainWindowBase::modelAdded(model); | 4700 MainWindowBase::modelAdded(modelId); |
4643 if (dynamic_cast<DenseTimeValueModel *>(model)) { | 4701 if (ModelById::isa<DenseTimeValueModel>(modelId)) { |
4644 setupPaneAndLayerMenus(); | 4702 setupPaneAndLayerMenus(); |
4645 } | 4703 } |
4646 } | 4704 } |
4647 | 4705 |
4648 void | 4706 void |
4649 MainWindow::mainModelChanged(WaveFileModel *model) | 4707 MainWindow::mainModelChanged(ModelId modelId) |
4650 { | 4708 { |
4651 m_panLayer->setModel(model); | 4709 m_panLayer->setModel(modelId); |
4652 | 4710 |
4653 MainWindowBase::mainModelChanged(model); | 4711 MainWindowBase::mainModelChanged(modelId); |
4654 | 4712 |
4655 if (m_playTarget || m_audioIO) { | 4713 if (m_playTarget || m_audioIO) { |
4656 connect(m_mainLevelPan, SIGNAL(levelChanged(float)), | 4714 connect(m_mainLevelPan, SIGNAL(levelChanged(float)), |
4657 this, SLOT(mainModelGainChanged(float))); | 4715 this, SLOT(mainModelGainChanged(float))); |
4658 connect(m_mainLevelPan, SIGNAL(panChanged(float)), | 4716 connect(m_mainLevelPan, SIGNAL(panChanged(float)), |
4677 if (m_playTarget) { | 4735 if (m_playTarget) { |
4678 m_playTarget->setOutputBalance(balance); | 4736 m_playTarget->setOutputBalance(balance); |
4679 } else if (m_audioIO) { | 4737 } else if (m_audioIO) { |
4680 m_audioIO->setOutputBalance(balance); | 4738 m_audioIO->setOutputBalance(balance); |
4681 } | 4739 } |
4682 } | |
4683 | |
4684 void | |
4685 MainWindow::modelAboutToBeDeleted(Model *model) | |
4686 { | |
4687 if (model == m_panLayer->getModel()) { | |
4688 if (model == getMainModel()) { | |
4689 m_panLayer->setModel(nullptr); | |
4690 } else { | |
4691 m_panLayer->setModel(getMainModel()); | |
4692 } | |
4693 } | |
4694 MainWindowBase::modelAboutToBeDeleted(model); | |
4695 } | 4740 } |
4696 | 4741 |
4697 void | 4742 void |
4698 MainWindow::setInstantsNumbering() | 4743 MainWindow::setInstantsNumbering() |
4699 { | 4744 { |