comparison framework/MainWindowBase.cpp @ 728:2dce002539a0

Merge from branch spectrogram-export
author Chris Cannam
date Fri, 10 Jan 2020 14:54:43 +0000
parents e2ad6fe768b0
children 15da3ab3d416
comparison
equal deleted inserted replaced
720:55f317633b93 728:2dce002539a0
35 #include "layer/SliceableLayer.h" 35 #include "layer/SliceableLayer.h"
36 #include "layer/ImageLayer.h" 36 #include "layer/ImageLayer.h"
37 #include "layer/NoteLayer.h" 37 #include "layer/NoteLayer.h"
38 #include "layer/FlexiNoteLayer.h" 38 #include "layer/FlexiNoteLayer.h"
39 #include "layer/RegionLayer.h" 39 #include "layer/RegionLayer.h"
40 #include "layer/SpectrogramLayer.h"
40 41
41 #include "widgets/ListInputDialog.h" 42 #include "widgets/ListInputDialog.h"
42 #include "widgets/CommandHistory.h" 43 #include "widgets/CommandHistory.h"
43 #include "widgets/ProgressDialog.h" 44 #include "widgets/ProgressDialog.h"
44 #include "widgets/MIDIFileImportDialog.h" 45 #include "widgets/MIDIFileImportDialog.h"
58 #include "data/fileio/BZipFileDevice.h" 59 #include "data/fileio/BZipFileDevice.h"
59 #include "data/fileio/FileSource.h" 60 #include "data/fileio/FileSource.h"
60 #include "data/fileio/AudioFileReaderFactory.h" 61 #include "data/fileio/AudioFileReaderFactory.h"
61 #include "rdf/RDFImporter.h" 62 #include "rdf/RDFImporter.h"
62 #include "rdf/RDFExporter.h" 63 #include "rdf/RDFExporter.h"
64
65 #include "transform/ModelTransformerFactory.h"
63 66
64 #include "base/RecentFiles.h" 67 #include "base/RecentFiles.h"
65 68
66 #include "base/XmlExportable.h" 69 #include "base/XmlExportable.h"
67 #include "base/Profiler.h" 70 #include "base/Profiler.h"
157 m_midiInput(nullptr), 160 m_midiInput(nullptr),
158 m_recentFiles("RecentFiles", 20), 161 m_recentFiles("RecentFiles", 20),
159 m_recentTransforms("RecentTransforms", 20), 162 m_recentTransforms("RecentTransforms", 20),
160 m_documentModified(false), 163 m_documentModified(false),
161 m_openingAudioFile(false), 164 m_openingAudioFile(false),
162 m_abandoning(false),
163 m_labeller(nullptr), 165 m_labeller(nullptr),
164 m_lastPlayStatusSec(0), 166 m_lastPlayStatusSec(0),
165 m_initialDarkBackground(false), 167 m_initialDarkBackground(false),
166 m_defaultFfwdRwdStep(2, 0), 168 m_defaultFfwdRwdStep(2, 0),
167 m_audioRecordMode(RecordCreateAdditionalModel), 169 m_audioRecordMode(RecordCreateAdditionalModel),
525 { 527 {
526 if (m_oscQueue && m_oscQueue->isOK()) { 528 if (m_oscQueue && m_oscQueue->isOK()) {
527 connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC())); 529 connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC()));
528 QTimer *oscTimer = new QTimer(this); 530 QTimer *oscTimer = new QTimer(this);
529 connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC())); 531 connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC()));
530 oscTimer->start(1000); 532 oscTimer->start(2000);
531 533
532 if (m_oscQueue->hasPort()) { 534 if (m_oscQueue->hasPort()) {
533 SVDEBUG << "Finished setting up OSC interface" << endl; 535 SVDEBUG << "Finished setting up OSC interface" << endl;
534 } else { 536 } else {
535 SVDEBUG << "Finished setting up internal-only OSC queue" << endl; 537 SVDEBUG << "Finished setting up internal-only OSC queue" << endl;
684 dynamic_cast<FlexiNoteLayer *>(currentLayer) || 686 dynamic_cast<FlexiNoteLayer *>(currentLayer) ||
685 dynamic_cast<RegionLayer *>(currentLayer))); 687 dynamic_cast<RegionLayer *>(currentLayer)));
686 bool haveCurrentColour3DPlot = 688 bool haveCurrentColour3DPlot =
687 (haveCurrentLayer && 689 (haveCurrentLayer &&
688 dynamic_cast<Colour3DPlotLayer *>(currentLayer)); 690 dynamic_cast<Colour3DPlotLayer *>(currentLayer));
691 bool haveCurrentSpectrogram =
692 (haveCurrentLayer &&
693 dynamic_cast<SpectrogramLayer *>(currentLayer));
689 bool haveClipboardContents = 694 bool haveClipboardContents =
690 (m_viewManager && 695 (m_viewManager &&
691 !m_viewManager->getClipboard().empty()); 696 !m_viewManager->getClipboard().empty());
692 bool haveTabularLayer = 697 bool haveTabularLayer =
693 (haveCurrentLayer && 698 (haveCurrentLayer &&
702 emit canReplaceMainAudio(haveMainModel); 707 emit canReplaceMainAudio(haveMainModel);
703 emit canImportLayer(haveMainModel && haveCurrentPane); 708 emit canImportLayer(haveMainModel && haveCurrentPane);
704 emit canExportAudio(haveMainModel); 709 emit canExportAudio(haveMainModel);
705 emit canChangeSessionTemplate(haveMainModel); 710 emit canChangeSessionTemplate(haveMainModel);
706 emit canExportLayer(haveMainModel && 711 emit canExportLayer(haveMainModel &&
707 (haveCurrentEditableLayer || haveCurrentColour3DPlot)); 712 (haveCurrentEditableLayer ||
713 haveCurrentColour3DPlot ||
714 haveCurrentSpectrogram));
708 emit canExportImage(haveMainModel && haveCurrentPane); 715 emit canExportImage(haveMainModel && haveCurrentPane);
709 emit canDeleteCurrentLayer(haveCurrentLayer); 716 emit canDeleteCurrentLayer(haveCurrentLayer);
710 emit canRenameLayer(haveCurrentLayer); 717 emit canRenameLayer(haveCurrentLayer);
711 emit canEditLayer(haveCurrentEditableLayer); 718 emit canEditLayer(haveCurrentEditableLayer);
712 emit canEditLayerTabular(haveCurrentEditableLayer || haveTabularLayer); 719 emit canEditLayerTabular(haveCurrentEditableLayer || haveTabularLayer);
2795 return false; 2802 return false;
2796 } 2803 }
2797 } 2804 }
2798 2805
2799 bool 2806 bool
2800 MainWindowBase::exportLayerTo(Layer *layer, QString path, QString &error) 2807 MainWindowBase::exportLayerTo(Layer *layer, View *fromView,
2801 { 2808 MultiSelection *selectionsToWrite,
2809 QString path, QString &error)
2810 {
2811 //!!! should we pull out the whole export logic into another
2812 // class? then we can more reasonably query it for things like
2813 // "can we export this layer type to this file format? can we
2814 // export selections, or only the whole layer?"
2815
2802 if (QFileInfo(path).suffix() == "") path += ".svl"; 2816 if (QFileInfo(path).suffix() == "") path += ".svl";
2803 2817
2804 QString suffix = QFileInfo(path).suffix().toLower(); 2818 QString suffix = QFileInfo(path).suffix().toLower();
2805 2819
2806 auto model = ModelById::get(layer->getModel()); 2820 auto model = ModelById::get(layer->getExportModel(fromView));
2807 if (!model) { 2821 if (!model) {
2808 error = tr("Internal error: unknown model"); 2822 error = tr("Internal error: unknown model");
2809 return false; 2823 return false;
2810 } 2824 }
2811 2825
2837 2851
2838 auto nm = ModelById::getAs<NoteModel>(layer->getModel()); 2852 auto nm = ModelById::getAs<NoteModel>(layer->getModel());
2839 2853
2840 if (!nm) { 2854 if (!nm) {
2841 error = tr("Can't export non-note layers to MIDI"); 2855 error = tr("Can't export non-note layers to MIDI");
2856 } else if (!selectionsToWrite) {
2857 MIDIFileWriter writer(path, nm.get(), nm->getSampleRate());
2858 writer.write();
2859 if (!writer.isOK()) {
2860 error = writer.getError();
2861 }
2842 } else { 2862 } else {
2843 MIDIFileWriter writer(path, nm.get(), nm->getSampleRate()); 2863 NoteModel temporary(nm->getSampleRate(),
2864 nm->getResolution(),
2865 nm->getValueMinimum(),
2866 nm->getValueMaximum(),
2867 false);
2868 temporary.setScaleUnits(nm->getScaleUnits());
2869 for (const auto &s: selectionsToWrite->getSelections()) {
2870 EventVector ev(nm->getEventsStartingWithin
2871 (s.getStartFrame(), s.getDuration()));
2872 for (const auto &e: ev) {
2873 temporary.add(e);
2874 }
2875 }
2876 MIDIFileWriter writer(path, &temporary, temporary.getSampleRate());
2844 writer.write(); 2877 writer.write();
2845 if (!writer.isOK()) { 2878 if (!writer.isOK()) {
2846 error = writer.getError(); 2879 error = writer.getError();
2847 } 2880 }
2848 } 2881 }
2859 } 2892 }
2860 } 2893 }
2861 2894
2862 } else { 2895 } else {
2863 2896
2864 CSVFileWriter writer(path, model.get(), 2897 ProgressDialog dialog {
2898 QObject::tr("Exporting layer..."), true, 500, this,
2899 Qt::ApplicationModal
2900 };
2901
2902 CSVFileWriter writer(path, model.get(), &dialog,
2865 ((suffix == "csv") ? "," : "\t")); 2903 ((suffix == "csv") ? "," : "\t"));
2866 writer.write(); 2904
2905 if (selectionsToWrite) {
2906 writer.writeSelection(*selectionsToWrite);
2907 } else {
2908 writer.write();
2909 }
2867 2910
2868 if (!writer.isOK()) { 2911 if (!writer.isOK()) {
2869 error = writer.getError(); 2912 error = writer.getError();
2913 if (error == "") {
2914 error = tr("Failed to export layer for an unknown reason");
2915 }
2870 } 2916 }
2871 } 2917 }
2872 2918
2873 return (error == ""); 2919 return (error == "");
2874 } 2920 }
4162 4208
4163 void 4209 void
4164 MainWindowBase::pollOSC() 4210 MainWindowBase::pollOSC()
4165 { 4211 {
4166 if (!m_oscQueue || m_oscQueue->isEmpty()) return; 4212 if (!m_oscQueue || m_oscQueue->isEmpty()) return;
4167 SVDEBUG << "MainWindowBase::pollOSC: have " << m_oscQueue->getMessagesAvailable() << " messages" << endl; 4213
4168 4214 while (!m_oscQueue->isEmpty()) {
4169 if (m_openingAudioFile) return; 4215
4170 4216 if (m_openingAudioFile) {
4171 OSCMessage message = m_oscQueue->readMessage(); 4217 SVDEBUG << "MainWindowBase::pollOSC: "
4172 4218 << "waiting for audio to finish loading"
4173 if (message.getTarget() != 0) { 4219 << endl;
4174 return; //!!! for now -- this class is target 0, others not handled yet 4220 return;
4175 } 4221 }
4176 4222
4177 handleOSCMessage(message); 4223 if (ModelTransformerFactory::getInstance()->haveRunningTransformers()) {
4224 SVDEBUG << "MainWindowBase::pollOSC: "
4225 << "waiting for running transforms to complete"
4226 << endl;
4227 return;
4228 }
4229
4230 SVDEBUG << "MainWindowBase::pollOSC: have "
4231 << m_oscQueue->getMessagesAvailable()
4232 << " messages" << endl;
4233
4234 OSCMessage message = m_oscQueue->readMessage();
4235
4236 if (message.getTarget() != 0) {
4237 SVCERR << "MainWindowBase::pollOSC: ignoring message with target "
4238 << message.getTarget() << " (we are target 0)" << endl;
4239 continue;
4240 }
4241
4242 handleOSCMessage(message);
4243
4244 disconnect(m_oscQueue, SIGNAL(messagesAvailable()),
4245 this, SLOT(pollOSC()));
4246
4247 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents |
4248 QEventLoop::ExcludeSocketNotifiers);
4249
4250 connect(m_oscQueue, SIGNAL(messagesAvailable()),
4251 this, SLOT(pollOSC()));
4252 }
4178 } 4253 }
4179 4254
4180 void 4255 void
4181 MainWindowBase::inProgressSelectionChanged() 4256 MainWindowBase::inProgressSelectionChanged()
4182 { 4257 {