Mercurial > hg > svcore
changeset 1676:3b51df7695a4 single-point
Merge from branch osc-script
author | Chris Cannam |
---|---|
date | Thu, 28 Mar 2019 10:39:24 +0000 |
parents | b5580d93f28b (current diff) 6804af71b7be (diff) |
children | f97d64b8674f |
files | |
diffstat | 14 files changed, 155 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/base/Event.h Wed Mar 27 14:13:32 2019 +0000 +++ b/base/Event.h Thu Mar 28 10:39:24 2019 +0000 @@ -256,21 +256,44 @@ return m_uri < p.m_uri; } + struct ExportNameOptions { + + ExportNameOptions() : + valueAtttributeName("value"), + uriAttributeName("uri") { } + + QString valueAtttributeName; + QString uriAttributeName; + }; + void toXml(QTextStream &stream, QString indent = "", - QString extraAttributes = "") const { + QString extraAttributes = "", + ExportNameOptions opts = ExportNameOptions()) const { // For I/O purposes these are points, not events stream << indent << QString("<point frame=\"%1\" ").arg(m_frame); - if (m_haveValue) stream << QString("value=\"%1\" ").arg(m_value); - if (m_haveDuration) stream << QString("duration=\"%1\" ").arg(m_duration); - if (m_haveLevel) stream << QString("level=\"%1\" ").arg(m_level); - if (m_haveReferenceFrame) stream << QString("referenceFrame=\"%1\" ") - .arg(m_referenceFrame); - stream << QString("label=\"%1\" ") - .arg(XmlExportable::encodeEntities(m_label)); + if (m_haveValue) { + stream << QString("%1=\"%2\" ") + .arg(opts.valueAtttributeName).arg(m_value); + } + if (m_haveDuration) { + stream << QString("duration=\"%1\" ").arg(m_duration); + } + if (m_haveLevel) { + stream << QString("level=\"%1\" ").arg(m_level); + } + if (m_haveReferenceFrame) { + stream << QString("referenceFrame=\"%1\" ") + .arg(m_referenceFrame); + } + if (m_label != "") { + stream << QString("label=\"%1\" ") + .arg(XmlExportable::encodeEntities(m_label)); + } if (m_uri != QString()) { - stream << QString("uri=\"%1\" ") + stream << QString("%1=\"%2\" ") + .arg(opts.uriAttributeName) .arg(XmlExportable::encodeEntities(m_uri)); } stream << extraAttributes << "/>\n";
--- a/base/EventSeries.cpp Wed Mar 27 14:13:32 2019 +0000 +++ b/base/EventSeries.cpp Thu Mar 28 10:39:24 2019 +0000 @@ -485,12 +485,21 @@ QString indent, QString extraAttributes) const { + toXml(out, indent, extraAttributes, Event::ExportNameOptions()); +} + +void +EventSeries::toXml(QTextStream &out, + QString indent, + QString extraAttributes, + Event::ExportNameOptions options) const +{ out << indent << QString("<dataset id=\"%1\" %2>\n") .arg(getObjectExportId(this)) .arg(extraAttributes); for (const auto &p: m_events) { - p.toXml(out, indent + " "); + p.toXml(out, indent + " ", "", options); } out << indent << "</dataset>\n";
--- a/base/EventSeries.h Wed Mar 27 14:13:32 2019 +0000 +++ b/base/EventSeries.h Thu Mar 28 10:39:24 2019 +0000 @@ -205,6 +205,14 @@ void toXml(QTextStream &out, QString indent, QString extraAttributes) const override; + + /** + * Emit to XML as a dataset element. + */ + void toXml(QTextStream &out, + QString indent, + QString extraAttributes, + Event::ExportNameOptions) const; private: /**
--- a/data/model/AlignmentModel.cpp Wed Mar 27 14:13:32 2019 +0000 +++ b/data/model/AlignmentModel.cpp Thu Mar 28 10:39:24 2019 +0000 @@ -54,6 +54,8 @@ AlignmentModel::~AlignmentModel() { + SVDEBUG << "AlignmentModel(" << this << ")::~AlignmentModel()" << endl; + if (m_inputModel) m_inputModel->aboutToDelete(); delete m_inputModel; @@ -201,8 +203,8 @@ m_rawPath->isReady(&completion); #ifdef DEBUG_ALIGNMENT_MODEL - cerr << "AlignmentModel::pathCompletionChanged: completion = " - << completion << endl; + SVCERR << "AlignmentModel::pathCompletionChanged: completion = " + << completion << endl; #endif m_pathComplete = (completion == 100); @@ -211,7 +213,8 @@ constructPath(); constructReversePath(); - + + SVDEBUG << "AlignmentModel: path complete, deleting input" << endl; if (m_inputModel) m_inputModel->aboutToDelete(); delete m_inputModel; m_inputModel = nullptr;
--- a/data/model/ImageModel.h Wed Mar 27 14:13:32 2019 +0000 +++ b/data/model/ImageModel.h Thu Mar 28 10:39:24 2019 +0000 @@ -142,7 +142,7 @@ void add(Event e) override { { QMutexLocker locker(&m_mutex); - m_events.add(e.withoutDuration()); + m_events.add(e.withoutDuration().withoutValue().withoutLevel()); } m_notifier.update(e.getFrame(), m_resolution); @@ -255,8 +255,11 @@ // subsequent events are always notified .arg(getObjectExportId(&m_events)) .arg(extraAttributes)); + + Event::ExportNameOptions options; + options.uriAttributeName = "image"; - m_events.toXml(out, indent, QString("dimensions=\"1\"")); + m_events.toXml(out, indent, QString("dimensions=\"1\""), options); } protected:
--- a/data/model/Model.cpp Wed Mar 27 14:13:32 2019 +0000 +++ b/data/model/Model.cpp Thu Mar 28 10:39:24 2019 +0000 @@ -22,7 +22,7 @@ Model::~Model() { -// SVDEBUG << "Model::~Model(" << this << ")" << endl; + SVDEBUG << "Model::~Model(" << this << ")" << endl; if (!m_aboutToDelete) { SVDEBUG << "NOTE: Model(" << this << ", \"" @@ -73,9 +73,10 @@ void Model::aboutToDelete() { -// SVDEBUG << "Model(" << this << ", \"" -// << objectName() << "\", type uri <" -// << m_typeUri << ">)::aboutToDelete()" << endl; + SVDEBUG << "Model(" << this << ", \"" + << objectName() << "\", type name \"" + << getTypeName() << "\", type uri <" + << m_typeUri << ">)::aboutToDelete()" << endl; if (m_aboutToDelete) { SVDEBUG << "WARNING: Model(" << this << ", \"" @@ -98,6 +99,9 @@ void Model::setAlignment(AlignmentModel *alignment) { + SVDEBUG << "Model(" << this << "): accepting alignment model " + << alignment << endl; + if (m_alignment) { m_alignment->aboutToDelete(); delete m_alignment;
--- a/data/model/PathModel.h Wed Mar 27 14:13:32 2019 +0000 +++ b/data/model/PathModel.h Thu Mar 28 10:39:24 2019 +0000 @@ -76,7 +76,7 @@ m_end(0) { } - QString getTypeName() const override { return tr("Text"); } + QString getTypeName() const override { return tr("Path"); } bool isSparse() const { return true; } bool isOK() const override { return true; } @@ -179,7 +179,14 @@ .arg(getObjectExportId(&m_points)) .arg(extraAttributes)); + out << indent << QString("<dataset id=\"%1\" dimensions=\"2\">\n") + .arg(getObjectExportId(&m_points)); + for (PathPoint p: m_points) { + p.toXml(out, indent + " ", ""); + } + + out << indent << "</dataset>\n"; } protected:
--- a/data/model/TextModel.h Wed Mar 27 14:13:32 2019 +0000 +++ b/data/model/TextModel.h Thu Mar 28 10:39:24 2019 +0000 @@ -137,7 +137,7 @@ void add(Event e) override { { QMutexLocker locker(&m_mutex); - m_events.add(e.withoutDuration()); + m_events.add(e.withoutDuration().withoutLevel()); } m_notifier.update(e.getFrame(), m_resolution); @@ -250,8 +250,11 @@ // subsequent events are always notified .arg(getObjectExportId(&m_events)) .arg(extraAttributes)); + + Event::ExportNameOptions options; + options.valueAtttributeName = "height"; - m_events.toXml(out, indent, QString("dimensions=\"2\"")); + m_events.toXml(out, indent, QString("dimensions=\"2\""), options); } protected:
--- a/data/model/test/TestSparseModels.h Wed Mar 27 14:13:32 2019 +0000 +++ b/data/model/test/TestSparseModels.h Thu Mar 28 10:39:24 2019 +0000 @@ -19,6 +19,7 @@ #include "../NoteModel.h" #include "../TextModel.h" #include "../PathModel.h" +#include "../ImageModel.h" #include <QObject> #include <QtTest> @@ -106,8 +107,9 @@ void s1d_xml() { SparseOneDimensionalModel m(100, 10, false); m.setObjectName("This \"&\" that"); - Event p1(20), p2(20), p3(50); - p2 = p2.withLabel("Label &'\">"); + Event p1(20); + Event p2(20, "Label &'\">"); + Event p3(50, 12.4f, 16, ""); // value + duration should not be saved m.add(p1); m.add(p2); m.add(p3); @@ -118,9 +120,9 @@ QString expected = "<model id='1' name='This "&" that' sampleRate='100' start='20' end='60' type='sparse' dimensions='1' resolution='10' notifyOnAdd='true' dataset='0' />\n" "<dataset id='0' dimensions='1'>\n" - " <point frame='20' label='' />\n" + " <point frame='20' />\n" " <point frame='20' label='Label &'">' />\n" - " <point frame='50' label='' />\n" + " <point frame='50' />\n" "</dataset>\n"; expected.replace("\'", "\""); if (xml != expected) { @@ -226,7 +228,7 @@ Event p2(20, 0.0f, "text 2"); Event p3(50, 0.3f, "text 3"); m.add(p1); - m.add(p2); + m.add(p2.withLevel(0.8f)); m.add(p3); QString xml; QTextStream str(&xml, QIODevice::WriteOnly); @@ -276,6 +278,28 @@ QCOMPARE(xml, expected); } + void image_xml() { + ImageModel m(100, 10, false); + Event p1(20, 30, 40, "a label"); // value + duration should not be saved + m.add(p1.withURI("/path/to/thing.png").withLevel(0.8f)); + QString xml; + QTextStream str(&xml, QIODevice::WriteOnly); + m.toXml(str); + str.flush(); + + QString expected = + "<model id='4' name='' sampleRate='100' start='20' end='30' type='sparse' dimensions='1' resolution='10' notifyOnAdd='true' dataset='2' subtype='image' />\n" + "<dataset id='2' dimensions='1'>\n" + " <point frame='20' label='a label' image='/path/to/thing.png' />\n" + "</dataset>\n"; + expected.replace("\'", "\""); + if (xml != expected) { + cerr << "Obtained xml:\n" << xml + << "\nExpected:\n" << expected << endl; + } + QCOMPARE(xml, expected); + } + }; #endif
--- a/data/osc/OSCMessage.h Wed Mar 27 14:13:32 2019 +0000 +++ b/data/osc/OSCMessage.h Thu Mar 28 10:39:24 2019 +0000 @@ -50,6 +50,18 @@ int getArgCount() const; const QVariant &getArg(int i) const; + // For debugging purposes, not for interchange + QString toString() const { + QString s = QString("[%1][%2] %3") + .arg(m_target) + .arg(m_targetData) + .arg(m_method); + for (auto a: m_args) { + s.push_back(" \"" + a.toString() + "\""); + } + return s; + } + private: int m_target; int m_targetData;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/osc/OSCMessageCallback.h Thu Mar 28 10:39:24 2019 +0000 @@ -0,0 +1,25 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef SV_OSC_MESSAGE_CALLBACK_H +#define SV_OSC_MESSAGE_CALLBACK_H + +class OSCMessage; + +class OSCMessageCallback { +public: + virtual void handleOSCMessage(const OSCMessage &) = 0; +}; + +#endif
--- a/data/osc/OSCQueue.cpp Wed Mar 27 14:13:32 2019 +0000 +++ b/data/osc/OSCQueue.cpp Thu Mar 28 10:39:24 2019 +0000 @@ -30,6 +30,8 @@ #include <unistd.h> +#include <QThread> + void OSCQueue::oscError(int num, const char *msg, const char *path) { @@ -155,6 +157,9 @@ OSCMessage *message = m_buffer.readOne(); OSCMessage rmessage = *message; delete message; + SVDEBUG << "OSCQueue::readMessage: In thread " + << QThread::currentThreadId() << ": message follows:\n" + << rmessage.toString() << endl; return rmessage; }
--- a/data/osc/OSCQueue.h Wed Mar 27 14:13:32 2019 +0000 +++ b/data/osc/OSCQueue.h Thu Mar 28 10:39:24 2019 +0000 @@ -43,6 +43,7 @@ bool isEmpty() const { return getMessagesAvailable() == 0; } int getMessagesAvailable() const; + void postMessage(OSCMessage); OSCMessage readMessage(); QString getOSCURL() const; @@ -59,7 +60,6 @@ int, lo_message, void *); #endif - void postMessage(OSCMessage); bool parseOSCPath(QString path, int &target, int &targetData, QString &method); RingBuffer<OSCMessage *> m_buffer;
--- a/files.pri Wed Mar 27 14:13:32 2019 +0000 +++ b/files.pri Thu Mar 28 10:39:24 2019 +0000 @@ -104,6 +104,7 @@ data/model/ReadOnlyWaveFileModel.h \ data/model/WritableWaveFileModel.h \ data/osc/OSCMessage.h \ + data/osc/OSCMessageCallback.h \ data/osc/OSCQueue.h \ plugin/PluginScan.h \ plugin/DSSIPluginFactory.h \