I add move-to-next-bar to my unittest, but it turns out that (unlike 
move-to-next-note) this requires
the SequenceManager, which in turn requires TransportDialog, 
RosegardenMainWindow etc.

So I'm doing a bit of rearchitecture around SequenceManager.
Here's a first step, maybe you want to review that design change?

-- 
David Faure, [email protected], http://www.davidfaure.fr
Working on KDE Frameworks 5
>From 2c2b7505bc8338e0193906fd7668d64f94f2cbe4 Mon Sep 17 00:00:00 2001
From: David Faure <[email protected]>
Date: Sat, 30 Apr 2016 23:02:50 +0200
Subject: [PATCH] Use signals for communication between SequenceManager and
 TransportDialog.

This allows to test "move to next bar" (SequenceManager::fastforward())
without a transport dialog.

>From a design point of view, it's better core/gui separation,
SequenceManager would keep working even if there is no transport dialog one day.
---
 src/gui/application/RosegardenMainWindow.cpp | 22 ++++----
 src/gui/dialogs/TransportDialog.cpp          | 52 +++++++++----------
 src/gui/dialogs/TransportDialog.h            | 16 +++---
 src/gui/seqmanager/SequenceManager.cpp       | 76 ++++++++++++++++------------
 src/gui/seqmanager/SequenceManager.h         | 18 ++++---
 5 files changed, 100 insertions(+), 84 deletions(-)

diff --git a/src/gui/application/RosegardenMainWindow.cpp b/src/gui/application/RosegardenMainWindow.cpp
index 068f824..a969dce 100644
--- a/src/gui/application/RosegardenMainWindow.cpp
+++ b/src/gui/application/RosegardenMainWindow.cpp
@@ -414,14 +414,13 @@ RosegardenMainWindow::RosegardenMainWindow(bool useSequencer,
 //    connect(m_parameterArea, SIGNAL(hidden()),
 //            this, SLOT(slotParameterAreaHidden()));
 
+    m_seqManager = new SequenceManager();
+
     // Load the initial document (this includes doc's own autoload)
     //
     setDocument(doc);
 
     emit startupStatusMessage(tr("Starting sequence manager..."));
-
-    // transport is created by setupActions()
-    m_seqManager = new SequenceManager(getTransport());
     m_seqManager->setDocument(m_doc);
 
     connect(m_seqManager,
@@ -1151,7 +1150,7 @@ RosegardenMainWindow::initView()
 
     // set the tempo in the transport
     //
-    getTransport()->setTempo(comp.getCurrentTempo());
+    m_seqManager->setTempo(comp.getCurrentTempo());
 
     // bring the transport to the front
     //
@@ -2910,9 +2909,14 @@ RosegardenMainWindow::createAndSetupTransport()
     connect(m_transport, SIGNAL(setLoopStartTime()), SLOT(slotSetLoopStart()));
     connect(m_transport, SIGNAL(setLoopStopTime()), SLOT(slotSetLoopStop()));
 
-    if (m_seqManager != 0)
-        m_seqManager->setTransport(m_transport);
-
+    if (m_seqManager != 0) {
+        connect(m_seqManager, SIGNAL(signalTempoChanged(tempoT)), m_transport, SLOT(slotTempoChanged(tempoT)));
+        connect(m_seqManager, SIGNAL(signalMidiInLabel(const MappedEvent*)), m_transport, SLOT(slotMidiInLabel(const MappedEvent*)));
+        connect(m_seqManager, SIGNAL(signalMidiOutLabel(const MappedEvent*)), m_transport, SLOT(slotMidiOutLabel(const MappedEvent*)));
+        connect(m_seqManager, SIGNAL(signalPlayButtonChecked(bool)), m_transport, SLOT(slotPlayButtonChecked(bool)));
+        connect(m_seqManager, SIGNAL(signalRecordButtonChecked(bool)), m_transport, SLOT(slotRecordButtonChecked(bool)));
+        connect(m_seqManager, SIGNAL(signalMetronomeButtonChecked(bool)), m_transport, SLOT(slotMetronomeButtonChecked(bool)));
+    }
 }
 
 void
@@ -4858,7 +4862,7 @@ RosegardenMainWindow::slotUpdateUI()
 
     MappedEvent ev;
     bool haveEvent = SequencerDataBlock::getInstance()->getVisual(ev);
-    if (haveEvent) getTransport()->setMidiOutLabel(&ev);
+    if (haveEvent) getTransport()->slotMidiOutLabel(&ev);
 
 
     // Update the playback position pointer
@@ -5010,7 +5014,7 @@ RosegardenMainWindow::slotSetPointerPosition(timeT t)
     getTransport()->setTimeSignature(comp.getTimeSignatureAt(t));
 
     // and the tempo
-    getTransport()->setTempo(comp.getTempoAtTime(t));
+    m_seqManager->setTempo(comp.getTempoAtTime(t));
 
     // and the time
     //
diff --git a/src/gui/dialogs/TransportDialog.cpp b/src/gui/dialogs/TransportDialog.cpp
index e0cb4b0..b546ea5 100644
--- a/src/gui/dialogs/TransportDialog.cpp
+++ b/src/gui/dialogs/TransportDialog.cpp
@@ -85,7 +85,6 @@ TransportDialog::TransportDialog(QWidget *parent):
     m_hundreths(0),
     m_thousandths(0),
     m_tenThousandths(0),
-    m_tempo(0),
     m_numerator(0),
     m_denominator(0),
     m_framesPerSecond(24),
@@ -853,31 +852,6 @@ TransportDialog::updateTimeDisplay()
 }
 
 void
-TransportDialog::setTempo(const tempoT &tempo)
-{
-    if (m_tempo == tempo)
-        return ;
-    m_tempo = tempo;
-
-    // Send the quarter note length to the sequencer - shouldn't
-    // really hang this off here but at least it's a single point
-    // where the tempo should always be consistent.  Quarter Note
-    // Length is sent (MIDI CLOCK) at 24ppqn.
-    //
-    double qnD = 60.0 / Composition::getTempoQpm(tempo);
-    RealTime qnTime =
-        RealTime(long(qnD),
-                 long((qnD - double(long(qnD))) * 1000000000.0));
-
-    StudioControl::sendQuarterNoteLength(qnTime);
-
-    QString tempoString;
-    tempoString.sprintf("%4.3f", Composition::getTempoQpm(tempo));
-
-    ui->TempoDisplay->setText(tempoString);
-}
-
-void
 TransportDialog::setTimeSignature(const TimeSignature &timeSig)
 {
     int numerator = timeSig.getNumerator();
@@ -893,7 +867,7 @@ TransportDialog::setTimeSignature(const TimeSignature &timeSig)
 }
 
 void
-TransportDialog::setMidiInLabel(const MappedEvent *mE)
+TransportDialog::slotMidiInLabel(const MappedEvent *mE)
 {
     // If MIDI label updates have been turned off, bail.
     if (!m_enableMIDILabels)
@@ -986,7 +960,7 @@ TransportDialog::slotClearMidiInLabel()
 }
 
 void
-TransportDialog::setMidiOutLabel(const MappedEvent *mE)
+TransportDialog::slotMidiOutLabel(const MappedEvent *mE)
 {
     // If MIDI label updates have been turned off, bail.
     if (!m_enableMIDILabels)
@@ -1112,6 +1086,28 @@ TransportDialog::slotSetStopLoopingPointAtMarkerPos()
     emit setLoopStopTime();
 }
 
+void TransportDialog::slotTempoChanged(tempoT tempo)
+{
+    QString tempoString;
+    tempoString.sprintf("%4.3f", Composition::getTempoQpm(tempo));
+    ui->TempoDisplay->setText(tempoString);
+}
+
+void TransportDialog::slotPlayButtonChecked(bool checked)
+{
+    ui->PlayButton->setChecked(checked);
+}
+
+void TransportDialog::slotRecordButtonChecked(bool checked)
+{
+    ui->RecordButton->setChecked(checked);
+}
+
+void TransportDialog::slotMetronomeButtonChecked(bool checked)
+{
+    ui->MetronomeButton->setChecked(checked);
+}
+
 void
 TransportDialog::slotPanelOpenButtonClicked()
 {
diff --git a/src/gui/dialogs/TransportDialog.h b/src/gui/dialogs/TransportDialog.h
index f2191ae..deff347 100644
--- a/src/gui/dialogs/TransportDialog.h
+++ b/src/gui/dialogs/TransportDialog.h
@@ -75,18 +75,11 @@ public:
     void displayFrameTime(const RealTime &rt);
     void displayBarTime(int bar, int beat, int unit);
 
-    void setTempo(const tempoT &tempo);
     void setTimeSignature(const TimeSignature &timeSig);
 
     void setSMPTEResolution(int framesPerSecond, int bitsPerFrame);
     void getSMPTEResolution(int &framesPerSecond, int &bitsPerFrame);
 
-    // Called indirectly from the sequencer and from the GUI to
-    // show incoming and outgoing MIDI events on the Transport
-    //
-    void setMidiInLabel(const MappedEvent *mE);
-    void setMidiOutLabel(const MappedEvent *mE);
-
     // Return the shortcut object
     //
     QShortcut* getShortcuts() { return m_shortcuts; }
@@ -142,6 +135,14 @@ public slots:
     void slotSetStartLoopingPointAtMarkerPos();
     void slotSetStopLoopingPointAtMarkerPos();
 
+    // Connected to SequenceManager
+    void slotTempoChanged(tempoT);
+    void slotMidiInLabel(const MappedEvent *event); // show incoming MIDI events on the Transport
+    void slotMidiOutLabel(const MappedEvent *event); // show outgoing  MIDI events on the Transport
+    void slotPlayButtonChecked(bool checked);
+    void slotRecordButtonChecked(bool checked);
+    void slotMetronomeButtonChecked(bool checked);
+
 signals:
     void closed();
 
@@ -198,7 +199,6 @@ private:
     int m_thousandths;
     int m_tenThousandths;
 
-    tempoT m_tempo;
     int m_numerator;
     int m_denominator;
 
diff --git a/src/gui/seqmanager/SequenceManager.cpp b/src/gui/seqmanager/SequenceManager.cpp
index 2df6cf0..f915fc9 100644
--- a/src/gui/seqmanager/SequenceManager.cpp
+++ b/src/gui/seqmanager/SequenceManager.cpp
@@ -84,7 +84,7 @@
 namespace Rosegarden
 {
 
-SequenceManager::SequenceManager(TransportDialog *transport) :
+SequenceManager::SequenceManager() :
     m_doc(0),
     m_compositionMapper(0),
     m_metronomeMapper(0),
@@ -92,7 +92,6 @@ SequenceManager::SequenceManager(TransportDialog *transport) :
     m_timeSigSegmentMapper(0),
     m_transportStatus(STOPPED),
     m_soundDriverStatus(NO_DRIVER),
-    m_transport(transport),
     m_lastRewoundAt(clock()),
     m_countdownDialog(0),
     m_countdownTimer(0),
@@ -104,7 +103,8 @@ SequenceManager::SequenceManager(TransportDialog *transport) :
     m_canReport(true),
     m_lastLowLatencySwitchSent(false),
     m_lastTransportStartPosition(0),
-    m_sampleRate(0)
+    m_sampleRate(0),
+    m_tempo(0)
 {
     // The owner of this sequence manager will need to call
     // checkSoundDriverStatus on it to set up its status appropriately
@@ -216,7 +216,7 @@ SequenceManager::play()
 
     // make sure we toggle the play button
     //
-    m_transport->PlayButton()->setChecked(true);
+    emit signalPlayButtonChecked(true);
 
     //!!! disable the record button, because recording while playing is horribly
     // broken, and disabling it is less complicated than fixing it
@@ -234,14 +234,7 @@ SequenceManager::play()
 
     // Send initial tempo
     //
-    double qnD = 60.0 / comp.getTempoQpm(comp.getCurrentTempo());
-    RealTime qnTime =
-        RealTime(long(qnD),
-                 long((qnD - double(long(qnD))) * 1000000000.0));
-    StudioControl::sendQuarterNoteLength(qnTime);
-
-    // set the tempo in the transport
-    m_transport->setTempo(comp.getCurrentTempo());
+    setTempo(comp.getCurrentTempo());
 
     // The arguments for the Sequencer
     RealTime startPos = comp.getElapsedRealTime(comp.getPosition());
@@ -329,9 +322,8 @@ SequenceManager::stopping()
     //
     if (m_transportStatus == RECORDING_ARMED) {
         m_transportStatus = STOPPED;
-        m_transport->RecordButton()->setChecked(false);
-        m_transport->MetronomeButton()->
-          setChecked(m_doc->getComposition().usePlayMetronome());
+        emit signalRecordButtonChecked(false);
+        emit signalMetronomeButtonChecked(m_doc->getComposition().usePlayMetronome());
         return ;
     }
 
@@ -351,9 +343,8 @@ SequenceManager::stop()
     // Toggle off the buttons - first record
     //
     if (m_transportStatus == RECORDING) {
-        m_transport->RecordButton()->setChecked(false);
-        m_transport->MetronomeButton()->
-          setChecked(m_doc->getComposition().usePlayMetronome());
+        emit signalRecordButtonChecked(false);
+        emit signalMetronomeButtonChecked(m_doc->getComposition().usePlayMetronome());
 
         // Remove the countdown dialog and stop the timer
         //
@@ -362,7 +353,7 @@ SequenceManager::stop()
     }
 
     // Now playback
-    m_transport->PlayButton()->setChecked(false);
+    emit signalPlayButtonChecked(false);
 
     // re-enable the record button if it was previously disabled when
     // going into play mode - DMM
@@ -404,7 +395,7 @@ SequenceManager::stop()
 
     // always untoggle the play button at this stage
     //
-    m_transport->PlayButton()->setChecked(false);
+    emit signalPlayButtonChecked(false);
     SEQMAN_DEBUG << "SequenceManager::stop() - stopped playing";
     // We don't reset controllers at this point - what happens with static
     // controllers the next time we play otherwise?  [rwb]
@@ -512,7 +503,7 @@ SequenceManager::record(bool toggled)
 
         if (instr && instr->getType() == Instrument::Audio) {
             if (!m_doc || !(m_soundDriverStatus & AUDIO_OK)) {
-                m_transport->RecordButton()->setChecked(false);
+                emit signalRecordButtonChecked(false);
                 throw(Exception(QObject::tr("Audio subsystem is not available - can't record audio")));
             }
             // throws BadAudioPathException if path is not valid:
@@ -528,8 +519,8 @@ SequenceManager::record(bool toggled)
             m_transportStatus = STOPPED;
 
             // Toggle the buttons
-            m_transport->MetronomeButton()->setChecked(comp.usePlayMetronome());
-            m_transport->RecordButton()->setChecked(false);
+            emit signalMetronomeButtonChecked(comp.usePlayMetronome());
+            emit signalRecordButtonChecked(false);
 
             return ;
         }
@@ -539,8 +530,8 @@ SequenceManager::record(bool toggled)
             m_transportStatus = RECORDING_ARMED;
 
             // Toggle the buttons
-            m_transport->MetronomeButton()->setChecked(comp.useRecordMetronome());
-            m_transport->RecordButton()->setChecked(true);
+            emit signalMetronomeButtonChecked(comp.useRecordMetronome());
+            emit signalRecordButtonChecked(true);
 
             return ;
         }
@@ -609,7 +600,6 @@ punchin:
         }
 
         if (!haveInstrument) {
-            m_transport->RecordButton()->setDown(false);
             // TRANSLATORS: the pixmap in this error string contains no English
             // text and is suitable for use by all languages
             throw(Exception(QObject::tr("<qt><p>No tracks were armed for recording.</p><p>Please arm at least one of the recording LEDs <img src=\":pixmaps/tooltip/record-leds.png\"> and try again</p></qt>")));
@@ -619,7 +609,7 @@ punchin:
         checkSoundDriverStatus(false);
 
         // toggle the Metronome button if it's in use
-        m_transport->MetronomeButton()->setChecked(comp.useRecordMetronome());
+        emit signalMetronomeButtonChecked(comp.useRecordMetronome());
 
         // Update record metronome status
         //
@@ -687,8 +677,8 @@ punchin:
         }
 
         // set the buttons
-        m_transport->RecordButton()->setChecked(true);
-        m_transport->PlayButton()->setChecked(true);
+        emit signalRecordButtonChecked(true);
+        emit signalPlayButtonChecked(true);
 
         if (comp.getCurrentTempo() == 0) {
             SEQMAN_DEBUG << "SequenceManager::play() - setting Tempo to Default value of 120.000";
@@ -699,7 +689,7 @@ punchin:
 
         // set the tempo in the transport
         //
-        m_transport->setTempo(comp.getCurrentTempo());
+        setTempo(comp.getCurrentTempo());
 
         // The arguments for the Sequencer - record is similar to playback,
         // we must being playing to record.
@@ -855,13 +845,13 @@ SequenceManager::processAsynchronousMidi(const MappedEventList &mC,
     // send to the MIDI labels (which can only hold one event at a time)
     i = mC.begin();
     if (i != mC.end()) {
-        m_transport->setMidiInLabel(*i);
+        emit signalMidiInLabel(*i);
     }
 
     i = tempMC.begin();
     while (i != tempMC.end()) {
         if ((*i)->getRecordedDevice() != Device::CONTROL_DEVICE) {
-            m_transport->setMidiOutLabel(*i);
+            emit signalMidiOutLabel(*i);
             break;
         }
         ++i;
@@ -1403,12 +1393,32 @@ SequenceManager::panic()
     //    resetControllers();
 }
 
+void SequenceManager::setTempo(const tempoT tempo)
+{
+    if (m_tempo == tempo)
+        return;
+    m_tempo = tempo;
+
+    // Send the quarter note length to the sequencer.
+    // Quarter Note Length is sent (MIDI CLOCK) at 24ppqn.
+    //
+    double qnD = 60.0 / Composition::getTempoQpm(tempo);
+    RealTime qnTime =
+        RealTime(long(qnD),
+                 long((qnD - double(long(qnD))) * 1000000000.0));
+
+    StudioControl::sendQuarterNoteLength(qnTime);
+
+    // set the tempo in the transport
+    emit signalTempoChanged(tempo);
+}
+
 void
 SequenceManager::showVisuals(const MappedEventList &mC)
 {
     MappedEventList::const_iterator it = mC.begin();
     if (it != mC.end())
-        m_transport->setMidiOutLabel(*it);
+        emit signalMidiOutLabel(*it);
 }
 
 MappedEventList
diff --git a/src/gui/seqmanager/SequenceManager.h b/src/gui/seqmanager/SequenceManager.h
index 942e5a1..ea299bc 100644
--- a/src/gui/seqmanager/SequenceManager.h
+++ b/src/gui/seqmanager/SequenceManager.h
@@ -62,7 +62,7 @@ public:
      * designed to operate without a document; you must call
      * setDocument before you do anything with it.
      */
-    SequenceManager(TransportDialog *transport);
+    SequenceManager();
     ~SequenceManager();
 
     /** Used to transmit the type of sequencer warning, so the WarningWidget
@@ -155,6 +155,9 @@ public:
     /// Send all note offs and resets to MIDI devices
     void panic();
 
+    /// Set tempo (also notifies StudioControl and TransportDialog)
+    void setTempo(const tempoT tempo);
+
     /// Send an MC to the view
     void showVisuals(const MappedEventList &mC);
 
@@ -202,8 +205,6 @@ public:
     void filtersChanged(MidiFilter thruFilter,
                         MidiFilter recordFilter);
 
-    void setTransport(TransportDialog* t) { m_transport = t; }
-    
     int getSampleRate(); // may return 0 if sequencer uncontactable
 
 public slots:
@@ -221,6 +222,13 @@ signals:
     /// signal RosegardenMainWindow to display a warning on the WarningWidget
     void sendWarning(int type, QString text, QString informativeText);
 
+    void signalTempoChanged(tempoT);
+    void signalMidiInLabel(const MappedEvent *event);
+    void signalMidiOutLabel(const MappedEvent *event);
+    void signalPlayButtonChecked(bool checked);
+    void signalRecordButtonChecked(bool checked);
+    void signalMetronomeButtonChecked(bool checked);
+
 protected slots:
     void slotCountdownTimerTimeout();
 
@@ -264,9 +272,6 @@ protected:
     TransportStatus            m_transportStatus;
     unsigned int               m_soundDriverStatus;
 
-    // pointer to the transport dialog
-    TransportDialog *m_transport;
-
     clock_t                    m_lastRewoundAt;
 
     CountdownDialog           *m_countdownDialog;
@@ -304,6 +309,7 @@ protected:
 
     int                        m_sampleRate;
 
+    tempoT m_tempo;
 };
 
 
-- 
2.1.4

------------------------------------------------------------------------------
Find and fix application performance issues faster with Applications Manager
Applications Manager provides deep performance insights into multiple tiers of
your business applications. It resolves application problems quickly and
reduces your MTTR. Get your free trial!
https://ad.doubleclick.net/ddm/clk/302982198;130105516;z
_______________________________________________
Rosegarden-devel mailing list
[email protected] - use the link below to unsubscribe
https://lists.sourceforge.net/lists/listinfo/rosegarden-devel

Reply via email to