Mercurial > hg > sonic-visualiser
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 { |