# HG changeset patch # User Chris Cannam # Date 1158857030 0 # Node ID 544ab25d2372e26f7e1d2ce88801cdf640675081 # Parent e3b32dc5180b283448ee95620ccf070ddaf3fb6a * Add support for plugin classification using category files. Add separate menus listing plugins by category, maker, and plugin name. diff -r e3b32dc5180b -r 544ab25d2372 main/MainWindow.cpp --- a/main/MainWindow.cpp Thu Sep 21 11:17:19 2006 +0000 +++ b/main/MainWindow.cpp Thu Sep 21 16:43:50 2006 +0000 @@ -87,6 +87,10 @@ using std::cerr; using std::endl; +using std::vector; +using std::map; +using std::set; + MainWindow::MainWindow() : m_document(0), @@ -571,14 +575,80 @@ TransformFactory::TransformList transforms = TransformFactory::getInstance()->getAllTransforms(); - std::vector types = + vector types = TransformFactory::getInstance()->getAllTransformTypes(); - std::map transformMenus; - - for (std::vector::iterator i = types.begin(); i != types.end(); ++i) { - transformMenus[*i] = m_layerMenu->addMenu(*i); - m_rightButtonLayerMenu->addMenu(transformMenus[*i]); + map > categoryMenus; + map > makerMenus; + + map byPluginNameMenus; + map > pluginNameMenus; + + for (vector::iterator i = types.begin(); i != types.end(); ++i) { + + if (i != types.begin()) { + m_layerMenu->addSeparator(); + m_rightButtonLayerMenu->addSeparator(); + } + + QString byCategoryLabel = tr("%1 by Category").arg(*i); + QMenu *byCategoryMenu = m_layerMenu->addMenu(byCategoryLabel); + m_rightButtonLayerMenu->addMenu(byCategoryMenu); + + vector categories = + TransformFactory::getInstance()->getTransformCategories(*i); + + for (vector::iterator j = categories.begin(); + j != categories.end(); ++j) { + + QString category = *j; + if (category == "") category = tr("Unclassified"); + + if (categories.size() < 2) { + categoryMenus[*i][category] = byCategoryMenu; + continue; + } + + QStringList components = category.split(" > "); + QString key; + + for (QStringList::iterator k = components.begin(); + k != components.end(); ++k) { + + QString parentKey = key; + if (key != "") key += " > "; + key += *k; + + if (categoryMenus[*i].find(key) == categoryMenus[*i].end()) { + if (parentKey == "") { + categoryMenus[*i][key] = byCategoryMenu->addMenu(*k); + } else { + categoryMenus[*i][key] = + categoryMenus[*i][parentKey]->addMenu(*k); + } + } + } + } + + QString byMakerLabel = tr("%1 by Maker").arg(*i); + QMenu *byMakerMenu = m_layerMenu->addMenu(byMakerLabel); + m_rightButtonLayerMenu->addMenu(byMakerMenu); + + vector makers = + TransformFactory::getInstance()->getTransformMakers(*i); + + for (vector::iterator j = makers.begin(); + j != makers.end(); ++j) { + + QString maker = *j; + if (maker == "") maker = tr("Unknown"); + + makerMenus[*i][maker] = byMakerMenu->addMenu(maker); + } + + QString byPluginNameLabel = tr("%1 by Plugin Name").arg(*i); + byPluginNameMenus[*i] = m_layerMenu->addMenu(byPluginNameLabel); + m_rightButtonLayerMenu->addMenu(byPluginNameMenus[*i]); } for (unsigned int i = 0; i < transforms.size(); ++i) { @@ -586,16 +656,63 @@ QString description = transforms[i].description; if (description == "") description = transforms[i].name; - QString actionText = description; - if (transforms[i].configurable) { - actionText = QString("%1...").arg(actionText); - } - - action = new QAction(actionText, this); + QString type = transforms[i].type; + + QString category = transforms[i].category; + if (category == "") category = tr("Unclassified"); + + QString maker = transforms[i].maker; + if (maker == "") maker = tr("Unknown"); + + QString pluginName = description.section(": ", 0, 0); + QString output = description.section(": ", 1); + + action = new QAction(tr("%1...").arg(description), this); connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); m_layerTransformActions[action] = transforms[i].name; connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); - transformMenus[transforms[i].type]->addAction(action); + + if (categoryMenus[type].find(category) == categoryMenus[type].end()) { + std::cerr << "WARNING: MainWindow::setupMenus: Internal error: " + << "No category menu for transform \"" + << description.toStdString() << "\" (category = \"" + << category.toStdString() << "\")" << std::endl; + } else { + categoryMenus[type][category]->addAction(action); + } + + if (makerMenus[type].find(maker) == makerMenus[type].end()) { + std::cerr << "WARNING: MainWindow::setupMenus: Internal error: " + << "No maker menu for transform \"" + << description.toStdString() << "\" (maker = \"" + << maker.toStdString() << "\")" << std::endl; + } else { + makerMenus[type][maker]->addAction(action); + } + + action = new QAction(tr("%1...").arg(output == "" ? pluginName : output), this); + connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); + m_layerTransformActions[action] = transforms[i].name; + connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); + + if (pluginNameMenus[type].find(pluginName) == + pluginNameMenus[type].end()) { + + if (output == "") { + byPluginNameMenus[type]->addAction(action); + } else { + pluginNameMenus[type][pluginName] = + byPluginNameMenus[type]->addMenu(pluginName); + connect(this, SIGNAL(canAddLayer(bool)), + pluginNameMenus[type][pluginName], + SLOT(setEnabled(bool))); + } + } + + if (pluginNameMenus[type].find(pluginName) != + pluginNameMenus[type].end()) { + pluginNameMenus[type][pluginName]->addAction(action); + } } m_rightButtonLayerMenu->addSeparator(); @@ -871,7 +988,7 @@ MainWindow::setupRecentFilesMenu() { m_recentFilesMenu->clear(); - std::vector files = RecentFiles::getInstance()->getRecentFiles(); + vector files = RecentFiles::getInstance()->getRecentFiles(); for (size_t i = 0; i < files.size(); ++i) { QAction *action = new QAction(files[i], this); connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile())); @@ -889,8 +1006,8 @@ m_existingLayersMenu->clear(); m_existingLayerActions.clear(); - std::vector orderedLayers; - std::set observedLayers; + vector orderedLayers; + set observedLayers; for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { @@ -914,7 +1031,7 @@ } } - std::map observedNames; + map observedNames; for (int i = 0; i < orderedLayers.size(); ++i) { @@ -2788,32 +2905,16 @@ } } - bool needConfiguration = false; - - //!!! actually we should probably always ask for configuration - //because we need the execution context - - if (factory->isTransformConfigurable(transform)) { - needConfiguration = true; - } else { - int minChannels, maxChannels; - int myChannels = m_document->getMainModel()->getChannelCount(); - if (factory->getTransformChannelRange(transform, - minChannels, - maxChannels)) { -// std::cerr << "myChannels: " << myChannels << ", minChannels: " << minChannels << ", maxChannels: " << maxChannels << std::endl; - needConfiguration = (myChannels > maxChannels && maxChannels == 1); - } - } + // We always ask for configuration, even if the plugin isn't + // supposed to be configurable, because we need to let the user + // change the execution context (block size etc). PluginTransform::ExecutionContext context(channel); - if (needConfiguration) { - bool ok = - factory->getConfigurationForTransform - (transform, m_document->getMainModel(), context, configurationXml); - if (!ok) return; - } + bool ok = + factory->getConfigurationForTransform + (transform, m_document->getMainModel(), context, configurationXml); + if (!ok) return; Layer *newLayer = m_document->createDerivedLayer(transform, m_document->getMainModel(), diff -r e3b32dc5180b -r 544ab25d2372 transform/FeatureExtractionPluginTransform.cpp --- a/transform/FeatureExtractionPluginTransform.cpp Thu Sep 21 11:17:19 2006 +0000 +++ b/transform/FeatureExtractionPluginTransform.cpp Thu Sep 21 16:43:50 2006 +0000 @@ -269,8 +269,8 @@ if (blockFrame >= endFrame) break; } - std::cerr << "FeatureExtractionPluginTransform::run: blockFrame " - << blockFrame << std::endl; +// std::cerr << "FeatureExtractionPluginTransform::run: blockFrame " +// << blockFrame << std::endl; long completion = (((blockFrame - startFrame) / m_context.stepSize) * 99) / @@ -463,16 +463,21 @@ binCount = m_descriptor->binCount; } + std::cerr << "FeatureExtractionPluginTransform::setCompletion(" + << completion << ")" << std::endl; + if (binCount == 0) { SparseOneDimensionalModel *model = getOutput(); if (!model) return; + std::cerr << "setting on SparseOneDimensionalModel" << std::endl; model->setCompletion(completion); } else if (binCount == 1) { SparseTimeValueModel *model = getOutput(); if (!model) return; + std::cerr << "setting on SparseTimeValueModel" << std::endl; model->setCompletion(completion); } else if (m_descriptor->sampleType == @@ -480,6 +485,7 @@ NoteModel *model = getOutput(); if (!model) return; + std::cerr << "setting on NoteModel" << std::endl; model->setCompletion(completion); } else { @@ -487,6 +493,7 @@ EditableDenseThreeDimensionalModel *model = getOutput(); if (!model) return; + std::cerr << "setting on EditableDenseThreeDimensionalModel" << std::endl; model->setCompletion(completion); } } diff -r e3b32dc5180b -r 544ab25d2372 transform/TransformFactory.cpp --- a/transform/TransformFactory.cpp Thu Sep 21 11:17:19 2006 +0000 +++ b/transform/TransformFactory.cpp Thu Sep 21 16:43:50 2006 +0000 @@ -79,6 +79,60 @@ return rv; } +std::vector +TransformFactory::getTransformCategories(QString transformType) +{ + if (m_transforms.empty()) populateTransforms(); + + std::set categories; + for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); + i != m_transforms.end(); ++i) { + if (i->second.type == transformType) { + categories.insert(i->second.category); + } + } + + bool haveEmpty = false; + + std::vector rv; + for (std::set::iterator i = categories.begin(); + i != categories.end(); ++i) { + if (*i != "") rv.push_back(*i); + else haveEmpty = true; + } + + if (haveEmpty) rv.push_back(""); // make sure empty category sorts last + + return rv; +} + +std::vector +TransformFactory::getTransformMakers(QString transformType) +{ + if (m_transforms.empty()) populateTransforms(); + + std::set makers; + for (TransformDescriptionMap::const_iterator i = m_transforms.begin(); + i != m_transforms.end(); ++i) { + if (i->second.type == transformType) { + makers.insert(i->second.maker); + } + } + + bool haveEmpty = false; + + std::vector rv; + for (std::set::iterator i = makers.begin(); + i != makers.end(); ++i) { + if (*i != "") rv.push_back(*i); + else haveEmpty = true; + } + + if (haveEmpty) rv.push_back(""); // make sure empty category sorts last + + return rv; +} + void TransformFactory::populateTransforms() { @@ -151,6 +205,8 @@ } QString pluginDescription = plugin->getDescription().c_str(); + QString category = factory->getPluginCategory(pluginId); + Vamp::Plugin::OutputList outputs = plugin->getOutputDescriptors(); @@ -178,6 +234,7 @@ transforms[transformName] = TransformDesc(tr("Analysis Plugins"), + category, transformName, userDescription, friendlyName, @@ -222,6 +279,7 @@ // std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " output ports" << std::endl; QString pluginDescription = descriptor->name.c_str(); + QString category = factory->getPluginCategory(pluginId); for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) { @@ -258,6 +316,7 @@ transforms[transformName] = TransformDesc(tr("Other Plugins"), + category, transformName, userDescription, userDescription, diff -r e3b32dc5180b -r 544ab25d2372 transform/TransformFactory.h --- a/transform/TransformFactory.h Thu Sep 21 11:17:19 2006 +0000 +++ b/transform/TransformFactory.h Thu Sep 21 16:43:50 2006 +0000 @@ -42,13 +42,16 @@ struct TransformDesc { TransformDesc() { } - TransformDesc(QString _type, TransformName _name, QString _description, + TransformDesc(QString _type, QString _category, + TransformName _name, QString _description, QString _friendlyName, QString _maker, QString _units, bool _configurable) : - type(_type), name(_name), description(_description), + type(_type), category(_category), + name(_name), description(_description), friendlyName(_friendlyName), maker(_maker), units(_units), configurable(_configurable) { } QString type; + QString category; TransformName name; QString description; QString friendlyName; @@ -62,6 +65,9 @@ std::vector getAllTransformTypes(); + std::vector getTransformCategories(QString transformType); + std::vector getTransformMakers(QString transformType); + /** * Get a configuration XML string for the given transform (by * asking the user, most likely). Returns true if the transform