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 {