# HG changeset patch # User Chris Cannam # Date 1385116648 0 # Node ID 226733f3cf3fcf1fd634f3f6230b12d050cf62ae # Parent f63051833723ad9a4fd56ce902359fbbe42faefc# Parent e50a8fee67529803a1512d1ddd83eb6a76d853c4 Merge from default branch diff -r f63051833723 -r 226733f3cf3f base/RingBuffer.h --- 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 #include "system/System.h" -#include "Scavenger.h" #include // 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 *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 > m_scavenger; - private: RingBuffer(const RingBuffer &); // not provided RingBuffer &operator=(const RingBuffer &); // not provided }; template -Scavenger > RingBuffer::m_scavenger; - -template RingBuffer::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 @@ -217,8 +213,6 @@ MUNLOCK((void *)m_buffer, m_size * sizeof(T)); } delete[] m_buffer; - - m_scavenger.scavenge(); } template @@ -233,30 +227,25 @@ } template -void -RingBuffer::resize(size_t newSize) +RingBuffer * +RingBuffer::resized(size_t newSize) const { #ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer[" << this << "]::resize(" << newSize << ")" << std::endl; + std::cerr << "RingBuffer[" << this << "]::resized(" << newSize << ")" << std::endl; #endif - m_scavenger.scavenge(); + RingBuffer *newBuffer = new RingBuffer(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(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 @@ -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; } diff -r f63051833723 -r 226733f3cf3f data/fileio/CSVFileWriter.cpp --- 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 #include @@ -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(); + } +} + + + diff -r f63051833723 -r 226733f3cf3f data/fileio/CSVFileWriter.h --- 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 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; diff -r f63051833723 -r 226733f3cf3f data/fileio/CSVFormat.cpp --- 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(); diff -r f63051833723 -r 226733f3cf3f data/fileio/FileFinder.h --- 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; diff -r f63051833723 -r 226733f3cf3f data/fileio/FileSource.cpp --- 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 #include #include +#include #include #include @@ -67,10 +68,11 @@ } #endif -static QNetworkAccessManager nm; +static QThreadStorage 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())); diff -r f63051833723 -r 226733f3cf3f data/fileio/FileSource.h --- 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; diff -r f63051833723 -r 226733f3cf3f data/model/DenseTimeValueModel.cpp --- 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 + 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"); +} diff -r f63051833723 -r 226733f3cf3f data/model/DenseTimeValueModel.h --- 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"); } }; diff -r f63051833723 -r 226733f3cf3f data/model/EditableDenseThreeDimensionalModel.cpp --- 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, diff -r f63051833723 -r 226733f3cf3f data/model/EditableDenseThreeDimensionalModel.h --- 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 = "", diff -r f63051833723 -r 226733f3cf3f data/model/Labeller.h --- 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 || diff -r f63051833723 -r 226733f3cf3f data/model/Model.h --- 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(); diff -r f63051833723 -r 226733f3cf3f data/model/RangeSummarisableTimeValueModel.h --- 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 RangeBlock; diff -r f63051833723 -r 226733f3cf3f data/model/SparseModel.h --- 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. */ diff -r f63051833723 -r 226733f3cf3f data/model/WaveFileModel.cpp --- 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; diff -r f63051833723 -r 226733f3cf3f system/System.cpp --- 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 diff -r f63051833723 -r 226733f3cf3f system/System.h --- 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 +#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 */