changeset 1730:649ac57c5a2d

Merge
author Chris Cannam
date Thu, 20 Jun 2019 14:58:20 +0100
parents 8efce64dd85e (diff) a47a23c824ac (current diff)
children 85b9b466a59f
files
diffstat 23 files changed, 84 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/base/Clipboard.h	Wed May 22 15:37:44 2019 +0100
+++ b/base/Clipboard.h	Thu Jun 20 14:58:20 2019 +0100
@@ -36,7 +36,7 @@
     bool referenceFramesDiffer() const;
 
 protected:
-     EventVector m_points;
+    EventVector m_points;
 };
 
 #endif
--- a/data/midi/MIDIInput.cpp	Wed May 22 15:37:44 2019 +0100
+++ b/data/midi/MIDIInput.cpp	Thu Jun 20 14:58:20 2019 +0100
@@ -119,7 +119,7 @@
             SVCERR << "ERROR: MIDIInput::postEvent: MIDI event queue is full and not clearing -- abandoning incoming event" << endl;
             return;
         }
-        SVCERR << "WARNING: MIDIInput::postEvent: MIDI event queue (capacity " << m_buffer.getSize() << " is full!" << endl;
+        SVCERR << "WARNING: MIDIInput::postEvent: MIDI event queue (capacity " << m_buffer.getSize() << ") is full!" << endl;
         SVDEBUG << "Waiting for something to be processed" << endl;
 #ifdef _WIN32
         Sleep(1);
--- a/data/model/AggregateWaveModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/AggregateWaveModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -62,7 +62,7 @@
     float getValueMaximum() const override { return  1.0f; }
 
     sv_frame_t getStartFrame() const override { return 0; }
-    sv_frame_t getEndFrame() const override { return getFrameCount(); }
+    sv_frame_t getTrueEndFrame() const override { return getFrameCount(); }
 
     floatvec_t getData(int channel, sv_frame_t start, sv_frame_t count) const override;
 
--- a/data/model/AlignmentModel.cpp	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/AlignmentModel.cpp	Thu Jun 20 14:58:20 2019 +0100
@@ -90,7 +90,7 @@
 }
 
 sv_frame_t
-AlignmentModel::getEndFrame() const
+AlignmentModel::getTrueEndFrame() const
 {
     sv_frame_t a = m_reference->getEndFrame();
     sv_frame_t b = m_aligned->getEndFrame();
--- a/data/model/AlignmentModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/AlignmentModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -41,7 +41,7 @@
     QString getError() const { return m_error; }
 
     sv_frame_t getStartFrame() const override;
-    sv_frame_t getEndFrame() const override;
+    sv_frame_t getTrueEndFrame() const override;
     sv_samplerate_t getSampleRate() const override;
     bool isReady(int *completion = 0) const override;
     int getCompletion() const override {
--- a/data/model/Dense3DModelPeakCache.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/Dense3DModelPeakCache.h	Thu Jun 20 14:58:20 2019 +0100
@@ -40,8 +40,8 @@
         return m_source->getStartFrame();
     }
 
-    sv_frame_t getEndFrame() const override {
-        return m_source->getEndFrame();
+    sv_frame_t getTrueEndFrame() const override {
+        return m_source->getTrueEndFrame();
     }
 
     int getResolution() const override {
--- a/data/model/EditableDenseThreeDimensionalModel.cpp	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/EditableDenseThreeDimensionalModel.cpp	Thu Jun 20 14:58:20 2019 +0100
@@ -83,7 +83,7 @@
 }
 
 sv_frame_t
-EditableDenseThreeDimensionalModel::getEndFrame() const
+EditableDenseThreeDimensionalModel::getTrueEndFrame() const
 {
     return m_resolution * m_data.size() + (m_resolution - 1);
 }
--- a/data/model/EditableDenseThreeDimensionalModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/EditableDenseThreeDimensionalModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -55,7 +55,7 @@
 
     sv_samplerate_t getSampleRate() const override;
     sv_frame_t getStartFrame() const override;
-    sv_frame_t getEndFrame() const override;
+    sv_frame_t getTrueEndFrame() const override;
 
     /**
      * Set the frame offset of the first column.
--- a/data/model/FFTModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/FFTModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -65,7 +65,7 @@
     float getValueAt(int x, int y) const override { return getMagnitudeAt(x, y); }
     bool isOK() const override { return m_model && m_model->isOK(); }
     sv_frame_t getStartFrame() const override { return 0; }
-    sv_frame_t getEndFrame() const override {
+    sv_frame_t getTrueEndFrame() const override {
         return sv_frame_t(getWidth()) * getResolution() + getResolution();
     }
     sv_samplerate_t getSampleRate() const override {
--- a/data/model/ImageModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/ImageModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -61,7 +61,7 @@
     sv_frame_t getStartFrame() const override {
         return m_events.getStartFrame();
     }
-    sv_frame_t getEndFrame() const override {
+    sv_frame_t getTrueEndFrame() const override {
         if (m_events.isEmpty()) return 0;
         sv_frame_t e = m_events.getEndFrame() + 1;
         if (e % m_resolution == 0) return e;
--- a/data/model/Model.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/Model.h	Thu Jun 20 14:58:20 2019 +0100
@@ -62,8 +62,36 @@
      * frames (as a multiple of the resolution) spanned by the
      * model. This is broadly consistent with the definition of the
      * end frame of a Selection object.
+     *
+     * If the end has been extended by extendEndFrame() beyond the
+     * true end frame, return the extended end instead. This is
+     * usually the behaviour you want.
      */
-    virtual sv_frame_t getEndFrame() const = 0;
+    sv_frame_t getEndFrame() const {
+        sv_frame_t trueEnd = getTrueEndFrame();
+        if (m_extendTo > trueEnd) {
+            return m_extendTo;
+        } else {
+            return trueEnd;
+        }
+    }
+
+    /**
+     * Return the audio frame at the end of the model. This is
+     * identical to getEndFrame(), except that it ignores any extended
+     * duration set with extendEndFrame().
+     */
+    virtual sv_frame_t getTrueEndFrame() const = 0;
+
+    /**
+     * Extend the end of the model. If this is set to something beyond
+     * the true end of the data within the model, then getEndFrame()
+     * will return this value instead of the true end. (This is used
+     * by the Tony application.)
+     */
+    void extendEndFrame(sv_frame_t to) {
+        m_extendTo = to;
+    }
 
     /**
      * Return the frame rate in frames per second.
@@ -315,7 +343,8 @@
         m_sourceModel(0), 
         m_alignment(0), 
         m_abandoning(false), 
-        m_aboutToDelete(false) { }
+        m_aboutToDelete(false),
+        m_extendTo(0) { }
 
     // Not provided.
     Model(const Model &);
@@ -327,7 +356,8 @@
     QString m_typeUri;
     bool m_abandoning;
     bool m_aboutToDelete;
-
+    sv_frame_t m_extendTo;
+    
     int getNextId();
 };
 
--- a/data/model/NoteModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/NoteModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -102,7 +102,7 @@
     sv_frame_t getStartFrame() const override {
         return m_events.getStartFrame();
     }
-    sv_frame_t getEndFrame() const override {
+    sv_frame_t getTrueEndFrame() const override {
         if (m_events.isEmpty()) return 0;
         sv_frame_t e = m_events.getEndFrame();
         if (e % m_resolution == 0) return e;
--- a/data/model/PathModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/PathModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -83,7 +83,7 @@
     sv_frame_t getStartFrame() const override {
         return m_start;
     }
-    sv_frame_t getEndFrame() const override {
+    sv_frame_t getTrueEndFrame() const override {
         return m_end;
     }
     
--- a/data/model/ReadOnlyWaveFileModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/ReadOnlyWaveFileModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -77,7 +77,7 @@
     float getValueMaximum() const override { return  1.0f; }
 
     sv_frame_t getStartFrame() const override { return m_startFrame; }
-    sv_frame_t getEndFrame() const override { return m_startFrame + getFrameCount(); }
+    sv_frame_t getTrueEndFrame() const override { return m_startFrame + getFrameCount(); }
 
     void setStartFrame(sv_frame_t startFrame) override { m_startFrame = startFrame; }
 
--- a/data/model/RegionModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/RegionModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -83,7 +83,7 @@
     sv_frame_t getStartFrame() const override {
         return m_events.getStartFrame();
     }
-    sv_frame_t getEndFrame() const override {
+    sv_frame_t getTrueEndFrame() const override {
         if (m_events.isEmpty()) return 0;
         sv_frame_t e = m_events.getEndFrame();
         if (e % m_resolution == 0) return e;
--- a/data/model/SparseOneDimensionalModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/SparseOneDimensionalModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -67,7 +67,7 @@
     sv_frame_t getStartFrame() const override {
         return m_events.getStartFrame();
     }
-    sv_frame_t getEndFrame() const override {
+    sv_frame_t getTrueEndFrame() const override {
         if (m_events.isEmpty()) return 0;
         sv_frame_t e = m_events.getEndFrame() + 1;
         if (e % m_resolution == 0) return e;
--- a/data/model/SparseTimeValueModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/SparseTimeValueModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -87,7 +87,7 @@
     sv_frame_t getStartFrame() const override {
         return m_events.getStartFrame();
     }
-    sv_frame_t getEndFrame() const override {
+    sv_frame_t getTrueEndFrame() const override {
         if (m_events.isEmpty()) return 0;
         sv_frame_t e = m_events.getEndFrame() + 1;
         if (e % m_resolution == 0) return e;
--- a/data/model/TextModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/TextModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -59,7 +59,7 @@
     sv_frame_t getStartFrame() const override {
         return m_events.getStartFrame();
     }
-    sv_frame_t getEndFrame() const override {
+    sv_frame_t getTrueEndFrame() const override {
         if (m_events.isEmpty()) return 0;
         sv_frame_t e = m_events.getEndFrame() + 1;
         if (e % m_resolution == 0) return e;
--- a/data/model/WaveFileModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/WaveFileModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -37,7 +37,7 @@
     QString getLocation() const override = 0;
 
     sv_frame_t getStartFrame() const override = 0;
-    sv_frame_t getEndFrame() const override = 0;
+    sv_frame_t getTrueEndFrame() const override = 0;
 
     virtual void setStartFrame(sv_frame_t startFrame) = 0;
 
--- a/data/model/WritableWaveFileModel.cpp	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/WritableWaveFileModel.cpp	Thu Jun 20 14:58:20 2019 +0100
@@ -248,6 +248,7 @@
     m_reader->updateDone();
     m_proportion = 100;
     emit modelChanged();
+    emit writeCompleted();
 }
 
 void
--- a/data/model/WritableWaveFileModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/WritableWaveFileModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -175,7 +175,7 @@
     float getValueMaximum() const override { return  1.0f; }
 
     sv_frame_t getStartFrame() const override { return m_startFrame; }
-    sv_frame_t getEndFrame() const override { return m_startFrame + getFrameCount(); }
+    sv_frame_t getTrueEndFrame() const override { return m_startFrame + getFrameCount(); }
 
     void setStartFrame(sv_frame_t startFrame) override;
 
@@ -196,6 +196,9 @@
                        QString indent = "",
                        QString extraAttributes = "") const override;
 
+signals:
+    void writeCompleted();
+    
 protected:
     ReadOnlyWaveFileModel *m_model;
 
--- a/data/model/test/MockWaveModel.h	Wed May 22 15:37:44 2019 +0100
+++ b/data/model/test/MockWaveModel.h	Thu Jun 20 14:58:20 2019 +0100
@@ -48,7 +48,7 @@
     QString getDefaultPlayClipId() const override { return ""; }
 
     sv_frame_t getStartFrame() const override { return 0; }
-    sv_frame_t getEndFrame() const override { return m_data[0].size(); }
+    sv_frame_t getTrueEndFrame() const override { return m_data[0].size(); }
     sv_samplerate_t getSampleRate() const override { return 44100; }
     bool isOK() const override { return true; }
     int getCompletion() const override { return 100; }
--- a/transform/ModelTransformerFactory.cpp	Wed May 22 15:37:44 2019 +0100
+++ b/transform/ModelTransformerFactory.cpp	Thu Jun 20 14:58:20 2019 +0100
@@ -32,11 +32,14 @@
 
 #include <iostream>
 #include <set>
+#include <map>
 
 #include <QRegExp>
 #include <QMutexLocker>
 
 using std::vector;
+using std::set;
+using std::map;
 
 ModelTransformerFactory *
 ModelTransformerFactory::m_instance = new ModelTransformerFactory;
@@ -53,7 +56,7 @@
 
 ModelTransformer::Input
 ModelTransformerFactory::getConfigurationForTransform(Transform &transform,
-                                                      const std::vector<Model *> &candidateInputModels,
+                                                      const vector<Model *> &candidateInputModels,
                                                       Model *defaultInputModel,
                                                       AudioPlaySource *source,
                                                       sv_frame_t startFrame,
@@ -260,8 +263,6 @@
 void
 ModelTransformerFactory::transformerFinished()
 {
-    QMutexLocker locker(&m_mutex);
-    
     QObject *s = sender();
     ModelTransformer *transformer = dynamic_cast<ModelTransformer *>(s);
     
@@ -272,6 +273,8 @@
         return;
     }
 
+    m_mutex.lock();
+    
     if (m_runningTransformers.find(transformer) == m_runningTransformers.end()) {
         cerr << "WARNING: ModelTransformerFactory::transformerFinished(" 
                   << transformer
@@ -281,16 +284,34 @@
 
     m_runningTransformers.erase(transformer);
 
+    map<AdditionalModelHandler *, vector<Model *>> toNotifyOfMore;
+    vector<AdditionalModelHandler *> toNotifyOfNoMore;
+    
     if (m_handlers.find(transformer) != m_handlers.end()) {
         if (transformer->willHaveAdditionalOutputModels()) {
             vector<Model *> mm = transformer->detachAdditionalOutputModels();
-            m_handlers[transformer]->moreModelsAvailable(mm);
+            toNotifyOfMore[m_handlers[transformer]] = mm;
         } else {
-            m_handlers[transformer]->noMoreModelsAvailable();
+            toNotifyOfNoMore.push_back(m_handlers[transformer]);
         }
         m_handlers.erase(transformer);
     }
 
+    m_mutex.unlock();
+
+    // These calls have to be made without the mutex held, as they may
+    // ultimately call back on us (e.g. we have one baroque situation
+    // where this could trigger a command to create a layer, which
+    // triggers the command history to clip the stack, which deletes a
+    // spare old model, which calls back on our modelAboutToBeDeleted)
+    
+    for (const auto &i: toNotifyOfMore) {
+        i.first->moreModelsAvailable(i.second);
+    }
+    for (AdditionalModelHandler *handler: toNotifyOfNoMore) {
+        handler->noMoreModelsAvailable();
+    }
+    
     if (transformer->isAbandoned()) {
         if (transformer->getMessage() != "") {
             emit transformFailed("", transformer->getMessage());