changeset 402:a0eedd10dee3 cxx11-types

Merge from default branch
author Chris Cannam
date Mon, 23 Mar 2015 10:33:32 +0000
parents 4b9b7ff3f19c (current diff) 1610b2b03203 (diff)
children cc33cdb114f6
files .hgsubstate configure configure.ac src/Analyser.cpp src/Analyser.h src/MainWindow.cpp src/MainWindow.h src/main.cpp
diffstat 8 files changed, 293 insertions(+), 123 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsubstate	Wed Mar 11 12:20:06 2015 +0000
+++ b/.hgsubstate	Mon Mar 23 10:33:32 2015 +0000
@@ -1,7 +1,7 @@
 e32a354434aa5fa7440efa17b716aacd761049fa chp
 d16f0fd6db6104d87882bc43788a3bb1b0f8c528 dataquay
-062f0e49187789937b6162d2904b1af20872ed5e pyin
+4cbbd87a8c7f95ccac8e7900eef4f08bbdbb032f pyin
 553a5f65ef64811747a6613f759622d655db63c1 sv-dependency-builds
 9429622647e63d68cd2aedf7c6c29ba6adaf4736 svapp
-98d4dabbf740a4224edeccea6c226e68d6d3ea40 svcore
-63510940080459584e0e7737cfa674f0f8312a02 svgui
+0559f25b99f2208ffb9ebb74ed173d3ec66f0e41 svcore
+50be12cf280271763a61c8630e442fd5f6e4dcc6 svgui
--- a/.hgtags	Wed Mar 11 12:20:06 2015 +0000
+++ b/.hgtags	Mon Mar 23 10:33:32 2015 +0000
@@ -10,3 +10,4 @@
 29455a21880ef7e60ac0b23beee34262e92a0284 v0.5
 29455a21880ef7e60ac0b23beee34262e92a0284 v0.5
 846df0ea9c82206ed9185536d7d3eab35eb68b07 v0.5
+7178bb4dcdfb77aac6f4efcd609233b95e9a46e7 v0.6
--- a/src/Analyser.cpp	Wed Mar 11 12:20:06 2015 +0000
+++ b/src/Analyser.cpp	Mon Mar 23 10:33:32 2015 +0000
@@ -374,7 +374,7 @@
 
     if (lowamp) {
         cerr << "setting parameters for lowamp suppression" << endl;
-        t.setParameter("lowampsuppression", 0.2f);
+        t.setParameter("lowampsuppression", 0.1f);
     } else {
         cerr << "setting parameters for no lowamp suppression" << endl;
         t.setParameter("lowampsuppression", 0.0f);
@@ -408,9 +408,9 @@
         pitchLayer->setBaseColour(cdb->getColourIndex(tr("Black")));
         PlayParameters *params = pitchLayer->getPlayParameters();
         if (params) params->setPlayPan(1);
+        connect(pitchLayer, SIGNAL(modelCompletionChanged()),
+                this, SLOT(layerCompletionChanged()));
     }
-    connect(pitchLayer, SIGNAL(modelCompletionChanged()),
-            this, SLOT(layerCompletionChanged()));
     
     FlexiNoteLayer *flexiNoteLayer = 
         qobject_cast<FlexiNoteLayer *>(m_layers[Notes]);
@@ -418,19 +418,47 @@
         flexiNoteLayer->setBaseColour(cdb->getColourIndex(tr("Bright Blue")));
         PlayParameters *params = flexiNoteLayer->getPlayParameters();
         if (params) params->setPlayPan(1);
+        connect(flexiNoteLayer, SIGNAL(modelCompletionChanged()),
+                this, SLOT(layerCompletionChanged()));
+        connect(flexiNoteLayer, SIGNAL(reAnalyseRegion(int, int, float, float)),
+                this, SLOT(reAnalyseRegion(int, int, float, float)));
+        connect(flexiNoteLayer, SIGNAL(materialiseReAnalysis()),
+                this, SLOT(materialiseReAnalysis()));
     }
-    connect(flexiNoteLayer, SIGNAL(modelCompletionChanged()),
-            this, SLOT(layerCompletionChanged()));
     
     return "";
 }
 
+void
+Analyser::reAnalyseRegion(int frame0, int frame1, float freq0, float freq1)
+{
+    cerr << "Analyser::reAnalyseRegion(" << frame0 << ", " << frame1
+         << ", " << freq0 << ", " << freq1 << ")" << endl;
+    showPitchCandidates(true);
+    (void)reAnalyseSelection(Selection(frame0, frame1),
+                             FrequencyRange(freq0, freq1));
+}
+
+void
+Analyser::materialiseReAnalysis()
+{
+    if (m_reAnalysingSelection.isEmpty()) return;
+    switchPitchCandidate(m_reAnalysingSelection, true); // or false, doesn't matter
+}
+
 QString
 Analyser::reAnalyseSelection(Selection sel, FrequencyRange range)
 {
     QMutexLocker locker(&m_asyncMutex);
 
-    if (sel == m_reAnalysingSelection || sel.isEmpty()) return "";
+    if (!m_reAnalysingSelection.isEmpty()) {
+        if (sel == m_reAnalysingSelection && range == m_reAnalysingRange) {
+            cerr << "selection & range are same as current analysis, ignoring" << endl;
+            return "";
+        }
+    }
+
+    if (sel.isEmpty()) return "";
 
     if (m_currentAsyncHandle) {
         m_document->cancelAsyncLayerCreation(m_currentAsyncHandle);
@@ -444,6 +472,7 @@
     }
 
     m_reAnalysingSelection = sel;
+    m_reAnalysingRange = range;
 
     m_preAnalysis = Clipboard();
     Layer *myLayer = m_layers[PitchTrack];
--- a/src/Analyser.h	Wed Mar 11 12:20:06 2015 +0000
+++ b/src/Analyser.h	Mon Mar 23 10:33:32 2015 +0000
@@ -108,6 +108,9 @@
         bool isConstrained() const { return min != max; }
         double min;
         double max;
+        bool operator==(const FrequencyRange &r) {
+            return min == r.min && max == r.max;
+        }
     };
 
     /**
@@ -215,6 +218,8 @@
 protected slots:
     void layerAboutToBeDeleted(Layer *);
     void layerCompletionChanged();
+    void reAnalyseRegion(int, int, float, float);
+    void materialiseReAnalysis();
 
 protected:
     Document *m_document;
@@ -226,6 +231,7 @@
 
     Clipboard m_preAnalysis;
     Selection m_reAnalysingSelection;
+    FrequencyRange m_reAnalysingRange;
     std::vector<Layer *> m_reAnalysisCandidates;
     int m_currentCandidate;
     bool m_candidatesVisible;
--- a/src/MainWindow.cpp	Wed Mar 11 12:20:06 2015 +0000
+++ b/src/MainWindow.cpp	Mon Mar 23 10:33:32 2015 +0000
@@ -88,7 +88,7 @@
 using std::vector;
 
 
-MainWindow::MainWindow(bool withAudioOutput) :
+MainWindow::MainWindow(bool withAudioOutput, bool withSonification, bool withSpectrogram) :
     MainWindowBase(withAudioOutput, false),
     m_overview(0),
     m_mainMenusCreated(false),
@@ -102,7 +102,9 @@
     m_intelligentActionOn(true), //GF: !!! temporary
     m_activityLog(new ActivityLog()),
     m_keyReference(new KeyReference()),
-    m_selectionAnchor(0)
+    m_selectionAnchor(0),
+    m_withSonification(withSonification),
+    m_withSpectrogram(withSpectrogram)
 {
     setWindowTitle(QApplication::applicationName());
 
@@ -160,8 +162,9 @@
     m_viewManager->setToolMode(ViewManager::NavigateMode);
     m_viewManager->setZoomWheelsEnabled(false);
     m_viewManager->setIlluminateLocalFeatures(true);
-    m_viewManager->setShowWorkTitle(true);
+    m_viewManager->setShowWorkTitle(false);
     m_viewManager->setShowCentreLine(false);
+    m_viewManager->setShowDuration(false);
     m_viewManager->setOverlayMode(ViewManager::GlobalOverlays);
 
     connect(m_viewManager, SIGNAL(selectionChangedByUser()),
@@ -187,8 +190,9 @@
     scroll->setWidget(m_paneStack);
 
     m_overview = new Overview(frame);
+    m_overview->setPlaybackFollow(PlaybackScrollPage);
     m_overview->setViewManager(m_viewManager);
-    m_overview->setFixedHeight(40);
+    m_overview->setFixedHeight(60);
 #ifndef _WIN32
     // For some reason, the contents of the overview never appear if we
     // make this setting on Windows.  I have no inclination at the moment
@@ -201,6 +205,7 @@
     m_panLayer = new WaveformLayer;
     m_panLayer->setChannelMode(WaveformLayer::MergeChannels);
     m_panLayer->setAggressiveCacheing(true);
+    m_panLayer->setGain(0.5);
     m_overview->addLayer(m_panLayer);
 
     if (m_viewManager->getGlobalDarkBackground()) {
@@ -253,41 +258,44 @@
     connect(m_gainAudio, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
     connect(m_gainAudio, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
 
-    m_gainPitch = new AudioDial(frame);
-    m_gainPitch->setMeterColor(Qt::darkRed);
-    m_gainPitch->setMinimum(-50);
-    m_gainPitch->setMaximum(50);
-    m_gainPitch->setValue(0);
-    m_gainPitch->setDefaultValue(0);
-    m_gainPitch->setFixedWidth(24);
-    m_gainPitch->setFixedHeight(24);
-    m_gainPitch->setNotchesVisible(true);
-    m_gainPitch->setPageStep(10);
-    m_gainPitch->setObjectName(tr("Pitch Track Gain"));
-    m_gainPitch->setRangeMapper(new LinearRangeMapper(-50, 50, -25, 25, tr("dB")));
-    m_gainPitch->setShowToolTip(true);
-    connect(m_gainPitch, SIGNAL(valueChanged(int)),
-            this, SLOT(pitchGainChanged(int)));
-    connect(m_gainPitch, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
-    connect(m_gainPitch, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
-
-    m_gainNotes = new AudioDial(frame);
-    m_gainNotes->setMeterColor(Qt::darkRed);
-    m_gainNotes->setMinimum(-50);
-    m_gainNotes->setMaximum(50);
-    m_gainNotes->setValue(0);
-    m_gainNotes->setDefaultValue(0);
-    m_gainNotes->setFixedWidth(24);
-    m_gainNotes->setFixedHeight(24);
-    m_gainNotes->setNotchesVisible(true);
-    m_gainNotes->setPageStep(10);
-    m_gainNotes->setObjectName(tr("Pitch Track Gain"));
-    m_gainNotes->setRangeMapper(new LinearRangeMapper(-50, 50, -25, 25, tr("dB")));
-    m_gainNotes->setShowToolTip(true);
-    connect(m_gainNotes, SIGNAL(valueChanged(int)),
-            this, SLOT(notesGainChanged(int)));
-    connect(m_gainNotes, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
-    connect(m_gainNotes, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
+    if (m_withSonification)
+    {   
+        m_gainPitch = new AudioDial(frame);
+        m_gainPitch->setMeterColor(Qt::darkRed);
+        m_gainPitch->setMinimum(-50);
+        m_gainPitch->setMaximum(50);
+        m_gainPitch->setValue(0);
+        m_gainPitch->setDefaultValue(0);
+        m_gainPitch->setFixedWidth(24);
+        m_gainPitch->setFixedHeight(24);
+        m_gainPitch->setNotchesVisible(true);
+        m_gainPitch->setPageStep(10);
+        m_gainPitch->setObjectName(tr("Pitch Track Gain"));
+        m_gainPitch->setRangeMapper(new LinearRangeMapper(-50, 50, -25, 25, tr("dB")));
+        m_gainPitch->setShowToolTip(true);
+        connect(m_gainPitch, SIGNAL(valueChanged(int)),
+                this, SLOT(pitchGainChanged(int)));
+        connect(m_gainPitch, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
+        connect(m_gainPitch, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
+
+        m_gainNotes = new AudioDial(frame);
+        m_gainNotes->setMeterColor(Qt::darkRed);
+        m_gainNotes->setMinimum(-50);
+        m_gainNotes->setMaximum(50);
+        m_gainNotes->setValue(0);
+        m_gainNotes->setDefaultValue(0);
+        m_gainNotes->setFixedWidth(24);
+        m_gainNotes->setFixedHeight(24);
+        m_gainNotes->setNotchesVisible(true);
+        m_gainNotes->setPageStep(10);
+        m_gainNotes->setObjectName(tr("Note Gain"));
+        m_gainNotes->setRangeMapper(new LinearRangeMapper(-50, 50, -25, 25, tr("dB")));
+        m_gainNotes->setShowToolTip(true);
+        connect(m_gainNotes, SIGNAL(valueChanged(int)),
+                this, SLOT(notesGainChanged(int)));
+        connect(m_gainNotes, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
+        connect(m_gainNotes, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
+    }
     // End of Gain controls
 
     // Pan controls
@@ -310,41 +318,47 @@
     connect(m_panAudio, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
     connect(m_panAudio, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
 
-    m_panPitch = new AudioDial(frame);
-    m_panPitch->setMeterColor(Qt::darkGreen);
-    m_panPitch->setMinimum(-100);
-    m_panPitch->setMaximum(100);
-    m_panPitch->setValue(100);
-    m_panPitch->setDefaultValue(100);
-    m_panPitch->setFixedWidth(24);
-    m_panPitch->setFixedHeight(24);
-    m_panPitch->setNotchesVisible(true);
-    m_panPitch->setPageStep(10);
-    m_panPitch->setObjectName(tr("Pitch Track Pan"));
-    m_panPitch->setRangeMapper(new LinearRangeMapper(-100, 100, -100, 100, tr("")));
-    m_panPitch->setShowToolTip(true);
-    connect(m_panPitch, SIGNAL(valueChanged(int)),
-            this, SLOT(pitchPanChanged(int)));
-    connect(m_panPitch, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
-    connect(m_panPitch, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
-
-    m_panNotes = new AudioDial(frame);
-    m_panNotes->setMeterColor(Qt::darkGreen);
-    m_panNotes->setMinimum(-100);
-    m_panNotes->setMaximum(100);
-    m_panNotes->setValue(100);
-    m_panNotes->setDefaultValue(100);
-    m_panNotes->setFixedWidth(24);
-    m_panNotes->setFixedHeight(24);
-    m_panNotes->setNotchesVisible(true);
-    m_panNotes->setPageStep(10);
-    m_panNotes->setObjectName(tr("Notes Track Pan"));
-    m_panNotes->setRangeMapper(new LinearRangeMapper(-100, 100, -100, 100, tr("")));
-    m_panNotes->setShowToolTip(true);
-    connect(m_panNotes, SIGNAL(valueChanged(int)),
-            this, SLOT(notesPanChanged(int)));
-    connect(m_panNotes, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
-    connect(m_panNotes, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
+
+
+    if (m_withSonification)
+    {   
+        m_panPitch = new AudioDial(frame);
+        m_panPitch->setMeterColor(Qt::darkGreen);
+        m_panPitch->setMinimum(-100);
+        m_panPitch->setMaximum(100);
+        m_panPitch->setValue(100);
+        m_panPitch->setDefaultValue(100);
+        m_panPitch->setFixedWidth(24);
+        m_panPitch->setFixedHeight(24);
+        m_panPitch->setNotchesVisible(true);
+        m_panPitch->setPageStep(10);
+        m_panPitch->setObjectName(tr("Pitch Track Pan"));
+        m_panPitch->setRangeMapper(new LinearRangeMapper(-100, 100, -100, 100, tr("")));
+        m_panPitch->setShowToolTip(true);
+        connect(m_panPitch, SIGNAL(valueChanged(int)),
+                this, SLOT(pitchPanChanged(int)));
+        connect(m_panPitch, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
+        connect(m_panPitch, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
+
+        m_panNotes = new AudioDial(frame);
+        m_panNotes->setMeterColor(Qt::darkGreen);
+        m_panNotes->setMinimum(-100);
+        m_panNotes->setMaximum(100);
+        m_panNotes->setValue(100);
+        m_panNotes->setDefaultValue(100);
+        m_panNotes->setFixedWidth(24);
+        m_panNotes->setFixedHeight(24);
+        m_panNotes->setNotchesVisible(true);
+        m_panNotes->setPageStep(10);
+        m_panNotes->setObjectName(tr("Note Pan"));
+        m_panNotes->setRangeMapper(new LinearRangeMapper(-100, 100, -100, 100, tr("")));
+        m_panNotes->setShowToolTip(true);
+        connect(m_panNotes, SIGNAL(valueChanged(int)),
+                this, SLOT(notesPanChanged(int)));
+        connect(m_panNotes, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
+        connect(m_panNotes, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));    
+    }
+    
     // End of Pan controls
 
     layout->setSpacing(4);
@@ -412,6 +426,17 @@
 MainWindow::setupMenus()
 {
     if (!m_mainMenusCreated) {
+
+#ifdef Q_OS_LINUX
+        // In Ubuntu 14.04 the window's menu bar goes missing entirely
+        // if the user is running any desktop environment other than Unity
+        // (in which the faux single-menubar appears). The user has a
+        // workaround, to remove the appmenu-qt5 package, but that is
+        // awkward and the problem is so severe that it merits disabling
+        // the system menubar integration altogether. Like this:
+	menuBar()->setNativeMenuBar(false);
+#endif
+
         m_rightButtonMenu = new QMenu();
     }
 
@@ -918,8 +943,16 @@
     IconLoader il;
 
     QString name = QApplication::applicationName();
-
-    QAction *action = new QAction(il.load("help"),
+    QAction *action;
+
+    action = new QAction(tr("&Key and Mouse Reference"), this);
+    action->setShortcut(tr("F2"));
+    action->setStatusTip(tr("Open a window showing the keystrokes you can use in %1").arg(name));
+    connect(action, SIGNAL(triggered()), this, SLOT(keyReference()));
+    m_keyReference->registerShortcut(action);
+    menu->addAction(action);
+
+    action = new QAction(il.load("help"),
                                   tr("&Help Reference"), this); 
     action->setShortcut(tr("F1"));
     action->setStatusTip(tr("Open the %1 reference manual").arg(name)); 
@@ -927,12 +960,6 @@
     m_keyReference->registerShortcut(action);
     menu->addAction(action);
 
-    action = new QAction(tr("&Key and Mouse Reference"), this);
-    action->setShortcut(tr("F2"));
-    action->setStatusTip(tr("Open a window showing the keystrokes you can use in %1").arg(name));
-    connect(action, SIGNAL(triggered()), this, SLOT(keyReference()));
-    m_keyReference->registerShortcut(action);
-    menu->addAction(action);
     
     action = new QAction(tr("%1 on the &Web").arg(name), this); 
     action->setStatusTip(tr("Open the %1 website").arg(name)); 
@@ -1168,14 +1195,18 @@
     connect(m_showPitch, SIGNAL(triggered()), this, SLOT(showPitchToggled()));
     connect(this, SIGNAL(canPlay(bool)), m_showPitch, SLOT(setEnabled(bool)));
 
-    m_playPitch = toolbar->addAction(il.load("speaker"), tr("Play Pitch Track"));
+    if (!m_withSonification) 
+    {
+        m_playPitch = new QAction(tr("Play Pitch Track"), this);
+    } else {
+        m_playPitch = toolbar->addAction(il.load("speaker"), tr("Play Pitch Track"));
+        toolbar->addWidget(m_gainPitch);
+        toolbar->addWidget(m_panPitch);
+    }
     m_playPitch->setCheckable(true);
     connect(m_playPitch, SIGNAL(triggered()), this, SLOT(playPitchToggled()));
     connect(this, SIGNAL(canPlayPitch(bool)), m_playPitch, SLOT(setEnabled(bool)));
 
-    toolbar->addWidget(m_gainPitch);
-    toolbar->addWidget(m_panPitch);
-
     // Notes
     spacer = new QLabel;
     spacer->setFixedWidth(40);
@@ -1186,25 +1217,35 @@
     connect(m_showNotes, SIGNAL(triggered()), this, SLOT(showNotesToggled()));
     connect(this, SIGNAL(canPlay(bool)), m_showNotes, SLOT(setEnabled(bool)));
 
-    m_playNotes = toolbar->addAction(il.load("speaker"), tr("Play Notes"));
+    if (!m_withSonification) 
+    {
+        m_playNotes = new QAction(tr("Play Notes"), this);
+    } else {
+        m_playNotes = toolbar->addAction(il.load("speaker"), tr("Play Notes"));
+        toolbar->addWidget(m_gainNotes);
+        toolbar->addWidget(m_panNotes);
+    }
     m_playNotes->setCheckable(true);
     connect(m_playNotes, SIGNAL(triggered()), this, SLOT(playNotesToggled()));
     connect(this, SIGNAL(canPlayNotes(bool)), m_playNotes, SLOT(setEnabled(bool)));
 
-    toolbar->addWidget(m_gainNotes);
-    toolbar->addWidget(m_panNotes);
-
     // Spectrogram
     spacer = new QLabel;
     spacer->setFixedWidth(40);
     toolbar->addWidget(spacer);
 
-    m_showSpect = toolbar->addAction(il.load("spectrogram"), tr("Show Spectrogram"));
+    if (!m_withSpectrogram)
+    {
+        m_showSpect = new QAction(tr("Show Spectrogram"), this);
+    } else {
+        m_showSpect = toolbar->addAction(il.load("spectrogram"), tr("Show Spectrogram"));
+    }
     m_showSpect->setCheckable(true);
     connect(m_showSpect, SIGNAL(triggered()), this, SLOT(showSpectToggled()));
     connect(this, SIGNAL(canPlay(bool)), m_showSpect, SLOT(setEnabled(bool)));
 
     Pane::registerShortcuts(*m_keyReference);
+
 }
 
 
@@ -1441,7 +1482,7 @@
     } else {
         settings.setValue("playpitchwas", m_playPitch->isChecked());
     }
-    m_analyser->setAudible(Analyser::PitchTrack, playOn);
+    m_analyser->setAudible(Analyser::PitchTrack, playOn && m_withSonification);
     m_playPitch->setChecked(playOn);
 
     settings.endGroup();
@@ -1470,7 +1511,7 @@
     } else {
         settings.setValue("playnoteswas", m_playNotes->isChecked());
     }
-    m_analyser->setAudible(Analyser::Notes, playOn);
+    m_analyser->setAudible(Analyser::Notes, playOn && m_withSonification);
     m_playNotes->setChecked(playOn);
 
     settings.endGroup();
@@ -1568,7 +1609,11 @@
     m_document->setAutoAlignment(true);
 
     Pane *pane = m_paneStack->addPane();
-
+    pane->setPlaybackFollow(PlaybackScrollPage);
+
+    m_viewManager->setGlobalCentreFrame
+        (pane->getFrameForX(width() / 2));
+    
     connect(pane, SIGNAL(contextHelpChanged(const QString &)),
             this, SLOT(contextHelpChanged(const QString &)));
 
@@ -1649,7 +1694,7 @@
 
     if (path.isEmpty()) return;
 
-    FileOpenStatus status = open(path, ReplaceSession);
+    FileOpenStatus status = openPath(path, ReplaceSession);
 
     if (status == FileOpenFailed) {
         QMessageBox::critical(this, tr("Failed to open file"),
@@ -1679,7 +1724,7 @@
 
     if (text.isEmpty()) return;
 
-    FileOpenStatus status = open(text, ReplaceSession);
+    FileOpenStatus status = openPath(text, ReplaceSession);
 
     if (status == FileOpenFailed) {
         QMessageBox::critical(this, tr("Failed to open location"),
@@ -1705,7 +1750,7 @@
     QString path = action->text();
     if (path == "") return;
 
-    FileOpenStatus status = open(path, ReplaceSession);
+    FileOpenStatus status = openPath(path, ReplaceSession);
 
     if (status == FileOpenFailed) {
         QMessageBox::critical(this, tr("Failed to open location"),
@@ -1743,7 +1788,7 @@
 
     for (QStringList::iterator i = uriList.begin(); i != uriList.end(); ++i) {
 
-        FileOpenStatus status = open(*i, ReplaceSession);
+        FileOpenStatus status = openPath(*i, ReplaceSession);
 
         if (status == FileOpenFailed) {
             QMessageBox::critical(this, tr("Failed to open dropped URL"),
@@ -2895,7 +2940,7 @@
     }
 
     bool haveSelection = false;
-    size_t startFrame = 0, endFrame = 0;
+    int startFrame = 0, endFrame = 0;
 
     if (m_viewManager && m_viewManager->haveInProgressSelection()) {
 
@@ -2935,7 +2980,7 @@
             .arg(startStr).arg(endStr).arg(durationStr);
     }
     
-    statusBar()->showMessage(m_myStatusMessage);
+    getStatusLabel()->setText(m_myStatusMessage);
 }
 
 void
@@ -3076,7 +3121,10 @@
         selectionStrip = m_paneStack->getPane(1);
     }
 
+    pane->setPlaybackFollow(PlaybackScrollPage);
+
     if (selectionStrip) {
+        selectionStrip->setPlaybackFollow(PlaybackScrollPage);
         selectionStrip->setFixedHeight(26);
         m_paneStack->sizePanesEqually();
         m_viewManager->clearToolModeOverrides();
@@ -3101,6 +3149,17 @@
                  QMessageBox::Ok);
         }
     }
+
+    if (!m_withSpectrogram) 
+    {
+        m_analyser->setVisible(Analyser::Spectrogram, false);
+    }
+
+    if (!m_withSonification) 
+    {
+        m_analyser->setAudible(Analyser::PitchTrack, false);
+        m_analyser->setAudible(Analyser::Notes, false);
+    }
 }
 
 void
@@ -3222,7 +3281,7 @@
 MainWindow::help()
 {
     //!!! todo: help URL!
-    openHelpUrl(tr("http://code.soundsoftware.ac.uk/projects/tony/"));
+    openHelpUrl(tr("http://code.soundsoftware.ac.uk/projects/tony/wiki/Reference"));
 }
 
 void
@@ -3280,5 +3339,73 @@
     settings.endGroup();
 }
 
-
-
+void
+MainWindow::ffwd()
+{
+    if (!getMainModel()) return;
+
+    int frame = m_viewManager->getPlaybackFrame();
+    ++frame;
+
+    size_t sr = getMainModel()->getSampleRate();
+
+    // The step is supposed to scale and be as wide as a step of 
+    // m_defaultFfwdRwdStep seconds at zoom level 720 and sr = 44100
+    size_t framesPerPixel = m_viewManager->getGlobalZoom();
+    size_t defaultZoom = (720 * 44100) / sr;
+
+    float scaler = (framesPerPixel * 1.0f) / defaultZoom;
+
+
+    frame = RealTime::realTime2Frame
+        (RealTime::frame2RealTime(frame, sr) + m_defaultFfwdRwdStep * scaler, sr);
+    if (frame > int(getMainModel()->getEndFrame())) {
+        frame = getMainModel()->getEndFrame();
+    }
+        
+    if (frame < 0) frame = 0;
+
+    if (m_viewManager->getPlaySelectionMode()) {
+        frame = m_viewManager->constrainFrameToSelection(size_t(frame));
+    }
+    
+    m_viewManager->setPlaybackFrame(frame);
+
+    if (frame == (int)getMainModel()->getEndFrame() &&
+        m_playSource &&
+        m_playSource->isPlaying() &&
+        !m_viewManager->getPlayLoopMode()) {
+        stop();
+    }
+}
+
+void
+MainWindow::rewind()
+{
+    if (!getMainModel()) return;
+
+    int frame = m_viewManager->getPlaybackFrame();
+    if (frame > 0) --frame;
+
+    size_t sr = getMainModel()->getSampleRate();
+
+    // The step is supposed to scale and be as wide as a step of 
+    // m_defaultFfwdRwdStep seconds at zoom level 720 and sr = 44100
+    size_t framesPerPixel = m_viewManager->getGlobalZoom();
+    size_t defaultZoom = (720 * 44100) / sr;
+
+    float scaler = (framesPerPixel * 1.0f) / defaultZoom;
+    frame = RealTime::realTime2Frame
+        (RealTime::frame2RealTime(frame, sr) - m_defaultFfwdRwdStep * scaler, sr);
+    if (frame < int(getMainModel()->getStartFrame())) {
+        frame = getMainModel()->getStartFrame();
+    }
+
+    if (frame < 0) frame = 0;
+
+    if (m_viewManager->getPlaySelectionMode()) {
+        frame = m_viewManager->constrainFrameToSelection(size_t(frame));
+    }
+
+    m_viewManager->setPlaybackFrame(frame);
+}
--- a/src/MainWindow.h	Wed Mar 11 12:20:06 2015 +0000
+++ b/src/MainWindow.h	Mon Mar 23 10:33:32 2015 +0000
@@ -27,7 +27,7 @@
     Q_OBJECT
 
 public:
-    MainWindow(bool withAudioOutput = true);
+    MainWindow(bool withAudioOutput = true, bool withSonification = true, bool withSpectrogram = true);
     virtual ~MainWindow();
 
 signals:
@@ -186,6 +186,9 @@
     void selectOneNoteRight();
     void selectOneNoteLeft();
 
+    void ffwd();
+    void rewind();
+
 protected:
     Analyser      *m_analyser;
 
@@ -230,6 +233,9 @@
 
     sv_frame_t m_selectionAnchor;
 
+    bool m_withSonification;
+    bool m_withSpectrogram;
+
     Analyser::FrequencyRange m_pendingConstraint;
 
     QString exportToSVL(QString path, Layer *layer);
--- a/src/main.cpp	Wed Mar 11 12:20:06 2015 +0000
+++ b/src/main.cpp	Mon Mar 23 10:33:32 2015 +0000
@@ -61,7 +61,7 @@
 class TonyApplication : public QApplication
 {
 public:
-    TonyApplication(int argc, char **argv) :
+    TonyApplication(int &argc, char **argv) :
         QApplication(argc, argv),
         m_mainWindow(0),
         m_readyForFiles(false)
@@ -100,6 +100,7 @@
     QStringList m_filepathQueue;
 
     virtual bool event(QEvent *event) {
+
         if (event->type() == QEvent::FileOpen) {
             QString path = static_cast<QFileOpenEvent *>(event)->file();
             if (m_readyForFiles) {
@@ -128,14 +129,7 @@
 
     TonyApplication application(argc, argv);
 
-    // For some weird reason, Mac builds are crashing on startup when
-    // this line is present. Eliminate it on that platform for now.
-#ifndef Q_OS_MAC
     QStringList args = application.arguments();
-#else
-    cerr << "NOTE: Command-line arguments are currently disabled on Mac, see comments in main.cpp" << endl;
-    QStringList args;
-#endif
 
     signal(SIGINT,  signalHandler);
     signal(SIGTERM, signalHandler);
@@ -146,15 +140,21 @@
 #endif
 
     bool audioOutput = true;
+    bool sonification = true;
+    bool spectrogram = true;
 
     if (args.contains("--help") || args.contains("-h") || args.contains("-?")) {
         std::cerr << QApplication::tr(
-            "\nTony is a program for interactive note and pitch analysis and annotation.\n\nUsage:\n\n  %1 [--no-audio] [<file> ...]\n\n  --no-audio: Do not attempt to open an audio output device\n  <file>: One or more Tony (.ton) and audio files may be provided.\n").arg(argv[0]).toStdString() << std::endl;
+            "\nTony is a program for interactive note and pitch analysis and annotation.\n\nUsage:\n\n  %1 [--no-audio] [--no-sonification] [--no-spectrogram] [<file> ...]\n\n  --no-audio: Do not attempt to open an audio output device\n  --no-sonification: Disable sonification of pitch tracks and notes and hide their toggles.\n  --no-spectrogram: Disable spectrogram.\n  <file>: One or more Tony (.ton) and audio files may be provided.").arg(argv[0]).toStdString() << std::endl;
         exit(2);
     }
 
     if (args.contains("--no-audio")) audioOutput = false;
 
+    if (args.contains("--no-sonification")) sonification = false;
+
+    if (args.contains("--no-spectrogram")) spectrogram = false;
+
     QApplication::setOrganizationName("QMUL");
     QApplication::setOrganizationDomain("qmul.ac.uk");
     QApplication::setApplicationName("Tony");
@@ -195,7 +195,7 @@
     qRegisterMetaType<size_t>("size_t");
     qRegisterMetaType<PropertyContainer::PropertyName>("PropertyContainer::PropertyName");
 
-    MainWindow *gui = new MainWindow(audioOutput);
+    MainWindow *gui = new MainWindow(audioOutput, sonification, spectrogram);
     application.setMainWindow(gui);
     if (splash) {
         QObject::connect(gui, SIGNAL(hideSplash()), splash, SLOT(hide()));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/version.h	Mon Mar 23 10:33:32 2015 +0000
@@ -0,0 +1,1 @@
+#define TONY_VERSION "0.7"