Mercurial > hg > svapp
changeset 654:4f53620962d9 osc-script
Toward running an OSC script in batch
author | Chris Cannam |
---|---|
date | Mon, 25 Mar 2019 15:49:23 +0000 |
parents | 365c61ac7680 |
children | 8ad6327b01cc |
files | files.pri framework/MainWindowBase.cpp framework/MainWindowBase.h framework/OSCScript.h |
diffstat | 4 files changed, 176 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/files.pri Fri Mar 22 17:49:23 2019 +0000 +++ b/files.pri Mon Mar 25 15:49:23 2019 +0000 @@ -9,6 +9,7 @@ framework/Align.h \ framework/Document.h \ framework/MainWindowBase.h \ + framework/OSCScript.h \ framework/SVFileReader.h \ framework/TransformUserConfigurator.h \ framework/VersionTester.h
--- a/framework/MainWindowBase.cpp Fri Mar 22 17:49:23 2019 +0000 +++ b/framework/MainWindowBase.cpp Mon Mar 25 15:49:23 2019 +0000 @@ -71,6 +71,7 @@ #include "data/osc/OSCQueue.h" #include "data/midi/MIDIInput.h" +#include "OSCScript.h" #include "system/System.h" @@ -148,6 +149,7 @@ m_audioIO(nullptr), m_oscQueue(nullptr), m_oscQueueStarter(nullptr), + m_oscScript(nullptr), m_midiInput(nullptr), m_recentFiles("RecentFiles", 20), m_recentTransforms("RecentTransforms", 20), @@ -327,6 +329,17 @@ delete m_viewManager; delete m_midiInput; + if (m_oscScript) { + disconnect(m_oscScript, nullptr, nullptr, nullptr); + m_oscScript->abandon(); + m_oscScript->wait(1000); + if (m_oscScript->isRunning()) { + m_oscScript->terminate(); + m_oscScript->wait(1000); + } + delete m_oscScript; + } + if (m_oscQueueStarter) { disconnect(m_oscQueueStarter, nullptr, nullptr, nullptr); m_oscQueueStarter->wait(1000); @@ -516,9 +529,39 @@ connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC())); oscTimer->start(1000); SVCERR << "Finished setting up OSC interface" << endl; + + if (m_oscScriptFile != QString()) { + startOSCScript(); + } } } +void +MainWindowBase::startOSCScript() +{ + m_oscScript = new OSCScript(m_oscScriptFile, m_oscQueue); + connect(m_oscScript, SIGNAL(finished()), + this, SLOT(oscScriptFinished())); + m_oscScriptFile = QString(); + m_oscScript->start(); +} + +void +MainWindowBase::cueOSCScript(QString fileName) +{ + m_oscScriptFile = fileName; + if (m_oscQueue && m_oscQueue->isOK()) { + startOSCScript(); + } +} + +void +MainWindowBase::oscScriptFinished() +{ + delete m_oscScript; + m_oscScript = 0; +} + QString MainWindowBase::getOpenFileName(FileFinder::FileType type) {
--- a/framework/MainWindowBase.h Fri Mar 22 17:49:23 2019 +0000 +++ b/framework/MainWindowBase.h Mon Mar 25 15:49:23 2019 +0000 @@ -34,6 +34,7 @@ #include "data/fileio/FileFinder.h" #include "data/fileio/FileSource.h" #include "data/osc/OSCQueue.h" +#include "data/osc/OSCMessageCallback.h" #include <map> class Document; @@ -58,6 +59,7 @@ class QTreeView; class QPushButton; class OSCMessage; +class OSCScript; class MIDIInput; class KeyReference; class Labeller; @@ -81,7 +83,9 @@ * to use different subclasses retaining the same general structure. */ -class MainWindowBase : public QMainWindow, public FrameTimer +class MainWindowBase : public QMainWindow, + public FrameTimer, + public OSCMessageCallback { Q_OBJECT @@ -135,6 +139,8 @@ virtual bool saveSessionFile(QString path); virtual bool saveSessionTemplate(QString path); + void cueOSCScript(QString filename); + /// Implementation of FrameTimer interface method sv_frame_t getFrame() const override; @@ -320,7 +326,7 @@ virtual void oscReady(); virtual void pollOSC(); - virtual void handleOSCMessage(const OSCMessage &) = 0; + virtual void oscScriptFinished(); virtual void contextHelpChanged(const QString &); virtual void inProgressSelectionChanged(); @@ -367,7 +373,11 @@ OSCQueue *m_oscQueue; OSCQueueStarter *m_oscQueueStarter; + OSCScript *m_oscScript; + QString m_oscScriptFile; + void startOSCQueue(); + void startOSCScript(); MIDIInput *m_midiInput;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/framework/OSCScript.h Mon Mar 25 15:49:23 2019 +0000 @@ -0,0 +1,120 @@ +/* -*- 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_SCRIPT_H +#define SV_OSC_SCRIPT_H + +#include <QThread> +#include <QFile> +#include <QTextStream> + +#include "base/Debug.h" +#include "base/StringBits.h" +#include "data/osc/OSCQueue.h" +#include "data/osc/OSCMessage.h" + +#include <stdexcept> + +class OSCScript : public QThread +{ + Q_OBJECT + +public: + OSCScript(QString filename, OSCQueue *queue) : + m_filename(filename), + m_queue(queue), + m_abandoning(false) { + } + + void run() override { + + QFile f(m_filename); + if (!f.open(QFile::ReadOnly | QFile::Text)) { + SVCERR << "OSCScript: Failed to open script file \"" + << m_filename << "\" for reading" << endl; + throw std::runtime_error("OSC script file not found"); + } + + if (!m_queue) { + SVCERR << "OSCScript: No OSC queue available" << endl; + throw std::runtime_error("OSC queue not running"); + } + + int lineno = 0; + QTextStream str(&f); + + while (!str.atEnd() && !m_abandoning) { + + ++lineno; + + QString line = str.readLine().trimmed(); + if (line == QString()) continue; + + if (line[0] == '#') { + continue; + + } else if (line[0].isDigit()) { + bool ok = false; + float pause = line.toFloat(&ok); + if (ok) { + SVCERR << "OSCScript: " << m_filename << ":" << lineno + << ": pausing for " << pause << " sec" << endl; + msleep(unsigned(round(pause * 1000.0f))); + continue; + } else { + SVCERR << "OSCScript: " << m_filename << ":" << lineno + << ": error: failed to parse sleep time, giving up" + << endl; + throw std::runtime_error("OSC script parse error"); + } + + } else if (line[0] == '/' && line.size() > 1) { + QStringList parts = StringBits::splitQuoted(line, ' '); + if (parts.empty()) { + SVCERR << "OSCScript: " << m_filename << ":" << lineno + << ": warning: empty command spec, ignoring" + << endl; + continue; + } + OSCMessage message; + message.setMethod(parts[0].mid(1)); + for (int i = 1; i < parts.size(); ++i) { + message.addArg(parts[i]); + } + SVCERR << "OSCScript: " << m_filename << ":" << lineno + << ": invoking: \"" << parts[0] << "\"" << endl; + m_queue->postMessage(message); + + } else { + SVCERR << "OSCScript: " << m_filename << ":" << lineno + << ": error: message expected" << endl; + throw std::runtime_error("OSC script parse error"); + } + } + + SVCERR << "OSCScript: " << m_filename << ": finished" << endl; + } + + void abandon() { + m_abandoning = true; + } + +private: + QString m_filename; + OSCQueue *m_queue; // I do not own this + bool m_abandoning; +}; + +#endif +