changeset 3:36855d576f53

* Updates to putative segmenter program
author Chris Cannam
date Tue, 09 Jun 2009 13:02:03 +0000
parents 965b71bb2d0f
children a88c2a0279ba
files main/MainWindow.cpp main/MainWindow.h
diffstat 2 files changed, 223 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/main/MainWindow.cpp	Thu Apr 23 08:58:15 2009 +0000
+++ b/main/MainWindow.cpp	Tue Jun 09 13:02:03 2009 +0000
@@ -67,6 +67,7 @@
 #include "base/UnitDatabase.h"
 #include "layer/ColourDatabase.h"
 #include "data/osc/OSCQueue.h"
+#include "rdf/PluginRDFDescription.h"
 
 //!!!
 #include "data/model/AggregateWaveModel.h"
@@ -122,6 +123,7 @@
     m_recentFilesMenu(0),
     m_rightButtonMenu(0),
     m_rightButtonPlaybackMenu(0),
+    m_segmentersMenu(0),
     m_deleteSelectedAction(0),
     m_ffwdAction(0),
     m_rwdAction(0),
@@ -165,13 +167,14 @@
 
     settings.setValue("waveform",
                       QString("<layer scale=\"%1\" channelMode=\"%2\"/>")
-                      .arg(int(WaveformLayer::MeterScale))
-//                      .arg(int(WaveformLayer::LinearScale))
+//                      .arg(int(WaveformLayer::MeterScale))
+                      .arg(int(WaveformLayer::LinearScale))
                       .arg(int(WaveformLayer::MergeChannels)));
 
     settings.setValue("timevalues",
                       QString("<layer plotStyle=\"%1\"/>")
-                      .arg(int(TimeValueLayer::PlotStems)));
+//                      .arg(int(TimeValueLayer::PlotStems)));
+                      .arg(int(TimeValueLayer::PlotCurve)));
 
     settings.setValue("spectrogram",
                       QString("<layer channel=\"-1\" windowSize=\"2048\" windowHopLevel=\"2\"/>"));
@@ -185,8 +188,8 @@
     settings.setValue("showstatusbar", false);
     settings.endGroup();
 
-    m_viewManager->setAlignMode(true);
-    m_viewManager->setPlaySoloMode(true);
+//    m_viewManager->setAlignMode(true);
+//    m_viewManager->setPlaySoloMode(true);
     m_viewManager->setToolMode(ViewManager::NavigateMode);
     m_viewManager->setZoomWheelsEnabled(false);
     m_viewManager->setIlluminateLocalFeatures(false);
@@ -319,6 +322,8 @@
 
     frame->setLayout(layout);
 
+    findSegmentationTransforms();
+
     setupMenus();
     setupToolbars();
     setupHelpMenu();
@@ -359,6 +364,7 @@
     setupFileMenu();
 //    setupEditMenu();
     setupViewMenu();
+    setupSegmentersMenu();
 
     m_mainMenusCreated = true;
 }
@@ -611,6 +617,72 @@
 }
 
 void
+MainWindow::setupSegmentersMenu()
+{
+    if (m_segmentersMenu) {
+        m_segmenterActions.clear();
+        m_segmentersMenu->clear();
+    } else {
+	m_segmentersMenu = menuBar()->addMenu(tr("&Segmenters")); 
+        m_segmentersMenu->setTearOffEnabled(true);
+        m_segmentersMenu->setSeparatorsCollapsible(true);
+    }
+
+    std::set<QString> seenNames, duplicateNames, seenPluginNames, duplicatePluginNames;
+    for (unsigned int i = 0; i < m_segmentationTransforms.size(); ++i) {
+        QString name = m_segmentationTransforms[i].name;
+        QString pluginName = name.section(": ", 0, 0);
+        if (seenNames.find(name) != seenNames.end()) {
+            duplicateNames.insert(name);
+        } else {
+            seenNames.insert(name);
+        }
+        if (seenPluginNames.find(pluginName) != seenPluginNames.end()) {
+            duplicatePluginNames.insert(pluginName);
+        } else {
+            seenPluginNames.insert(pluginName);
+        }
+    }
+
+    for (unsigned int i = 0; i < m_segmentationTransforms.size(); ++i) {
+	
+	QString name = m_segmentationTransforms[i].name;
+	if (name == "") name = m_segmentationTransforms[i].identifier;
+
+        QString maker = m_segmentationTransforms[i].maker;
+        if (maker == "") maker = tr("Unknown");
+        maker.replace(QRegExp(tr(" [\\(<].*$")), "");
+
+        QString pluginName = name.section(": ", 0, 0);
+        QString output = name.section(": ", 1);
+
+        if (duplicateNames.find(pluginName) != duplicateNames.end()) {
+            pluginName = QString("%1 <%2>")
+                .arg(pluginName)
+                .arg(m_segmentationTransforms[i].identifier.section(':', 1, 1));
+            if (output == "") {
+                name = pluginName;
+            } else {
+                name = QString("%1: %2")
+                    .arg(pluginName)
+                    .arg(output);
+            }
+        } else if (duplicatePluginNames.find(pluginName) ==
+                   duplicatePluginNames.end()) {
+            name = pluginName;
+        }            
+
+	QAction *action = new QAction(tr("%1...").arg(name), this);
+	connect(action, SIGNAL(triggered()), this, SLOT(addSegmentation()));
+	m_segmenterActions[action] = m_segmentationTransforms[i].identifier;
+	connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
+        action->setStatusTip(m_segmentationTransforms[i].longDescription);
+
+        m_segmentersMenu->addAction(action);
+    }
+}
+
+void
 MainWindow::setupHelpMenu()
 {
     QMenu *menu = menuBar()->addMenu(tr("&Help"));
@@ -928,15 +1000,18 @@
     createDocument();
     m_document->setAutoAlignment(true);
 
-    Pane *pane = m_paneStack->addPane();
+    Pane *pane;
+    Layer *waveform;
 
-    connect(pane, SIGNAL(contextHelpChanged(const QString &)),
-            this, SLOT(contextHelpChanged(const QString &)));
-
-    Layer *waveform = m_document->createMainModelLayer(LayerFactory::Waveform);
-    m_document->addLayerToView(pane, waveform);
-
-    m_overview->registerView(pane);
+    for (int i = 0; i < 2; ++i) {
+        pane = m_paneStack->addPane();
+        pane->setFollowGlobalPan(false);
+        connect(pane, SIGNAL(contextHelpChanged(const QString &)),
+                this, SLOT(contextHelpChanged(const QString &)));
+        waveform = m_document->createMainModelLayer(LayerFactory::Waveform);
+        m_document->addLayerToView(pane, waveform);
+        m_overview->registerView(pane);
+    }
 
     CommandHistory::getInstance()->clear();
     CommandHistory::getInstance()->documentSaved();
@@ -1073,12 +1148,16 @@
     }
 }
 
-Model *
+bool
 MainWindow::selectExistingModeLayer(Pane *pane, QString name)
 {   
-    Model *model = 0;
+    // return false if we do not need to go on and create a new layer
+    // -- either because a suitable hidden one has been dredged up, or
+    // because no layer that needed replacing was found in this pane
 
-    bool have = false;
+    if (!m_document) return false;
+
+    bool required = false;
 
     for (int i = 0; i < pane->getLayerCount(); ++i) {
         
@@ -1087,7 +1166,20 @@
         
         Model *lm = layer->getModel();
         while (lm && lm->getSourceModel()) lm = lm->getSourceModel();
-        if (dynamic_cast<WaveFileModel *>(lm)) model = lm;
+        if (dynamic_cast<WaveFileModel *>(lm)) {
+            if (lm == m_document->getMainModel()) {
+                required = true;
+                break;
+            }
+        }
+    }
+    
+    if (!required) return false;
+        
+    for (int i = 0; i < pane->getLayerCount(); ++i) {
+        
+        Layer *layer = pane->getLayer(i);
+        if (!layer) continue;
         
         QString ln = layer->objectName();
         if (ln != name) {
@@ -1095,11 +1187,7 @@
             m_document->removeLayerFromView(pane, layer);
             continue;
         }
-        
-        have = true;
     }
-    
-    if (have) return 0;
 
     LayerSet &ls = m_hiddenLayers[pane];
     bool found = false;
@@ -1112,9 +1200,97 @@
         }
     }
 
-    if (found) return 0;
+    return !found;
+}
 
-    return model;
+void
+MainWindow::addSegmentation()
+{
+    QObject *s = sender();
+    QAction *action = dynamic_cast<QAction *>(s);
+    
+    if (!action) {
+	std::cerr << "WARNING: MainWindow::addSegmentation: sender is not an action"
+		  << std::endl;
+	return;
+    }
+
+    TransformActionMap::iterator i = m_segmenterActions.find(action);
+    if (i == m_segmenterActions.end()) return;
+
+    // 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).
+
+    QString transformId = i->second;
+
+    Transform transform = TransformFactory::getInstance()->
+        getDefaultTransformFor(transformId);
+
+    Model *defaultInputModel = m_document->getMainModel();
+    std::vector<Model *> candidateInputModels;
+    candidateInputModels.push_back(defaultInputModel);
+
+    ModelTransformer::Input input = ModelTransformerFactory::getInstance()->
+        getConfigurationForTransform
+        (transform,
+         candidateInputModels,
+         defaultInputModel,
+         m_playSource,
+         0,
+         0);
+
+    if (!input.getModel()) return;
+
+//    std::cerr << "MainWindow::addLayer: Input model is " << input.getModel() << " \"" << input.getModel()->objectName().toStdString() << "\"" << std::endl << "transform:" << std::endl << transform.toXmlString().toStdString() << std::endl;
+
+    Layer *newLayer = m_document->createDerivedLayer(transform, input);
+
+    if (newLayer) {
+
+        AddPaneCommand *command = new AddPaneCommand(this);
+        CommandHistory::getInstance()->addCommand(command);
+
+        Pane *pane = command->getPane();
+        if (!pane) return;
+
+        // Set the source model to NULL to avoid us treating it as a
+        // different visualisation for the main model and replacing it
+        // when one of the visualisation mode toggles is activated
+        newLayer->getModel()->setSourceModel(0);
+
+        m_document->addLayerToView(pane, newLayer);
+        m_document->setChannel(newLayer, input.getChannel());
+//        m_paneStack->setCurrentLayer(pane, newLayer);
+    }
+
+    updateMenuStates();
+}
+
+void
+MainWindow::findSegmentationTransforms()
+{
+    m_segmentationTransforms.clear();
+    TransformList all = 
+        TransformFactory::getInstance()->getAllTransformDescriptions();
+    for (TransformList::iterator i = all.begin(); i != all.end(); ++i) {
+        if (i->type != Transform::FeatureExtraction) continue;
+        Transform t;
+        t.setIdentifier(i->identifier);
+        QString pluginId = t.getPluginIdentifier();
+        QString outputId = t.getOutput();
+        PluginRDFDescription desc(pluginId);
+        if (!desc.haveDescription()) continue;
+        QString feature = desc.getOutputEventTypeURI(outputId);
+        if (feature == "") continue;
+        std::cerr << "Feature: " << feature.toStdString() << std::endl;
+        //!!! This is grotesque
+        if (feature.endsWith("Segment") || feature.endsWith("Change")) {
+            m_segmentationTransforms.push_back(*i);
+        }
+    }
+    std::cerr << "MainWindow::findSegmentationTransforms: Found "
+              << m_segmentationTransforms.size() << " transforms" << std::endl;
 }
 
 void
@@ -1127,7 +1303,8 @@
         Pane *pane = m_paneStack->getPane(i);
         if (!pane) continue;
 
-        Model *model = selectExistingModeLayer(pane, name);
+        if (!selectExistingModeLayer(pane, name)) continue;
+        Model *model = m_document->getMainModel();
         if (!model) continue;
 
         TransformId id = "vamp:qm-vamp-plugins:qm-onsetdetector:detection_fn";
@@ -1145,7 +1322,8 @@
 
 //!!! no equivalent for this yet            context.updates = false;
 
-            Layer *newLayer = m_document->createDerivedLayer(transform, model);
+            Layer *newLayer = m_document->createDerivedLayer
+                (transform, model);
 
             if (newLayer) {
                 newLayer->setObjectName(name);
@@ -1154,7 +1332,7 @@
             }
             
         } else {
-            std::cerr << "No Aubio onset detector plugin available" << std::endl;
+            std::cerr << "No QM onset detector plugin available" << std::endl;
         }
     }
 
@@ -1171,7 +1349,8 @@
         Pane *pane = m_paneStack->getPane(i);
         if (!pane) continue;
 
-        Model *model = selectExistingModeLayer(pane, name);
+        if (!selectExistingModeLayer(pane, name)) continue;
+        Model *model = m_document->getMainModel();
         if (!model) continue;
 
         Layer *newLayer = m_document->createLayer(LayerFactory::Waveform);
@@ -1194,7 +1373,8 @@
         Pane *pane = m_paneStack->getPane(i);
         if (!pane) continue;
 
-        Model *model = selectExistingModeLayer(pane, name);
+        if (!selectExistingModeLayer(pane, name)) continue;
+        Model *model = m_document->getMainModel();
         if (!model) continue;
 
         Layer *newLayer = m_document->createLayer(LayerFactory::Spectrogram);
@@ -1217,7 +1397,8 @@
         Pane *pane = m_paneStack->getPane(i);
         if (!pane) continue;
 
-        Model *model = selectExistingModeLayer(pane, name);
+        if (!selectExistingModeLayer(pane, name)) continue;
+        Model *model = m_document->getMainModel();
         if (!model) continue;
 
         Layer *newLayer = m_document->createLayer
--- a/main/MainWindow.h	Thu Apr 23 08:58:15 2009 +0000
+++ b/main/MainWindow.h	Tue Jun 09 13:02:03 2009 +0000
@@ -29,6 +29,7 @@
 #include "base/RecentFiles.h"
 #include "layer/LayerFactory.h"
 #include "transform/Transform.h"
+#include "transform/TransformDescription.h"
 #include "framework/SVFileReader.h"
 #include "data/fileio/FileFinder.h"
 #include <map>
@@ -131,6 +132,8 @@
 
     virtual void setupRecentFilesMenu();
 
+    virtual void addSegmentation();
+
     virtual void showLayerTree();
 
     virtual void handleOSCMessage(const OSCMessage &);
@@ -156,6 +159,7 @@
     QMenu                   *m_recentFilesMenu;
     QMenu                   *m_rightButtonMenu;
     QMenu                   *m_rightButtonPlaybackMenu;
+    QMenu                   *m_segmentersMenu;
 
     QAction                 *m_deleteSelectedAction;
     QAction                 *m_ffwdAction;
@@ -170,10 +174,15 @@
     typedef std::map<Pane *, LayerSet> PaneLayerMap;
     PaneLayerMap             m_hiddenLayers;
 
+    TransformList            m_segmentationTransforms;
+    
+    void findSegmentationTransforms();
+
     virtual void setupMenus();
     virtual void setupFileMenu();
     virtual void setupEditMenu();
     virtual void setupViewMenu();
+    virtual void setupSegmentersMenu();
     virtual void setupHelpMenu();
     virtual void setupToolbars();
 
@@ -189,11 +198,14 @@
     typedef std::map<Model *, Model *> ModelPairMap;
     ModelPairMap m_fftModelMap;
 
+    typedef std::map<QAction *, TransformId> TransformActionMap;
+    TransformActionMap m_segmenterActions;
+
     virtual void closeEvent(QCloseEvent *e);
     bool checkSaveModified();
 
     virtual void configureNewPane(Pane *p);
-    virtual Model *selectExistingModeLayer(Pane *, QString);
+    virtual bool selectExistingModeLayer(Pane *, QString);
 
     virtual void updateVisibleRangeDisplay(Pane *p) const;
 };