# HG changeset patch # User Chris Cannam # Date 1205514861 0 # Node ID 183ee2a55fc77b4fa588add8fd49954fa51a127c # Parent 5858cc462d0a0335b36c04ef286a1e74f01f5acf * More work to abstract out interactive components used in the data library, so that it does not need to depend on QtGui. diff -r 5858cc462d0a -r 183ee2a55fc7 base/ProgressPrinter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/ProgressPrinter.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -0,0 +1,48 @@ +/* -*- 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 file copyright 2007 QMUL. + + 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. +*/ + +#include "ProgressPrinter.h" + +#include + +ProgressPrinter::ProgressPrinter(QString message, QObject *parent) : + ProgressReporter(parent), + m_prefix(message), + m_lastProgress(0) +{ +} + +ProgressPrinter::~ProgressPrinter() +{ + if (m_lastProgress > 0 && m_lastProgress != 100) { + std::cerr << "\r\n"; + } +// std::cerr << "(progress printer dtor)" << std::endl; +} + +void +ProgressPrinter::setProgress(int progress) +{ + if (progress == m_lastProgress) return; + if (progress == 100) std::cerr << "\r\n"; + else { + std::cerr << "\r" + << m_prefix.toStdString() + << (m_prefix == "" ? "" : " ") + << progress << "%"; + } + m_lastProgress = progress; +} + diff -r 5858cc462d0a -r 183ee2a55fc7 base/ProgressPrinter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/ProgressPrinter.h Fri Mar 14 17:14:21 2008 +0000 @@ -0,0 +1,37 @@ +/* -*- 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 file copyright 2007 QMUL. + + 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 _PROGRESS_PRINTER_H_ +#define _PROGRESS_PRINTER_H_ + +#include "ProgressReporter.h" + +class ProgressPrinter : public ProgressReporter +{ + Q_OBJECT + +public: + ProgressPrinter(QString message, QObject *parent = 0); + virtual ~ProgressPrinter(); + +public slots: + virtual void setProgress(int); + +protected: + QString m_prefix; + int m_lastProgress; +}; + +#endif diff -r 5858cc462d0a -r 183ee2a55fc7 base/ProgressReporter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/ProgressReporter.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -0,0 +1,26 @@ +/* -*- 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 file copyright 2007-2008 QMUL. + + 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. +*/ + +#include "ProgressReporter.h" + +ProgressReporter::ProgressReporter(QObject *parent) : + QObject(parent) +{ +} + +ProgressReporter::~ProgressReporter() +{ +} + diff -r 5858cc462d0a -r 183ee2a55fc7 base/ProgressReporter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/ProgressReporter.h Fri Mar 14 17:14:21 2008 +0000 @@ -0,0 +1,37 @@ +/* -*- 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 file copyright 2007-2008 QMUL. + + 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 _PROGRESS_REPORTER_H_ + +#include +#include + +class ProgressReporter : public QObject +{ + Q_OBJECT + +public: + ProgressReporter(QObject *parent = 0); + virtual ~ProgressReporter(); + +signals: + void cancelled(); + +public slots: + virtual void setMessage(QString text) = 0; + virtual void setProgress(int percentage) = 0; +}; + +#endif diff -r 5858cc462d0a -r 183ee2a55fc7 base/Thread.h --- a/base/Thread.h Thu Mar 13 14:06:03 2008 +0000 +++ b/base/Thread.h Fri Mar 14 17:14:21 2008 +0000 @@ -31,6 +31,9 @@ public slots: void start(); +protected: + virtual void run() = 0; + private: Type m_type; }; diff -r 5858cc462d0a -r 183ee2a55fc7 base/base.pro --- a/base/base.pro Thu Mar 13 14:06:03 2008 +0000 +++ b/base/base.pro Fri Mar 14 17:14:21 2008 +0000 @@ -26,6 +26,8 @@ PlayParameters.h \ Preferences.h \ Profiler.h \ + ProgressPrinter.h \ + ProgressReporter.h \ PropertyContainer.h \ RangeMapper.h \ RealTime.h \ @@ -54,6 +56,8 @@ PlayParameters.cpp \ Preferences.cpp \ Profiler.cpp \ + ProgressPrinter.cpp \ + ProgressReporter.cpp \ PropertyContainer.cpp \ RangeMapper.cpp \ RealTime.cpp \ diff -r 5858cc462d0a -r 183ee2a55fc7 data/data.pro --- a/data/data.pro Thu Mar 13 14:06:03 2008 +0000 +++ b/data/data.pro Fri Mar 14 17:14:21 2008 +0000 @@ -5,6 +5,7 @@ CONFIG += sv staticlib qt thread warn_on stl rtti exceptions QT += network +QT -= gui TARGET = svdata @@ -25,9 +26,9 @@ fileio/CodedAudioFileReader.h \ fileio/CSVFileReader.h \ fileio/CSVFileWriter.h \ + fileio/CSVFormat.h \ fileio/DataFileReader.h \ fileio/DataFileReaderFactory.h \ - fileio/FileFinder.h \ fileio/FileReadThread.h \ fileio/FileSource.h \ fileio/MatchFileReader.h \ @@ -38,7 +39,6 @@ fileio/MP3FileReader.h \ fileio/OggVorbisFileReader.h \ fileio/PlaylistFileReader.h \ - fileio/ProgressPrinter.h \ fileio/QuickTimeFileReader.h \ fileio/ResamplingWavFileReader.h \ fileio/WavFileReader.h \ @@ -75,8 +75,8 @@ fileio/CodedAudioFileReader.cpp \ fileio/CSVFileReader.cpp \ fileio/CSVFileWriter.cpp \ + fileio/CSVFormat.cpp \ fileio/DataFileReaderFactory.cpp \ - fileio/FileFinder.cpp \ fileio/FileReadThread.cpp \ fileio/FileSource.cpp \ fileio/MatchFileReader.cpp \ @@ -86,7 +86,6 @@ fileio/MP3FileReader.cpp \ fileio/OggVorbisFileReader.cpp \ fileio/PlaylistFileReader.cpp \ - fileio/ProgressPrinter.cpp \ fileio/QuickTimeFileReader.cpp \ fileio/ResamplingWavFileReader.cpp \ fileio/WavFileReader.cpp \ diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/AudioFileReaderFactory.cpp --- a/data/fileio/AudioFileReaderFactory.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/AudioFileReaderFactory.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -54,19 +54,22 @@ } AudioFileReader * -AudioFileReaderFactory::createReader(FileSource source, size_t targetRate) +AudioFileReaderFactory::createReader(FileSource source, size_t targetRate, + ProgressReporter *reporter) { - return create(source, targetRate, false); + return create(source, targetRate, false, reporter); } AudioFileReader * -AudioFileReaderFactory::createThreadingReader(FileSource source, size_t targetRate) +AudioFileReaderFactory::createThreadingReader(FileSource source, size_t targetRate, + ProgressReporter *reporter) { - return create(source, targetRate, true); + return create(source, targetRate, true, reporter); } AudioFileReader * -AudioFileReaderFactory::create(FileSource source, size_t targetRate, bool threading) +AudioFileReaderFactory::create(FileSource source, size_t targetRate, bool threading, + ProgressReporter *reporter) { QString err; @@ -99,7 +102,8 @@ ResamplingWavFileReader::ResampleThreaded : ResamplingWavFileReader::ResampleAtOnce, ResamplingWavFileReader::CacheInTemporaryFile, - targetRate); + targetRate, + reporter); } } @@ -113,7 +117,8 @@ OggVorbisFileReader::DecodeThreaded : OggVorbisFileReader::DecodeAtOnce, OggVorbisFileReader::CacheInTemporaryFile, - targetRate); + targetRate, + reporter); } } #endif @@ -128,7 +133,8 @@ MP3FileReader::DecodeThreaded : MP3FileReader::DecodeAtOnce, MP3FileReader::CacheInTemporaryFile, - targetRate); + targetRate, + reporter); } } #endif @@ -142,7 +148,8 @@ QuickTimeFileReader::DecodeThreaded : QuickTimeFileReader::DecodeAtOnce, QuickTimeFileReader::CacheInTemporaryFile, - targetRate); + targetRate, + reporter); } } #endif diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/AudioFileReaderFactory.h --- a/data/fileio/AudioFileReaderFactory.h Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/AudioFileReaderFactory.h Fri Mar 14 17:14:21 2008 +0000 @@ -21,6 +21,7 @@ #include "FileSource.h" class AudioFileReader; +class ProgressReporter; class AudioFileReaderFactory { @@ -42,10 +43,15 @@ * if you want to find out whether the file is being resampled * or not. * + * If a ProgressReporter is provided, it will be updated with + * progress status. Caller retains ownership of the reporter + * object. + * * Caller owns the returned object and must delete it after use. */ static AudioFileReader *createReader(FileSource source, - size_t targetRate = 0); + size_t targetRate = 0, + ProgressReporter *reporter = 0); /** * Return an audio file reader initialised to the file at the @@ -59,15 +65,24 @@ * if you want to find out whether the file is being resampled * or not. * + * If a ProgressReporter is provided, it will be updated with + * progress status. This will only be meaningful if threading + * mode is not used because the file reader in use does not + * support it; otherwise progress as reported will jump straight + * to 100% before threading mode takes over. Caller retains + * ownership of the reporter object. + * * Caller owns the returned object and must delete it after use. */ static AudioFileReader *createThreadingReader(FileSource source, - size_t targetRate = 0); + size_t targetRate = 0, + ProgressReporter *reporter = 0); protected: static AudioFileReader *create(FileSource source, size_t targetRate, - bool threading); + bool threading, + ProgressReporter *reporter); }; #endif diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/CSVFileReader.cpp --- a/data/fileio/CSVFileReader.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/CSVFileReader.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -27,18 +27,12 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -CSVFileReader::CSVFileReader(QString path, size_t mainModelSampleRate) : +CSVFileReader::CSVFileReader(QString path, CSVFormat format, + size_t mainModelSampleRate) : + m_format(format), m_file(0), m_mainModelSampleRate(mainModelSampleRate) { @@ -86,7 +80,7 @@ CSVFileReader::load() const { if (!m_file) return 0; - +/*!!! CSVFormatDialog *dialog = new CSVFormatDialog (0, m_file, m_mainModelSampleRate); @@ -94,20 +88,19 @@ delete dialog; throw DataFileReaderFactory::ImportCancelled; } +*/ - CSVFormatDialog::ModelType modelType = dialog->getModelType(); - CSVFormatDialog::TimingType timingType = dialog->getTimingType(); - CSVFormatDialog::TimeUnits timeUnits = dialog->getTimeUnits(); - QString separator = dialog->getSeparator(); - QString::SplitBehavior behaviour = dialog->getSplitBehaviour(); - size_t sampleRate = dialog->getSampleRate(); - size_t windowSize = dialog->getWindowSize(); + CSVFormat::ModelType modelType = m_format.getModelType(); + CSVFormat::TimingType timingType = m_format.getTimingType(); + CSVFormat::TimeUnits timeUnits = m_format.getTimeUnits(); + QString separator = m_format.getSeparator(); + QString::SplitBehavior behaviour = m_format.getSplitBehaviour(); + size_t sampleRate = m_format.getSampleRate(); + size_t windowSize = m_format.getWindowSize(); - delete dialog; - - if (timingType == CSVFormatDialog::ExplicitTiming) { + if (timingType == CSVFormat::ExplicitTiming) { windowSize = 1; - if (timeUnits == CSVFormatDialog::TimeSeconds) { + if (timeUnits == CSVFormat::TimeSeconds) { sampleRate = m_mainModelSampleRate; } } @@ -155,17 +148,17 @@ switch (modelType) { - case CSVFormatDialog::OneDimensionalModel: + case CSVFormat::OneDimensionalModel: model1 = new SparseOneDimensionalModel(sampleRate, windowSize); model = model1; break; - case CSVFormatDialog::TwoDimensionalModel: + case CSVFormat::TwoDimensionalModel: model2 = new SparseTimeValueModel(sampleRate, windowSize, false); model = model2; break; - case CSVFormatDialog::ThreeDimensionalModel: + case CSVFormat::ThreeDimensionalModel: model3 = new EditableDenseThreeDimensionalModel(sampleRate, windowSize, list.size()); @@ -187,13 +180,13 @@ s = s.mid(1, s.length() - 2); } - if (i == 0 && timingType == CSVFormatDialog::ExplicitTiming) { + if (i == 0 && timingType == CSVFormat::ExplicitTiming) { bool ok = false; QString numeric = s; numeric.remove(nonNumericRx); - if (timeUnits == CSVFormatDialog::TimeSeconds) { + if (timeUnits == CSVFormat::TimeSeconds) { double time = numeric.toDouble(&ok); frameNo = int(time * sampleRate + 0.00001); @@ -202,7 +195,7 @@ frameNo = numeric.toInt(&ok); - if (timeUnits == CSVFormatDialog::TimeWindows) { + if (timeUnits == CSVFormat::TimeWindows) { frameNo *= windowSize; } } @@ -224,7 +217,7 @@ } } - if (modelType == CSVFormatDialog::OneDimensionalModel) { + if (modelType == CSVFormat::OneDimensionalModel) { SparseOneDimensionalModel::Point point (frameNo, @@ -233,7 +226,7 @@ model1->addPoint(point); - } else if (modelType == CSVFormatDialog::TwoDimensionalModel) { + } else if (modelType == CSVFormat::TwoDimensionalModel) { SparseTimeValueModel::Point point (frameNo, @@ -242,7 +235,7 @@ model2->addPoint(point); - } else if (modelType == CSVFormatDialog::ThreeDimensionalModel) { + } else if (modelType == CSVFormat::ThreeDimensionalModel) { DenseThreeDimensionalModel::Column values; @@ -277,14 +270,14 @@ } ++lineno; - if (timingType == CSVFormatDialog::ImplicitTiming || + if (timingType == CSVFormat::ImplicitTiming || list.size() == 0) { frameNo += windowSize; } } } - if (modelType == CSVFormatDialog::ThreeDimensionalModel) { + if (modelType == CSVFormat::ThreeDimensionalModel) { model3->setMinimumLevel(min); model3->setMaximumLevel(max); } @@ -292,390 +285,3 @@ return model; } - -CSVFormatDialog::CSVFormatDialog(QWidget *parent, QFile *file, - size_t defaultSampleRate) : - QDialog(parent), - m_modelType(OneDimensionalModel), - m_timingType(ExplicitTiming), - m_timeUnits(TimeAudioFrames), - m_separator(""), - m_behaviour(QString::KeepEmptyParts) -{ - setModal(true); - setWindowTitle(tr("Select Data Format")); - - (void)guessFormat(file); - - QGridLayout *layout = new QGridLayout; - - layout->addWidget(new QLabel(tr("Select Data Format

Please select the correct data format for this file.")), - 0, 0, 1, 4); - - layout->addWidget(new QLabel(tr("Each row specifies:")), 1, 0); - - m_modelTypeCombo = new QComboBox; - m_modelTypeCombo->addItem(tr("A point in time")); - m_modelTypeCombo->addItem(tr("A value at a time")); - m_modelTypeCombo->addItem(tr("A set of values")); - layout->addWidget(m_modelTypeCombo, 1, 1, 1, 2); - connect(m_modelTypeCombo, SIGNAL(activated(int)), - this, SLOT(modelTypeChanged(int))); - m_modelTypeCombo->setCurrentIndex(int(m_modelType)); - - layout->addWidget(new QLabel(tr("The first column contains:")), 2, 0); - - m_timingTypeCombo = new QComboBox; - m_timingTypeCombo->addItem(tr("Time, in seconds")); - m_timingTypeCombo->addItem(tr("Time, in audio sample frames")); - m_timingTypeCombo->addItem(tr("Data (rows are consecutive in time)")); - layout->addWidget(m_timingTypeCombo, 2, 1, 1, 2); - connect(m_timingTypeCombo, SIGNAL(activated(int)), - this, SLOT(timingTypeChanged(int))); - m_timingTypeCombo->setCurrentIndex(m_timingType == ExplicitTiming ? - m_timeUnits == TimeSeconds ? 0 : 1 : 2); - - m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):")); - layout->addWidget(m_sampleRateLabel, 3, 0); - - size_t sampleRates[] = { - 8000, 11025, 12000, 22050, 24000, 32000, - 44100, 48000, 88200, 96000, 176400, 192000 - }; - - m_sampleRateCombo = new QComboBox; - m_sampleRate = defaultSampleRate; - for (size_t i = 0; i < sizeof(sampleRates) / sizeof(sampleRates[0]); ++i) { - m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i])); - if (sampleRates[i] == m_sampleRate) m_sampleRateCombo->setCurrentIndex(i); - } - m_sampleRateCombo->setEditable(true); - - layout->addWidget(m_sampleRateCombo, 3, 1); - connect(m_sampleRateCombo, SIGNAL(activated(QString)), - this, SLOT(sampleRateChanged(QString))); - connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)), - this, SLOT(sampleRateChanged(QString))); - - m_windowSizeLabel = new QLabel(tr("Frame increment between rows:")); - layout->addWidget(m_windowSizeLabel, 4, 0); - - m_windowSizeCombo = new QComboBox; - m_windowSize = 1024; - for (int i = 0; i <= 16; ++i) { - int value = 1 << i; - m_windowSizeCombo->addItem(QString("%1").arg(value)); - if (value == int(m_windowSize)) m_windowSizeCombo->setCurrentIndex(i); - } - m_windowSizeCombo->setEditable(true); - - layout->addWidget(m_windowSizeCombo, 4, 1); - connect(m_windowSizeCombo, SIGNAL(activated(QString)), - this, SLOT(windowSizeChanged(QString))); - connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)), - this, SLOT(windowSizeChanged(QString))); - - layout->addWidget(new QLabel(tr("\nExample data from file:")), 5, 0, 1, 4); - - m_exampleWidget = new QTableWidget - (std::min(10, m_example.size()), m_maxExampleCols); - - layout->addWidget(m_exampleWidget, 6, 0, 1, 4); - layout->setColumnStretch(3, 10); - layout->setRowStretch(4, 10); - - QPushButton *ok = new QPushButton(tr("OK")); - connect(ok, SIGNAL(clicked()), this, SLOT(accept())); - ok->setDefault(true); - - QPushButton *cancel = new QPushButton(tr("Cancel")); - connect(cancel, SIGNAL(clicked()), this, SLOT(reject())); - - QHBoxLayout *buttonLayout = new QHBoxLayout; - buttonLayout->addStretch(1); - buttonLayout->addWidget(ok); - buttonLayout->addWidget(cancel); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout(layout); - mainLayout->addLayout(buttonLayout); - - setLayout(mainLayout); - - timingTypeChanged(m_timingTypeCombo->currentIndex()); -} - -CSVFormatDialog::~CSVFormatDialog() -{ -} - -void -CSVFormatDialog::populateExample() -{ - m_exampleWidget->setColumnCount - (m_timingType == ExplicitTiming ? - m_maxExampleCols - 1 : m_maxExampleCols); - - m_exampleWidget->setHorizontalHeaderLabels(QStringList()); - - for (int i = 0; i < m_example.size(); ++i) { - for (int j = 0; j < m_example[i].size(); ++j) { - - QTableWidgetItem *item = new QTableWidgetItem(m_example[i][j]); - - if (j == 0) { - if (m_timingType == ExplicitTiming) { - m_exampleWidget->setVerticalHeaderItem(i, item); - continue; - } else { - QTableWidgetItem *header = - new QTableWidgetItem(QString("%1").arg(i)); - header->setFlags(Qt::ItemIsEnabled); - m_exampleWidget->setVerticalHeaderItem(i, header); - } - } - int index = j; - if (m_timingType == ExplicitTiming) --index; - item->setFlags(Qt::ItemIsEnabled); - m_exampleWidget->setItem(i, index, item); - } - } -} - -void -CSVFormatDialog::modelTypeChanged(int type) -{ - m_modelType = (ModelType)type; - - if (m_modelType == ThreeDimensionalModel) { - // We can't load 3d models with explicit timing, because the 3d - // model is dense so we need a fixed sample increment - m_timingTypeCombo->setCurrentIndex(2); - timingTypeChanged(2); - } -} - -void -CSVFormatDialog::timingTypeChanged(int type) -{ - switch (type) { - - case 0: - m_timingType = ExplicitTiming; - m_timeUnits = TimeSeconds; - m_sampleRateCombo->setEnabled(false); - m_sampleRateLabel->setEnabled(false); - m_windowSizeCombo->setEnabled(false); - m_windowSizeLabel->setEnabled(false); - if (m_modelType == ThreeDimensionalModel) { - m_modelTypeCombo->setCurrentIndex(1); - modelTypeChanged(1); - } - break; - - case 1: - m_timingType = ExplicitTiming; - m_timeUnits = TimeAudioFrames; - m_sampleRateCombo->setEnabled(true); - m_sampleRateLabel->setEnabled(true); - m_windowSizeCombo->setEnabled(false); - m_windowSizeLabel->setEnabled(false); - if (m_modelType == ThreeDimensionalModel) { - m_modelTypeCombo->setCurrentIndex(1); - modelTypeChanged(1); - } - break; - - case 2: - m_timingType = ImplicitTiming; - m_timeUnits = TimeWindows; - m_sampleRateCombo->setEnabled(true); - m_sampleRateLabel->setEnabled(true); - m_windowSizeCombo->setEnabled(true); - m_windowSizeLabel->setEnabled(true); - break; - } - - populateExample(); -} - -void -CSVFormatDialog::sampleRateChanged(QString rateString) -{ - bool ok = false; - int sampleRate = rateString.toInt(&ok); - if (ok) m_sampleRate = sampleRate; -} - -void -CSVFormatDialog::windowSizeChanged(QString sizeString) -{ - bool ok = false; - int size = sizeString.toInt(&ok); - if (ok) m_windowSize = size; -} - -bool -CSVFormatDialog::guessFormat(QFile *file) -{ - QTextStream in(file); - in.seek(0); - - unsigned int lineno = 0; - - bool nonIncreasingPrimaries = false; - bool nonNumericPrimaries = false; - bool floatPrimaries = false; - bool variableItemCount = false; - int itemCount = 1; - int earliestNonNumericItem = -1; - - float prevPrimary = 0.0; - - m_maxExampleCols = 0; - - while (!in.atEnd()) { - - // See comment about line endings in load() above - - QString chunk = in.readLine(); - QStringList lines = chunk.split('\r', QString::SkipEmptyParts); - - for (size_t li = 0; li < lines.size(); ++li) { - - QString line = lines[li]; - - if (line.startsWith("#")) continue; - - m_behaviour = QString::KeepEmptyParts; - - if (m_separator == "") { - //!!! to do: ask the user - if (line.split(",").size() >= 2) m_separator = ","; - else if (line.split("\t").size() >= 2) m_separator = "\t"; - else if (line.split("|").size() >= 2) m_separator = "|"; - else if (line.split("/").size() >= 2) m_separator = "/"; - else if (line.split(":").size() >= 2) m_separator = ":"; - else { - m_separator = " "; - m_behaviour = QString::SkipEmptyParts; - } - } - - QStringList list = line.split(m_separator, m_behaviour); - QStringList tidyList; - - for (int i = 0; i < list.size(); ++i) { - - QString s(list[i]); - bool numeric = false; - - if (s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"")) { - s = s.mid(1, s.length() - 2); - } else if (s.length() >= 2 && s.startsWith("'") && s.endsWith("'")) { - s = s.mid(1, s.length() - 2); - } else { - (void)s.toFloat(&numeric); - } - - tidyList.push_back(s); - - if (lineno == 0 || (list.size() < itemCount)) { - itemCount = list.size(); - } else { - if (itemCount != list.size()) { - variableItemCount = true; - } - } - - if (i == 0) { // primary - - if (numeric) { - - float primary = s.toFloat(); - - if (lineno > 0 && primary <= prevPrimary) { - nonIncreasingPrimaries = true; - } - - if (s.contains(".") || s.contains(",")) { - floatPrimaries = true; - } - - prevPrimary = primary; - - } else { - nonNumericPrimaries = true; - } - } else { // secondary - - if (!numeric) { - if (earliestNonNumericItem < 0 || - i < earliestNonNumericItem) { - earliestNonNumericItem = i; - } - } - } - } - - if (lineno < 10) { - m_example.push_back(tidyList); - if (lineno == 0 || tidyList.size() > m_maxExampleCols) { - m_maxExampleCols = tidyList.size(); - } - } - - ++lineno; - - if (lineno == 50) break; - } - } - - if (nonNumericPrimaries || nonIncreasingPrimaries) { - - // Primaries are probably not a series of times - - m_timingType = ImplicitTiming; - m_timeUnits = TimeWindows; - - if (nonNumericPrimaries) { - m_modelType = OneDimensionalModel; - } else if (itemCount == 1 || variableItemCount || - (earliestNonNumericItem != -1)) { - m_modelType = TwoDimensionalModel; - } else { - m_modelType = ThreeDimensionalModel; - } - - } else { - - // Increasing numeric primaries -- likely to be time - - m_timingType = ExplicitTiming; - - if (floatPrimaries) { - m_timeUnits = TimeSeconds; - } else { - m_timeUnits = TimeAudioFrames; - } - - if (itemCount == 1) { - m_modelType = OneDimensionalModel; - } else if (variableItemCount || (earliestNonNumericItem != -1)) { - if (earliestNonNumericItem != -1 && earliestNonNumericItem < 2) { - m_modelType = OneDimensionalModel; - } else { - m_modelType = TwoDimensionalModel; - } - } else { - m_modelType = ThreeDimensionalModel; - } - } - - std::cerr << "Estimated model type: " << m_modelType << std::endl; - std::cerr << "Estimated timing type: " << m_timingType << std::endl; - std::cerr << "Estimated units: " << m_timeUnits << std::endl; - - in.seek(0); - return true; -} diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/CSVFileReader.h --- a/data/fileio/CSVFileReader.h Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/CSVFileReader.h Fri Mar 14 17:14:21 2008 +0000 @@ -18,20 +18,17 @@ #include "DataFileReader.h" +#include "CSVFormat.h" + #include #include -#include class QFile; -class QTableWidget; -class QComboBox; -class QLabel; - class CSVFileReader : public DataFileReader { public: - CSVFileReader(QString path, size_t mainModelSampleRate); + CSVFileReader(QString path, CSVFormat format, size_t mainModelSampleRate); virtual ~CSVFileReader(); virtual bool isOK() const; @@ -39,77 +36,12 @@ virtual Model *load() const; protected: + CSVFormat m_format; QFile *m_file; QString m_error; size_t m_mainModelSampleRate; }; -class CSVFormatDialog : public QDialog -{ - Q_OBJECT - -public: - CSVFormatDialog(QWidget *parent, QFile *file, size_t defaultSampleRate); - - ~CSVFormatDialog(); - - enum ModelType { - OneDimensionalModel, - TwoDimensionalModel, - ThreeDimensionalModel - }; - - enum TimingType { - ExplicitTiming, - ImplicitTiming - }; - - enum TimeUnits { - TimeSeconds, - TimeAudioFrames, - TimeWindows - }; - - ModelType getModelType() const { return m_modelType; } - TimingType getTimingType() const { return m_timingType; } - TimeUnits getTimeUnits() const { return m_timeUnits; } - QString getSeparator() const { return m_separator; } - size_t getSampleRate() const { return m_sampleRate; } - size_t getWindowSize() const { return m_windowSize; } - - QString::SplitBehavior getSplitBehaviour() const { return m_behaviour; } - -protected slots: - void modelTypeChanged(int type); - void timingTypeChanged(int type); - void sampleRateChanged(QString); - void windowSizeChanged(QString); - -protected: - ModelType m_modelType; - TimingType m_timingType; - TimeUnits m_timeUnits; - QString m_separator; - size_t m_sampleRate; - size_t m_windowSize; - - QString::SplitBehavior m_behaviour; - - QList m_example; - int m_maxExampleCols; - QTableWidget *m_exampleWidget; - - QComboBox *m_modelTypeCombo; - QComboBox *m_timingTypeCombo; - QLabel *m_sampleRateLabel; - QComboBox *m_sampleRateCombo; - QLabel *m_windowSizeLabel; - QComboBox *m_windowSizeCombo; - - bool guessFormat(QFile *file); - void populateExample(); -}; - #endif diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/CSVFormat.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/fileio/CSVFormat.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -0,0 +1,202 @@ +/* -*- 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 file copyright 2006 Chris Cannam. + + 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. +*/ + +#include "CSVFormat.h" + +#include +#include +#include +#include +#include + +#include + +CSVFormat::CSVFormat(QString filename) : + m_modelType(TwoDimensionalModel), + m_timingType(ExplicitTiming), + m_timeUnits(TimeSeconds), + m_separator(","), + m_sampleRate(44100), + m_windowSize(1024), + m_behaviour(QString::KeepEmptyParts), + m_maxExampleCols(0) +{ + QFile file(filename); + if (!file.exists()) return; + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; + + QTextStream in(&file); + in.seek(0); + + unsigned int lineno = 0; + + bool nonIncreasingPrimaries = false; + bool nonNumericPrimaries = false; + bool floatPrimaries = false; + bool variableItemCount = false; + int itemCount = 1; + int earliestNonNumericItem = -1; + + float prevPrimary = 0.0; + + m_maxExampleCols = 0; + m_separator = ""; + + while (!in.atEnd()) { + + // See comment about line endings in CSVFileReader::load() + + QString chunk = in.readLine(); + QStringList lines = chunk.split('\r', QString::SkipEmptyParts); + + for (size_t li = 0; li < lines.size(); ++li) { + + QString line = lines[li]; + + if (line.startsWith("#")) continue; + + m_behaviour = QString::KeepEmptyParts; + + if (m_separator == "") { + //!!! to do: ask the user + if (line.split(",").size() >= 2) m_separator = ","; + else if (line.split("\t").size() >= 2) m_separator = "\t"; + else if (line.split("|").size() >= 2) m_separator = "|"; + else if (line.split("/").size() >= 2) m_separator = "/"; + else if (line.split(":").size() >= 2) m_separator = ":"; + else { + m_separator = " "; + m_behaviour = QString::SkipEmptyParts; + } + } + + std::cerr << "separator = \"" << m_separator.toStdString() << "\"" << std::endl; + + QStringList list = line.split(m_separator, m_behaviour); + QStringList tidyList; + + for (int i = 0; i < list.size(); ++i) { + + QString s(list[i]); + bool numeric = false; + + if (s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"")) { + s = s.mid(1, s.length() - 2); + } else if (s.length() >= 2 && s.startsWith("'") && s.endsWith("'")) { + s = s.mid(1, s.length() - 2); + } else { + float f = s.toFloat(&numeric); + std::cerr << "converted \"" << s.toStdString() << "\" to float, got " << f << " and success = " << numeric << std::endl; + } + + tidyList.push_back(s); + + if (lineno == 0 || (list.size() < itemCount)) { + itemCount = list.size(); + } else { + if (itemCount != list.size()) { + variableItemCount = true; + } + } + + if (i == 0) { // primary + + if (numeric) { + + float primary = s.toFloat(); + + if (lineno > 0 && primary <= prevPrimary) { + nonIncreasingPrimaries = true; + } + + if (s.contains(".") || s.contains(",")) { + floatPrimaries = true; + } + + prevPrimary = primary; + + } else { + nonNumericPrimaries = true; + } + } else { // secondary + + if (!numeric) { + if (earliestNonNumericItem < 0 || + i < earliestNonNumericItem) { + earliestNonNumericItem = i; + } + } + } + } + + if (lineno < 10) { + m_example.push_back(tidyList); + if (lineno == 0 || tidyList.size() > m_maxExampleCols) { + m_maxExampleCols = tidyList.size(); + } + } + + ++lineno; + + if (lineno == 50) break; + } + } + + if (nonNumericPrimaries || nonIncreasingPrimaries) { + + // Primaries are probably not a series of times + + m_timingType = CSVFormat::ImplicitTiming; + m_timeUnits = CSVFormat::TimeWindows; + + if (nonNumericPrimaries) { + m_modelType = CSVFormat::OneDimensionalModel; + } else if (itemCount == 1 || variableItemCount || + (earliestNonNumericItem != -1)) { + m_modelType = CSVFormat::TwoDimensionalModel; + } else { + m_modelType = CSVFormat::ThreeDimensionalModel; + } + + } else { + + // Increasing numeric primaries -- likely to be time + + m_timingType = CSVFormat::ExplicitTiming; + + if (floatPrimaries) { + m_timeUnits = CSVFormat::TimeSeconds; + } else { + m_timeUnits = CSVFormat::TimeAudioFrames; + } + + if (itemCount == 1) { + m_modelType = CSVFormat::OneDimensionalModel; + } else if (variableItemCount || (earliestNonNumericItem != -1)) { + if (earliestNonNumericItem != -1 && earliestNonNumericItem < 2) { + m_modelType = CSVFormat::OneDimensionalModel; + } else { + m_modelType = CSVFormat::TwoDimensionalModel; + } + } else { + m_modelType = CSVFormat::ThreeDimensionalModel; + } + } + + std::cerr << "Estimated model type: " << m_modelType << std::endl; + std::cerr << "Estimated timing type: " << m_timingType << std::endl; + std::cerr << "Estimated units: " << m_timeUnits << std::endl; +} + diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/CSVFormat.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/fileio/CSVFormat.h Fri Mar 14 17:14:21 2008 +0000 @@ -0,0 +1,90 @@ +/* -*- 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 file copyright 2006 Chris Cannam. + + 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 _CSV_FORMAT_H_ +#define _CSV_FORMAT_H_ + +#include +#include + +class CSVFormat +{ +public: + enum ModelType { + OneDimensionalModel, + TwoDimensionalModel, + ThreeDimensionalModel + }; + + enum TimingType { + ExplicitTiming, + ImplicitTiming + }; + + enum TimeUnits { + TimeSeconds, + TimeAudioFrames, + TimeWindows + }; + + CSVFormat(QString path); // guess format + + CSVFormat() : // arbitrary defaults + m_modelType(TwoDimensionalModel), + m_timingType(ExplicitTiming), + m_timeUnits(TimeSeconds), + m_separator(","), + m_sampleRate(44100), + m_windowSize(1024), + m_behaviour(QString::KeepEmptyParts) + { } + + ModelType getModelType() const { return m_modelType; } + TimingType getTimingType() const { return m_timingType; } + TimeUnits getTimeUnits() const { return m_timeUnits; } + QString getSeparator() const { return m_separator; } + size_t getSampleRate() const { return m_sampleRate; } + size_t getWindowSize() const { return m_windowSize; } + + QString::SplitBehavior getSplitBehaviour() const { return m_behaviour; } + + void setModelType(ModelType t) { m_modelType = t; } + void setTimingType(TimingType t) { m_timingType = t; } + void setTimeUnits(TimeUnits t) { m_timeUnits = t; } + void setSeparator(QString s) { m_separator = s; } + void setSampleRate(size_t r) { m_sampleRate = r; } + void setWindowSize(size_t s) { m_windowSize = s; } + + void setSplitBehaviour(QString::SplitBehavior b) { m_behaviour = b; } + + // only valid if constructor that guesses format was used: + QList getExample() const { return m_example; } + int getMaxExampleCols() const { return m_maxExampleCols; } + +protected: + ModelType m_modelType; + TimingType m_timingType; + TimeUnits m_timeUnits; + QString m_separator; + size_t m_sampleRate; + size_t m_windowSize; + + QString::SplitBehavior m_behaviour; + + QList m_example; + int m_maxExampleCols; +}; + +#endif diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/DataFileReaderFactory.cpp --- a/data/fileio/DataFileReaderFactory.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/DataFileReaderFactory.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -28,29 +28,57 @@ } DataFileReader * -DataFileReaderFactory::createReader(QString path, size_t mainModelSampleRate) +DataFileReaderFactory::createReader(QString path, + bool csv, + MIDIFileImportPreferenceAcquirer *acquirer, + CSVFormat format, + size_t mainModelSampleRate) { QString err; DataFileReader *reader = 0; - reader = new MIDIFileReader(path, mainModelSampleRate); - if (reader->isOK()) return reader; - if (reader->getError() != "") err = reader->getError(); - delete reader; + if (!csv) { + reader = new MIDIFileReader(path, acquirer, mainModelSampleRate); + if (reader->isOK()) return reader; + if (reader->getError() != "") err = reader->getError(); + delete reader; + } - reader = new CSVFileReader(path, mainModelSampleRate); - if (reader->isOK()) return reader; - if (reader->getError() != "") err = reader->getError(); - delete reader; + if (csv) { + reader = new CSVFileReader(path, format, mainModelSampleRate); + if (reader->isOK()) return reader; + if (reader->getError() != "") err = reader->getError(); + delete reader; + } + + return 0; +} + +DataFileReader * +DataFileReaderFactory::createReader(QString path, + MIDIFileImportPreferenceAcquirer *acquirer, + size_t mainModelSampleRate) +{ + DataFileReader *reader = createReader + (path, false, acquirer, CSVFormat(), mainModelSampleRate); + if (reader) return reader; + + reader = createReader + (path, true, acquirer, CSVFormat(path), mainModelSampleRate); + if (reader) return reader; return 0; } Model * -DataFileReaderFactory::load(QString path, size_t mainModelSampleRate) +DataFileReaderFactory::load(QString path, + MIDIFileImportPreferenceAcquirer *acquirer, + size_t mainModelSampleRate) { - DataFileReader *reader = createReader(path, mainModelSampleRate); + DataFileReader *reader = createReader(path, + acquirer, + mainModelSampleRate); if (!reader) return NULL; try { @@ -63,3 +91,42 @@ } } +Model * +DataFileReaderFactory::loadNonCSV(QString path, + MIDIFileImportPreferenceAcquirer *acquirer, + size_t mainModelSampleRate) +{ + DataFileReader *reader = createReader(path, false, + acquirer, + CSVFormat(), + mainModelSampleRate); + if (!reader) return NULL; + + try { + Model *model = reader->load(); + delete reader; + return model; + } catch (Exception) { + delete reader; + throw; + } +} + +Model * +DataFileReaderFactory::loadCSV(QString path, CSVFormat format, + size_t mainModelSampleRate) +{ + DataFileReader *reader = createReader(path, true, 0, format, + mainModelSampleRate); + if (!reader) return NULL; + + try { + Model *model = reader->load(); + delete reader; + return model; + } catch (Exception) { + delete reader; + throw; + } +} + diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/DataFileReaderFactory.h --- a/data/fileio/DataFileReaderFactory.h Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/DataFileReaderFactory.h Fri Mar 14 17:14:21 2008 +0000 @@ -18,6 +18,9 @@ #include +#include "CSVFormat.h" +#include "MIDIFileReader.h" + class DataFileReader; class Model; @@ -37,16 +40,50 @@ * Return a data file reader initialised to the file at the * given path, or NULL if no suitable reader for this path is * available or the file cannot be opened. + * * Caller owns the returned object and must delete it after use. + * + * Note that this function is non-interactive -- the user is not + * asked for file format preferences. */ static DataFileReader *createReader(QString path, + MIDIFileImportPreferenceAcquirer *, size_t mainModelSampleRate); /** * Read the given path, if a suitable reader is available. * Return NULL if no reader succeeded in reading this file. + * + * Note that this function is non-interactive -- the user is not + * asked for file format preferences. If the CSV file reader is + * used, it is with default format. */ - static Model *load(QString path, size_t mainModelSampleRate); + static Model *load(QString path, + MIDIFileImportPreferenceAcquirer *acquirer, + size_t mainModelSampleRate); + + /** + * Read the given path, if a suitable reader is available. + * Return NULL if no reader succeeded in reading this file. + * Do not attempt the general CSV reader. + */ + static Model *loadNonCSV(QString path, + MIDIFileImportPreferenceAcquirer *acquirer, + size_t mainModelSampleRate); + + /** + * Read the given path using the CSV reader with the given format. + * Return NULL if it failed in reading this file. + */ + static Model *loadCSV(QString path, + CSVFormat format, + size_t mainModelSampleRate); + +protected: + static DataFileReader *createReader(QString path, bool csv, + MIDIFileImportPreferenceAcquirer *, + CSVFormat format, + size_t mainModelSampleRate); }; #endif diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/FileFinder.cpp --- a/data/fileio/FileFinder.cpp Thu Mar 13 14:06:03 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,511 +0,0 @@ -/* -*- 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 file copyright 2007 QMUL. - - 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. -*/ - -#include "FileFinder.h" -#include "FileSource.h" -#include "AudioFileReaderFactory.h" -#include "DataFileReaderFactory.h" - -#include -#include -#include -#include -#include -#include - -#include - -FileFinder * -FileFinder::m_instance = 0; - -FileFinder::FileFinder() : - m_lastLocatedLocation("") -{ -} - -FileFinder::~FileFinder() -{ -} - -FileFinder * -FileFinder::getInstance() -{ - if (m_instance == 0) { - m_instance = new FileFinder(); - } - return m_instance; -} - -QString -FileFinder::getOpenFileName(FileType type, QString fallbackLocation) -{ - QString settingsKey; - QString lastPath = fallbackLocation; - - QString title = tr("Select file"); - QString filter = tr("All files (*.*)"); - - switch (type) { - - case SessionFile: - settingsKey = "sessionpath"; - title = tr("Select a session file"); - filter = tr("Sonic Visualiser session files (*.sv)\nAll files (*.*)"); - break; - - case AudioFile: - settingsKey = "audiopath"; - title = "Select an audio file"; - filter = tr("Audio files (%1)\nAll files (*.*)") - .arg(AudioFileReaderFactory::getKnownExtensions()); - break; - - case LayerFile: - settingsKey = "layerpath"; - filter = tr("All supported files (%1)\nSonic Visualiser Layer XML files (*.svl)\nComma-separated data files (*.csv)\nSpace-separated .lab files (*.lab)\nMIDI files (*.mid)\nText files (*.txt)\nAll files (*.*)").arg(DataFileReaderFactory::getKnownExtensions()); - break; - - case LayerFileNoMidi: - settingsKey = "layerpath"; - filter = tr("All supported files (%1)\nSonic Visualiser Layer XML files (*.svl)\nComma-separated data files (*.csv)\nSpace-separated .lab files (*.lab)\nText files (*.txt)\nAll files (*.*)").arg(DataFileReaderFactory::getKnownExtensions()); - break; - - case SessionOrAudioFile: - settingsKey = "lastpath"; - filter = tr("All supported files (*.sv %1)\nSonic Visualiser session files (*.sv)\nAudio files (%1)\nAll files (*.*)") - .arg(AudioFileReaderFactory::getKnownExtensions()); - break; - - case ImageFile: - settingsKey = "imagepath"; - { - QStringList fmts; - QList formats = QImageReader::supportedImageFormats(); - for (QList::iterator i = formats.begin(); - i != formats.end(); ++i) { - fmts.push_back(QString("*.%1") - .arg(QString::fromLocal8Bit(*i).toLower())); - } - filter = tr("Image files (%1)\nAll files (*.*)").arg(fmts.join(" ")); - } - break; - - case AnyFile: - settingsKey = "lastpath"; - filter = tr("All supported files (*.sv %1 %2)\nSonic Visualiser session files (*.sv)\nAudio files (%1)\nLayer files (%2)\nAll files (*.*)") - .arg(AudioFileReaderFactory::getKnownExtensions()) - .arg(DataFileReaderFactory::getKnownExtensions()); - break; - }; - - if (lastPath == "") { - char *home = getenv("HOME"); - if (home) lastPath = home; - else lastPath = "."; - } else if (QFileInfo(lastPath).isDir()) { - lastPath = QFileInfo(lastPath).canonicalPath(); - } else { - lastPath = QFileInfo(lastPath).absoluteDir().canonicalPath(); - } - - QSettings settings; - settings.beginGroup("FileFinder"); - lastPath = settings.value(settingsKey, lastPath).toString(); - - QString path = ""; - - // Use our own QFileDialog just for symmetry with getSaveFileName below - - QFileDialog dialog; - dialog.setFilters(filter.split('\n')); - dialog.setWindowTitle(title); - dialog.setDirectory(lastPath); - - dialog.setAcceptMode(QFileDialog::AcceptOpen); - dialog.setFileMode(QFileDialog::ExistingFile); - - if (dialog.exec()) { - QStringList files = dialog.selectedFiles(); - if (!files.empty()) path = *files.begin(); - - QFileInfo fi(path); - - if (!fi.exists()) { - - QMessageBox::critical(0, tr("File does not exist"), - tr("File \"%1\" does not exist").arg(path)); - path = ""; - - } else if (!fi.isReadable()) { - - QMessageBox::critical(0, tr("File is not readable"), - tr("File \"%1\" can not be read").arg(path)); - path = ""; - - } else if (fi.isDir()) { - - QMessageBox::critical(0, tr("Directory selected"), - tr("File \"%1\" is a directory").arg(path)); - path = ""; - - } else if (!fi.isFile()) { - - QMessageBox::critical(0, tr("Non-file selected"), - tr("Path \"%1\" is not a file").arg(path)); - path = ""; - - } else if (fi.size() == 0) { - - QMessageBox::critical(0, tr("File is empty"), - tr("File \"%1\" is empty").arg(path)); - path = ""; - } - } - - if (path != "") { - settings.setValue(settingsKey, - QFileInfo(path).absoluteDir().canonicalPath()); - } - - return path; -} - -QString -FileFinder::getSaveFileName(FileType type, QString fallbackLocation) -{ - QString settingsKey; - QString lastPath = fallbackLocation; - - QString title = tr("Select file"); - QString filter = tr("All files (*.*)"); - - switch (type) { - - case SessionFile: - settingsKey = "savesessionpath"; - title = tr("Select a session file"); - filter = tr("Sonic Visualiser session files (*.sv)\nAll files (*.*)"); - break; - - case AudioFile: - settingsKey = "saveaudiopath"; - title = "Select an audio file"; - title = tr("Select a file to export to"); - filter = tr("WAV audio files (*.wav)\nAll files (*.*)"); - break; - - case LayerFile: - settingsKey = "savelayerpath"; - title = tr("Select a file to export to"); - filter = tr("Sonic Visualiser Layer XML files (*.svl)\nComma-separated data files (*.csv)\nMIDI files (*.mid)\nText files (*.txt)\nAll files (*.*)"); - break; - - case LayerFileNoMidi: - settingsKey = "savelayerpath"; - title = tr("Select a file to export to"); - filter = tr("Sonic Visualiser Layer XML files (*.svl)\nComma-separated data files (*.csv)\nText files (*.txt)\nAll files (*.*)"); - break; - - case SessionOrAudioFile: - std::cerr << "ERROR: Internal error: FileFinder::getSaveFileName: SessionOrAudioFile cannot be used here" << std::endl; - abort(); - - case ImageFile: - settingsKey = "saveimagepath"; - title = tr("Select a file to export to"); - filter = tr("Portable Network Graphics files (*.png)\nAll files (*.*)"); - break; - - case AnyFile: - std::cerr << "ERROR: Internal error: FileFinder::getSaveFileName: AnyFile cannot be used here" << std::endl; - abort(); - }; - - if (lastPath == "") { - char *home = getenv("HOME"); - if (home) lastPath = home; - else lastPath = "."; - } else if (QFileInfo(lastPath).isDir()) { - lastPath = QFileInfo(lastPath).canonicalPath(); - } else { - lastPath = QFileInfo(lastPath).absoluteDir().canonicalPath(); - } - - QSettings settings; - settings.beginGroup("FileFinder"); - lastPath = settings.value(settingsKey, lastPath).toString(); - - QString path = ""; - - // Use our own QFileDialog instead of static functions, as we may - // need to adjust the file extension based on the selected filter - - QFileDialog dialog; - dialog.setFilters(filter.split('\n')); - dialog.setWindowTitle(title); - dialog.setDirectory(lastPath); - - dialog.setAcceptMode(QFileDialog::AcceptSave); - dialog.setFileMode(QFileDialog::AnyFile); - dialog.setConfirmOverwrite(false); // we'll do that - - if (type == SessionFile) { - dialog.setDefaultSuffix("sv"); - } else if (type == AudioFile) { - dialog.setDefaultSuffix("wav"); - } else if (type == ImageFile) { - dialog.setDefaultSuffix("png"); - } - - bool good = false; - - while (!good) { - - path = ""; - - if (!dialog.exec()) break; - - QStringList files = dialog.selectedFiles(); - if (files.empty()) break; - path = *files.begin(); - - QFileInfo fi(path); - - std::cerr << "type = " << type << ", suffix = " << fi.suffix().toStdString() << std::endl; - - if ((type == LayerFile || type == LayerFileNoMidi) - && fi.suffix() == "") { - QString expectedExtension; - QString selectedFilter = dialog.selectedFilter(); - if (selectedFilter.contains(".svl")) { - expectedExtension = "svl"; - } else if (selectedFilter.contains(".txt")) { - expectedExtension = "txt"; - } else if (selectedFilter.contains(".csv")) { - expectedExtension = "csv"; - } else if (selectedFilter.contains(".mid")) { - expectedExtension = "mid"; - } - std::cerr << "expected extension = " << expectedExtension.toStdString() << std::endl; - if (expectedExtension != "") { - path = QString("%1.%2").arg(path).arg(expectedExtension); - fi = QFileInfo(path); - } - } - - if (fi.isDir()) { - QMessageBox::critical(0, tr("Directory selected"), - tr("File \"%1\" is a directory").arg(path)); - continue; - } - - if (fi.exists()) { - if (QMessageBox::question(0, tr("File exists"), - tr("The file \"%1\" already exists.\nDo you want to overwrite it?").arg(path), - QMessageBox::Ok, - QMessageBox::Cancel) != QMessageBox::Ok) { - continue; - } - } - - good = true; - } - - if (path != "") { - settings.setValue(settingsKey, - QFileInfo(path).absoluteDir().canonicalPath()); - } - - return path; -} - -void -FileFinder::registerLastOpenedFilePath(FileType type, QString path) -{ - QString settingsKey; - - switch (type) { - case SessionFile: - settingsKey = "sessionpath"; - break; - - case AudioFile: - settingsKey = "audiopath"; - break; - - case LayerFile: - settingsKey = "layerpath"; - break; - - case LayerFileNoMidi: - settingsKey = "layerpath"; - break; - - case SessionOrAudioFile: - settingsKey = "lastpath"; - break; - - case ImageFile: - settingsKey = "imagepath"; - break; - - case AnyFile: - settingsKey = "lastpath"; - break; - } - - if (path != "") { - QSettings settings; - settings.beginGroup("FileFinder"); - path = QFileInfo(path).absoluteDir().canonicalPath(); - settings.setValue(settingsKey, path); - settings.setValue("lastpath", path); - } -} - -QString -FileFinder::find(FileType type, QString location, QString lastKnownLocation) -{ - if (FileSource::canHandleScheme(location)) { - if (FileSource(location).isAvailable()) { - std::cerr << "FileFinder::find: ok, it's available... returning" << std::endl; - return location; - } - } - - if (QFileInfo(location).exists()) return location; - - QString foundAt = ""; - - if ((foundAt = findRelative(location, lastKnownLocation)) != "") { - return foundAt; - } - - if ((foundAt = findRelative(location, m_lastLocatedLocation)) != "") { - return foundAt; - } - - return locateInteractive(type, location); -} - -QString -FileFinder::findRelative(QString location, QString relativeTo) -{ - if (relativeTo == "") return ""; - - std::cerr << "Looking for \"" << location.toStdString() << "\" next to \"" - << relativeTo.toStdString() << "\"..." << std::endl; - - QString fileName; - QString resolved; - - if (FileSource::isRemote(location)) { - fileName = QUrl(location).path().section('/', -1, -1, - QString::SectionSkipEmpty); - } else { - if (QUrl(location).scheme() == "file") { - location = QUrl(location).toLocalFile(); - } - fileName = QFileInfo(location).fileName(); - } - - if (FileSource::isRemote(relativeTo)) { - resolved = QUrl(relativeTo).resolved(fileName).toString(); - if (!FileSource(resolved).isAvailable()) resolved = ""; - std::cerr << "resolved: " << resolved.toStdString() << std::endl; - } else { - if (QUrl(relativeTo).scheme() == "file") { - relativeTo = QUrl(relativeTo).toLocalFile(); - } - resolved = QFileInfo(relativeTo).dir().filePath(fileName); - if (!QFileInfo(resolved).exists() || - !QFileInfo(resolved).isFile() || - !QFileInfo(resolved).isReadable()) { - resolved = ""; - } - } - - return resolved; -} - -QString -FileFinder::locateInteractive(FileType type, QString thing) -{ - QString question; - if (type == AudioFile) { - question = tr("Audio file \"%1\" could not be opened.\nDo you want to locate it?"); - } else { - question = tr("File \"%1\" could not be opened.\nDo you want to locate it?"); - } - - QString path = ""; - bool done = false; - - while (!done) { - - int rv = QMessageBox::question - (0, - tr("Failed to open file"), - question.arg(thing), - tr("Locate file..."), - tr("Use URL..."), - tr("Cancel"), - 0, 2); - - switch (rv) { - - case 0: // Locate file - - if (QFileInfo(thing).dir().exists()) { - path = QFileInfo(thing).dir().canonicalPath(); - } - - path = getOpenFileName(type, path); - done = (path != ""); - break; - - case 1: // Use URL - { - bool ok = false; - path = QInputDialog::getText - (0, tr("Use URL"), - tr("Please enter the URL to use for this file:"), - QLineEdit::Normal, "", &ok); - - if (ok && path != "") { - if (FileSource(path).isAvailable()) { - done = true; - } else { - QMessageBox::critical - (0, tr("Failed to open location"), - tr("URL \"%1\" could not be opened").arg(path)); - path = ""; - } - } - break; - } - - case 2: // Cancel - path = ""; - done = true; - break; - } - } - - if (path != "") m_lastLocatedLocation = path; - return path; -} - - diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/FileFinder.h --- a/data/fileio/FileFinder.h Thu Mar 13 14:06:03 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* -*- 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 file copyright 2007 QMUL. - - 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 _FILE_FINDER_H_ -#define _FILE_FINDER_H_ - -#include -#include - -class FileFinder : public QObject -{ - Q_OBJECT - -public: - virtual ~FileFinder(); - - enum FileType { - SessionFile, - AudioFile, - LayerFile, - LayerFileNoMidi, - SessionOrAudioFile, - ImageFile, - AnyFile - }; - - QString getOpenFileName(FileType type, QString fallbackLocation = ""); - QString getSaveFileName(FileType type, QString fallbackLocation = ""); - void registerLastOpenedFilePath(FileType type, QString path); - - QString find(FileType type, QString location, QString lastKnownLocation = ""); - - static FileFinder *getInstance(); - -protected: - FileFinder(); - static FileFinder *m_instance; - - QString findRelative(QString location, QString relativeTo); - QString locateInteractive(FileType type, QString thing); - - QString m_lastLocatedLocation; -}; - -#endif - diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/FileSource.cpp --- a/data/fileio/FileSource.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/FileSource.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -14,17 +14,16 @@ */ #include "FileSource.h" -#include "ProgressPrinter.h" #include "base/TempDirectory.h" #include "base/Exceptions.h" +#include "base/ProgressReporter.h" #include #include #include #include -#include -#include +#include #include #include @@ -46,7 +45,7 @@ QMutex FileSource::m_mapMutex; -FileSource::FileSource(QString fileOrUrl, ShowProgressType progressType) : +FileSource::FileSource(QString fileOrUrl, ProgressReporter *reporter) : m_url(fileOrUrl), m_ftp(0), m_http(0), @@ -56,10 +55,7 @@ m_remote(isRemote(fileOrUrl)), m_done(false), m_leaveLocalFile(false), - m_progressType(progressType), - m_progressPrinter(0), - m_progressDialog(0), - m_progressShowTimer(this), + m_reporter(reporter), m_refCounted(false) { #ifdef DEBUG_FILE_SOURCE @@ -113,7 +109,7 @@ } } -FileSource::FileSource(QUrl url, ShowProgressType progressType) : +FileSource::FileSource(QUrl url, ProgressReporter *reporter) : m_url(url), m_ftp(0), m_http(0), @@ -123,10 +119,7 @@ m_remote(isRemote(url.toString())), m_done(false), m_leaveLocalFile(false), - m_progressType(progressType), - m_progressPrinter(0), - m_progressDialog(0), - m_progressShowTimer(this), + m_reporter(reporter), m_refCounted(false) { #ifdef DEBUG_FILE_SOURCE @@ -153,10 +146,7 @@ m_remote(rf.m_remote), m_done(false), m_leaveLocalFile(false), - m_progressType(rf.m_progressType), - m_progressPrinter(0), - m_progressDialog(0), - m_progressShowTimer(0), + m_reporter(rf.m_reporter), m_refCounted(false) { #ifdef DEBUG_FILE_SOURCE @@ -304,28 +294,12 @@ m_refCountMap[m_url]++; m_refCounted = true; - switch (m_progressType) { - - case ProgressNone: break; - - case ProgressDialog: - m_progressDialog = new QProgressDialog - (tr("Downloading %1...").arg(m_url.toString()), - tr("Cancel"), 0, 100); - m_progressDialog->hide(); - connect(&m_progressShowTimer, SIGNAL(timeout()), - this, SLOT(showProgressDialog())); - connect(m_progressDialog, SIGNAL(canceled()), - this, SLOT(cancelled())); - m_progressShowTimer.setSingleShot(true); - m_progressShowTimer.start(2000); - break; - - case ProgressToConsole: - m_progressPrinter = new ProgressPrinter(tr("Downloading...")); + if (m_reporter) { + m_reporter->setMessage + (tr("Downloading %1...").arg(m_url.toString())); + connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled())); connect(this, SIGNAL(progress(int)), - m_progressPrinter, SLOT(progress(int))); - break; + m_reporter, SLOT(setProgress(int))); } } } @@ -441,10 +415,6 @@ f->abort(); f->deleteLater(); } - delete m_progressDialog; - m_progressDialog = 0; - delete m_progressPrinter; - m_progressPrinter = 0; delete m_localFile; // does not actually delete the file m_localFile = 0; } @@ -486,7 +456,7 @@ { while (m_ok && (!m_done && m_lastStatus == 0)) { // std::cerr << "waitForStatus: processing (last status " << m_lastStatus << ")" << std::endl; - QApplication::processEvents(); + QCoreApplication::processEvents(); } } @@ -495,7 +465,7 @@ { while (m_ok && !m_done) { // std::cerr << "FileSource::waitForData: calling QApplication::processEvents" << std::endl; - QApplication::processEvents(); + QCoreApplication::processEvents(); } } @@ -621,13 +591,6 @@ { int percent = int((double(done) / double(total)) * 100.0 - 0.1); emit progress(percent); - - if (!m_progressDialog) return; - - if (percent > 0) { - m_progressDialog->setValue(percent); - m_progressDialog->show(); - } } void @@ -743,12 +706,6 @@ m_done = true; } -void -FileSource::showProgressDialog() -{ - if (m_progressDialog) m_progressDialog->show(); -} - bool FileSource::createCacheFile() { diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/FileSource.h --- a/data/fileio/FileSource.h Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/FileSource.h Fri Mar 14 17:14:21 2008 +0000 @@ -26,9 +26,8 @@ class QFtp; class QHttp; class QFile; -class QProgressDialog; class QHttpResponseHeader; -class ProgressPrinter; +class ProgressReporter; /** * FileSource is a class used to refer to the contents of a file that @@ -62,37 +61,26 @@ Q_OBJECT public: - - enum ShowProgressType { - ProgressNone, - ProgressDialog, - ProgressToConsole - }; - /** * Construct a FileSource using the given local file path or URL. * The URL may be raw or encoded. * - * If progressType is ProgressDialog, a progress dialog will be - * shown for any network transfers; if it is ProgressToConsole, a - * progress indication will be sent to the console. - * Note that the progress() signal will also be emitted regularly - * during retrieval, even if progressType is ProgressNone. + * If a ProgressReporter is provided, it will be updated with + * progress status. Note that the progress() signal will also be + * emitted regularly during retrieval, even if no reporter is + * supplied here. Caller retains ownership of the reporter object. */ - FileSource(QString fileOrUrl, - ShowProgressType progressType = ProgressNone); + FileSource(QString fileOrUrl, ProgressReporter *reporter = 0); /** * Construct a FileSource using the given remote URL. * - * If progressType is ProgressDialog, a progress dialog will be - * shown for any network transfers; if it is ProgressToConsole, a - * progress indication will be sent to the console. - * Note that the progress() signal also will be emitted regularly - * during retrieval, even if progressType is ProgressNone. + * If a ProgressReporter is provided, it will be updated with + * progress status. Note that the progress() signal will also be + * emitted regularly during retrieval, even if no reporter is + * supplied here. Caller retains ownership of the reporter object. */ - FileSource(QUrl url, - ShowProgressType progressType = ProgressNone); + FileSource(QUrl url, ProgressReporter *reporter = 0); FileSource(const FileSource &); @@ -212,7 +200,6 @@ void ftpCommandFinished(int, bool); void dataTransferProgress(qint64 done, qint64 total); void done(bool error); - void showProgressDialog(); void cancelled(); protected: @@ -230,10 +217,7 @@ bool m_remote; bool m_done; bool m_leaveLocalFile; - ShowProgressType m_progressType; - ProgressPrinter *m_progressPrinter; - QProgressDialog *m_progressDialog; - QTimer m_progressShowTimer; + ProgressReporter *m_reporter; typedef std::map RemoteRefCountMap; typedef std::map RemoteLocalMap; diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/MIDIFileReader.cpp --- a/data/fileio/MIDIFileReader.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/MIDIFileReader.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -36,8 +36,6 @@ #include "model/NoteModel.h" #include -#include -#include #include @@ -58,6 +56,7 @@ MIDIFileReader::MIDIFileReader(QString path, + MIDIFileImportPreferenceAcquirer *acquirer, size_t mainModelSampleRate) : m_timingDivision(0), m_format(MIDI_FILE_BAD_FORMAT), @@ -67,7 +66,8 @@ m_path(path), m_midiFile(0), m_fileSize(0), - m_mainModelSampleRate(mainModelSampleRate) + m_mainModelSampleRate(mainModelSampleRate), + m_acquirer(acquirer) { if (parseFile()) { m_error = ""; @@ -813,9 +813,10 @@ if (!isOK()) return 0; if (m_loadableTracks.empty()) { - QMessageBox::critical(0, tr("No notes in MIDI file"), - tr("MIDI file \"%1\" has no notes in any track") - .arg(m_path)); + if (m_acquirer) { + m_acquirer->showError + (tr("MIDI file \"%1\" has no notes in any track").arg(m_path)); + } return 0; } @@ -827,19 +828,7 @@ } else { - QStringList available; - QString allTracks = tr("Merge all tracks"); - QString allNonPercussion = tr("Merge all non-percussion tracks"); - - int nonTrackItems = 1; - - available << allTracks; - - if (!m_percussionTracks.empty() && - (m_percussionTracks.size() < m_loadableTracks.size())) { - available << allNonPercussion; - ++nonTrackItems; - } + QStringList displayNames; for (set::iterator i = m_loadableTracks.begin(); i != m_loadableTracks.end(); ++i) { @@ -859,37 +848,49 @@ } else { label = tr("Track %1 (untitled)%3").arg(trackNo).arg(perc); } - available << label; + + displayNames << label; } - bool ok = false; - QString selected = QInputDialog::getItem - (0, tr("Select track or tracks to import"), - tr("Select track to import

You can only import this file as a single annotation layer, but the file contains more than one track, or notes on more than one channel.

Please select the track or merged tracks you wish to import:"), - available, 0, false, &ok); + QString singleTrack; - if (!ok || selected.isEmpty()) return 0; - - if (selected == allTracks || selected == allNonPercussion) { + bool haveSomePercussion = + (!m_percussionTracks.empty() && + (m_percussionTracks.size() < m_loadableTracks.size())); - for (set::iterator i = m_loadableTracks.begin(); - i != m_loadableTracks.end(); ++i) { - - if (selected == allTracks || + MIDIFileImportPreferenceAcquirer::TrackPreference pref; + + if (m_acquirer) { + pref = m_acquirer->getTrackImportPreference(displayNames, + haveSomePercussion, + singleTrack); + } else { + pref = MIDIFileImportPreferenceAcquirer::MergeAllTracks; + } + + if (pref == MIDIFileImportPreferenceAcquirer::ImportNothing) return 0; + + if (pref == MIDIFileImportPreferenceAcquirer::MergeAllTracks || + pref == MIDIFileImportPreferenceAcquirer::MergeAllNonPercussionTracks) { + + for (set::iterator i = m_loadableTracks.begin(); + i != m_loadableTracks.end(); ++i) { + + if (pref == MIDIFileImportPreferenceAcquirer::MergeAllTracks || m_percussionTracks.find(*i) == m_percussionTracks.end()) { - + tracksToLoad.insert(*i); } } } else { - int j = nonTrackItems; + int j = 0; for (set::iterator i = m_loadableTracks.begin(); i != m_loadableTracks.end(); ++i) { - if (selected == available[j]) { + if (singleTrack == displayNames[j]) { tracksToLoad.insert(*i); break; } diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/MIDIFileReader.h --- a/data/fileio/MIDIFileReader.h Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/MIDIFileReader.h Fri Mar 14 17:14:21 2008 +0000 @@ -35,12 +35,34 @@ typedef unsigned char MIDIByte; +class MIDIFileImportPreferenceAcquirer // welcome to our grand marble foyer +{ +public: + enum TrackPreference { + ImportNothing, + ImportSingleTrack, + MergeAllTracks, + MergeAllNonPercussionTracks + }; + + virtual ~MIDIFileImportPreferenceAcquirer() { } + + virtual TrackPreference getTrackImportPreference + (QStringList trackNames, bool haveSomePercussion, + QString &singleTrack) const = 0; + + virtual void showError(QString error) = 0; +}; + + class MIDIFileReader : public DataFileReader { Q_OBJECT public: - MIDIFileReader(QString path, size_t mainModelSampleRate); + MIDIFileReader(QString path, + MIDIFileImportPreferenceAcquirer *pref, + size_t mainModelSampleRate); virtual ~MIDIFileReader(); virtual bool isOK() const; @@ -104,6 +126,8 @@ size_t m_fileSize; QString m_error; size_t m_mainModelSampleRate; + + MIDIFileImportPreferenceAcquirer *m_acquirer; }; diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/MP3FileReader.cpp --- a/data/fileio/MP3FileReader.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/MP3FileReader.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -17,7 +17,7 @@ #ifdef HAVE_MAD #include "MP3FileReader.h" -#include "ProgressPrinter.h" +#include "base/ProgressReporter.h" #include "system/System.h" @@ -32,12 +32,11 @@ #endif #define DEBUG_ID3TAG 1 -#include #include -#include MP3FileReader::MP3FileReader(FileSource source, DecodeMode decodeMode, - CacheMode mode, size_t targetRate) : + CacheMode mode, size_t targetRate, + ProgressReporter *reporter) : CodedAudioFileReader(mode, targetRate), m_source(source), m_path(source.getLocalFilename()), @@ -51,7 +50,7 @@ m_cancelled = false; m_completion = 0; m_done = false; - m_progress = 0; + m_reporter = reporter; struct stat stat; if (::stat(m_path.toLocal8Bit().data(), &stat) == -1 || stat.st_size == 0) { @@ -108,14 +107,10 @@ if (decodeMode == DecodeAtOnce) { - if (dynamic_cast(QCoreApplication::instance())) { - m_progress = new QProgressDialog - (QObject::tr("Decoding %1...").arg(QFileInfo(m_path).fileName()), - QObject::tr("Stop"), 0, 100); - m_progress->hide(); - } else { - ProgressPrinter *pp = new ProgressPrinter(tr("Decoding..."), this); - connect(this, SIGNAL(progress(int)), pp, SLOT(progress(int))); + if (m_reporter) { + connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled())); + m_reporter->setMessage + (tr("Decoding %1...").arg(QFileInfo(m_path).fileName())); } if (!decode(m_filebuffer, m_fileSize)) { @@ -127,10 +122,9 @@ if (isDecodeCacheInitialised()) finishDecodeCache(); - delete m_progress; - m_progress = 0; + } else { - } else { + if (m_reporter) m_reporter->setProgress(100); m_decodeThread = new DecodeThread(this); m_decodeThread->start(); @@ -154,6 +148,12 @@ } void +MP3FileReader::cancelled() +{ + m_cancelled = true; +} + +void MP3FileReader::loadTags() { m_title = ""; @@ -366,20 +366,9 @@ int p = int(percent); if (p < 1) p = 1; if (p > 99) p = 99; - if (m_completion != p || (m_progress && !m_progress->isVisible())) { + if (m_completion != p && m_reporter) { m_completion = p; - emit progress(m_completion); - if (m_progress) { - if (m_completion > m_progress->value()) { - m_progress->setValue(m_completion); - m_progress->show(); - m_progress->raise(); - qApp->processEvents(); - if (m_progress->wasCanceled()) { - m_cancelled = true; - } - } - } + m_reporter->setProgress(m_completion); } } diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/MP3FileReader.h --- a/data/fileio/MP3FileReader.h Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/MP3FileReader.h Fri Mar 14 17:14:21 2008 +0000 @@ -25,20 +25,23 @@ #include -class QProgressDialog; +class ProgressReporter; class MP3FileReader : public CodedAudioFileReader { + Q_OBJECT + public: enum DecodeMode { - DecodeAtOnce, // decode the file on construction, with progress dialog + DecodeAtOnce, // decode the file on construction, with progress DecodeThreaded // decode in a background thread after construction }; MP3FileReader(FileSource source, DecodeMode decodeMode, CacheMode cacheMode, - size_t targetRate = 0); + size_t targetRate = 0, + ProgressReporter *reporter = 0); virtual ~MP3FileReader(); virtual QString getError() const { return m_error; } @@ -58,6 +61,9 @@ return m_decodeThread && m_decodeThread->isRunning(); } +public slots: + void cancelled(); + protected: FileSource m_source; QString m_path; @@ -74,7 +80,7 @@ float **m_samplebuffer; size_t m_samplebuffersize; - QProgressDialog *m_progress; + ProgressReporter *m_reporter; bool m_cancelled; struct DecoderData diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/OggVorbisFileReader.cpp --- a/data/fileio/OggVorbisFileReader.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/OggVorbisFileReader.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -17,8 +17,8 @@ #ifdef HAVE_FISHSOUND #include "OggVorbisFileReader.h" -#include "ProgressPrinter.h" +#include "base/ProgressReporter.h" #include "base/Profiler.h" #include "system/System.h" @@ -28,20 +28,19 @@ #include #include -#include #include -#include static int instances = 0; OggVorbisFileReader::OggVorbisFileReader(FileSource source, DecodeMode decodeMode, CacheMode mode, - size_t targetRate) : + size_t targetRate, + ProgressReporter *reporter) : CodedAudioFileReader(mode, targetRate), m_source(source), m_path(source.getLocalFilename()), - m_progress(0), + m_reporter(reporter), m_fileSize(0), m_bytesRead(0), m_commentsRead(false), @@ -72,14 +71,10 @@ if (decodeMode == DecodeAtOnce) { - if (dynamic_cast(QCoreApplication::instance())) { - m_progress = new QProgressDialog - (QObject::tr("Decoding %1...").arg(QFileInfo(m_path).fileName()), - QObject::tr("Stop"), 0, 100); - m_progress->hide(); - } else { - ProgressPrinter *pp = new ProgressPrinter(tr("Decoding..."), this); - connect(this, SIGNAL(progress(int)), pp, SLOT(progress(int))); + if (m_reporter) { + connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled())); + m_reporter->setMessage + (tr("Decoding %1...").arg(QFileInfo(m_path).fileName())); } while (oggz_read(m_oggz, 1024) > 0); @@ -91,10 +86,9 @@ if (isDecodeCacheInitialised()) finishDecodeCache(); - delete m_progress; - m_progress = 0; + } else { - } else { + if (m_reporter) m_reporter->setProgress(100); while (oggz_read(m_oggz, 1024) > 0 && (m_channelCount == 0 || m_fileRate == 0 || m_sampleRate == 0)); @@ -117,6 +111,12 @@ } void +OggVorbisFileReader::cancelled() +{ + m_cancelled = true; +} + +void OggVorbisFileReader::DecodeThread::run() { if (m_reader->m_cacheMode == CacheInTemporaryFile) { @@ -156,16 +156,8 @@ reader->m_completion = p; reader->progress(p); - if (reader->m_fileSize > 0 && reader->m_progress) { - if (p > reader->m_progress->value()) { - reader->m_progress->setValue(p); - reader->m_progress->show(); - reader->m_progress->raise(); - qApp->processEvents(); - if (reader->m_progress->wasCanceled()) { - reader->m_cancelled = true; - } - } + if (reader->m_fileSize > 0 && reader->m_reporter) { + reader->m_reporter->setProgress(p); } if (reader->m_cancelled) return 1; diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/OggVorbisFileReader.h --- a/data/fileio/OggVorbisFileReader.h Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/OggVorbisFileReader.h Fri Mar 14 17:14:21 2008 +0000 @@ -27,20 +27,23 @@ #include -class QProgressDialog; +class ProgressReporter; class OggVorbisFileReader : public CodedAudioFileReader { + Q_OBJECT + public: enum DecodeMode { - DecodeAtOnce, // decode the file on construction, with progress dialog + DecodeAtOnce, // decode the file on construction, with progress DecodeThreaded // decode in a background thread after construction }; OggVorbisFileReader(FileSource source, DecodeMode decodeMode, CacheMode cacheMode, - size_t targetRate = 0); + size_t targetRate = 0, + ProgressReporter *reporter = 0); virtual ~OggVorbisFileReader(); virtual QString getError() const { return m_error; } @@ -60,6 +63,9 @@ return m_decodeThread && m_decodeThread->isRunning(); } +public slots: + void cancelled(); + protected: FileSource m_source; QString m_path; @@ -69,7 +75,7 @@ OGGZ *m_oggz; FishSound *m_fishSound; - QProgressDialog *m_progress; + ProgressReporter *m_reporter; size_t m_fileSize; size_t m_bytesRead; bool m_commentsRead; diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/ProgressPrinter.cpp --- a/data/fileio/ProgressPrinter.cpp Thu Mar 13 14:06:03 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* -*- 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 file copyright 2007 QMUL. - - 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. -*/ - -#include "ProgressPrinter.h" - -#include - -ProgressPrinter::ProgressPrinter(QString prefix, QObject *parent) : - QObject(parent), - m_prefix(prefix), - m_lastProgress(0) -{ -} - -ProgressPrinter::~ProgressPrinter() -{ - if (m_lastProgress > 0 && m_lastProgress != 100) { - std::cerr << "\r\n"; - } - std::cerr << "(progress printer dtor)" << std::endl; -} - -void -ProgressPrinter::progress(int progress) -{ - if (progress == m_lastProgress) return; - if (progress == 100) std::cerr << "\r\n"; - else { - std::cerr << "\r" - << m_prefix.toStdString() - << (m_prefix == "" ? "" : " ") - << progress << "%"; - } - m_lastProgress = progress; -} - diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/ProgressPrinter.h --- a/data/fileio/ProgressPrinter.h Thu Mar 13 14:06:03 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* -*- 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 file copyright 2007 QMUL. - - 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 _PROGRESS_PRINTER_H_ -#define _PROGRESS_PRINTER_H_ - -#include -#include - -class ProgressPrinter : public QObject -{ - Q_OBJECT - -public: - ProgressPrinter(QString prefix = "", QObject *parent = 0); - virtual ~ProgressPrinter(); - -public slots: - void progress(int); - -protected: - QString m_prefix; - int m_lastProgress; -}; - -#endif diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/QuickTimeFileReader.cpp --- a/data/fileio/QuickTimeFileReader.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/QuickTimeFileReader.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -20,11 +20,10 @@ #include "QuickTimeFileReader.h" #include "base/Profiler.h" +#include "base/ProgressReporter.h" #include "system/System.h" -#include #include -#include #ifdef _WIN32 #include @@ -51,12 +50,13 @@ QuickTimeFileReader::QuickTimeFileReader(FileSource source, DecodeMode decodeMode, CacheMode mode, - size_t targetRate) : + size_t targetRate, + ProgressReporter *reporter) : CodedAudioFileReader(mode, targetRate), m_source(source), m_path(source.getLocalFilename()), m_d(new D), - m_progress(0), + m_reporter(reporter), m_cancelled(false), m_completion(0), m_decodeThread(0) @@ -216,11 +216,10 @@ if (decodeMode == DecodeAtOnce) { - if (dynamic_cast(QCoreApplication::instance())) { - m_progress = new QProgressDialog - (QObject::tr("Decoding %1...").arg(QFileInfo(m_path).fileName()), - QObject::tr("Stop"), 0, 100); - m_progress->hide(); + if (m_reporter) { + connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled())); + m_reporter->setMessage + (tr("Decoding %1...").arg(QFileInfo(m_path).fileName())); } while (1) { @@ -255,10 +254,9 @@ m_completion = 100; - delete m_progress; - m_progress = 0; + } else { + if (m_reporter) m_reporter->setProgress(100); - } else { if (m_channelCount > 0) { m_decodeThread = new DecodeThread(this); m_decodeThread->start(); @@ -286,6 +284,12 @@ } void +QuickTimeFileReader::cancelled() +{ + m_cancelled = true; +} + +void QuickTimeFileReader::DecodeThread::run() { if (m_reader->m_cacheMode == CacheInTemporaryFile) { diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/QuickTimeFileReader.h --- a/data/fileio/QuickTimeFileReader.h Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/QuickTimeFileReader.h Fri Mar 14 17:14:21 2008 +0000 @@ -27,20 +27,23 @@ #include -class QProgressDialog; +class ProgressReporter; class QuickTimeFileReader : public CodedAudioFileReader { + Q_OBJECT + public: enum DecodeMode { - DecodeAtOnce, // decode the file on construction, with progress dialog + DecodeAtOnce, // decode the file on construction, with progress DecodeThreaded // decode in a background thread after construction }; QuickTimeFileReader(FileSource source, DecodeMode decodeMode, CacheMode cacheMode, - size_t targetRate = 0); + size_t targetRate = 0, + ProgressReporter *reporter = 0); virtual ~QuickTimeFileReader(); virtual QString getError() const { return m_error; } @@ -58,6 +61,9 @@ return m_decodeThread && m_decodeThread->isRunning(); } +public slots: + void cancelled(); + protected: FileSource m_source; QString m_path; @@ -67,7 +73,7 @@ class D; D *m_d; - QProgressDialog *m_progress; + ProgressReporter *m_reporter; bool m_cancelled; int m_completion; diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/ResamplingWavFileReader.cpp --- a/data/fileio/ResamplingWavFileReader.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/ResamplingWavFileReader.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -17,15 +17,15 @@ #include "WavFileReader.h" #include "base/Profiler.h" +#include "base/ProgressReporter.h" -#include #include -#include ResamplingWavFileReader::ResamplingWavFileReader(FileSource source, ResampleMode resampleMode, CacheMode mode, - size_t targetRate) : + size_t targetRate, + ProgressReporter *reporter) : CodedAudioFileReader(mode, targetRate), m_source(source), m_path(source.getLocalFilename()), @@ -33,7 +33,7 @@ m_processed(0), m_completion(0), m_original(0), - m_progress(0), + m_reporter(reporter), m_decodeThread(0) { m_channelCount = 0; @@ -57,11 +57,10 @@ if (resampleMode == ResampleAtOnce) { - if (dynamic_cast(QCoreApplication::instance())) { - m_progress = new QProgressDialog - (QObject::tr("Resampling %1...").arg(QFileInfo(m_path).fileName()), - QObject::tr("Stop"), 0, 100); - m_progress->hide(); + if (m_reporter) { + connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled())); + m_reporter->setMessage + (tr("Resampling %1...").arg(QFileInfo(m_path).fileName())); } size_t blockSize = 16384; @@ -85,10 +84,9 @@ delete m_original; m_original = 0; - delete m_progress; - m_progress = 0; + } else { - } else { + if (m_reporter) m_reporter->setProgress(100); m_decodeThread = new DecodeThread(this); m_decodeThread->start(); @@ -107,6 +105,12 @@ } void +ResamplingWavFileReader::cancelled() +{ + m_cancelled = true; +} + +void ResamplingWavFileReader::DecodeThread::run() { if (m_reader->m_cacheMode == CacheInTemporaryFile) { @@ -151,16 +155,8 @@ if (progress > 99) progress = 99; m_completion = progress; - if (m_progress) { - if (progress > m_progress->value()) { - m_progress->setValue(progress); - m_progress->show(); - m_progress->raise(); - qApp->processEvents(); - if (m_progress->wasCanceled()) { - m_cancelled = true; - } - } + if (m_reporter) { + m_reporter->setProgress(progress); } } diff -r 5858cc462d0a -r 183ee2a55fc7 data/fileio/ResamplingWavFileReader.h --- a/data/fileio/ResamplingWavFileReader.h Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/ResamplingWavFileReader.h Fri Mar 14 17:14:21 2008 +0000 @@ -23,10 +23,11 @@ #include class WavFileReader; -class QProgressDialog; +class ProgressReporter; class ResamplingWavFileReader : public CodedAudioFileReader { + Q_OBJECT public: enum ResampleMode { ResampleAtOnce, // resample the file on construction, with progress dialog @@ -36,7 +37,8 @@ ResamplingWavFileReader(FileSource source, ResampleMode resampleMode, CacheMode cacheMode, - size_t targetRate = 0); + size_t targetRate = 0, + ProgressReporter *reporter = 0); virtual ~ResamplingWavFileReader(); virtual QString getError() const { return m_error; } @@ -52,6 +54,9 @@ return m_decodeThread && m_decodeThread->isRunning(); } +public slots: + void cancelled(); + protected: FileSource m_source; QString m_path; @@ -61,7 +66,7 @@ int m_completion; WavFileReader *m_original; - QProgressDialog *m_progress; + ProgressReporter *m_reporter; void addBlock(const SampleBlock &frames); diff -r 5858cc462d0a -r 183ee2a55fc7 data/model/WaveFileModel.cpp --- a/data/model/WaveFileModel.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/model/WaveFileModel.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -20,7 +20,6 @@ #include "system/System.h" -#include #include #include