comparison main/MainWindow.cpp @ 2300:eb7f4579e5cc by-id

Updates throughout for ModelById logic
author Chris Cannam
date Thu, 04 Jul 2019 14:32:08 +0100
parents f78177863e26
children 23fea10161a6
comparison
equal deleted inserted replaced
2299:bb0f5a8f93fe 2300:eb7f4579e5cc
1292 LayerFactory::Spectrum 1292 LayerFactory::Spectrum
1293 }; 1293 };
1294 int backgroundTypeCount = int(sizeof(backgroundTypes) / 1294 int backgroundTypeCount = int(sizeof(backgroundTypes) /
1295 sizeof(backgroundTypes[0])); 1295 sizeof(backgroundTypes[0]));
1296 1296
1297 std::vector<Model *> models; 1297 std::vector<ModelId> models;
1298 if (m_document) models = m_document->getTransformInputModels(); 1298 if (m_document) models = m_document->getTransformInputModels();
1299 bool plural = (models.size() > 1); 1299 bool plural = (models.size() > 1);
1300 if (models.empty()) { 1300 if (models.empty()) {
1301 models.push_back(getMainModel()); // probably 0 1301 models.push_back(getMainModelId()); // probably None at this point
1302 } 1302 }
1303 1303
1304 for (int i = 0; i < backgroundTypeCount; ++i) { 1304 for (int i = 0; i < backgroundTypeCount; ++i) {
1305 1305
1306 const int paneMenuType = 0, layerMenuType = 1; 1306 const int paneMenuType = 0, layerMenuType = 1;
1380 break; 1380 break;
1381 1381
1382 default: break; 1382 default: break;
1383 } 1383 }
1384 1384
1385 std::vector<Model *> candidateModels = models; 1385 std::vector<ModelId> candidateModels = models;
1386 if (candidateModels.empty()) {
1387 throw std::logic_error("candidateModels should not be empty");
1388 }
1386 1389
1387 for (std::vector<Model *>::iterator mi = 1390 for (auto modelId: candidateModels) {
1388 candidateModels.begin(); 1391
1389 mi != candidateModels.end(); ++mi) { 1392 auto model = ModelById::get(modelId);
1390 1393
1391 Model *model = *mi;
1392
1393 int channels = 0; 1394 int channels = 0;
1394 if (model) { 1395 if (model) {
1395 DenseTimeValueModel *dtvm = 1396 if (auto dtvm = ModelById::getAs<DenseTimeValueModel>
1396 dynamic_cast<DenseTimeValueModel *>(model); 1397 (modelId)) {
1397 if (dtvm) channels = dtvm->getChannelCount(); 1398 channels = dtvm->getChannelCount();
1399 }
1398 } 1400 }
1399 if (channels < 1 && getMainModel()) { 1401 if (channels < 1 && getMainModel()) {
1400 channels = getMainModel()->getChannelCount(); 1402 channels = getMainModel()->getChannelCount();
1401 } 1403 }
1402 if (channels < 1) channels = 1; 1404 if (channels < 1) channels = 1;
1417 connect(action, SIGNAL(triggered()), 1419 connect(action, SIGNAL(triggered()),
1418 this, SLOT(addPane())); 1420 this, SLOT(addPane()));
1419 connect(this, SIGNAL(canAddPane(bool)), 1421 connect(this, SIGNAL(canAddPane(bool)),
1420 action, SLOT(setEnabled(bool))); 1422 action, SLOT(setEnabled(bool)));
1421 m_paneActions.push_back 1423 m_paneActions.push_back
1422 ({ action, LayerConfiguration(type, model) }); 1424 ({ action, LayerConfiguration(type, modelId) });
1423 } else { 1425 } else {
1424 connect(action, SIGNAL(triggered()), 1426 connect(action, SIGNAL(triggered()),
1425 this, SLOT(addLayer())); 1427 this, SLOT(addLayer()));
1426 connect(this, SIGNAL(canAddLayer(bool)), 1428 connect(this, SIGNAL(canAddLayer(bool)),
1427 action, SLOT(setEnabled(bool))); 1429 action, SLOT(setEnabled(bool)));
1428 m_layerActions.push_back 1430 m_layerActions.push_back
1429 ({ action, LayerConfiguration(type, model) }); 1431 ({ action, LayerConfiguration(type, modelId) });
1430 } 1432 }
1431 if (shortcutText != "") { 1433 if (shortcutText != "") {
1432 m_keyReference->registerShortcut(action); 1434 m_keyReference->registerShortcut(action);
1433 } 1435 }
1434 menu->addAction(action); 1436 menu->addAction(action);
1459 .arg(actionText); 1461 .arg(actionText);
1460 } 1462 }
1461 1463
1462 if (isDefault) { 1464 if (isDefault) {
1463 action = new QAction(icon, actionText, this); 1465 action = new QAction(icon, actionText, this);
1464 if (!model || model == getMainModel()) { 1466 if (!model || modelId == getMainModelId()) {
1465 // Default for the shortcut is to 1467 // Default for the shortcut is to
1466 // attach to an action that uses the 1468 // attach to an action that uses the
1467 // main model as input. But this may 1469 // main model as input. But this may
1468 // change when the user selects a 1470 // change when the user selects a
1469 // different pane - see 1471 // different pane - see
1480 connect(action, SIGNAL(triggered()), 1482 connect(action, SIGNAL(triggered()),
1481 this, SLOT(addPane())); 1483 this, SLOT(addPane()));
1482 connect(this, SIGNAL(canAddPane(bool)), 1484 connect(this, SIGNAL(canAddPane(bool)),
1483 action, SLOT(setEnabled(bool))); 1485 action, SLOT(setEnabled(bool)));
1484 m_paneActions.push_back 1486 m_paneActions.push_back
1485 ({ action, LayerConfiguration(type, model, c - 1) }); 1487 ({ action, LayerConfiguration(type, modelId, c - 1) });
1486 } else { 1488 } else {
1487 connect(action, SIGNAL(triggered()), 1489 connect(action, SIGNAL(triggered()),
1488 this, SLOT(addLayer())); 1490 this, SLOT(addLayer()));
1489 connect(this, SIGNAL(canAddLayer(bool)), 1491 connect(this, SIGNAL(canAddLayer(bool)),
1490 action, SLOT(setEnabled(bool))); 1492 action, SLOT(setEnabled(bool)));
1491 m_layerActions.push_back 1493 m_layerActions.push_back
1492 ({ action, LayerConfiguration(type, model, c - 1) }); 1494 ({ action, LayerConfiguration(type, modelId, c - 1) });
1493 } 1495 }
1494 1496
1495 submenu->addAction(action); 1497 submenu->addAction(action);
1496 } 1498 }
1497 1499
1498 if (isDefault && menuType == layerMenuType && 1500 if (isDefault && menuType == layerMenuType &&
1499 mi == candidateModels.begin()) { 1501 modelId == *candidateModels.begin()) {
1500 // only add for one model, one channel, one menu on 1502 // only add for one model, one channel, one menu on
1501 // right button -- the action itself will discover 1503 // right button -- the action itself will discover
1502 // which model is the correct one (based on pane) 1504 // which model is the correct one (based on pane)
1503 action = new QAction(icon, mainText, this); 1505 action = new QAction(icon, mainText, this);
1504 action->setStatusTip(tipText); 1506 action->setStatusTip(tipText);
1505 connect(action, SIGNAL(triggered()), 1507 connect(action, SIGNAL(triggered()),
1506 this, SLOT(addLayer())); 1508 this, SLOT(addLayer()));
1507 connect(this, SIGNAL(canAddLayer(bool)), 1509 connect(this, SIGNAL(canAddLayer(bool)),
1508 action, SLOT(setEnabled(bool))); 1510 action, SLOT(setEnabled(bool)));
1509 m_layerActions.push_back 1511 m_layerActions.push_back
1510 ({ action, LayerConfiguration(type, nullptr, 0) }); 1512 ({ action, LayerConfiguration(type, ModelId(), 0) });
1511 m_rightButtonLayerMenu->addAction(action); 1513 m_rightButtonLayerMenu->addAction(action);
1512 } 1514 }
1513 } 1515 }
1514 } 1516 }
1515 } 1517 }
1618 1620
1619 finaliseMenus(); 1621 finaliseMenus();
1620 } 1622 }
1621 1623
1622 void 1624 void
1623 MainWindow::updateLayerShortcutsFor(Model *model) 1625 MainWindow::updateLayerShortcutsFor(ModelId modelId)
1624 { 1626 {
1625 // Called when e.g. the current pane has changed, to ensure the 1627 // Called when e.g. the current pane has changed, to ensure the
1626 // various layer shortcuts select an action whose input model is 1628 // various layer shortcuts select an action whose input model is
1627 // the active one in this pane 1629 // the active one in this pane
1628 1630
1629 set<LayerFactory::LayerType> seen; 1631 set<LayerFactory::LayerType> seen;
1630 1632
1631 for (auto &a : m_paneActions) { 1633 for (auto &a : m_paneActions) {
1632 if (!a.second.sourceModel) continue; // empty pane/layer shortcut 1634 if (a.second.sourceModel.isNone()) {
1635 continue; // empty pane/layer shortcut
1636 }
1633 auto type = a.second.layer; 1637 auto type = a.second.layer;
1634 if (a.second.sourceModel == model && seen.find(type) == seen.end()) { 1638 if (a.second.sourceModel == modelId && seen.find(type) == seen.end()) {
1635 a.first->setShortcut(shortcutFor(type, true)); 1639 a.first->setShortcut(shortcutFor(type, true));
1636 seen.insert(type); 1640 seen.insert(type);
1637 } else { 1641 } else {
1638 a.first->setShortcut(QString()); 1642 a.first->setShortcut(QString());
1639 } 1643 }
1640 } 1644 }
1641 1645
1642 seen.clear(); 1646 seen.clear();
1643 1647
1644 for (auto &a : m_layerActions) { 1648 for (auto &a : m_layerActions) {
1645 if (!a.second.sourceModel) continue; // empty pane/layer shortcut 1649 if (a.second.sourceModel.isNone()) {
1650 continue; // empty pane/layer shortcut
1651 }
1646 auto type = a.second.layer; 1652 auto type = a.second.layer;
1647 if (a.second.sourceModel == model && seen.find(type) == seen.end()) { 1653 if (a.second.sourceModel == modelId && seen.find(type) == seen.end()) {
1648 a.first->setShortcut(shortcutFor(type, false)); 1654 a.first->setShortcut(shortcutFor(type, false));
1649 seen.insert(type); 1655 seen.insert(type);
1650 } else { 1656 } else {
1651 a.first->setShortcut(QString()); 1657 a.first->setShortcut(QString());
1652 } 1658 }
2688 } 2694 }
2689 2695
2690 void 2696 void
2691 MainWindow::exportAudio(bool asData) 2697 MainWindow::exportAudio(bool asData)
2692 { 2698 {
2693 if (!getMainModel()) return; 2699 auto modelId = getMainModelId();
2694 2700 if (modelId.isNone()) return;
2695 RangeSummarisableTimeValueModel *model = getMainModel(); 2701
2696 std::set<RangeSummarisableTimeValueModel *> otherModels; 2702 std::set<ModelId> otherModelIds;
2697 RangeSummarisableTimeValueModel *current = model; 2703 ModelId current = modelId;
2704
2698 if (m_paneStack) { 2705 if (m_paneStack) {
2699 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { 2706 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
2700 Pane *pane = m_paneStack->getPane(i); 2707 Pane *pane = m_paneStack->getPane(i);
2701 if (!pane) continue; 2708 if (!pane) continue;
2702 for (int j = 0; j < pane->getLayerCount(); ++j) { 2709 for (int j = 0; j < pane->getLayerCount(); ++j) {
2703 Layer *layer = pane->getLayer(j); 2710 Layer *layer = pane->getLayer(j);
2704 if (!layer) continue; 2711 if (!layer) continue;
2705 cerr << "layer = " << layer->objectName() << endl; 2712 cerr << "layer = " << layer->objectName() << endl;
2706 Model *m = layer->getModel(); 2713 ModelId m = layer->getModel();
2707 RangeSummarisableTimeValueModel *wm = 2714 if (ModelById::isa<RangeSummarisableTimeValueModel>(m)) {
2708 dynamic_cast<RangeSummarisableTimeValueModel *>(m); 2715 otherModelIds.insert(m);
2709 if (wm) {
2710 cerr << "found: " << wm->objectName() << endl;
2711 otherModels.insert(wm);
2712 if (pane == m_paneStack->getCurrentPane()) { 2716 if (pane == m_paneStack->getCurrentPane()) {
2713 current = wm; 2717 current = m;
2714 } 2718 }
2715 } 2719 }
2716 } 2720 }
2717 } 2721 }
2718 } 2722 }
2719 if (!otherModels.empty()) { 2723 if (!otherModelIds.empty()) {
2720 std::map<QString, RangeSummarisableTimeValueModel *> m; 2724 std::map<QString, ModelId> m;
2721 m[tr("1. %2").arg(model->objectName())] = model; 2725 QString unnamed = tr("<unnamed>");
2726 QString oname = unnamed;
2727 if (auto mp = ModelById::get(modelId)) {
2728 oname = mp->objectName();
2729 }
2730 m[tr("1. %2").arg(oname)] = modelId;
2722 int n = 2; 2731 int n = 2;
2723 int c = 0; 2732 int c = 0;
2724 for (std::set<RangeSummarisableTimeValueModel *>::const_iterator i 2733 for (auto otherModelId: otherModelIds) {
2725 = otherModels.begin(); 2734 if (otherModelId == modelId) continue;
2726 i != otherModels.end(); ++i) { 2735 oname = unnamed;
2727 if (*i == model) continue; 2736 if (auto mp = ModelById::get(otherModelId)) {
2728 m[tr("%1. %2").arg(n).arg((*i)->objectName())] = *i; 2737 oname = mp->objectName();
2738 }
2739 m[tr("%1. %2").arg(n).arg(oname)] = otherModelId;
2729 ++n; 2740 ++n;
2730 if (*i == current) c = n-1; 2741 if (otherModelId == current) c = n-1;
2731 } 2742 }
2732 QStringList items; 2743 QStringList items;
2733 for (std::map<QString, RangeSummarisableTimeValueModel *> 2744 for (auto i: m) {
2734 ::const_iterator i = m.begin(); 2745 items << i.first;
2735 i != m.end(); ++i) {
2736 items << i->first;
2737 } 2746 }
2738 if (items.size() > 1) { 2747 if (items.size() > 1) {
2739 bool ok = false; 2748 bool ok = false;
2740 QString item = QInputDialog::getItem 2749 QString item = QInputDialog::getItem
2741 (this, tr("Select audio file to export"), 2750 (this, tr("Select audio file to export"),
2742 tr("Which audio file do you want to export from?"), 2751 tr("Which audio file do you want to export from?"),
2743 items, c, false, &ok); 2752 items, c, false, &ok);
2744 if (!ok || item.isEmpty()) return; 2753 if (!ok || item.isEmpty()) return;
2745 if (m.find(item) == m.end()) { 2754 if (m.find(item) == m.end()) {
2746 cerr << "WARNING: Model " << item 2755 SVCERR << "WARNING: Model " << item
2747 << " not found in list!" << endl; 2756 << " not found in list!" << endl;
2748 } else { 2757 } else {
2749 model = m[item]; 2758 modelId = m[item];
2750 } 2759 }
2751 } 2760 }
2752 } 2761 }
2753 2762
2763 auto model = ModelById::getAs<DenseTimeValueModel>(modelId);
2764 if (!model) {
2765 SVCERR << "ERROR: Chosen model is not a DenseTimeValueModel!" << endl;
2766 return;
2767 }
2768
2754 QString path; 2769 QString path;
2755 if (asData) { 2770 if (asData) {
2756 path = getSaveFileName(FileFinder::CSVFile); 2771 path = getSaveFileName(FileFinder::CSVFile);
2757 } else { 2772 } else {
2758 path = getSaveFileName(FileFinder::AudioFile); 2773 path = getSaveFileName(FileFinder::AudioFile);
2833 2848
2834 WavFileWriter subwriter(subpath, 2849 WavFileWriter subwriter(subpath,
2835 model->getSampleRate(), 2850 model->getSampleRate(),
2836 model->getChannelCount(), 2851 model->getChannelCount(),
2837 WavFileWriter::WriteToTemporary); 2852 WavFileWriter::WriteToTemporary);
2838 subwriter.writeModel(model, &subms); 2853 subwriter.writeModel(model.get(), &subms);
2839 ok = subwriter.isOK(); 2854 ok = subwriter.isOK();
2840 2855
2841 if (!ok) { 2856 if (!ok) {
2842 error = subwriter.getError(); 2857 error = subwriter.getError();
2843 break; 2858 break;
2854 true, 2869 true,
2855 0, 2870 0,
2856 this, 2871 this,
2857 Qt::ApplicationModal 2872 Qt::ApplicationModal
2858 }; 2873 };
2859 CSVFileWriter writer(path, model, &dialog, 2874 CSVFileWriter writer(path, model.get(), &dialog,
2860 ((QFileInfo(path).suffix() == "csv") ? 2875 ((QFileInfo(path).suffix() == "csv") ?
2861 "," : "\t")); 2876 "," : "\t"));
2862 if (selectionToWrite) { 2877 if (selectionToWrite) {
2863 writer.writeSelection(*selectionToWrite); 2878 writer.writeSelection(*selectionToWrite);
2864 } else { 2879 } else {
2869 } else { 2884 } else {
2870 WavFileWriter writer(path, 2885 WavFileWriter writer(path,
2871 model->getSampleRate(), 2886 model->getSampleRate(),
2872 model->getChannelCount(), 2887 model->getChannelCount(),
2873 WavFileWriter::WriteToTemporary); 2888 WavFileWriter::WriteToTemporary);
2874 writer.writeModel(model, selectionToWrite); 2889 writer.writeModel(model.get(), selectionToWrite);
2875 ok = writer.isOK(); 2890 ok = writer.isOK();
2876 error = writer.getError(); 2891 error = writer.getError();
2877 } 2892 }
2878 } 2893 }
2879 2894
2934 delete model; 2949 delete model;
2935 status = FileOpenFailed; 2950 status = FileOpenFailed;
2936 2951
2937 } else { 2952 } else {
2938 2953
2954 auto modelId = ModelById::add(std::shared_ptr<Model>(model));
2955
2939 status = addOpenedAudioModel(path, 2956 status = addOpenedAudioModel(path,
2940 model, 2957 modelId,
2941 CreateAdditionalModel, 2958 CreateAdditionalModel,
2942 getDefaultSessionTemplate(), 2959 getDefaultSessionTemplate(),
2943 false); 2960 false);
2944 } 2961 }
2945 2962
2995 if (!pane) return; 3012 if (!pane) return;
2996 3013
2997 Layer *layer = pane->getSelectedLayer(); 3014 Layer *layer = pane->getSelectedLayer();
2998 if (!layer) return; 3015 if (!layer) return;
2999 3016
3000 Model *model = layer->getModel(); 3017 ModelId modelId = layer->getModel();
3001 if (!model) return; 3018 if (modelId.isNone()) return;
3002 3019
3003 FileFinder::FileType type = FileFinder::LayerFileNoMidi; 3020 FileFinder::FileType type = FileFinder::LayerFileNoMidi;
3004 if (dynamic_cast<NoteModel *>(model)) type = FileFinder::LayerFile; 3021 if (ModelById::isa<NoteModel>(modelId)) type = FileFinder::LayerFile;
3005 QString path = getSaveFileName(type); 3022 QString path = getSaveFileName(type);
3006 3023
3007 if (path == "") return; 3024 if (path == "") return;
3008 3025
3009 QString error; 3026 QString error;
3385 << endl; 3402 << endl;
3386 return; 3403 return;
3387 } 3404 }
3388 3405
3389 QString mainModelLocation; 3406 QString mainModelLocation;
3390 WaveFileModel *mm = getMainModel(); 3407 auto mm = getMainModel();
3391 if (mm) mainModelLocation = mm->getLocation(); 3408 if (mm) mainModelLocation = mm->getLocation();
3392 if (mainModelLocation != "") { 3409 if (mainModelLocation != "") {
3393 openAudio(mainModelLocation, ReplaceSession, n); 3410 openAudio(mainModelLocation, ReplaceSession, n);
3394 } else { 3411 } else {
3395 openSessionTemplate(n); 3412 openSessionTemplate(n);
3835 m_document->addLayerToView(pane, m_timeRulerLayer); 3852 m_document->addLayerToView(pane, m_timeRulerLayer);
3836 } 3853 }
3837 3854
3838 Layer *newLayer = m_document->createLayer(configuration.layer); 3855 Layer *newLayer = m_document->createLayer(configuration.layer);
3839 3856
3840 Model *suggestedModel = configuration.sourceModel; 3857 ModelId suggestedModelId = configuration.sourceModel;
3841 Model *model = nullptr; 3858 ModelId modelId;
3842 3859
3843 if (suggestedModel) { 3860 if (!suggestedModelId.isNone()) {
3844 3861
3845 // check its validity 3862 // check its validity
3846 std::vector<Model *> inputModels = m_document->getTransformInputModels(); 3863 std::vector<ModelId> inputModels = m_document->getTransformInputModels();
3847 for (size_t j = 0; j < inputModels.size(); ++j) { 3864 for (auto im: inputModels) {
3848 if (inputModels[j] == suggestedModel) { 3865 if (im == suggestedModelId) {
3849 model = suggestedModel; 3866 modelId = suggestedModelId;
3850 break;
3851 } 3867 }
3852 } 3868 }
3853 3869
3854 if (!model) { 3870 if (modelId.isNone()) {
3855 cerr << "WARNING: Model " << (void *)suggestedModel 3871 cerr << "WARNING: Model " << modelId
3856 << " appears in pane action map, but is not reported " 3872 << " appears in pane action map, but is not reported "
3857 << "by document as a valid transform source" << endl; 3873 << "by document as a valid transform source" << endl;
3858 } 3874 }
3859 } 3875 }
3860 3876
3861 if (!model) { 3877 if (modelId.isNone()) {
3862 model = m_document->getMainModel(); 3878 modelId = m_document->getMainModel();
3863 } 3879 }
3864 3880
3865 m_document->setModel(newLayer, model); 3881 m_document->setModel(newLayer, modelId);
3866 3882
3867 m_document->setChannel(newLayer, configuration.channel); 3883 m_document->setChannel(newLayer, configuration.channel);
3868 m_document->addLayerToView(pane, newLayer); 3884 m_document->addLayerToView(pane, newLayer);
3869 3885
3870 m_paneStack->setCurrentPane(pane); 3886 m_paneStack->setCurrentPane(pane);
3974 } 3990 }
3975 } 3991 }
3976 3992
3977 } else { 3993 } else {
3978 3994
3979 Model *model = i->second.sourceModel; 3995 ModelId modelId = i->second.sourceModel;
3980 3996
3981 cerr << "model = "<< model << endl; 3997 if (modelId.isNone()) {
3982
3983 if (!model) {
3984 if (type == LayerFactory::TimeRuler) { 3998 if (type == LayerFactory::TimeRuler) {
3985 newLayer = m_document->createMainModelLayer(type); 3999 newLayer = m_document->createMainModelLayer(type);
3986 } else { 4000 } else {
3987 // if model is unspecified and this is not a 4001 // if model is unspecified and this is not a
3988 // time-ruler layer, use any plausible model from 4002 // time-ruler layer, use any plausible model from
3989 // the current pane -- this is the case for 4003 // the current pane -- this is the case for
3990 // right-button menu layer additions 4004 // right-button menu layer additions
3991 Pane::ModelSet ms = pane->getModels(); 4005 Pane::ModelSet ms = pane->getModels();
3992 foreach (Model *m, ms) { 4006 for (ModelId m: ms) {
3993 RangeSummarisableTimeValueModel *r = 4007 if (ModelById::isa<RangeSummarisableTimeValueModel>(m)) {
3994 dynamic_cast<RangeSummarisableTimeValueModel *>(m); 4008 modelId = m;
3995 if (r) model = m; 4009 }
3996 } 4010 }
3997 if (!model) model = getMainModel(); 4011 if (modelId.isNone()) {
4012 modelId = getMainModelId();
4013 }
3998 } 4014 }
3999 } 4015 }
4000 4016
4001 if (model) { 4017 if (!modelId.isNone()) {
4002 newLayer = m_document->createLayer(type); 4018 newLayer = m_document->createLayer(type);
4003 if (m_document->isKnownModel(model)) { 4019 if (m_document->isKnownModel(modelId)) {
4004 m_document->setChannel(newLayer, i->second.channel); 4020 m_document->setChannel(newLayer, i->second.channel);
4005 m_document->setModel(newLayer, model); 4021 m_document->setModel(newLayer, modelId);
4006 } else { 4022 } else {
4007 cerr << "WARNING: MainWindow::addLayer: unknown model " 4023 SVCERR << "WARNING: MainWindow::addLayer: unknown model "
4008 << model 4024 << modelId << " in layer action map" << endl;
4009 << " (\""
4010 << model->objectName()
4011 << "\") in layer action map"
4012 << endl;
4013 } 4025 }
4014 } 4026 }
4015 } 4027 }
4016 4028
4017 if (newLayer) { 4029 if (newLayer) {
4064 tr("<b>Failed to query transform attributes</b><p>Plugin or server error: %1</p>") 4076 tr("<b>Failed to query transform attributes</b><p>Plugin or server error: %1</p>")
4065 .arg(e.what())); 4077 .arg(e.what()));
4066 return; 4078 return;
4067 } 4079 }
4068 4080
4069 std::vector<Model *> candidateInputModels = 4081 std::vector<ModelId> candidateInputModels =
4070 m_document->getTransformInputModels(); 4082 m_document->getTransformInputModels();
4071 4083
4072 Model *defaultInputModel = nullptr; 4084 ModelId defaultInputModelId;
4073 4085
4074 for (int j = 0; j < pane->getLayerCount(); ++j) { 4086 for (int j = 0; j < pane->getLayerCount(); ++j) {
4075 4087
4076 Layer *layer = pane->getLayer(j); 4088 Layer *layer = pane->getLayer(j);
4077 if (!layer) continue; 4089 if (!layer) continue;
4078 4090
4079 if (LayerFactory::getInstance()->getLayerType(layer) != 4091 if (LayerFactory::getInstance()->getLayerType(layer) !=
4080 LayerFactory::Waveform && 4092 LayerFactory::Waveform &&
4081 !layer->isLayerOpaque()) continue; 4093 !layer->isLayerOpaque()) {
4082 4094 continue;
4083 Model *model = layer->getModel(); 4095 }
4084 if (!model) continue; 4096
4085 4097 ModelId modelId = layer->getModel();
4086 for (size_t k = 0; k < candidateInputModels.size(); ++k) { 4098 if (modelId.isNone()) continue;
4087 if (candidateInputModels[k] == model) { 4099
4088 defaultInputModel = model; 4100 for (ModelId candidateId: candidateInputModels) {
4101 if (candidateId == modelId) {
4102 defaultInputModelId = modelId;
4089 break; 4103 break;
4090 } 4104 }
4091 } 4105 }
4092 4106
4093 if (defaultInputModel) break; 4107 if (!defaultInputModelId.isNone()) break;
4094 } 4108 }
4095 4109
4096 AggregateWaveModel *aggregate = nullptr; 4110 ModelId aggregate;
4097 4111
4098 if (candidateInputModels.size() > 1) { 4112 if (candidateInputModels.size() > 1) {
4099 // Add an aggregate model as another option 4113 // Add an aggregate model as another option
4100 AggregateWaveModel::ChannelSpecList sl; 4114 AggregateWaveModel::ChannelSpecList sl;
4101 foreach (Model *m, candidateInputModels) { 4115 for (ModelId mid: candidateInputModels) {
4102 RangeSummarisableTimeValueModel *r = 4116 if (ModelById::isa<RangeSummarisableTimeValueModel>(mid)) {
4103 qobject_cast<RangeSummarisableTimeValueModel *>(m); 4117 sl.push_back(AggregateWaveModel::ModelChannelSpec(mid, -1));
4104 if (r) {
4105 sl.push_back(AggregateWaveModel::ModelChannelSpec(r->getId(), -1));
4106 } 4118 }
4107 } 4119 }
4108 if (!sl.empty()) { 4120 if (!sl.empty()) {
4109 aggregate = new AggregateWaveModel(sl); 4121 auto aggregate = std::make_shared<AggregateWaveModel>(sl);
4110 aggregate->setObjectName(tr("Multiplex all of the above")); 4122 aggregate->setObjectName(tr("Multiplex all of the above"));
4111 candidateInputModels.push_back(aggregate); 4123 candidateInputModels.push_back(ModelById::add(aggregate));
4112 } 4124 }
4113 } 4125 }
4114 4126
4115 sv_frame_t startFrame = 0, duration = 0; 4127 sv_frame_t startFrame = 0, duration = 0;
4116 sv_frame_t endFrame = 0; 4128 sv_frame_t endFrame = 0;
4122 4134
4123 ModelTransformer::Input input = ModelTransformerFactory::getInstance()-> 4135 ModelTransformer::Input input = ModelTransformerFactory::getInstance()->
4124 getConfigurationForTransform 4136 getConfigurationForTransform
4125 (transform, 4137 (transform,
4126 candidateInputModels, 4138 candidateInputModels,
4127 defaultInputModel, 4139 defaultInputModelId,
4128 m_playSource, 4140 m_playSource,
4129 startFrame, 4141 startFrame,
4130 duration, 4142 duration,
4131 &configurator); 4143 &configurator);
4132 4144
4133 if (aggregate) { 4145 if (!aggregate.isNone()) {
4134 if (input.getModel() == aggregate) { 4146 if (input.getModel() == aggregate) {
4135 aggregate->setObjectName(tr("Multiplexed audio")); 4147 if (auto aggregateModel = ModelById::get(aggregate)) {
4148 aggregateModel->setObjectName(tr("Multiplexed audio"));
4149 }
4136 m_document->addAggregateModel(aggregate); 4150 m_document->addAggregateModel(aggregate);
4137 } else { 4151 } else {
4138 aggregate->aboutToDelete(); 4152 ModelById::release(aggregate);
4139 delete aggregate; 4153 }
4140 } 4154 }
4141 } 4155
4142 4156 if (input.getModel().isNone()) return;
4143 if (!input.getModel()) return;
4144 4157
4145 // SVDEBUG << "MainWindow::addLayer: Input model is " << input.getModel() << " \"" << input.getModel()->objectName() << "\"" << endl << "transform:" << endl << transform.toXmlString() << endl; 4158 // SVDEBUG << "MainWindow::addLayer: Input model is " << input.getModel() << " \"" << input.getModel()->objectName() << "\"" << endl << "transform:" << endl << transform.toXmlString() << endl;
4146 4159
4147 try { 4160 try {
4148 Layer *newLayer = m_document->createDerivedLayer(transform, input); 4161 Layer *newLayer = m_document->createDerivedLayer(transform, input);
4328 --i; 4341 --i;
4329 Layer *layer = pane->getLayer(i); 4342 Layer *layer = pane->getLayer(i);
4330 if (layer && 4343 if (layer &&
4331 LayerFactory::getInstance()->getLayerType(layer) == 4344 LayerFactory::getInstance()->getLayerType(layer) ==
4332 LayerFactory::Waveform && 4345 LayerFactory::Waveform &&
4333 layer->getModel() == getMainModel()) { 4346 layer->getModel() == getMainModelId()) {
4334 containsMainModel = true; 4347 containsMainModel = true;
4335 break; 4348 break;
4336 } 4349 }
4337 } 4350 }
4338 4351
4339 bool panLayerSet = false; 4352 bool panLayerSet = false;
4340 4353
4341 for (int i = pane->getLayerCount(); i > 0; ) { 4354 for (int i = pane->getLayerCount(); i > 0; ) {
4342 --i; 4355 --i;
4343 Layer *layer = pane->getLayer(i); 4356 Layer *layer = pane->getLayer(i);
4344 RangeSummarisableTimeValueModel *tvm = 4357 ModelId modelId = layer->getModel();
4345 qobject_cast<RangeSummarisableTimeValueModel *>(layer->getModel()); 4358 if (ModelById::isa<RangeSummarisableTimeValueModel>(modelId)) {
4346 if (tvm) {
4347 auto type = LayerFactory::getInstance()->getLayerType(layer); 4359 auto type = LayerFactory::getInstance()->getLayerType(layer);
4348 if (type != LayerFactory::TimeRuler) { 4360 if (type != LayerFactory::TimeRuler) {
4349 updateLayerShortcutsFor(tvm); 4361 updateLayerShortcutsFor(modelId);
4350 } 4362 }
4351 if (type == LayerFactory::Waveform) { 4363 if (type == LayerFactory::Waveform) {
4352 m_panLayer->setModel(tvm); 4364 m_panLayer->setModel(modelId);
4353 panLayerSet = true; 4365 panLayerSet = true;
4354 break; 4366 break;
4355 } 4367 }
4356 } 4368 }
4357 } 4369 }
4358 4370
4359 if (containsMainModel && !panLayerSet) { 4371 if (containsMainModel && !panLayerSet) {
4360 m_panLayer->setModel(getMainModel()); 4372 m_panLayer->setModel(getMainModelId());
4361 } 4373 }
4362 } 4374 }
4363 4375
4364 void 4376 void
4365 MainWindow::updateVisibleRangeDisplay(Pane *p) const 4377 MainWindow::updateVisibleRangeDisplay(Pane *p) const
4366 { 4378 {
4367 if (!getMainModel() || !p) { 4379 sv_samplerate_t sampleRate = 0;
4380 if (auto mm = getMainModel()) {
4381 sampleRate = mm->getSampleRate();
4382 } else {
4383 return;
4384 }
4385 if (!p) {
4368 return; 4386 return;
4369 } 4387 }
4370 4388
4371 bool haveSelection = false; 4389 bool haveSelection = false;
4372 sv_frame_t startFrame = 0, endFrame = 0; 4390 sv_frame_t startFrame = 0, endFrame = 0;
4386 if (!haveSelection) { 4404 if (!haveSelection) {
4387 startFrame = p->getFirstVisibleFrame(); 4405 startFrame = p->getFirstVisibleFrame();
4388 endFrame = p->getLastVisibleFrame(); 4406 endFrame = p->getLastVisibleFrame();
4389 } 4407 }
4390 4408
4391 RealTime start = RealTime::frame2RealTime 4409 RealTime start = RealTime::frame2RealTime(startFrame, sampleRate);
4392 (startFrame, getMainModel()->getSampleRate()); 4410 RealTime end = RealTime::frame2RealTime(endFrame, sampleRate);
4393
4394 RealTime end = RealTime::frame2RealTime
4395 (endFrame, getMainModel()->getSampleRate());
4396
4397 RealTime duration = end - start; 4411 RealTime duration = end - start;
4398 4412
4399 QString startStr, endStr, durationStr; 4413 QString startStr, endStr, durationStr;
4400 startStr = start.toText(true).c_str(); 4414 startStr = start.toText(true).c_str();
4401 endStr = end.toText(true).c_str(); 4415 endStr = end.toText(true).c_str();
4584 4598
4585 if (!noteOn) continue; 4599 if (!noteOn) continue;
4586 4600
4587 if (!m_playSource || !m_playSource->isPlaying()) continue; 4601 if (!m_playSource || !m_playSource->isPlaying()) continue;
4588 4602
4589 Model *model = static_cast<Layer *>(currentTimeValueLayer)->getModel(); 4603 ModelId modelId = currentTimeValueLayer->getModel();
4590 SparseTimeValueModel *tvm = 4604 if (ModelById::isa<SparseTimeValueModel>(modelId)) {
4591 dynamic_cast<SparseTimeValueModel *>(model);
4592 if (tvm) {
4593 Event point(frame, float(ev.getPitch() % 12), ""); 4605 Event point(frame, float(ev.getPitch() % 12), "");
4594 AddEventCommand *command = new AddEventCommand 4606 AddEventCommand *command = new AddEventCommand
4595 (tvm, point, tr("Add Point")); 4607 (modelId.untyped, point, tr("Add Point"));
4596 CommandHistory::getInstance()->addCommand(command); 4608 CommandHistory::getInstance()->addCommand(command);
4597 } 4609 }
4598 4610
4599 continue; 4611 continue;
4600 } 4612 }
4637 setupExistingLayersMenus(); 4649 setupExistingLayersMenus();
4638 MainWindowBase::layerInAView(layer, inAView); 4650 MainWindowBase::layerInAView(layer, inAView);
4639 } 4651 }
4640 4652
4641 void 4653 void
4642 MainWindow::modelAdded(Model *model) 4654 MainWindow::modelAdded(ModelId modelId)
4643 { 4655 {
4644 MainWindowBase::modelAdded(model); 4656 MainWindowBase::modelAdded(modelId);
4645 if (dynamic_cast<DenseTimeValueModel *>(model)) { 4657 if (ModelById::isa<DenseTimeValueModel>(modelId)) {
4646 setupPaneAndLayerMenus(); 4658 setupPaneAndLayerMenus();
4647 } 4659 }
4648 } 4660 }
4649 4661
4650 void 4662 void
4651 MainWindow::mainModelChanged(WaveFileModel *model) 4663 MainWindow::mainModelChanged(ModelId modelId)
4652 { 4664 {
4653 m_panLayer->setModel(model); 4665 m_panLayer->setModel(modelId);
4654 4666
4655 MainWindowBase::mainModelChanged(model); 4667 MainWindowBase::mainModelChanged(modelId);
4656 4668
4657 if (m_playTarget || m_audioIO) { 4669 if (m_playTarget || m_audioIO) {
4658 connect(m_mainLevelPan, SIGNAL(levelChanged(float)), 4670 connect(m_mainLevelPan, SIGNAL(levelChanged(float)),
4659 this, SLOT(mainModelGainChanged(float))); 4671 this, SLOT(mainModelGainChanged(float)));
4660 connect(m_mainLevelPan, SIGNAL(panChanged(float)), 4672 connect(m_mainLevelPan, SIGNAL(panChanged(float)),
4679 if (m_playTarget) { 4691 if (m_playTarget) {
4680 m_playTarget->setOutputBalance(balance); 4692 m_playTarget->setOutputBalance(balance);
4681 } else if (m_audioIO) { 4693 } else if (m_audioIO) {
4682 m_audioIO->setOutputBalance(balance); 4694 m_audioIO->setOutputBalance(balance);
4683 } 4695 }
4684 }
4685
4686 void
4687 MainWindow::modelAboutToBeDeleted(Model *model)
4688 {
4689 if (model == m_panLayer->getModel()) {
4690 if (model == getMainModel()) {
4691 m_panLayer->setModel(nullptr);
4692 } else {
4693 m_panLayer->setModel(getMainModel());
4694 }
4695 }
4696 MainWindowBase::modelAboutToBeDeleted(model);
4697 } 4696 }
4698 4697
4699 void 4698 void
4700 MainWindow::setInstantsNumbering() 4699 MainWindow::setInstantsNumbering()
4701 { 4700 {