changeset 841:226733f3cf3f tonioni

Merge from default branch
author Chris Cannam
date Fri, 22 Nov 2013 10:37:28 +0000
parents f63051833723 (current diff) e50a8fee6752 (diff)
children 2d53205f70cd
files
diffstat 18 files changed, 207 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/base/RingBuffer.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/base/RingBuffer.h	Fri Nov 22 10:37:28 2013 +0000
@@ -24,7 +24,6 @@
 #include <sys/types.h>
 
 #include "system/System.h"
-#include "Scavenger.h"
 
 #include <cstring> // memcpy, memset &c
 
@@ -67,11 +66,15 @@
     size_t getSize() const;
 
     /**
-     * Resize the ring buffer.  This also empties it.  Actually swaps
-     * in a new, larger buffer; the old buffer is scavenged after a
-     * seemly delay.  Should be called from the write thread.
+     * Return a new ring buffer (allocated with "new" -- caller must
+     * delete when no longer needed) of the given size, containing the
+     * same data as this one as perceived by reader 0 of this buffer.
+     * If another thread reads from or writes to this buffer during
+     * the call, the contents of the new buffer may be incomplete or
+     * inconsistent.  If this buffer's data will not fit in the new
+     * size, the contents are undefined.
      */
-    void resize(size_t newSize);
+    RingBuffer<T, N> *resized(size_t newSize) const;
 
     /**
      * Lock the ring buffer into physical memory.  Returns true
@@ -167,17 +170,12 @@
     size_t  m_size;
     size_t  m_spare;
 
-    static Scavenger<ScavengerArrayWrapper<T> > m_scavenger;
-
 private:
     RingBuffer(const RingBuffer &); // not provided
     RingBuffer &operator=(const RingBuffer &); // not provided
 };
 
 template <typename T, int N>
-Scavenger<ScavengerArrayWrapper<T> > RingBuffer<T, N>::m_scavenger;
-
-template <typename T, int N>
 RingBuffer<T, N>::RingBuffer(size_t n) :
     m_buffer(new T[n + 1]),
     m_mlocked(false),
@@ -200,8 +198,6 @@
 */
     
     for (int i = 0; i < N; ++i) m_readers[i] = 0;
-
-    m_scavenger.scavenge();
 }
 
 template <typename T, int N>
@@ -217,8 +213,6 @@
 	MUNLOCK((void *)m_buffer, m_size * sizeof(T));
     }
     delete[] m_buffer;
-
-    m_scavenger.scavenge();
 }
 
 template <typename T, int N>
@@ -233,30 +227,25 @@
 }
 
 template <typename T, int N>
-void
-RingBuffer<T, N>::resize(size_t newSize)
+RingBuffer<T, N> *
+RingBuffer<T, N>::resized(size_t newSize) const
 {
 #ifdef DEBUG_RINGBUFFER
-    std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resize(" << newSize << ")" << std::endl;
+    std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resized(" << newSize << ")" << std::endl;
 #endif
 
-    m_scavenger.scavenge();
+    RingBuffer<T, N> *newBuffer = new RingBuffer<T, N>(newSize);
 
-    if (m_mlocked) {
-	MUNLOCK((void *)m_buffer, m_size * sizeof(T));
+    int w = m_writer;
+    int r = m_readers[0];
+
+    while (r != w) {
+        T value = m_buffer[r];
+        newBuffer->write(&value, 1);
+        if (++r == m_size) r = 0;
     }
 
-    m_scavenger.claim(new ScavengerArrayWrapper<T>(m_buffer));
-
-    reset();
-    m_buffer = new T[newSize + 1];
-    m_size = newSize + 1;
-
-    if (m_mlocked) {
-	if (MLOCK((void *)m_buffer, m_size * sizeof(T))) {
-	    m_mlocked = false;
-	}
-    }
+    return newBuffer;
 }
 
 template <typename T, int N>
@@ -350,6 +339,7 @@
 	memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
     }
 
+    MBARRIER();
     m_readers[R] = (m_readers[R] + n) % m_size;
 
 #ifdef DEBUG_RINGBUFFER
@@ -392,6 +382,7 @@
 	}
     }
 
+    MBARRIER();
     m_readers[R] = (m_readers[R] + n) % m_size;
     return n;
 }
@@ -414,6 +405,7 @@
 	return t;
     }
     T value = m_buffer[m_readers[R]];
+    MBARRIER();
     if (++m_readers[R] == m_size) m_readers[R] = 0;
     return value;
 }
@@ -520,6 +512,7 @@
 	memcpy(m_buffer, source + here, (n - here) * sizeof(T));
     }
 
+    MBARRIER();
     m_writer = (m_writer + n) % m_size;
 
 #ifdef DEBUG_RINGBUFFER
@@ -554,7 +547,8 @@
 	memset(m_buffer + m_writer, 0, here * sizeof(T));
 	memset(m_buffer, 0, (n - here) * sizeof(T));
     }
-
+    
+    MBARRIER();
     m_writer = (m_writer + n) % m_size;
     return n;
 }
--- a/data/fileio/CSVFileWriter.cpp	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/fileio/CSVFileWriter.cpp	Fri Nov 22 10:37:28 2013 +0000
@@ -23,6 +23,7 @@
 
 #include "base/TempWriteFile.h"
 #include "base/Exceptions.h"
+#include "base/Selection.h"
 
 #include <QFile>
 #include <QTextStream>
@@ -75,4 +76,36 @@
     }
 }
 
+void
+CSVFileWriter::writeSelection(MultiSelection *selection)
+{
+    try {
+        TempWriteFile temp(m_path);
 
+        QFile file(temp.getTemporaryFilename());
+        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+            m_error = tr("Failed to open file %1 for writing")
+                .arg(temp.getTemporaryFilename());
+            return;
+        }
+    
+        QTextStream out(&file);
+
+        for (MultiSelection::SelectionList::iterator i =
+                 selection->getSelections().begin();
+             i != selection->getSelections().end(); ++i) {
+	
+            size_t f0(i->getStartFrame()), f1(i->getEndFrame());
+            out << m_model->toDelimitedDataString(m_delimiter, f0, f1);
+        }
+
+        file.close();
+        temp.moveToTarget();
+
+    } catch (FileOperationFailed &f) {
+        m_error = f.what();
+    }
+}
+
+
+
--- a/data/fileio/CSVFileWriter.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/fileio/CSVFileWriter.h	Fri Nov 22 10:37:28 2013 +0000
@@ -20,6 +20,7 @@
 #include <QString>
 
 class Model;
+class MultiSelection;
 
 class CSVFileWriter : public QObject
 {
@@ -33,6 +34,7 @@
     virtual QString getError() const;
 
     virtual void write();
+    virtual void writeSelection(MultiSelection *selection);
 
 protected:
     QString m_path;
--- a/data/fileio/CSVFormat.cpp	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/fileio/CSVFormat.cpp	Fri Nov 22 10:37:28 2013 +0000
@@ -73,8 +73,10 @@
 
             guessQualities(line, lineno);
 
-            if (++lineno == 50) break;
+            ++lineno;
         }
+
+        if (lineno >= 50) break;
     }
 
     guessPurposes();
--- a/data/fileio/FileFinder.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/fileio/FileFinder.h	Fri Nov 22 10:37:28 2013 +0000
@@ -28,7 +28,8 @@
         LayerFileNoMidi,
         SessionOrAudioFile,
         ImageFile,
-        AnyFile
+        AnyFile,
+        CSVFile,
     };
 
     virtual QString getOpenFileName(FileType type, QString fallbackLocation = "") = 0;
--- a/data/fileio/FileSource.cpp	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/fileio/FileSource.cpp	Fri Nov 22 10:37:28 2013 +0000
@@ -25,6 +25,7 @@
 #include <QFileInfo>
 #include <QDir>
 #include <QCoreApplication>
+#include <QThreadStorage>
 
 #include <iostream>
 #include <cstdlib>
@@ -67,10 +68,11 @@
 }
 #endif
 
-static QNetworkAccessManager nm;
+static QThreadStorage<QNetworkAccessManager *> nms;
 
 FileSource::FileSource(QString fileOrUrl, ProgressReporter *reporter,
                        QString preferredContentType) :
+    m_rawFileOrUrl(fileOrUrl),
     m_url(fileOrUrl, QUrl::StrictMode),
     m_localFile(0),
     m_reply(0),
@@ -111,6 +113,9 @@
         std::cerr << "FileSource::FileSource: Failed to open local file with URL \"" << m_url.toString() << "\"; trying again assuming filename was encoded" << std::endl;
 #endif
         m_url = QUrl::fromEncoded(fileOrUrl.toLatin1());
+#ifdef DEBUG_FILE_SOURCE
+        std::cerr << "FileSource::FileSource: URL is now \"" << m_url.toString() << "\"" << std::endl;
+#endif
         init();
     }
 
@@ -260,6 +265,13 @@
 void
 FileSource::init()
 {
+    { // check we have a QNetworkAccessManager
+        QMutexLocker locker(&m_mapMutex);
+        if (!nms.hasLocalData()) {
+            nms.setLocalData(new QNetworkAccessManager());
+        }
+    }
+
     if (isResource()) {
 #ifdef DEBUG_FILE_SOURCE
         std::cerr << "FileSource::init: Is a resource" << std::endl;
@@ -282,15 +294,20 @@
 #endif
         bool literal = false;
         m_localFilename = m_url.toLocalFile();
+
         if (m_localFilename == "") {
             // QUrl may have mishandled the scheme (e.g. in a DOS path)
-            m_localFilename = m_url.toString();
+            m_localFilename = m_rawFileOrUrl;
+#ifdef DEBUG_FILE_SOURCE
+            std::cerr << "FileSource::init: Trying literal local filename \""
+                      << m_localFilename << "\"" << std::endl;
+#endif
             literal = true;
         }
         m_localFilename = QFileInfo(m_localFilename).absoluteFilePath();
 
 #ifdef DEBUG_FILE_SOURCE
-        std::cerr << "FileSource::init: URL translates to local filename \""
+        std::cerr << "FileSource::init: URL translates to absolute filename \""
                   << m_localFilename << "\" (with literal=" << literal << ")"
                   << std::endl;
 #endif
@@ -306,7 +323,7 @@
 #endif
                 // Again, QUrl may have been mistreating us --
                 // e.g. dropping a part that looks like query data
-                m_localFilename = m_url.toString();
+                m_localFilename = m_rawFileOrUrl;
                 literal = true;
                 if (!QFileInfo(m_localFilename).exists()) {
                     m_lastStatus = 404;
@@ -443,7 +460,7 @@
              QString("%1, */*").arg(m_preferredContentType).toLatin1());
     }
 
-    m_reply = nm.get(req);
+    m_reply = nms.localData()->get(req);
 
     connect(m_reply, SIGNAL(readyRead()),
             this, SLOT(readyRead()));
--- a/data/fileio/FileSource.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/fileio/FileSource.h	Fri Nov 22 10:37:28 2013 +0000
@@ -218,6 +218,7 @@
 protected:
     FileSource &operator=(const FileSource &); // not provided
 
+    QString m_rawFileOrUrl;
     QUrl m_url;
     QFile *m_localFile;
     QNetworkReply *m_reply;
--- a/data/model/DenseTimeValueModel.cpp	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/model/DenseTimeValueModel.cpp	Fri Nov 22 10:37:28 2013 +0000
@@ -16,6 +16,8 @@
 #include "DenseTimeValueModel.h"
 #include "base/PlayParameterRepository.h"
 
+#include <QStringList>
+
 DenseTimeValueModel::DenseTimeValueModel()
 {
     PlayParameterRepository::getInstance()->addPlayable(this);
@@ -26,3 +28,36 @@
     PlayParameterRepository::getInstance()->removePlayable(this);
 }
 	
+QString
+DenseTimeValueModel::toDelimitedDataString(QString delimiter, size_t f0, size_t f1) const
+{
+    size_t ch = getChannelCount();
+
+    std::cerr << "f0 = " << f0 << ", f1 = " << f1 << std::endl;
+
+    if (f1 <= f0) return "";
+
+    float **all = new float *[ch];
+    for (size_t c = 0; c < ch; ++c) {
+        all[c] = new float[f1 - f0];
+    }
+
+    size_t n = getData(0, ch - 1, f0, f1 - f0, all);
+
+    QStringList list;
+    for (size_t i = 0; i < n; ++i) {
+        QStringList parts;
+        parts << QString("%1").arg(f0 + i);
+        for (size_t c = 0; c < ch; ++c) {
+            parts << QString("%1").arg(all[c][i]);
+        }
+        list << parts.join(delimiter);
+    }
+
+    for (size_t c = 0; c < ch; ++c) {
+        delete[] all[c];
+    }
+    delete[] all;
+
+    return list.join("\n");
+}
--- a/data/model/DenseTimeValueModel.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/model/DenseTimeValueModel.h	Fri Nov 22 10:37:28 2013 +0000
@@ -86,6 +86,8 @@
     virtual QString getDefaultPlayPluginId() const { return ""; }
     virtual QString getDefaultPlayPluginConfiguration() const { return ""; }
 
+    virtual QString toDelimitedDataString(QString delimiter, size_t f0, size_t f1) const;
+
     QString getTypeName() const { return tr("Dense Time-Value"); }
 };
 
--- a/data/model/EditableDenseThreeDimensionalModel.cpp	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/model/EditableDenseThreeDimensionalModel.cpp	Fri Nov 22 10:37:28 2013 +0000
@@ -483,6 +483,24 @@
     return s;
 }
 
+QString
+EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter, size_t f0, size_t f1) const
+{
+    QReadLocker locker(&m_lock);
+    QString s;
+    for (size_t i = 0; i < m_data.size(); ++i) {
+        size_t fr = m_startFrame + i * m_resolution;
+        if (fr >= f0 && fr < f1) {
+            QStringList list;
+            for (size_t j = 0; j < m_data.at(i).size(); ++j) {
+                list << QString("%1").arg(m_data.at(i).at(j));
+            }
+            s += list.join(delimiter) + "\n";
+        }
+    }
+    return s;
+}
+
 void
 EditableDenseThreeDimensionalModel::toXml(QTextStream &out,
                                           QString indent,
--- a/data/model/EditableDenseThreeDimensionalModel.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/model/EditableDenseThreeDimensionalModel.h	Fri Nov 22 10:37:28 2013 +0000
@@ -139,6 +139,7 @@
     QString getTypeName() const { return tr("Editable Dense 3-D"); }
 
     virtual QString toDelimitedDataString(QString delimiter) const;
+    virtual QString toDelimitedDataString(QString delimiter, size_t f0, size_t f1) const;
 
     virtual void toXml(QTextStream &out,
                        QString indent = "",
--- a/data/model/Labeller.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/model/Labeller.h	Fri Nov 22 10:37:28 2013 +0000
@@ -134,6 +134,12 @@
 
     void setSampleRate(float rate) { m_rate = rate; }
 
+    void resetCounters() {
+        m_counter = 1;
+        m_counter2 = 1;
+        m_cycle = 4;
+    }
+
     void incrementCounter() {
         m_counter++;
         if (m_type == ValueFromCyclicalCounter ||
--- a/data/model/Model.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/model/Model.h	Fri Nov 22 10:37:28 2013 +0000
@@ -213,7 +213,12 @@
                        QString indent = "",
                        QString extraAttributes = "") const;
 
-    virtual QString toDelimitedDataString(QString) const { return ""; }
+    virtual QString toDelimitedDataString(QString delimiter) const {
+        return toDelimitedDataString(delimiter, getStartFrame(), getEndFrame());
+    }
+    virtual QString toDelimitedDataString(QString, size_t f0, size_t f1) const {
+        return "";
+    }
 
 public slots:
     void aboutToDelete();
--- a/data/model/RangeSummarisableTimeValueModel.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/model/RangeSummarisableTimeValueModel.h	Fri Nov 22 10:37:28 2013 +0000
@@ -37,41 +37,6 @@
 public:
     RangeSummarisableTimeValueModel() { }
 
-#define RANGE_USE_SHORT 1
-#ifdef RANGE_USE_SHORT
-    class Range
-    {
-    public:
-        Range() : 
-            m_min(0), m_max(0), m_absmean(0) { }
-        Range(const Range &r) : 
-            m_min(r.m_min), m_max(r.m_max), m_absmean(r.m_absmean) { }
-        Range(float min, float max, float absmean)
-        { setMin(min); setMax(max); setAbsmean(absmean); }
-        
-        float min() const { return i2f(m_min); }
-        float max() const { return i2f(m_max); }
-        float absmean() const { return i2f(m_absmean); }
-
-        void setMin(float min) { m_min = f2i(min); }
-        void setMax(float max) { m_max = f2i(max); }
-        void setAbsmean(float absmean) { m_absmean = f2i(absmean); }
-
-    private:
-        static inline int16_t f2i(float f) {
-            if (f > 1.f) f = 1.f;
-            if (f < -1.f) f = -1.f;
-            return int16_t(f * 32767.f);
-        }
-        static inline float i2f(int16_t i) {
-            return float(i) / 32767.f;
-        }
-
-        int16_t m_min;
-        int16_t m_max;
-        int16_t m_absmean;
-    };
-#else
     class Range
     {
     public:
@@ -95,7 +60,6 @@
         float m_max;
         float m_absmean;
     };
-#endif
 
     typedef std::vector<Range> RangeBlock;
 
--- a/data/model/SparseModel.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/model/SparseModel.h	Fri Nov 22 10:37:28 2013 +0000
@@ -157,6 +157,17 @@
         return s;
     }
 
+    virtual QString toDelimitedDataString(QString delimiter, size_t f0, size_t f1) const
+    { 
+        QString s;
+        for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) {
+            if (i->frame >= f0 && i->frame < f1) {
+                s += i->toDelimitedDataString(delimiter, m_sampleRate) + "\n";
+            }
+        }
+        return s;
+    }
+
     /**
      * Command to add a point, with undo.
      */
--- a/data/model/WaveFileModel.cpp	Wed Jul 17 16:01:28 2013 +0100
+++ b/data/model/WaveFileModel.cpp	Fri Nov 22 10:37:28 2013 +0000
@@ -463,7 +463,7 @@
             if (sample > max || got == 0) max = sample;
 	    if (sample < min || got == 0) min = sample;
             total += fabsf(sample);
-	    
+
 	    ++i;
             ++got;
             
--- a/system/System.cpp	Wed Jul 17 16:01:28 2013 +0100
+++ b/system/System.cpp	Fri Nov 22 10:37:28 2013 +0000
@@ -274,6 +274,30 @@
 #endif
 }
 
+#ifdef _WIN32
+extern void SystemMemoryBarrier()
+{
+#ifdef __MSVC__
+    MemoryBarrier();
+#else /* mingw */
+    LONG Barrier = 0;
+    __asm__ __volatile__("xchgl %%eax,%0 "
+                         : "=r" (Barrier));
+#endif
+}
+#else /* !_WIN32 */
+#if !defined(__APPLE__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0))
+void
+SystemMemoryBarrier()
+{
+    pthread_mutex_t dummy = PTHREAD_MUTEX_INITIALIZER;
+    pthread_mutex_lock(&dummy);
+    pthread_mutex_unlock(&dummy);
+}
+#endif /* !defined(__APPLE__) etc */
+#endif /* !_WIN32 */
+
+
 static char *startupLocale = 0;
 
 void
--- a/system/System.h	Wed Jul 17 16:01:28 2013 +0100
+++ b/system/System.h	Fri Nov 22 10:37:28 2013 +0000
@@ -30,6 +30,9 @@
 #define MUNLOCK_SAMPLEBLOCK(a) 1
 #define MUNLOCKALL() 1
 
+extern void SystemMemoryBarrier();
+#define MBARRIER()   SystemMemoryBarrier()
+
 #define DLOPEN(a,b)  LoadLibrary((a).toStdWString().c_str())
 #define DLSYM(a,b)   GetProcAddress((HINSTANCE)(a),(b))
 #define DLCLOSE(a)   (!FreeLibrary((HINSTANCE)(a)))
@@ -99,6 +102,9 @@
 
 #define MUNLOCKALL() 1
 
+#include <libkern/OSAtomic.h>
+#define MBARRIER() OSMemoryBarrier()
+
 #else 
 
 #ifdef sun
@@ -122,7 +128,14 @@
 
 #define MUNLOCKALL() ::munlockall()
 
-#endif /* __APPLE__ */
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
+#define MBARRIER() __sync_synchronize()
+#else
+extern void SystemMemoryBarrier();
+#define MBARRIER() SystemMemoryBarrier()
+#endif
+
+#endif /* ! __APPLE__ */
 
 #endif /* ! _WIN32 */