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 { |
