Mercurial > hg > svapp
diff framework/MainWindowBase.cpp @ 673:d62fd61082a1
Merge from branch tuning-difference
author | Chris Cannam |
---|---|
date | Fri, 17 May 2019 09:46:22 +0100 |
parents | 331be52cd473 |
children | 5e9b1956b609 |
line wrap: on
line diff
--- a/framework/MainWindowBase.cpp Thu Apr 04 16:17:11 2019 +0100 +++ b/framework/MainWindowBase.cpp Fri May 17 09:46:22 2019 +0100 @@ -22,7 +22,6 @@ #include "data/model/WritableWaveFileModel.h" #include "data/model/SparseOneDimensionalModel.h" #include "data/model/NoteModel.h" -#include "data/model/FlexiNoteModel.h" #include "data/model/Labeller.h" #include "data/model/TabularModel.h" #include "view/ViewManager.h" @@ -55,10 +54,12 @@ #include "data/fileio/PlaylistFileReader.h" #include "data/fileio/WavFileWriter.h" #include "data/fileio/MIDIFileWriter.h" +#include "data/fileio/CSVFileWriter.h" #include "data/fileio/BZipFileDevice.h" #include "data/fileio/FileSource.h" #include "data/fileio/AudioFileReaderFactory.h" #include "rdf/RDFImporter.h" +#include "rdf/RDFExporter.h" #include "base/RecentFiles.h" @@ -72,6 +73,7 @@ #include "data/osc/OSCQueue.h" #include "data/midi/MIDIInput.h" +#include "OSCScript.h" #include "system/System.h" @@ -149,6 +151,7 @@ m_audioIO(nullptr), m_oscQueue(nullptr), m_oscQueueStarter(nullptr), + m_oscScript(nullptr), m_midiInput(nullptr), m_recentFiles("RecentFiles", 20), m_recentTransforms("RecentTransforms", 20), @@ -328,6 +331,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); @@ -501,9 +515,9 @@ } void -MainWindowBase::startOSCQueue() +MainWindowBase::startOSCQueue(bool withNetworkPort) { - m_oscQueueStarter = new OSCQueueStarter(this); + m_oscQueueStarter = new OSCQueueStarter(this, withNetworkPort); connect(m_oscQueueStarter, SIGNAL(finished()), this, SLOT(oscReady())); m_oscQueueStarter->start(); } @@ -516,10 +530,45 @@ QTimer *oscTimer = new QTimer(this); connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC())); oscTimer->start(1000); - SVCERR << "Finished setting up OSC interface" << endl; + + if (m_oscQueue->hasPort()) { + SVDEBUG << "Finished setting up OSC interface" << endl; + } else { + SVDEBUG << "Finished setting up internal-only OSC queue" << 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) { @@ -699,16 +748,46 @@ } void +MainWindowBase::updateWindowTitle() +{ + QString title; + + if (m_sessionFile != "") { + if (m_originalLocation != "" && + m_originalLocation != m_sessionFile) { // session + location + title = tr("%1: %2 [%3]") + .arg(QApplication::applicationName()) + .arg(QFileInfo(m_sessionFile).fileName()) + .arg(m_originalLocation); + } else { // session only + title = tr("%1: %2") + .arg(QApplication::applicationName()) + .arg(QFileInfo(m_sessionFile).fileName()); + } + } else { + if (m_originalLocation != "") { // location only + title = tr("%1: %2") + .arg(QApplication::applicationName()) + .arg(m_originalLocation); + } else { // neither + title = QApplication::applicationName(); + } + } + + if (m_documentModified) { + title = tr("%1 (modified)").arg(title); + } + + setWindowTitle(title); +} + +void MainWindowBase::documentModified() { // SVDEBUG << "MainWindowBase::documentModified" << endl; - if (!m_documentModified) { - //!!! this in subclass implementation? - setWindowTitle(tr("%1 (modified)").arg(windowTitle())); - } - m_documentModified = true; + updateWindowTitle(); updateMenuStates(); } @@ -717,14 +796,8 @@ { // SVDEBUG << "MainWindowBase::documentRestored" << endl; - if (m_documentModified) { - //!!! this in subclass implementation? - QString wt(windowTitle()); - wt.replace(tr(" (modified)"), ""); - setWindowTitle(wt); - } - m_documentModified = false; + updateWindowTitle(); updateMenuStates(); } @@ -1136,46 +1209,44 @@ if (layer) { Model *model = layer->getModel(); - SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> - (model); + SparseOneDimensionalModel *sodm = + dynamic_cast<SparseOneDimensionalModel *>(model); if (sodm) { - SparseOneDimensionalModel::Point point(frame, ""); - - SparseOneDimensionalModel::Point prevPoint(0); + Event point(frame, ""); + Event prevPoint(0); bool havePrevPoint = false; - SparseOneDimensionalModel::EditCommand *command = - new SparseOneDimensionalModel::EditCommand(sodm, tr("Add Point")); + ChangeEventsCommand *command = + new ChangeEventsCommand(sodm, tr("Add Point")); if (m_labeller) { if (m_labeller->requiresPrevPoint()) { - - SparseOneDimensionalModel::PointList prevPoints = - sodm->getPreviousPoints(frame); - - if (!prevPoints.empty()) { - prevPoint = *prevPoints.begin(); + + if (sodm->getNearestEventMatching + (frame, + [](Event) { return true; }, + EventSeries::Backward, + prevPoint)) { havePrevPoint = true; } } m_labeller->setSampleRate(sodm->getSampleRate()); - if (m_labeller->actingOnPrevPoint() && havePrevPoint) { - command->deletePoint(prevPoint); - } - - m_labeller->label<SparseOneDimensionalModel::Point> + Labeller::Relabelling relabelling = m_labeller->label (point, havePrevPoint ? &prevPoint : nullptr); - if (m_labeller->actingOnPrevPoint() && havePrevPoint) { - command->addPoint(prevPoint); + if (relabelling.first == Labeller::AppliesToPreviousEvent) { + command->remove(prevPoint); + command->add(relabelling.second); + } else { + point = relabelling.second; } } - command->addPoint(point); + command->add(point); command->setName(tr("Add Point at %1 s") .arg(RealTime::frame2RealTime @@ -1231,14 +1302,12 @@ RegionModel *rm = dynamic_cast<RegionModel *>(layer->getModel()); if (rm) { - RegionModel::Point point(alignedStart, - rm->getValueMaximum() + 1, - alignedDuration, - ""); - RegionModel::EditCommand *command = - new RegionModel::EditCommand(rm, tr("Add Point")); - command->addPoint(point); - command->setName(name); + Event point(alignedStart, + rm->getValueMaximum() + 1, + alignedDuration, + ""); + ChangeEventsCommand *command = new ChangeEventsCommand(rm, name); + command->add(point); c = command->finish(); } @@ -1249,15 +1318,13 @@ NoteModel *nm = dynamic_cast<NoteModel *>(layer->getModel()); if (nm) { - NoteModel::Point point(alignedStart, - nm->getValueMinimum(), - alignedDuration, - 1.f, - ""); - NoteModel::EditCommand *command = - new NoteModel::EditCommand(nm, tr("Add Point")); - command->addPoint(point); - command->setName(name); + Event point(alignedStart, + nm->getValueMinimum(), + alignedDuration, + 1.f, + ""); + ChangeEventsCommand *command = new ChangeEventsCommand(nm, name); + command->add(point); c = command->finish(); } @@ -1265,25 +1332,6 @@ CommandHistory::getInstance()->addCommand(c, false); return; } - - FlexiNoteModel *fnm = dynamic_cast<FlexiNoteModel *>(layer->getModel()); - if (fnm) { - FlexiNoteModel::Point point(alignedStart, - fnm->getValueMinimum(), - alignedDuration, - 1.f, - ""); - FlexiNoteModel::EditCommand *command = - new FlexiNoteModel::EditCommand(fnm, tr("Add Point")); - command->addPoint(point); - command->setName(name); - c = command->finish(); - } - - if (c) { - CommandHistory::getInstance()->addCommand(c, false); - return; - } } void @@ -1306,9 +1354,10 @@ Labeller labeller(*m_labeller); labeller.setSampleRate(sodm->getSampleRate()); - +/*!!! to be updated after SODM API update Command *c = labeller.labelAll<SparseOneDimensionalModel::Point>(*sodm, &ms); if (c) CommandHistory::getInstance()->addCommand(c, false); +*/ } void @@ -1332,9 +1381,12 @@ Labeller labeller(*m_labeller); labeller.setSampleRate(sodm->getSampleRate()); + (void)n; +/*!!! to be updated after SODM API update Command *c = labeller.subdivide<SparseOneDimensionalModel::Point> (*sodm, &ms, n); if (c) CommandHistory::getInstance()->addCommand(c, false); +*/ } void @@ -1358,9 +1410,12 @@ Labeller labeller(*m_labeller); labeller.setSampleRate(sodm->getSampleRate()); + (void)n; +/*!!! to be updated after SODM API update Command *c = labeller.winnow<SparseOneDimensionalModel::Point> (*sodm, &ms, n); if (c) CommandHistory::getInstance()->addCommand(c, false); +*/ } MainWindowBase::FileOpenStatus @@ -1632,7 +1687,7 @@ } emit activity(tr("Import audio file \"%1\"").arg(source.getLocation())); - + if (mode == ReplaceMainModel) { Model *prevMain = getMainModel(); @@ -1648,22 +1703,15 @@ setupMenus(); + m_originalLocation = source.getLocation(); + if (loadedTemplate || (m_sessionFile == "")) { - //!!! shouldn't be dealing directly with title from here -- call a method - setWindowTitle(tr("%1: %2") - .arg(QApplication::applicationName()) - .arg(source.getLocation())); CommandHistory::getInstance()->clear(); CommandHistory::getInstance()->documentSaved(); m_documentModified = false; } else { - setWindowTitle(tr("%1: %2 [%3]") - .arg(QApplication::applicationName()) - .arg(QFileInfo(m_sessionFile).fileName()) - .arg(source.getLocation())); if (m_documentModified) { m_documentModified = false; - documentModified(); // so as to restore "(modified)" window title } } @@ -1671,6 +1719,8 @@ m_audioFile = source.getLocalFilename(); } + updateWindowTitle(); + } else if (mode == CreateAdditionalModel) { SVCERR << "Mode is CreateAdditionalModel" << endl; @@ -2133,10 +2183,6 @@ emit activity(tr("Import session file \"%1\"").arg(source.getLocation())); - setWindowTitle(tr("%1: %2") - .arg(QApplication::applicationName()) - .arg(source.getLocation())); - if (!source.isRemote() && !m_document->isIncomplete()) { // Setting the session file path enables the Save (as // opposed to Save As...) option. We can't do this if we @@ -2153,6 +2199,7 @@ QMessageBox::Ok); } + updateWindowTitle(); setupMenus(); findTimeRulerLayer(); @@ -2169,12 +2216,13 @@ source.getLocalFilename()); } + m_originalLocation = source.getLocation(); + emit sessionLoaded(); - } else { - setWindowTitle(QApplication::applicationName()); + updateWindowTitle(); } - + return ok ? FileOpenSucceeded : FileOpenFailed; } @@ -2240,8 +2288,6 @@ bool ok = (error == ""); - setWindowTitle(QApplication::applicationName()); - if (ok) { emit activity(tr("Open session template \"%1\"").arg(source.getLocation())); @@ -2257,6 +2303,8 @@ emit sessionLoaded(); } + updateWindowTitle(); + return ok ? FileOpenSucceeded : FileOpenFailed; } @@ -2279,13 +2327,11 @@ setupMenus(); findTimeRulerLayer(); - - setWindowTitle(tr("%1: %2") - .arg(QApplication::applicationName()) - .arg(source.getLocation())); + CommandHistory::getInstance()->clear(); CommandHistory::getInstance()->documentSaved(); m_documentModified = false; + updateWindowTitle(); emit sessionLoaded(); @@ -2649,6 +2695,8 @@ connect(m_document, SIGNAL(alignmentFailed(QString)), this, SLOT(alignmentFailed(QString))); + m_document->setAutoAlignment(m_viewManager->getAlignMode()); + emit replacedDocument(); } @@ -2736,6 +2784,79 @@ } } +bool +MainWindowBase::exportLayerTo(Layer *layer, QString path, QString &error) +{ + if (QFileInfo(path).suffix() == "") path += ".svl"; + + QString suffix = QFileInfo(path).suffix().toLower(); + + Model *model = layer->getModel(); + + if (suffix == "xml" || suffix == "svl") { + + QFile file(path); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + error = tr("Failed to open file %1 for writing").arg(path); + } else { + QTextStream out(&file); + out.setCodec(QTextCodec::codecForName("UTF-8")); + out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + << "<!DOCTYPE sonic-visualiser>\n" + << "<sv>\n" + << " <data>\n"; + + model->toXml(out, " "); + + out << " </data>\n" + << " <display>\n"; + + layer->toXml(out, " "); + + out << " </display>\n" + << "</sv>\n"; + } + + } else if (suffix == "mid" || suffix == "midi") { + + NoteModel *nm = dynamic_cast<NoteModel *>(model); + + if (!nm) { + error = tr("Can't export non-note layers to MIDI"); + } else { + MIDIFileWriter writer(path, nm, nm->getSampleRate()); + writer.write(); + if (!writer.isOK()) { + error = writer.getError(); + } + } + + } else if (suffix == "ttl" || suffix == "n3") { + + if (!RDFExporter::canExportModel(model)) { + error = tr("Sorry, cannot export this layer type to RDF (supported types are: region, note, text, time instants, time values)"); + } else { + RDFExporter exporter(path, model); + exporter.write(); + if (!exporter.isOK()) { + error = exporter.getError(); + } + } + + } else { + + CSVFileWriter writer(path, model, + ((suffix == "csv") ? "," : "\t")); + writer.write(); + + if (!writer.isOK()) { + error = writer.getError(); + } + } + + return (error == ""); +} + void MainWindowBase::toXml(QTextStream &out, bool asTemplate) { @@ -3181,25 +3302,16 @@ setupMenus(); findTimeRulerLayer(); + m_originalLocation = model->getLocation(); + if (loadedTemplate || (m_sessionFile == "")) { - //!!! shouldn't be dealing directly with title from here -- call a method - setWindowTitle(tr("%1: %2") - .arg(QApplication::applicationName()) - .arg(model->getLocation())); CommandHistory::getInstance()->clear(); CommandHistory::getInstance()->documentSaved(); - m_documentModified = false; - } else { - setWindowTitle(tr("%1: %2 [%3]") - .arg(QApplication::applicationName()) - .arg(QFileInfo(m_sessionFile).fileName()) - .arg(model->getLocation())); - if (m_documentModified) { - m_documentModified = false; - documentModified(); // so as to restore "(modified)" window title - } } + m_documentModified = false; + updateWindowTitle(); + } else { CommandHistory::getInstance()->startCompoundOperation