Revision: 788
http://sv1.svn.sourceforge.net/sv1/?rev=788&view=rev
Author: cannam
Date: 2007-10-18 08:31:20 -0700 (Thu, 18 Oct 2007)
Log Message:
-----------
* Make RemoteFile far more pervasive, and use it for local files as well
so that we can handle both transparently. Make it shallow copy with
reference counting, so it can be used by value without having to worry
about the cache file lifetime. Use RemoteFile for MainWindow file-open
functions, etc
Modified Paths:
--------------
sonic-visualiser/trunk/data/fileio/AudioFileReader.h
sonic-visualiser/trunk/data/fileio/AudioFileReaderFactory.cpp
sonic-visualiser/trunk/data/fileio/AudioFileReaderFactory.h
sonic-visualiser/trunk/data/fileio/FileFinder.cpp
sonic-visualiser/trunk/data/fileio/MP3FileReader.cpp
sonic-visualiser/trunk/data/fileio/MP3FileReader.h
sonic-visualiser/trunk/data/fileio/OggVorbisFileReader.cpp
sonic-visualiser/trunk/data/fileio/OggVorbisFileReader.h
sonic-visualiser/trunk/data/fileio/QuickTimeFileReader.cpp
sonic-visualiser/trunk/data/fileio/QuickTimeFileReader.h
sonic-visualiser/trunk/data/fileio/RemoteFile.cpp
sonic-visualiser/trunk/data/fileio/RemoteFile.h
sonic-visualiser/trunk/data/fileio/ResamplingWavFileReader.cpp
sonic-visualiser/trunk/data/fileio/ResamplingWavFileReader.h
sonic-visualiser/trunk/data/fileio/WavFileReader.cpp
sonic-visualiser/trunk/data/fileio/WavFileReader.h
sonic-visualiser/trunk/data/model/WaveFileModel.cpp
sonic-visualiser/trunk/data/model/WaveFileModel.h
sonic-visualiser/trunk/data/model/WritableWaveFileModel.cpp
sonic-visualiser/trunk/layer/ImageLayer.cpp
sonic-visualiser/trunk/sv/document/SVFileReader.cpp
sonic-visualiser/trunk/sv/main/MainWindow.cpp
sonic-visualiser/trunk/sv/main/MainWindow.h
sonic-visualiser/trunk/sv/main/main.cpp
sonic-visualiser/trunk/widgets/ImageDialog.cpp
Modified: sonic-visualiser/trunk/data/fileio/AudioFileReader.h
===================================================================
--- sonic-visualiser/trunk/data/fileio/AudioFileReader.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/AudioFileReader.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -19,6 +19,8 @@
#include <QString>
#include "model/Model.h" // for SampleBlock
+#include "RemoteFile.h"
+
class AudioFileReader : public QObject
{
Q_OBJECT
Modified: sonic-visualiser/trunk/data/fileio/AudioFileReaderFactory.cpp
===================================================================
--- sonic-visualiser/trunk/data/fileio/AudioFileReaderFactory.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/AudioFileReaderFactory.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -54,24 +54,25 @@
}
AudioFileReader *
-AudioFileReaderFactory::createReader(QString path, size_t targetRate)
+AudioFileReaderFactory::createReader(RemoteFile source, size_t targetRate)
{
QString err;
- std::cerr << "AudioFileReaderFactory::createReader(\"" << path.toStdString() << "\"): Requested rate: " << targetRate << std::endl;
+ std::cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation().toStdString() << "\"): Requested rate: " << targetRate << std::endl;
+ if (!source.isOK() || !source.isAvailable()) {
+ std::cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation().toStdString() << "\": Source unavailable" << std::endl;
+ return 0;
+ }
+
AudioFileReader *reader = 0;
- // First try to construct a preferred reader based on the
- // extension. If we can't identify one or it fails to load the
- // file, fall back to trying all readers in no particular order.
+ // Try to construct a preferred reader based on the extension or
+ // MIME type.
- QString ext = QFileInfo(path).suffix().toLower();
- std::set<QString> extensions;
+ if (WavFileReader::supports(source)) {
- WavFileReader::getSupportedExtensions(extensions);
- if (extensions.find(ext) != extensions.end()) {
- reader = new WavFileReader(path);
+ reader = new WavFileReader(source);
if (targetRate != 0 &&
reader->isOK() &&
@@ -81,7 +82,7 @@
delete reader;
reader = new ResamplingWavFileReader
- (path,
+ (source,
ResamplingWavFileReader::ResampleThreaded,
ResamplingWavFileReader::CacheInTemporaryFile,
targetRate);
@@ -91,11 +92,9 @@
#ifdef HAVE_OGGZ
#ifdef HAVE_FISHSOUND
if (!reader) {
- extensions.clear();
- OggVorbisFileReader::getSupportedExtensions(extensions);
- if (extensions.find(ext) != extensions.end()) {
+ if (OggVorbisFileReader::supports(source)) {
reader = new OggVorbisFileReader
- (path,
+ (source,
OggVorbisFileReader::DecodeThreaded,
OggVorbisFileReader::CacheInTemporaryFile,
targetRate);
@@ -106,11 +105,9 @@
#ifdef HAVE_MAD
if (!reader) {
- extensions.clear();
- MP3FileReader::getSupportedExtensions(extensions);
- if (extensions.find(ext) != extensions.end()) {
+ if (MP3FileReader::supports(source)) {
reader = new MP3FileReader
- (path,
+ (source,
MP3FileReader::DecodeThreaded,
MP3FileReader::CacheInTemporaryFile,
targetRate);
@@ -120,11 +117,9 @@
#ifdef HAVE_QUICKTIME
if (!reader) {
- extensions.clear();
- QuickTimeFileReader::getSupportedExtensions(extensions);
- if (extensions.find(ext) != extensions.end()) {
+ if (QuickTimeFileReader::supports(source)) {
reader = new QuickTimeFileReader
- (path,
+ (source,
QuickTimeFileReader::DecodeThreaded,
QuickTimeFileReader::CacheInTemporaryFile,
targetRate);
@@ -133,20 +128,24 @@
#endif
if (reader) {
- if (reader->isOK()) return reader;
+ if (reader->isOK()) {
+ std::cerr << "AudioFileReaderFactory: Reader is OK" << std::endl;
+ return reader;
+ }
+ std::cerr << "AudioFileReaderFactory: Preferred reader for "
+ << "url \"" << source.getLocation().toStdString()
+ << "\" (content type \""
+ << source.getContentType().toStdString() << "\") failed";
+
if (reader->getError() != "") {
- std::cerr << "AudioFileReaderFactory: Preferred reader for "
- << "extension \"" << ext.toStdString() << "\" failed: \""
- << reader->getError().toStdString() << "\"" << std::endl;
- } else {
- std::cerr << "AudioFileReaderFactory: Preferred reader for "
- << "extension \"" << ext.toStdString() << "\" failed"
- << std::endl;
- }
+ std::cerr << ": \"" << reader->getError().toStdString() << "\"";
+ }
+ std::cerr << std::endl;
delete reader;
reader = 0;
}
+ std::cerr << "AudioFileReaderFactory: No reader" << std::endl;
return reader;
}
Modified: sonic-visualiser/trunk/data/fileio/AudioFileReaderFactory.h
===================================================================
--- sonic-visualiser/trunk/data/fileio/AudioFileReaderFactory.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/AudioFileReaderFactory.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -18,6 +18,8 @@
#include <QString>
+#include "RemoteFile.h"
+
class AudioFileReader;
class AudioFileReaderFactory
@@ -42,7 +44,7 @@
*
* Caller owns the returned object and must delete it after use.
*/
- static AudioFileReader *createReader(QString path, size_t targetRate = 0);
+ static AudioFileReader *createReader(RemoteFile source, size_t targetRate = 0);
};
#endif
Modified: sonic-visualiser/trunk/data/fileio/FileFinder.cpp
===================================================================
--- sonic-visualiser/trunk/data/fileio/FileFinder.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/FileFinder.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -380,11 +380,11 @@
{
if (QFileInfo(location).exists()) return location;
- if (RemoteFile::canHandleScheme(QUrl(location))) {
- RemoteFile rf(location);
- bool available = rf.isAvailable();
- rf.deleteLocalFile();
- if (available) return location;
+ if (RemoteFile::isRemote(location)) {
+ if (RemoteFile(location).isAvailable()) {
+ std::cerr << "FileFinder::find: ok, it's available... returning" << std::endl;
+ return location;
+ }
}
QString foundAt = "";
@@ -411,19 +411,17 @@
QString fileName;
QString resolved;
- if (RemoteFile::canHandleScheme(QUrl(location))) {
+ if (RemoteFile::isRemote(location)) {
fileName = QUrl(location).path().section('/', -1, -1,
QString::SectionSkipEmpty);
} else {
fileName = QFileInfo(location).fileName();
}
- if (RemoteFile::canHandleScheme(QUrl(relativeTo))) {
+ if (RemoteFile::isRemote(relativeTo)) {
resolved = QUrl(relativeTo).resolved(fileName).toString();
- RemoteFile rf(resolved);
- if (!rf.isAvailable()) resolved = "";
+ if (!RemoteFile(resolved).isAvailable()) resolved = "";
std::cerr << "resolved: " << resolved.toStdString() << std::endl;
- rf.deleteLocalFile();
} else {
resolved = QFileInfo(relativeTo).dir().filePath(fileName);
if (!QFileInfo(resolved).exists() ||
@@ -481,8 +479,7 @@
QLineEdit::Normal, "", &ok);
if (ok && path != "") {
- RemoteFile rf(path);
- if (rf.isAvailable()) {
+ if (RemoteFile(path).isAvailable()) {
done = true;
} else {
QMessageBox::critical
@@ -490,7 +487,6 @@
tr("URL \"%1\" could not be opened").arg(path));
path = "";
}
- rf.deleteLocalFile();
}
break;
}
Modified: sonic-visualiser/trunk/data/fileio/MP3FileReader.cpp
===================================================================
--- sonic-visualiser/trunk/data/fileio/MP3FileReader.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/MP3FileReader.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -34,10 +34,11 @@
#include <QFileInfo>
#include <QProgressDialog>
-MP3FileReader::MP3FileReader(QString path, DecodeMode decodeMode,
+MP3FileReader::MP3FileReader(RemoteFile source, DecodeMode decodeMode,
CacheMode mode, size_t targetRate) :
CodedAudioFileReader(mode, targetRate),
- m_path(path),
+ m_source(source),
+ m_path(source.getLocalFilename()),
m_decodeThread(0)
{
m_channelCount = 0;
@@ -51,20 +52,20 @@
m_progress = 0;
struct stat stat;
- if (::stat(path.toLocal8Bit().data(), &stat) == -1 || stat.st_size == 0) {
- m_error = QString("File %1 does not exist.").arg(path);
+ if (::stat(m_path.toLocal8Bit().data(), &stat) == -1 || stat.st_size == 0) {
+ m_error = QString("File %1 does not exist.").arg(m_path);
return;
}
m_fileSize = stat.st_size;
int fd = -1;
- if ((fd = ::open(path.toLocal8Bit().data(), O_RDONLY
+ if ((fd = ::open(m_path.toLocal8Bit().data(), O_RDONLY
#ifdef _WIN32
| O_BINARY
#endif
, 0)) < 0) {
- m_error = QString("Failed to open file %1 for reading.").arg(path);
+ m_error = QString("Failed to open file %1 for reading.").arg(m_path);
return;
}
@@ -86,7 +87,7 @@
sz = ::read(fd, m_filebuffer + offset, m_fileSize - offset);
if (sz < 0) {
m_error = QString("Read error for file %1 (after %2 bytes)")
- .arg(path).arg(offset);
+ .arg(m_path).arg(offset);
delete[] m_filebuffer;
::close(fd);
return;
@@ -106,12 +107,12 @@
if (decodeMode == DecodeAtOnce) {
m_progress = new QProgressDialog
- (QObject::tr("Decoding %1...").arg(QFileInfo(path).fileName()),
+ (QObject::tr("Decoding %1...").arg(QFileInfo(m_path).fileName()),
QObject::tr("Stop"), 0, 100);
m_progress->hide();
if (!decode(m_filebuffer, m_fileSize)) {
- m_error = QString("Failed to decode file %1.").arg(path);
+ m_error = QString("Failed to decode file %1.").arg(m_path);
}
delete[] m_filebuffer;
@@ -394,4 +395,26 @@
extensions.insert("mp3");
}
+bool
+MP3FileReader::supportsExtension(QString extension)
+{
+ std::set<QString> extensions;
+ getSupportedExtensions(extensions);
+ return (extensions.find(extension.toLower()) != extensions.end());
+}
+
+bool
+MP3FileReader::supportsContentType(QString type)
+{
+ return (type == "audio/mpeg");
+}
+
+bool
+MP3FileReader::supports(RemoteFile &source)
+{
+ return (supportsExtension(source.getExtension()) ||
+ supportsContentType(source.getContentType()));
+}
+
+
#endif
Modified: sonic-visualiser/trunk/data/fileio/MP3FileReader.h
===================================================================
--- sonic-visualiser/trunk/data/fileio/MP3FileReader.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/MP3FileReader.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -35,7 +35,7 @@
DecodeThreaded // decode in a background thread after construction
};
- MP3FileReader(QString path,
+ MP3FileReader(RemoteFile source,
DecodeMode decodeMode,
CacheMode cacheMode,
size_t targetRate = 0);
@@ -46,7 +46,10 @@
virtual QString getTitle() const { return m_title; }
static void getSupportedExtensions(std::set<QString> &extensions);
-
+ static bool supportsExtension(QString ext);
+ static bool supportsContentType(QString type);
+ static bool supports(RemoteFile &source);
+
virtual int getDecodeCompletion() const { return m_completion; }
virtual bool isUpdating() const {
@@ -54,6 +57,7 @@
}
protected:
+ RemoteFile m_source;
QString m_path;
QString m_error;
QString m_title;
Modified: sonic-visualiser/trunk/data/fileio/OggVorbisFileReader.cpp
===================================================================
--- sonic-visualiser/trunk/data/fileio/OggVorbisFileReader.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/OggVorbisFileReader.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -32,12 +32,13 @@
static int instances = 0;
-OggVorbisFileReader::OggVorbisFileReader(QString path,
+OggVorbisFileReader::OggVorbisFileReader(RemoteFile source,
DecodeMode decodeMode,
CacheMode mode,
size_t targetRate) :
CodedAudioFileReader(mode, targetRate),
- m_path(path),
+ m_source(source),
+ m_path(source.getLocalFilename()),
m_progress(0),
m_fileSize(0),
m_bytesRead(0),
@@ -49,15 +50,15 @@
m_channelCount = 0;
m_fileRate = 0;
- std::cerr << "OggVorbisFileReader::OggVorbisFileReader(" << path.toLocal8Bit().data() << "): now have " << (++instances) << " instances" << std::endl;
+ std::cerr << "OggVorbisFileReader::OggVorbisFileReader(" << m_path.toLocal8Bit().data() << "): now have " << (++instances) << " instances" << std::endl;
Profiler profiler("OggVorbisFileReader::OggVorbisFileReader", true);
- QFileInfo info(path);
+ QFileInfo info(m_path);
m_fileSize = info.size();
- if (!(m_oggz = oggz_open(path.toLocal8Bit().data(), OGGZ_READ))) {
- m_error = QString("File %1 is not an OGG file.").arg(path);
+ if (!(m_oggz = oggz_open(m_path.toLocal8Bit().data(), OGGZ_READ))) {
+ m_error = QString("File %1 is not an OGG file.").arg(m_path);
return;
}
@@ -70,7 +71,7 @@
if (decodeMode == DecodeAtOnce) {
m_progress = new QProgressDialog
- (QObject::tr("Decoding %1...").arg(QFileInfo(path).fileName()),
+ (QObject::tr("Decoding %1...").arg(QFileInfo(m_path).fileName()),
QObject::tr("Stop"), 0, 100);
m_progress->hide();
@@ -201,5 +202,26 @@
extensions.insert("ogg");
}
+bool
+OggVorbisFileReader::supportsExtension(QString extension)
+{
+ std::set<QString> extensions;
+ getSupportedExtensions(extensions);
+ return (extensions.find(extension.toLower()) != extensions.end());
+}
+
+bool
+OggVorbisFileReader::supportsContentType(QString type)
+{
+ return (type == "application/ogg");
+}
+
+bool
+OggVorbisFileReader::supports(RemoteFile &source)
+{
+ return (supportsExtension(source.getExtension()) ||
+ supportsContentType(source.getContentType()));
+}
+
#endif
#endif
Modified: sonic-visualiser/trunk/data/fileio/OggVorbisFileReader.h
===================================================================
--- sonic-visualiser/trunk/data/fileio/OggVorbisFileReader.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/OggVorbisFileReader.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -37,7 +37,7 @@
DecodeThreaded // decode in a background thread after construction
};
- OggVorbisFileReader(QString path,
+ OggVorbisFileReader(RemoteFile source,
DecodeMode decodeMode,
CacheMode cacheMode,
size_t targetRate = 0);
@@ -48,6 +48,9 @@
virtual QString getTitle() const { return m_title; }
static void getSupportedExtensions(std::set<QString> &extensions);
+ static bool supportsExtension(QString ext);
+ static bool supportsContentType(QString type);
+ static bool supports(RemoteFile &source);
virtual int getDecodeCompletion() const { return m_completion; }
@@ -56,6 +59,7 @@
}
protected:
+ RemoteFile m_source;
QString m_path;
QString m_error;
QString m_title;
Modified: sonic-visualiser/trunk/data/fileio/QuickTimeFileReader.cpp
===================================================================
--- sonic-visualiser/trunk/data/fileio/QuickTimeFileReader.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/QuickTimeFileReader.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -48,12 +48,13 @@
};
-QuickTimeFileReader::QuickTimeFileReader(QString path,
+QuickTimeFileReader::QuickTimeFileReader(RemoteFile source,
DecodeMode decodeMode,
CacheMode mode,
size_t targetRate) :
CodedAudioFileReader(mode, targetRate),
- m_path(path),
+ m_source(source),
+ m_path(source.getLocalFilename()),
m_d(new D),
m_progress(0),
m_cancelled(false),
@@ -65,7 +66,7 @@
Profiler profiler("QuickTimeFileReader::QuickTimeFileReader", true);
-std::cerr << "QuickTimeFileReader: path is \"" << path.toStdString() << "\"" << std::endl;
+std::cerr << "QuickTimeFileReader: path is \"" << m_path.toStdString() << "\"" << std::endl;
long QTversion;
@@ -90,8 +91,8 @@
CFURLRef url = CFURLCreateFromFileSystemRepresentation
(kCFAllocatorDefault,
- (const UInt8 *)path.toLocal8Bit().data(),
- (CFIndex)path.length(),
+ (const UInt8 *)m_path.toLocal8Bit().data(),
+ (CFIndex)m_path.length(),
false);
@@ -216,7 +217,7 @@
if (decodeMode == DecodeAtOnce) {
m_progress = new QProgressDialog
- (QObject::tr("Decoding %1...").arg(QFileInfo(path).fileName()),
+ (QObject::tr("Decoding %1...").arg(QFileInfo(m_path).fileName()),
QObject::tr("Stop"), 0, 100);
m_progress->hide();
@@ -335,5 +336,32 @@
extensions.insert("wav");
}
+bool
+QuickTimeFileReader::supportsExtension(QString extension)
+{
+ std::set<QString> extensions;
+ getSupportedExtensions(extensions);
+ return (extensions.find(extension.toLower()) != extensions.end());
+}
+
+bool
+QuickTimeFileReader::supportsContentType(QString type)
+{
+ return (type == "audio/x-aiff" ||
+ type == "audio/x-wav" ||
+ type == "audio/mpeg" ||
+ type == "audio/basic" ||
+ type == "audio/x-aac" ||
+ type == "video/mp4" ||
+ type == "video/quicktime");
+}
+
+bool
+QuickTimeFileReader::supports(RemoteFile &source)
+{
+ return (supportsExtension(source.getExtension()) ||
+ supportsContentType(source.getContentType()));
+}
+
#endif
Modified: sonic-visualiser/trunk/data/fileio/QuickTimeFileReader.h
===================================================================
--- sonic-visualiser/trunk/data/fileio/QuickTimeFileReader.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/QuickTimeFileReader.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -37,7 +37,7 @@
DecodeThreaded // decode in a background thread after construction
};
- QuickTimeFileReader(QString path,
+ QuickTimeFileReader(RemoteFile source,
DecodeMode decodeMode,
CacheMode cacheMode,
size_t targetRate = 0);
@@ -47,6 +47,9 @@
virtual QString getTitle() const { return m_title; }
static void getSupportedExtensions(std::set<QString> &extensions);
+ static bool supportsExtension(QString ext);
+ static bool supportsContentType(QString type);
+ static bool supports(RemoteFile &source);
virtual int getDecodeCompletion() const { return m_completion; }
@@ -55,6 +58,7 @@
}
protected:
+ RemoteFile m_source;
QString m_path;
QString m_error;
QString m_title;
Modified: sonic-visualiser/trunk/data/fileio/RemoteFile.cpp
===================================================================
--- sonic-visualiser/trunk/data/fileio/RemoteFile.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/RemoteFile.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -42,156 +42,303 @@
QMutex
RemoteFile::m_mapMutex;
-RemoteFile::RemoteFile(QUrl url) :
- m_url(url),
+RemoteFile::RemoteFile(QString fileOrUrl, bool showProgress) :
+ m_url(fileOrUrl),
m_ftp(0),
m_http(0),
m_localFile(0),
m_ok(false),
m_lastStatus(0),
+ m_remote(isRemote(fileOrUrl)),
m_done(false),
+ m_leaveLocalFile(false),
m_progressDialog(0),
m_progressShowTimer(this),
- m_referenced(false)
+ m_refCounted(false)
{
- if (!canHandleScheme(url)) {
- std::cerr << "RemoteFile::RemoteFile: ERROR: Unsupported scheme in URL \"" << url.toString().toStdString() << "\"" << std::endl;
+ std::cerr << "RemoteFile::RemoteFile(" << fileOrUrl.toStdString() << ")" << std::endl;
+
+ if (!canHandleScheme(m_url)) {
+ std::cerr << "RemoteFile::RemoteFile: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl;
+ m_errorString = tr("Unsupported scheme in URL");
return;
}
- QMutexLocker locker(&m_mapMutex);
+ init(showProgress);
- std::cerr << "RemoteFile::RemoteFile: refcount is " << m_refCountMap[m_url] << std::endl;
+ if (isRemote() &&
+ (fileOrUrl.contains('%') ||
+ fileOrUrl.contains("--"))) { // for IDNA
- if (m_refCountMap[m_url] > 0) {
- m_refCountMap[m_url]++;
- m_localFilename = m_remoteLocalMap[m_url];
- std::cerr << "raising it" << std::endl;
- m_ok = true;
- m_done = true;
- m_referenced = true;
- return;
+ waitForStatus();
+
+ if (!isAvailable()) {
+ // The URL was created on the assumption that the string
+ // was human-readable. Let's try again, this time
+ // assuming it was already encoded.
+ std::cerr << "RemoteFile::RemoteFile: Failed to retrieve URL \""
+ << fileOrUrl.toStdString()
+ << "\" as human-readable URL; "
+ << "trying again treating it as encoded URL"
+ << std::endl;
+ m_url.setEncodedUrl(fileOrUrl.toAscii());
+ init(showProgress);
+ }
}
+}
- m_localFilename = createLocalFile(url);
- if (m_localFilename == "") return;
- m_localFile = new QFile(m_localFilename);
- m_localFile->open(QFile::WriteOnly);
+RemoteFile::RemoteFile(QUrl url, bool showProgress) :
+ m_url(url),
+ m_ftp(0),
+ m_http(0),
+ m_localFile(0),
+ m_ok(false),
+ m_lastStatus(0),
+ m_remote(isRemote(url.toString())),
+ m_done(false),
+ m_leaveLocalFile(false),
+ m_progressDialog(0),
+ m_progressShowTimer(this),
+ m_refCounted(false)
+{
+ std::cerr << "RemoteFile::RemoteFile(" << url.toString().toStdString() << ") [as url]" << std::endl;
- QString scheme = url.scheme().toLower();
+ if (!canHandleScheme(m_url)) {
+ std::cerr << "RemoteFile::RemoteFile: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl;
+ m_errorString = tr("Unsupported scheme in URL");
+ return;
+ }
- if (scheme == "http") {
+ init(showProgress);
+}
- m_ok = true;
- m_http = new QHttp(url.host(), url.port(80));
- connect(m_http, SIGNAL(done(bool)), this, SLOT(done(bool)));
- connect(m_http, SIGNAL(dataReadProgress(int, int)),
- this, SLOT(dataReadProgress(int, int)));
- connect(m_http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
- this, SLOT(httpResponseHeaderReceived(const QHttpResponseHeader &)));
+RemoteFile::RemoteFile(const RemoteFile &rf) :
+ QObject(),
+ m_url(rf.m_url),
+ m_ftp(0),
+ m_http(0),
+ m_localFile(0),
+ m_ok(rf.m_ok),
+ m_lastStatus(rf.m_lastStatus),
+ m_remote(rf.m_remote),
+ m_done(false),
+ m_leaveLocalFile(false),
+ m_progressDialog(0),
+ m_progressShowTimer(0),
+ m_refCounted(false)
+{
+ std::cerr << "RemoteFile::RemoteFile(" << m_url.toString().toStdString() << ") [copy ctor]" << std::endl;
- // I don't quite understand this. url.path() returns a path
- // without percent encoding; for example, spaces appear as
- // literal spaces. This generally won't work if sent to the
- // server directly. You can retrieve a correctly encoded URL
- // from QUrl using url.toEncoded(), but that gives you the
- // whole URL; there doesn't seem to be any way to retrieve
- // only an encoded path. Furthermore there doesn't seem to be
- // any way to convert a retrieved path into an encoded path
- // without explicitly specifying that you don't want the path
- // separators ("/") to be encoded. (Besides being painful to
- // manage, I don't see how this can work correctly in any case
- // where a percent-encoded "/" is supposed to appear within a
- // path element?) There also seems to be no way to retrieve
- // the path plus query string, i.e. everything that I need to
- // send to the HTTP server. And no way for QHttp to take a
- // QUrl argument. I'm obviously missing something.
+ if (!canHandleScheme(m_url)) {
+ std::cerr << "RemoteFile::RemoteFile: ERROR: Unsupported scheme in URL \"" << m_url.toString().toStdString() << "\"" << std::endl;
+ m_errorString = tr("Unsupported scheme in URL");
+ return;
+ }
- // So, two ways to do this: query the bits from the URL,
- // encode them individually, and glue them back together
- // again...
- /*
- QString path = QUrl::toPercentEncoding(url.path(), "/");
- QList<QPair<QString, QString> > query = url.queryItems();
- if (!query.empty()) {
- QStringList q2;
- for (QList<QPair<QString, QString> >::iterator i = query.begin();
- i != query.end(); ++i) {
- q2.push_back(QString("%1=%3")
- .arg(QString(QUrl::toPercentEncoding(i->first)))
- .arg(QString(QUrl::toPercentEncoding(i->second))));
- }
- path = QString("%1%2%3")
- .arg(path).arg("?")
- .arg(q2.join("&"));
+ if (!isRemote()) {
+ m_localFilename = rf.m_localFilename;
+ } else {
+ QMutexLocker locker(&m_mapMutex);
+ std::cerr << "RemoteFile::RemoteFile(copy ctor): ref count is "
+ << m_refCountMap[m_url] << std::endl;
+ if (m_refCountMap[m_url] > 0) {
+ m_refCountMap[m_url]++;
+ std::cerr << "raised it to " << m_refCountMap[m_url] << std::endl;
+ m_localFilename = m_remoteLocalMap[m_url];
+ m_refCounted = true;
+ } else {
+ m_ok = false;
+ m_lastStatus = 404;
}
- */
+ }
- // ...or, much simpler but relying on knowledge about the
- // scheme://host/path/path/query etc format of the URL, we can
- // get the whole URL ready-encoded and then split it on "/" as
- // appropriate...
-
- QString path = "/" + QString(url.toEncoded()).section('/', 3);
+ m_done = true;
+}
- std::cerr << "RemoteFile: path is \""
- << path.toStdString() << "\"" << std::endl;
+RemoteFile::~RemoteFile()
+{
+ std::cerr << "RemoteFile(" << m_url.toString().toStdString() << ")::~RemoteFile" << std::endl;
- m_http->get(path, m_localFile);
+ cleanup();
- } else if (scheme == "ftp") {
+ if (isRemote() && !m_leaveLocalFile) deleteCacheFile();
+}
+void
+RemoteFile::init(bool showProgress)
+{
+ if (!isRemote()) {
+ m_localFilename = m_url.toLocalFile();
m_ok = true;
- m_ftp = new QFtp;
- connect(m_ftp, SIGNAL(done(bool)), this, SLOT(done(bool)));
- connect(m_ftp, SIGNAL(commandFinished(int, bool)),
- this, SLOT(ftpCommandFinished(int, bool)));
- connect(m_ftp, SIGNAL(dataTransferProgress(qint64, qint64)),
- this, SLOT(dataTransferProgress(qint64, qint64)));
- m_ftp->connectToHost(url.host(), url.port(21));
-
- QString username = url.userName();
- if (username == "") {
- username = "anonymous";
+ if (!QFileInfo(m_localFilename).exists()) {
+ m_lastStatus = 404;
+ } else {
+ m_lastStatus = 200;
}
+ m_done = true;
+ return;
+ }
- QString password = url.password();
- if (password == "") {
- password = QString("%1@..."));
+ if (createCacheFile()) {
+ std::cerr << "RemoteFile::init: Already have this one" << std::endl;
+ m_ok = true;
+ if (!QFileInfo(m_localFilename).exists()) {
+ m_lastStatus = 404;
+ } else {
+ m_lastStatus = 200;
}
+ m_done = true;
+ return;
+ }
- m_ftp->login(username, password);
+ if (m_localFilename == "") return;
+ m_localFile = new QFile(m_localFilename);
+ m_localFile->open(QFile::WriteOnly);
- QString dirpath = url.path().section('/', 0, -2);
- QString filename = url.path().section('/', -1);
+ QString scheme = m_url.scheme().toLower();
- if (dirpath == "") dirpath = "/";
- m_ftp->cd(dirpath);
- m_ftp->get(filename, m_localFile);
+ std::cerr << "RemoteFile::init: Don't have local copy of \""
+ << m_url.toString().toStdString() << "\", retrieving" << std::endl;
+
+ if (scheme == "http") {
+ initHttp();
+ } else if (scheme == "ftp") {
+ initFtp();
+ } else {
+ m_remote = false;
+ m_ok = false;
}
if (m_ok) {
+
+ QMutexLocker locker(&m_mapMutex);
+ if (m_refCountMap[m_url] > 0) {
+ // someone else has been doing the same thing at the same time,
+ // but has got there first
+ cleanup();
+ m_refCountMap[m_url]++;
+ std::cerr << "RemoteFile::init: Another RemoteFile has got there first, abandoning our download and using theirs" << std::endl;
+ m_localFilename = m_remoteLocalMap[m_url];
+ m_refCounted = true;
+ m_ok = true;
+ if (!QFileInfo(m_localFilename).exists()) {
+ m_lastStatus = 404;
+ }
+ m_done = true;
+ return;
+ }
+
m_remoteLocalMap[m_url] = m_localFilename;
m_refCountMap[m_url]++;
- m_referenced = true;
+ m_refCounted = true;
- m_progressDialog = new QProgressDialog(tr("Downloading %1...").arg(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);
+ if (showProgress) {
+ 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);
+ }
}
}
-RemoteFile::~RemoteFile()
+void
+RemoteFile::initHttp()
{
- cleanup();
+ m_ok = true;
+ m_http = new QHttp(m_url.host(), m_url.port(80));
+ connect(m_http, SIGNAL(done(bool)), this, SLOT(done(bool)));
+ connect(m_http, SIGNAL(dataReadProgress(int, int)),
+ this, SLOT(dataReadProgress(int, int)));
+ connect(m_http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
+ this, SLOT(httpResponseHeaderReceived(const QHttpResponseHeader &)));
+
+ // I don't quite understand this. url.path() returns a path
+ // without percent encoding; for example, spaces appear as
+ // literal spaces. This generally won't work if sent to the
+ // server directly. You can retrieve a correctly encoded URL
+ // from QUrl using url.toEncoded(), but that gives you the
+ // whole URL; there doesn't seem to be any way to retrieve
+ // only an encoded path. Furthermore there doesn't seem to be
+ // any way to convert a retrieved path into an encoded path
+ // without explicitly specifying that you don't want the path
+ // separators ("/") to be encoded. (Besides being painful to
+ // manage, I don't see how this can work correctly in any case
+ // where a percent-encoded "/" is supposed to appear within a
+ // path element?) There also seems to be no way to retrieve
+ // the path plus query string, i.e. everything that I need to
+ // send to the HTTP server. And no way for QHttp to take a
+ // QUrl argument. I'm obviously missing something.
+
+ // So, two ways to do this: query the bits from the URL,
+ // encode them individually, and glue them back together
+ // again...
+/*
+ QString path = QUrl::toPercentEncoding(m_url.path(), "/");
+ QList<QPair<QString, QString> > query = m_url.queryItems();
+ if (!query.empty()) {
+ QStringList q2;
+ for (QList<QPair<QString, QString> >::iterator i = query.begin();
+ i != query.end(); ++i) {
+ q2.push_back(QString("%1=%3")
+ .arg(QString(QUrl::toPercentEncoding(i->first)))
+ .arg(QString(QUrl::toPercentEncoding(i->second))));
+ }
+ path = QString("%1%2%3")
+ .arg(path).arg("?")
+ .arg(q2.join("&"));
+ }
+*/
+
+ // ...or, much simpler but relying on knowledge about the
+ // scheme://host/path/path/query etc format of the URL, we can
+ // get the whole URL ready-encoded and then split it on "/" as
+ // appropriate...
+
+ QString path = "/" + QString(m_url.toEncoded()).section('/', 3);
+
+ std::cerr << "RemoteFile: path is \""
+ << path.toStdString() << "\"" << std::endl;
+
+ m_http->get(path, m_localFile);
}
void
+RemoteFile::initFtp()
+{
+ m_ok = true;
+ m_ftp = new QFtp;
+ connect(m_ftp, SIGNAL(done(bool)), this, SLOT(done(bool)));
+ connect(m_ftp, SIGNAL(commandFinished(int, bool)),
+ this, SLOT(ftpCommandFinished(int, bool)));
+ connect(m_ftp, SIGNAL(dataTransferProgress(qint64, qint64)),
+ this, SLOT(dataTransferProgress(qint64, qint64)));
+ m_ftp->connectToHost(m_url.host(), m_url.port(21));
+
+ QString username = m_url.userName();
+ if (username == "") {
+ username = "anonymous";
+ }
+
+ QString password = m_url.password();
+ if (password == "") {
+ password = QString("%1@..."));
+ }
+
+ m_ftp->login(username, password);
+
+ QString dirpath = m_url.path().section('/', 0, -2);
+ QString filename = m_url.path().section('/', -1);
+
+ if (dirpath == "") dirpath = "/";
+ m_ftp->cd(dirpath);
+ m_ftp->get(filename, m_localFile);
+}
+
+void
RemoteFile::cleanup()
{
m_done = true;
@@ -216,22 +363,22 @@
bool
RemoteFile::isRemote(QString fileOrUrl)
{
- return (fileOrUrl.startsWith("http:") || fileOrUrl.startsWith("ftp:"));
+ QString scheme = QUrl(fileOrUrl).scheme().toLower();
+ return (scheme == "http" || scheme == "ftp");
}
bool
RemoteFile::canHandleScheme(QUrl url)
{
QString scheme = url.scheme().toLower();
- return (scheme == "http" || scheme == "ftp");
+ return (scheme == "http" || scheme == "ftp" ||
+ scheme == "file" || scheme == "");
}
bool
RemoteFile::isAvailable()
{
- while (m_ok && (!m_done && m_lastStatus == 0)) {
- QApplication::processEvents();
- }
+ waitForStatus();
bool available = true;
if (!m_ok) available = false;
else available = (m_lastStatus / 100 == 2);
@@ -241,13 +388,28 @@
}
void
-RemoteFile::wait()
+RemoteFile::waitForStatus()
{
+ while (m_ok && (!m_done && m_lastStatus == 0)) {
+// std::cerr << "waitForStatus: processing (last status " << m_lastStatus << ")" << std::endl;
+ QApplication::processEvents();
+ }
+}
+
+void
+RemoteFile::waitForData()
+{
while (m_ok && !m_done) {
QApplication::processEvents();
}
}
+void
+RemoteFile::setLeaveLocalFile(bool leave)
+{
+ m_leaveLocalFile = leave;
+}
+
bool
RemoteFile::isOK() const
{
@@ -260,13 +422,41 @@
return m_done;
}
+bool
+RemoteFile::isRemote() const
+{
+ return m_remote;
+}
+
QString
+RemoteFile::getLocation() const
+{
+ return m_url.toString();
+}
+
+QString
RemoteFile::getLocalFilename() const
{
return m_localFilename;
}
QString
+RemoteFile::getContentType() const
+{
+ return m_contentType;
+}
+
+QString
+RemoteFile::getExtension() const
+{
+ if (m_localFilename != "") {
+ return QFileInfo(m_localFilename).suffix().toLower();
+ } else {
+ return QFileInfo(m_url.toLocalFile()).suffix().toLower();
+ }
+}
+
+QString
RemoteFile::getErrorString() const
{
return m_errorString;
@@ -339,8 +529,9 @@
void
RemoteFile::cancelled()
{
- deleteLocalFile();
m_done = true;
+ cleanup();
+
m_ok = false;
m_errorString = tr("Download cancelled");
}
@@ -380,7 +571,8 @@
}
if (error) {
- deleteLocalFile();
+ std::cerr << "RemoteFile::done: error is " << error << ", deleting cache file" << std::endl;
+ deleteCacheFile();
}
m_ok = !error;
@@ -389,21 +581,29 @@
}
void
-RemoteFile::deleteLocalFile()
+RemoteFile::deleteCacheFile()
{
-// std::cerr << "RemoteFile::deleteLocalFile" << std::endl;
+ std::cerr << "RemoteFile::deleteCacheFile(\"" << m_localFilename.toStdString() << "\")" << std::endl;
cleanup();
- if (m_localFilename == "") return;
+ if (m_localFilename == "") {
+ return;
+ }
- if (m_referenced) {
+ if (!isRemote()) {
+ std::cerr << "not a cache file" << std::endl;
+ return;
+ }
+ if (m_refCounted) {
+
QMutexLocker locker(&m_mapMutex);
- m_referenced = false;
+ m_refCounted = false;
if (m_refCountMap[m_url] > 0) {
m_refCountMap[m_url]--;
+ std::cerr << "reduced ref count to " << m_refCountMap[m_url] << std::endl;
if (m_refCountMap[m_url] > 0) {
m_done = true;
return;
@@ -414,8 +614,9 @@
m_fileCreationMutex.lock();
if (!QFile(m_localFilename).remove()) {
- std::cerr << "RemoteFile::deleteLocalFile: ERROR: Failed to delete file \"" << m_localFilename.toStdString() << "\"" << std::endl;
+ std::cerr << "RemoteFile::deleteCacheFile: ERROR: Failed to delete file \"" << m_localFilename.toStdString() << "\"" << std::endl;
} else {
+ std::cerr << "RemoteFile::deleteCacheFile: Deleted cache file \"" << m_localFilename.toStdString() << "\"" << std::endl;
m_localFilename = "";
}
@@ -430,19 +631,33 @@
if (m_progressDialog) m_progressDialog->show();
}
-QString
-RemoteFile::createLocalFile(QUrl url)
+bool
+RemoteFile::createCacheFile()
{
+ {
+ QMutexLocker locker(&m_mapMutex);
+
+ std::cerr << "RemoteFile::createCacheFile: refcount is " << m_refCountMap[m_url] << std::endl;
+
+ if (m_refCountMap[m_url] > 0) {
+ m_refCountMap[m_url]++;
+ m_localFilename = m_remoteLocalMap[m_url];
+ std::cerr << "raised it to " << m_refCountMap[m_url] << std::endl;
+ m_refCounted = true;
+ return true;
+ }
+ }
+
QDir dir;
try {
dir = TempDirectory::getInstance()->getSubDirectoryPath("download");
} catch (DirectoryCreationFailed f) {
- std::cerr << "RemoteFile::createLocalFile: ERROR: Failed to create temporary directory: " << f.what() << std::endl;
+ std::cerr << "RemoteFile::createCacheFile: ERROR: Failed to create temporary directory: " << f.what() << std::endl;
return "";
}
- QString filepart = url.path().section('/', -1, -1,
- QString::SectionSkipEmpty);
+ QString filepart = m_url.path().section('/', -1, -1,
+ QString::SectionSkipEmpty);
QString extension = filepart.section('.', -1);
QString base = filepart;
@@ -461,17 +676,18 @@
QString filepath(dir.filePath(filename));
- std::cerr << "RemoteFile::createLocalFile: URL is \"" << url.toString().toStdString() << "\", dir is \"" << dir.path().toStdString() << "\", base \"" << base.toStdString() << "\", extension \"" << extension.toStdString() << "\", filebase \"" << filename.toStdString() << "\", filename \"" << filepath.toStdString() << "\"" << std::endl;
+ std::cerr << "RemoteFile::createCacheFile: URL is \"" << m_url.toString().toStdString() << "\", dir is \"" << dir.path().toStdString() << "\", base \"" << base.toStdString() << "\", extension \"" << extension.toStdString() << "\", filebase \"" << filename.toStdString() << "\", filename \"" << filepath.toStdString() << "\"" << std::endl;
- m_fileCreationMutex.lock();
+ QMutexLocker fcLocker(&m_fileCreationMutex);
+
++m_count;
if (QFileInfo(filepath).exists() ||
!QFile(filepath).open(QFile::WriteOnly)) {
- std::cerr << "RemoteFile::createLocalFile: Failed to create local file \""
+ std::cerr << "RemoteFile::createCacheFile: Failed to create local file \""
<< filepath.toStdString() << "\" for URL \""
- << url.toString().toStdString() << "\" (or file already exists): appending suffix instead" << std::endl;
+ << m_url.toString().toStdString() << "\" (or file already exists): appending suffix instead" << std::endl;
if (extension == "") {
@@ -484,20 +700,19 @@
if (QFileInfo(filepath).exists() ||
!QFile(filepath).open(QFile::WriteOnly)) {
- std::cerr << "RemoteFile::createLocalFile: ERROR: Failed to create local file \""
+ std::cerr << "RemoteFile::createCacheFile: ERROR: Failed to create local file \""
<< filepath.toStdString() << "\" for URL \""
- << url.toString().toStdString() << "\" (or file already exists)" << std::endl;
+ << m_url.toString().toStdString() << "\" (or file already exists)" << std::endl;
- m_fileCreationMutex.unlock();
return "";
}
}
- m_fileCreationMutex.unlock();
-
- std::cerr << "RemoteFile::createLocalFile: url "
- << url.toString().toStdString() << " -> local filename "
+ std::cerr << "RemoteFile::createCacheFile: url "
+ << m_url.toString().toStdString() << " -> local filename "
<< filepath.toStdString() << std::endl;
+
+ m_localFilename = filepath;
- return filepath;
+ return false;
}
Modified: sonic-visualiser/trunk/data/fileio/RemoteFile.h
===================================================================
--- sonic-visualiser/trunk/data/fileio/RemoteFile.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/RemoteFile.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -34,23 +34,30 @@
Q_OBJECT
public:
- RemoteFile(QUrl url);
+ RemoteFile(QString fileOrUrl, bool showProgress = true);
+ RemoteFile(QUrl url, bool showProgress = true);
+ RemoteFile(const RemoteFile &);
+
virtual ~RemoteFile();
bool isAvailable();
- void wait();
+ void waitForStatus();
+ void waitForData();
+ void setLeaveLocalFile(bool leave);
+
bool isOK() const;
bool isDone() const;
+ bool isRemote() const;
+ QString getLocation() const;
+ QString getLocalFilename() const;
QString getContentType() const;
+ QString getExtension() const;
- QString getLocalFilename() const;
QString getErrorString() const;
- void deleteLocalFile();
-
static bool isRemote(QString fileOrUrl);
static bool canHandleScheme(QUrl url);
@@ -68,6 +75,8 @@
void cancelled();
protected:
+ RemoteFile &operator=(const RemoteFile &); // not provided
+
QUrl m_url;
QFtp *m_ftp;
QHttp *m_http;
@@ -77,7 +86,9 @@
QString m_contentType;
bool m_ok;
int m_lastStatus;
+ bool m_remote;
bool m_done;
+ bool m_leaveLocalFile;
QProgressDialog *m_progressDialog;
QTimer m_progressShowTimer;
@@ -86,11 +97,18 @@
static RemoteRefCountMap m_refCountMap;
static RemoteLocalMap m_remoteLocalMap;
static QMutex m_mapMutex;
- bool m_referenced;
+ bool m_refCounted;
+ void init(bool showProgress);
+ void initHttp();
+ void initFtp();
+
void cleanup();
- QString createLocalFile(QUrl url);
+ // Create a local file for m_url. If it already existed, return true.
+ // The local filename is stored in m_localFilename.
+ bool createCacheFile();
+ void deleteCacheFile();
static QMutex m_fileCreationMutex;
static int m_count;
Modified: sonic-visualiser/trunk/data/fileio/ResamplingWavFileReader.cpp
===================================================================
--- sonic-visualiser/trunk/data/fileio/ResamplingWavFileReader.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/ResamplingWavFileReader.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -22,12 +22,13 @@
#include <QFileInfo>
#include <QApplication>
-ResamplingWavFileReader::ResamplingWavFileReader(QString path,
+ResamplingWavFileReader::ResamplingWavFileReader(RemoteFile source,
ResampleMode resampleMode,
CacheMode mode,
size_t targetRate) :
CodedAudioFileReader(mode, targetRate),
- m_path(path),
+ m_source(source),
+ m_path(source.getLocalFilename()),
m_cancelled(false),
m_processed(0),
m_completion(0),
@@ -39,11 +40,11 @@
m_fileRate = 0;
std::cerr << "ResamplingWavFileReader::ResamplingWavFileReader(\""
- << path.toStdString() << "\"): rate " << targetRate << std::endl;
+ << m_path.toStdString() << "\"): rate " << targetRate << std::endl;
Profiler profiler("ResamplingWavFileReader::ResamplingWavFileReader", true);
- m_original = new WavFileReader(path);
+ m_original = new WavFileReader(m_path);
if (!m_original->isOK()) {
m_error = m_original->getError();
return;
@@ -57,7 +58,7 @@
if (resampleMode == ResampleAtOnce) {
m_progress = new QProgressDialog
- (QObject::tr("Resampling %1...").arg(QFileInfo(path).fileName()),
+ (QObject::tr("Resampling %1...").arg(QFileInfo(m_path).fileName()),
QObject::tr("Stop"), 0, 100);
m_progress->hide();
@@ -167,4 +168,22 @@
WavFileReader::getSupportedExtensions(extensions);
}
+bool
+ResamplingWavFileReader::supportsExtension(QString extension)
+{
+ return WavFileReader::supportsExtension(extension);
+}
+bool
+ResamplingWavFileReader::supportsContentType(QString type)
+{
+ return WavFileReader::supportsContentType(type);
+}
+
+bool
+ResamplingWavFileReader::supports(RemoteFile &source)
+{
+ return WavFileReader::supports(source);
+}
+
+
Modified: sonic-visualiser/trunk/data/fileio/ResamplingWavFileReader.h
===================================================================
--- sonic-visualiser/trunk/data/fileio/ResamplingWavFileReader.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/ResamplingWavFileReader.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -33,15 +33,17 @@
ResampleThreaded // resample in a background thread after construction
};
- ResamplingWavFileReader(QString path,
+ ResamplingWavFileReader(RemoteFile source,
ResampleMode resampleMode,
CacheMode cacheMode,
size_t targetRate = 0);
virtual ~ResamplingWavFileReader();
virtual QString getError() const { return m_error; }
-
static void getSupportedExtensions(std::set<QString> &extensions);
+ static bool supportsExtension(QString ext);
+ static bool supportsContentType(QString type);
+ static bool supports(RemoteFile &source);
virtual int getDecodeCompletion() const { return m_completion; }
@@ -50,6 +52,7 @@
}
protected:
+ RemoteFile m_source;
QString m_path;
QString m_error;
bool m_cancelled;
Modified: sonic-visualiser/trunk/data/fileio/WavFileReader.cpp
===================================================================
--- sonic-visualiser/trunk/data/fileio/WavFileReader.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/WavFileReader.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -18,10 +18,12 @@
#include <iostream>
#include <QMutexLocker>
+#include <QFileInfo>
-WavFileReader::WavFileReader(QString path, bool fileUpdating) :
+WavFileReader::WavFileReader(RemoteFile source, bool fileUpdating) :
m_file(0),
- m_path(path),
+ m_source(source),
+ m_path(source.getLocalFilename()),
m_buffer(0),
m_bufsiz(0),
m_lastStart(0),
@@ -171,6 +173,7 @@
if (sf_command(0, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof(count))) {
extensions.insert("wav");
extensions.insert("aiff");
+ extensions.insert("aifc");
extensions.insert("aif");
return;
}
@@ -179,7 +182,32 @@
for (int i = 0; i < count; ++i) {
info.format = i;
if (!sf_command(0, SFC_GET_FORMAT_MAJOR, &info, sizeof(info))) {
- extensions.insert(info.extension);
+ extensions.insert(QString(info.extension).toLower());
}
}
}
+
+bool
+WavFileReader::supportsExtension(QString extension)
+{
+ std::set<QString> extensions;
+ getSupportedExtensions(extensions);
+ return (extensions.find(extension.toLower()) != extensions.end());
+}
+
+bool
+WavFileReader::supportsContentType(QString type)
+{
+ return (type == "audio/x-wav" ||
+ type == "audio/x-aiff" ||
+ type == "audio/basic");
+}
+
+bool
+WavFileReader::supports(RemoteFile &source)
+{
+ return (supportsExtension(source.getExtension()) ||
+ supportsContentType(source.getContentType()));
+}
+
+
Modified: sonic-visualiser/trunk/data/fileio/WavFileReader.h
===================================================================
--- sonic-visualiser/trunk/data/fileio/WavFileReader.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/fileio/WavFileReader.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -26,7 +26,7 @@
class WavFileReader : public AudioFileReader
{
public:
- WavFileReader(QString path, bool fileUpdating = false);
+ WavFileReader(RemoteFile source, bool fileUpdating = false);
virtual ~WavFileReader();
virtual QString getError() const { return m_error; }
@@ -39,6 +39,9 @@
SampleBlock &frames) const;
static void getSupportedExtensions(std::set<QString> &extensions);
+ static bool supportsExtension(QString ext);
+ static bool supportsContentType(QString type);
+ static bool supports(RemoteFile &source);
virtual int getDecodeCompletion() const { return 100; }
@@ -51,6 +54,7 @@
SF_INFO m_fileInfo;
SNDFILE *m_file;
+ RemoteFile m_source;
QString m_path;
QString m_error;
Modified: sonic-visualiser/trunk/data/model/WaveFileModel.cpp
===================================================================
--- sonic-visualiser/trunk/data/model/WaveFileModel.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/model/WaveFileModel.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -39,8 +39,9 @@
PowerOfSqrtTwoZoomConstraint
WaveFileModel::m_zoomConstraint;
-WaveFileModel::WaveFileModel(QString path, size_t targetRate) :
- m_path(path),
+WaveFileModel::WaveFileModel(RemoteFile source, size_t targetRate) :
+ m_source(source),
+ m_path(source.getLocation()),
m_myReader(true),
m_startFrame(0),
m_fillThread(0),
@@ -48,31 +49,22 @@
m_lastFillExtent(0),
m_exiting(false)
{
- m_reader = AudioFileReaderFactory::createReader(path, targetRate);
- if (m_reader) std::cerr << "WaveFileModel::WaveFileModel: reader rate: " << m_reader->getSampleRate() << std::endl;
+ m_source.waitForData();
+ if (m_source.isOK()) {
+ m_reader = AudioFileReaderFactory::createReader(m_source, targetRate);
+ if (m_reader) {
+ std::cerr << "WaveFileModel::WaveFileModel: reader rate: "
+ << m_reader->getSampleRate() << std::endl;
+ }
+ }
if (m_reader) setObjectName(m_reader->getTitle());
- if (objectName() == "") setObjectName(QFileInfo(path).fileName());
+ if (objectName() == "") setObjectName(QFileInfo(m_path).fileName());
if (isOK()) fillCache();
}
-WaveFileModel::WaveFileModel(QString path, QString originalLocation, size_t targetRate) :
- m_path(originalLocation),
- m_myReader(true),
- m_startFrame(0),
- m_fillThread(0),
- m_updateTimer(0),
- m_lastFillExtent(0),
- m_exiting(false)
-{
- m_reader = AudioFileReaderFactory::createReader(path, targetRate);
- if (m_reader) std::cerr << "WaveFileModel::WaveFileModel: reader rate: " << m_reader->getSampleRate() << std::endl;
- if (m_reader) setObjectName(m_reader->getTitle());
- if (objectName() == "") setObjectName(QFileInfo(originalLocation).fileName());
- if (isOK()) fillCache();
-}
-
-WaveFileModel::WaveFileModel(QString path, AudioFileReader *reader) :
- m_path(path),
+WaveFileModel::WaveFileModel(RemoteFile source, AudioFileReader *reader) :
+ m_source(source),
+ m_path(source.getLocation()),
m_myReader(false),
m_startFrame(0),
m_fillThread(0),
@@ -82,7 +74,7 @@
{
m_reader = reader;
if (m_reader) setObjectName(m_reader->getTitle());
- if (objectName() == "") setObjectName(QFileInfo(path).fileName());
+ if (objectName() == "") setObjectName(QFileInfo(m_path).fileName());
fillCache();
}
@@ -131,7 +123,7 @@
Model *
WaveFileModel::clone() const
{
- WaveFileModel *model = new WaveFileModel(m_path);
+ WaveFileModel *model = new WaveFileModel(m_source);
return model;
}
Modified: sonic-visualiser/trunk/data/model/WaveFileModel.h
===================================================================
--- sonic-visualiser/trunk/data/model/WaveFileModel.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/model/WaveFileModel.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -20,6 +20,8 @@
#include <QMutex>
#include <QTimer>
+#include "data/fileio/RemoteFile.h"
+
#include "RangeSummarisableTimeValueModel.h"
#include "PowerOfSqrtTwoZoomConstraint.h"
@@ -32,9 +34,8 @@
Q_OBJECT
public:
- WaveFileModel(QString path, size_t targetRate = 0);
- WaveFileModel(QString path, QString originalLocation, size_t targetRate = 0);
- WaveFileModel(QString originalLocation, AudioFileReader *reader);
+ WaveFileModel(RemoteFile source, size_t targetRate = 0);
+ WaveFileModel(RemoteFile source, AudioFileReader *reader);
~WaveFileModel();
bool isOK() const;
@@ -102,7 +103,8 @@
};
void fillCache();
-
+
+ RemoteFile m_source;
QString m_path;
AudioFileReader *m_reader;
bool m_myReader;
Modified: sonic-visualiser/trunk/data/model/WritableWaveFileModel.cpp
===================================================================
--- sonic-visualiser/trunk/data/model/WritableWaveFileModel.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/data/model/WritableWaveFileModel.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -60,7 +60,9 @@
return;
}
- m_reader = new WavFileReader(m_writer->getPath(), true);
+ RemoteFile source(m_writer->getPath());
+
+ m_reader = new WavFileReader(source, true);
if (!m_reader->getError().isEmpty()) {
std::cerr << "WritableWaveFileModel: Error in creating wave file reader" << std::endl;
delete m_reader;
@@ -68,7 +70,7 @@
return;
}
- m_model = new WaveFileModel(m_writer->getPath(), m_reader);
+ m_model = new WaveFileModel(source, m_reader);
if (!m_model->isOK()) {
std::cerr << "WritableWaveFileModel: Error in creating wave file model" << std::endl;
delete m_model;
Modified: sonic-visualiser/trunk/layer/ImageLayer.cpp
===================================================================
--- sonic-visualiser/trunk/layer/ImageLayer.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/layer/ImageLayer.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -892,16 +892,13 @@
return;
}
- QUrl url(img);
- if (RemoteFile::canHandleScheme(url)) {
- RemoteFile *rf = new RemoteFile(url);
- if (rf->isOK()) {
- std::cerr << "ok, adding it (local filename = " << rf->getLocalFilename().toStdString() << ")" << std::endl;
- m_remoteFiles[img] = rf;
- connect(rf, SIGNAL(ready()), this, SLOT(remoteFileReady()));
- } else {
- delete rf;
- }
+ RemoteFile *rf = new RemoteFile(img);
+ if (rf->isOK()) {
+ std::cerr << "ok, adding it (local filename = " << rf->getLocalFilename().toStdString() << ")" << std::endl;
+ m_remoteFiles[img] = rf;
+ connect(rf, SIGNAL(ready()), this, SLOT(remoteFileReady()));
+ } else {
+ delete rf;
}
}
}
Modified: sonic-visualiser/trunk/sv/document/SVFileReader.cpp
===================================================================
--- sonic-visualiser/trunk/sv/document/SVFileReader.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/sv/document/SVFileReader.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -412,25 +412,18 @@
QString originalPath = attributes.value("file");
QString path = ff->find(FileFinder::AudioFile,
originalPath, m_location);
- QUrl url(path);
- if (RemoteFile::canHandleScheme(url)) {
+ RemoteFile file(path);
+ file.waitForStatus();
- RemoteFile rf(url);
- rf.wait();
-
- if (rf.isOK()) {
-
- model = new WaveFileModel(rf.getLocalFilename(), path);
- if (!model->isOK()) {
- delete model;
- model = 0;
- //!!! and delete local file?
- }
- }
+ if (!file.isOK()) {
+ std::cerr << "SVFileReader::readModel: Failed to retrieve file \"" << path.toStdString() << "\" for wave file model: " << file.getErrorString().toStdString() << std::endl;
+ } else if (!file.isAvailable()) {
+ std::cerr << "SVFileReader::readModel: Failed to retrieve file \"" << path.toStdString() << "\" for wave file model: Source unavailable" << std::endl;
} else {
- model = new WaveFileModel(path);
+ file.waitForData();
+ model = new WaveFileModel(file);
if (!model->isOK()) {
delete model;
model = 0;
Modified: sonic-visualiser/trunk/sv/main/MainWindow.cpp
===================================================================
--- sonic-visualiser/trunk/sv/main/MainWindow.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/sv/main/MainWindow.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -2525,7 +2525,7 @@
QString path = getOpenFileName(FileFinder::AudioFile);
if (path != "") {
- if (openAudioFile(path, ReplaceMainModel) == FileOpenFailed) {
+ if (openAudio(path, ReplaceMainModel) == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open file"),
tr("<b>File open failed</b><p>Audio file \"%1\" could not be opened").arg(path));
}
@@ -2538,7 +2538,7 @@
QString path = getOpenFileName(FileFinder::AudioFile);
if (path != "") {
- if (openAudioFile(path, CreateAdditionalModel) == FileOpenFailed) {
+ if (openAudio(path, CreateAdditionalModel) == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open file"),
tr("<b>File open failed</b><p>Audio file \"%1\" could not be opened").arg(path));
}
@@ -2673,7 +2673,7 @@
if (path != "") {
- FileOpenStatus status = openLayerFile(path);
+ FileOpenStatus status = openLayer(path);
if (status == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open file"),
@@ -2686,154 +2686,6 @@
}
}
-MainWindow::FileOpenStatus
-MainWindow::openLayerFile(QString path)
-{
- return openLayerFile(path, path);
-}
-
-MainWindow::FileOpenStatus
-MainWindow::openLayerFile(QString path, QString location)
-{
- Pane *pane = m_paneStack->getCurrentPane();
-
- if (!pane) {
- // shouldn't happen, as the menu action should have been disabled
- std::cerr << "WARNING: MainWindow::openLayerFile: no current pane" << std::endl;
- return FileOpenWrongMode;
- }
-
- if (!getMainModel()) {
- // shouldn't happen, as the menu action should have been disabled
- std::cerr << "WARNING: MainWindow::openLayerFile: No main model -- hence no default sample rate available" << std::endl;
- return FileOpenWrongMode;
- }
-
- bool realFile = (location == path);
-
- if (path.endsWith(".svl") || path.endsWith(".xml")) {
-
- PaneCallback callback(this);
- QFile file(path);
-
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- std::cerr << "ERROR: MainWindow::openLayerFile("
- << location.toStdString()
- << "): Failed to open file for reading" << std::endl;
- return FileOpenFailed;
- }
-
- SVFileReader reader(m_document, callback, location);
- reader.setCurrentPane(pane);
-
- QXmlInputSource inputSource(&file);
- reader.parse(inputSource);
-
- if (!reader.isOK()) {
- std::cerr << "ERROR: MainWindow::openLayerFile("
- << location.toStdString()
- << "): Failed to read XML file: "
- << reader.getErrorString().toStdString() << std::endl;
- return FileOpenFailed;
- }
-
- m_recentFiles.addFile(location);
-
- if (realFile) {
- registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog
- }
-
- return FileOpenSucceeded;
-
- } else {
-
- try {
-
- Model *model = DataFileReaderFactory::load
- (path, getMainModel()->getSampleRate());
-
- if (model) {
-
- Layer *newLayer = m_document->createImportedLayer(model);
-
- if (newLayer) {
-
- m_document->addLayerToView(pane, newLayer);
- m_recentFiles.addFile(location);
-
- if (realFile) {
- registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog
- }
-
- return FileOpenSucceeded;
- }
- }
- } catch (DataFileReaderFactory::Exception e) {
- if (e == DataFileReaderFactory::ImportCancelled) {
- return FileOpenCancelled;
- }
- }
- }
-
- return FileOpenFailed;
-}
-
-MainWindow::FileOpenStatus
-MainWindow::openImageFile(QString path)
-{
- return openImageFile(path, path);
-}
-
-MainWindow::FileOpenStatus
-MainWindow::openImageFile(QString path, QString location)
-{
- Pane *pane = m_paneStack->getCurrentPane();
-
- if (!pane) {
- // shouldn't happen, as the menu action should have been disabled
- std::cerr << "WARNING: MainWindow::openImageFile: no current pane" << std::endl;
- return FileOpenWrongMode;
- }
-
- if (!m_document->getMainModel()) {
- return FileOpenWrongMode;
- }
-
- bool newLayer = false;
-
- ImageLayer *il = dynamic_cast<ImageLayer *>(pane->getSelectedLayer());
- if (!il) {
- for (int i = pane->getLayerCount()-1; i >= 0; --i) {
- il = dynamic_cast<ImageLayer *>(pane->getLayer(i));
- if (il) break;
- }
- }
- if (!il) {
- il = dynamic_cast<ImageLayer *>
- (m_document->createEmptyLayer(LayerFactory::Image));
- if (!il) return FileOpenFailed;
- newLayer = true;
- }
-
- // We don't put the image file in Recent Files
-
- std::cerr << "openImageFile: trying location \"" << location.toStdString() << "\" in image layer" << std::endl;
-
- if (!il->addImage(m_viewManager->getGlobalCentreFrame(), location)) {
- if (newLayer) {
- m_document->setModel(il, 0); // releasing its model
- delete il;
- }
- return FileOpenFailed;
- } else {
- if (newLayer) {
- m_document->addLayerToView(pane, il);
- }
- m_paneStack->setCurrentLayer(pane, il);
- return FileOpenSucceeded;
- }
-}
-
void
MainWindow::exportLayer()
{
@@ -3006,20 +2858,48 @@
}
MainWindow::FileOpenStatus
-MainWindow::openAudioFile(QString path, AudioFileOpenMode mode)
+MainWindow::open(QString fileOrUrl, AudioFileOpenMode mode)
{
- return openAudioFile(path, path, mode);
+ return open(RemoteFile(fileOrUrl), mode);
}
MainWindow::FileOpenStatus
-MainWindow::openAudioFile(QString path, QString location, AudioFileOpenMode mode)
+MainWindow::open(RemoteFile source, AudioFileOpenMode mode)
{
- if (!(QFileInfo(path).exists() &&
- QFileInfo(path).isFile() &&
- QFileInfo(path).isReadable())) {
+ FileOpenStatus status;
+
+ if (!source.isAvailable()) return FileOpenFailed;
+ source.waitForData();
+
+ bool canImportLayer = (getMainModel() != 0 &&
+ m_paneStack != 0 &&
+ m_paneStack->getCurrentPane() != 0);
+
+ if ((status = openAudio(source, mode)) != FileOpenFailed) {
+ return status;
+ } else if ((status = openSession(source)) != FileOpenFailed) {
+ return status;
+ } else if ((status = openPlaylist(source, mode)) != FileOpenFailed) {
+ return status;
+ } else if (!canImportLayer) {
+ return FileOpenWrongMode;
+ } else if ((status = openImage(source)) != FileOpenFailed) {
+ return status;
+ } else if ((status = openLayer(source)) != FileOpenFailed) {
+ return status;
+ } else {
return FileOpenFailed;
}
+}
+MainWindow::FileOpenStatus
+MainWindow::openAudio(RemoteFile source, AudioFileOpenMode mode)
+{
+ std::cerr << "MainWindow::openAudio(" << source.getLocation().toStdString() << ")" << std::endl;
+
+ if (!source.isAvailable()) return FileOpenFailed;
+ source.waitForData();
+
m_openingAudioFile = true;
size_t rate = 0;
@@ -3028,7 +2908,7 @@
rate = m_playSource->getSourceSampleRate();
}
- WaveFileModel *newModel = new WaveFileModel(path, location, rate);
+ WaveFileModel *newModel = new WaveFileModel(source, rate);
if (!newModel->isOK()) {
delete newModel;
@@ -3036,15 +2916,11 @@
return FileOpenFailed;
}
- bool realFile = (location == path);
-
std::cerr << "mode = " << mode << std::endl;
if (mode == AskUser) {
if (getMainModel()) {
- std::cerr << "ask user, have main model" << std::endl;
-
static bool prevSetAsMain = true;
bool setAsMain = true;
@@ -3077,37 +2953,25 @@
if (mode == ReplaceCurrentPane) {
-// std::cerr << "replace current pane" << std::endl;
-
Pane *pane = m_paneStack->getCurrentPane();
if (pane) {
-// std::cerr << "have pane" << std::endl;
-
if (getMainModel()) {
-// std::cerr << "have main model" << std::endl;
-
View::ModelSet models(pane->getModels());
if (models.find(getMainModel()) != models.end()) {
-// std::cerr << "main model is in pane, setting to ReplaceMainModel" << std::endl;
mode = ReplaceMainModel;
}
} else {
-// std::cerr << "no main model, setting to ReplaceMainModel" << std::endl;
mode = ReplaceMainModel;
}
} else {
-// std::cerr << "no pane, setting to CreateAdditionalModel" << std::endl;
mode = CreateAdditionalModel;
}
}
if (mode == CreateAdditionalModel && !getMainModel()) {
-// std::cerr << "mode is CreateAdditionalModel and no main model, setting to ReplaceMainModel" << std::endl;
mode = ReplaceMainModel;
}
-// std::cerr << "mode now " << mode << std::endl;
-
if (mode == ReplaceMainModel) {
Model *prevMain = getMainModel();
@@ -3122,26 +2986,26 @@
if (m_sessionFile == "") {
setWindowTitle(tr("Sonic Visualiser: %1")
- .arg(QFileInfo(location).fileName()));
+ .arg(source.getLocation()));
CommandHistory::getInstance()->clear();
CommandHistory::getInstance()->documentSaved();
m_documentModified = false;
} else {
setWindowTitle(tr("Sonic Visualiser: %1 [%2]")
.arg(QFileInfo(m_sessionFile).fileName())
- .arg(QFileInfo(location).fileName()));
+ .arg(source.getLocation()));
if (m_documentModified) {
m_documentModified = false;
documentModified(); // so as to restore "(modified)" window title
}
}
- if (realFile) m_audioFile = path;
+ if (!source.isRemote()) m_audioFile = source.getLocalFilename();
} else if (mode == CreateAdditionalModel) {
CommandHistory::getInstance()->startCompoundOperation
- (tr("Import \"%1\"").arg(QFileInfo(location).fileName()), true);
+ (tr("Import \"%1\"").arg(source.getLocation()), true);
m_document->addImportedModel(newModel);
@@ -3185,7 +3049,7 @@
}
CommandHistory::getInstance()->startCompoundOperation
- (tr("Import \"%1\"").arg(QFileInfo(location).fileName()), true);
+ (tr("Import \"%1\"").arg(source.getLocation()), true);
m_document->addImportedModel(newModel);
@@ -3203,9 +3067,11 @@
}
updateMenuStates();
- m_recentFiles.addFile(location);
- if (realFile) {
- registerLastOpenedFilePath(FileFinder::AudioFile, path); // for file dialog
+ m_recentFiles.addFile(source.getLocation());
+ if (!source.isRemote()) {
+ // for file dialog
+ registerLastOpenedFilePath(FileFinder::AudioFile,
+ source.getLocalFilename());
}
m_openingAudioFile = false;
@@ -3215,26 +3081,17 @@
}
MainWindow::FileOpenStatus
-MainWindow::openPlaylistFile(QString path, AudioFileOpenMode mode)
+MainWindow::openPlaylist(RemoteFile source, AudioFileOpenMode mode)
{
- return openPlaylistFile(path, path, mode);
-}
-
-MainWindow::FileOpenStatus
-MainWindow::openPlaylistFile(QString path, QString location, AudioFileOpenMode mode)
-{
- if (!(QFileInfo(path).exists() &&
- QFileInfo(path).isFile() &&
- QFileInfo(path).isReadable())) {
- return FileOpenFailed;
- }
-
std::set<QString> extensions;
PlaylistFileReader::getSupportedExtensions(extensions);
- QString extension = QFileInfo(path).suffix();
+ QString extension = source.getExtension();
if (extensions.find(extension) == extensions.end()) return FileOpenFailed;
- PlaylistFileReader reader(path);
+ if (!source.isAvailable()) return FileOpenFailed;
+ source.waitForData();
+
+ PlaylistFileReader reader(source.getLocalFilename());
if (!reader.isOK()) return FileOpenFailed;
PlaylistFileReader::Playlist playlist = reader.load();
@@ -3244,7 +3101,7 @@
for (PlaylistFileReader::Playlist::const_iterator i = playlist.begin();
i != playlist.end(); ++i) {
- FileOpenStatus status = openURL(*i, mode);
+ FileOpenStatus status = openAudio(*i, mode);
if (status == FileOpenCancelled) {
return FileOpenCancelled;
@@ -3260,6 +3117,206 @@
else return FileOpenFailed;
}
+MainWindow::FileOpenStatus
+MainWindow::openLayer(RemoteFile source)
+{
+ Pane *pane = m_paneStack->getCurrentPane();
+
+ if (!pane) {
+ // shouldn't happen, as the menu action should have been disabled
+ std::cerr << "WARNING: MainWindow::openLayer: no current pane" << std::endl;
+ return FileOpenWrongMode;
+ }
+
+ if (!getMainModel()) {
+ // shouldn't happen, as the menu action should have been disabled
+ std::cerr << "WARNING: MainWindow::openLayer: No main model -- hence no default sample rate available" << std::endl;
+ return FileOpenWrongMode;
+ }
+
+ if (!source.isAvailable()) return FileOpenFailed;
+ source.waitForData();
+
+ QString path = source.getLocalFilename();
+
+ if (source.getExtension() == "svl" || source.getExtension() == "xml") {
+
+ PaneCallback callback(this);
+ QFile file(path);
+
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ std::cerr << "ERROR: MainWindow::openLayer("
+ << source.getLocation().toStdString()
+ << "): Failed to open file for reading" << std::endl;
+ return FileOpenFailed;
+ }
+
+ SVFileReader reader(m_document, callback, source.getLocation());
+ reader.setCurrentPane(pane);
+
+ QXmlInputSource inputSource(&file);
+ reader.parse(inputSource);
+
+ if (!reader.isOK()) {
+ std::cerr << "ERROR: MainWindow::openLayer("
+ << source.getLocation().toStdString()
+ << "): Failed to read XML file: "
+ << reader.getErrorString().toStdString() << std::endl;
+ return FileOpenFailed;
+ }
+
+ m_recentFiles.addFile(source.getLocation());
+
+ if (!source.isRemote()) {
+ registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog
+ }
+
+ } else {
+
+ try {
+
+ Model *model = DataFileReaderFactory::load
+ (path, getMainModel()->getSampleRate());
+
+ if (model) {
+
+ Layer *newLayer = m_document->createImportedLayer(model);
+
+ if (newLayer) {
+
+ m_document->addLayerToView(pane, newLayer);
+ m_recentFiles.addFile(source.getLocation());
+
+ if (!source.isRemote()) {
+ registerLastOpenedFilePath
+ (FileFinder::LayerFile,
+ path); // for file dialog
+ }
+
+ return FileOpenSucceeded;
+ }
+ }
+ } catch (DataFileReaderFactory::Exception e) {
+ if (e == DataFileReaderFactory::ImportCancelled) {
+ return FileOpenCancelled;
+ }
+ }
+ }
+
+ source.setLeaveLocalFile(true);
+ return FileOpenFailed;
+}
+
+MainWindow::FileOpenStatus
+MainWindow::openImage(RemoteFile source)
+{
+ Pane *pane = m_paneStack->getCurrentPane();
+
+ if (!pane) {
+ // shouldn't happen, as the menu action should have been disabled
+ std::cerr << "WARNING: MainWindow::openImage: no current pane" << std::endl;
+ return FileOpenWrongMode;
+ }
+
+ if (!m_document->getMainModel()) {
+ return FileOpenWrongMode;
+ }
+
+ bool newLayer = false;
+
+ ImageLayer *il = dynamic_cast<ImageLayer *>(pane->getSelectedLayer());
+ if (!il) {
+ for (int i = pane->getLayerCount()-1; i >= 0; --i) {
+ il = dynamic_cast<ImageLayer *>(pane->getLayer(i));
+ if (il) break;
+ }
+ }
+ if (!il) {
+ il = dynamic_cast<ImageLayer *>
+ (m_document->createEmptyLayer(LayerFactory::Image));
+ if (!il) return FileOpenFailed;
+ newLayer = true;
+ }
+
+ // We don't put the image file in Recent Files
+
+ std::cerr << "openImage: trying location \"" << source.getLocation().toStdString() << "\" in image layer" << std::endl;
+
+ if (!il->addImage(m_viewManager->getGlobalCentreFrame(), source.getLocation())) {
+ if (newLayer) {
+ m_document->setModel(il, 0); // releasing its model
+ delete il;
+ }
+ return FileOpenFailed;
+ } else {
+ if (newLayer) {
+ m_document->addLayerToView(pane, il);
+ }
+ m_paneStack->setCurrentLayer(pane, il);
+ }
+
+ return FileOpenSucceeded;
+}
+
+MainWindow::FileOpenStatus
+MainWindow::openSession(RemoteFile source)
+{
+ if (!source.isAvailable()) return FileOpenFailed;
+ if (source.getExtension() != "sv") return FileOpenFailed;
+ source.waitForData();
+
+ BZipFileDevice bzFile(source.getLocalFilename());
+ if (!bzFile.open(QIODevice::ReadOnly)) return FileOpenFailed;
+
+ if (!checkSaveModified()) return FileOpenCancelled;
+
+ QString error;
+ closeSession();
+ createDocument();
+
+ PaneCallback callback(this);
+ m_viewManager->clearSelections();
+
+ SVFileReader reader(m_document, callback, source.getLocation());
+ QXmlInputSource inputSource(&bzFile);
+ reader.parse(inputSource);
+
+ if (!reader.isOK()) {
+ error = tr("SV XML file read error:\n%1").arg(reader.getErrorString());
+ }
+
+ bzFile.close();
+
+ bool ok = (error == "");
+
+ if (ok) {
+
+ setWindowTitle(tr("Sonic Visualiser: %1")
+ .arg(source.getLocation()));
+
+ if (!source.isRemote()) m_sessionFile = source.getLocalFilename();
+
+ setupMenus();
+ CommandHistory::getInstance()->clear();
+ CommandHistory::getInstance()->documentSaved();
+ m_documentModified = false;
+ updateMenuStates();
+
+ m_recentFiles.addFile(source.getLocation());
+
+ if (!source.isRemote()) {
+ // for file dialog
+ registerLastOpenedFilePath(FileFinder::SessionFile,
+ source.getLocalFilename());
+ }
+
+ } else {
+ setWindowTitle(tr("Sonic Visualiser"));
+ }
+
+ return ok ? FileOpenSucceeded : FileOpenFailed;
+}
+
void
MainWindow::createPlayTarget()
{
@@ -3406,7 +3463,7 @@
if (path.isEmpty()) return;
- if (openSessionFile(path) == FileOpenFailed) {
+ if (openSession(path) == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open file"),
tr("<b>File open failed</b><p>Session file \"%1\" could not be opened").arg(path));
}
@@ -3423,7 +3480,7 @@
if (path.isEmpty()) return;
- FileOpenStatus status = openSomeFile(path, AskUser);
+ FileOpenStatus status = open(path, AskUser);
if (status == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open file"),
@@ -3453,7 +3510,7 @@
if (text.isEmpty()) return;
- FileOpenStatus status = openURL(QUrl(text));
+ FileOpenStatus status = open(text);
if (status == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open location"),
@@ -3479,7 +3536,7 @@
QString path = action->text();
if (path == "") return;
- FileOpenStatus status = openURL(path);
+ FileOpenStatus status = open(path);
if (status == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open location"),
@@ -3490,186 +3547,6 @@
}
}
-MainWindow::FileOpenStatus
-MainWindow::openURL(QUrl url, AudioFileOpenMode mode)
-{
- if (url.scheme().toLower() == "file" || url.scheme() == "") {
-
- return openSomeFile(url.toLocalFile(), mode);
-
- } else if (!RemoteFile::canHandleScheme(url)) {
-
- QMessageBox::critical(this, tr("Unsupported scheme in URL"),
- tr("<b>Download failed</b><p>The URL scheme \"%1\" is not supported")
- .arg(url.scheme()));
- return FileOpenFailed;
-
- } else {
- RemoteFile rf(url);
- rf.wait();
- if (!rf.isOK()) {
- QMessageBox::critical(this, tr("File download failed"),
- tr("<b>Download failed</b><p>Failed to download URL \"%1\": %2")
- .arg(url.toString()).arg(rf.getErrorString()));
- return FileOpenFailed;
- }
- FileOpenStatus status;
- if ((status = openSomeFile(rf.getLocalFilename(), url.toString(),
- mode)) !=
- FileOpenSucceeded) {
- rf.deleteLocalFile();
- }
- return status;
- }
-}
-
-MainWindow::FileOpenStatus
-MainWindow::openURL(QString ustr, AudioFileOpenMode mode)
-{
- // This function is used when we don't know whether the string is
- // an encoded or human-readable url
-
- QUrl url(ustr);
-
- if (url.scheme().toLower() == "file" || url.scheme() == "") {
-
- FileOpenStatus status = openSomeFile(url.toLocalFile(), mode);
- if (status == FileOpenFailed) {
- url.setEncodedUrl(ustr.toAscii());
- status = openSomeFile(url.toLocalFile(), mode);
- }
- return status;
-
- } else if (!RemoteFile::canHandleScheme(url)) {
-
- QMessageBox::critical(this, tr("Unsupported scheme in URL"),
- tr("<b>Download failed</b><p>The URL scheme \"%1\" is not supported")
- .arg(url.scheme()));
- return FileOpenFailed;
-
- } else {
- RemoteFile rf(url);
- rf.wait();
- if (!rf.isOK()) {
- // rf was created on the assumption that ustr was
- // human-readable. Let's try again, this time assuming it
- // was already encoded.
- std::cerr << "MainWindow::openURL: Failed to retrieve URL \""
- << ustr.toStdString() << "\" as human-readable URL; "
- << "trying again treating it as encoded URL"
- << std::endl;
- url.setEncodedUrl(ustr.toAscii());
- return openURL(url, mode);
- }
-
- FileOpenStatus status;
- if ((status = openSomeFile(rf.getLocalFilename(), ustr, mode)) !=
- FileOpenSucceeded) {
- rf.deleteLocalFile();
- }
- return status;
- }
-}
-
-MainWindow::FileOpenStatus
-MainWindow::openSomeFile(QString path, AudioFileOpenMode mode)
-{
- return openSomeFile(path, path, mode);
-}
-
-MainWindow::FileOpenStatus
-MainWindow::openSomeFile(QString path, QString location,
- AudioFileOpenMode mode)
-{
- FileOpenStatus status;
-
- bool canImportLayer = (getMainModel() != 0 &&
- m_paneStack != 0 &&
- m_paneStack->getCurrentPane() != 0);
-
- if ((status = openPlaylistFile(path, location, mode)) != FileOpenFailed) {
- return status;
- } else if ((status = openAudioFile(path, location, mode)) != FileOpenFailed) {
- return status;
- } else if (QFileInfo(path).suffix().toLower() == "sv" &&
- (status = openSessionFile(path, location)) != FileOpenFailed) {
- return status;
- } else if (!canImportLayer) {
- return FileOpenWrongMode;
- } else if ((status = openImageFile(path, location)) != FileOpenFailed) {
- return status;
- } else if ((status = openLayerFile(path, location)) != FileOpenFailed) {
- return status;
- } else {
- return FileOpenFailed;
- }
-}
-
-MainWindow::FileOpenStatus
-MainWindow::openSessionFile(QString path)
-{
- return openSessionFile(path, path);
-}
-
-MainWindow::FileOpenStatus
-MainWindow::openSessionFile(QString path, QString location)
-{
- BZipFileDevice bzFile(path);
- if (!bzFile.open(QIODevice::ReadOnly)) {
- std::cerr << "Failed to open session file \"" << location.toStdString()
- << "\": " << bzFile.errorString().toStdString() << std::endl;
- return FileOpenFailed;
- }
-
- if (!checkSaveModified()) return FileOpenCancelled;
-
- QString error;
- closeSession();
- createDocument();
-
- PaneCallback callback(this);
- m_viewManager->clearSelections();
-
- SVFileReader reader(m_document, callback, location);
- QXmlInputSource inputSource(&bzFile);
- reader.parse(inputSource);
-
- if (!reader.isOK()) {
- error = tr("SV XML file read error:\n%1").arg(reader.getErrorString());
- }
-
- bzFile.close();
-
- bool ok = (error == "");
-
- bool realFile = (location == path);
-
- if (ok) {
-
- setWindowTitle(tr("Sonic Visualiser: %1")
- .arg(QFileInfo(location).fileName()));
-
- if (realFile) m_sessionFile = path;
-
- setupMenus();
- CommandHistory::getInstance()->clear();
- CommandHistory::getInstance()->documentSaved();
- m_documentModified = false;
- updateMenuStates();
-
- m_recentFiles.addFile(location);
-
- if (realFile) {
- registerLastOpenedFilePath(FileFinder::SessionFile, path); // for file dialog
- }
-
- } else {
- setWindowTitle(tr("Sonic Visualiser"));
- }
-
- return ok ? FileOpenSucceeded : FileOpenFailed;
-}
-
void
MainWindow::paneDropAccepted(Pane *pane, QStringList uriList)
{
@@ -3677,7 +3554,7 @@
for (QStringList::iterator i = uriList.begin(); i != uriList.end(); ++i) {
- FileOpenStatus status = openURL(*i, ReplaceCurrentPane);
+ FileOpenStatus status = open(*i, ReplaceCurrentPane);
if (status == FileOpenFailed) {
QMessageBox::critical(this, tr("Failed to open dropped URL"),
@@ -5057,7 +4934,7 @@
if (message.getArgCount() == 1 &&
message.getArg(0).canConvert(QVariant::String)) {
QString path = message.getArg(0).toString();
- if (openSomeFile(path, ReplaceMainModel) != FileOpenSucceeded) {
+ if (open(path, ReplaceMainModel) != FileOpenSucceeded) {
std::cerr << "MainWindow::handleOSCMessage: File open failed for path \""
<< path.toStdString() << "\"" << std::endl;
}
@@ -5070,7 +4947,7 @@
if (message.getArgCount() == 1 &&
message.getArg(0).canConvert(QVariant::String)) {
QString path = message.getArg(0).toString();
- if (openSomeFile(path, CreateAdditionalModel) != FileOpenSucceeded) {
+ if (open(path, CreateAdditionalModel) != FileOpenSucceeded) {
std::cerr << "MainWindow::handleOSCMessage: File open failed for path \""
<< path.toStdString() << "\"" << std::endl;
}
@@ -5087,7 +4964,7 @@
}
std::vector<QString> recent = m_recentFiles.getRecent();
if (n >= 0 && n < int(recent.size())) {
- if (openSomeFile(recent[n], ReplaceMainModel) != FileOpenSucceeded) {
+ if (open(recent[n], ReplaceMainModel) != FileOpenSucceeded) {
std::cerr << "MainWindow::handleOSCMessage: File open failed for path \""
<< recent[n].toStdString() << "\"" << std::endl;
}
Modified: sonic-visualiser/trunk/sv/main/MainWindow.h
===================================================================
--- sonic-visualiser/trunk/sv/main/MainWindow.h 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/sv/main/MainWindow.h 2007-10-18 15:31:20 UTC (rev 788)
@@ -30,6 +30,7 @@
#include "transform/Transform.h"
#include "document/SVFileReader.h"
#include "data/fileio/FileFinder.h"
+#include "data/fileio/RemoteFile.h"
#include <map>
class Document;
@@ -80,15 +81,15 @@
FileOpenWrongMode // attempted to open layer when no main model present
};
- FileOpenStatus openSomeFile(QString path, AudioFileOpenMode = AskUser);
- FileOpenStatus openAudioFile(QString path, AudioFileOpenMode = AskUser);
- FileOpenStatus openPlaylistFile(QString path, AudioFileOpenMode = AskUser);
- FileOpenStatus openLayerFile(QString path);
- FileOpenStatus openImageFile(QString path);
- FileOpenStatus openSessionFile(QString path);
- FileOpenStatus openURL(QUrl url, AudioFileOpenMode = AskUser);
- FileOpenStatus openURL(QString url, AudioFileOpenMode = AskUser);
+ FileOpenStatus open(QString fileOrUrl, AudioFileOpenMode = AskUser);
+ FileOpenStatus open(RemoteFile source, AudioFileOpenMode = AskUser);
+ FileOpenStatus openAudio(RemoteFile source, AudioFileOpenMode = AskUser);
+ FileOpenStatus openPlaylist(RemoteFile source, AudioFileOpenMode = AskUser);
+ FileOpenStatus openLayer(RemoteFile source);
+ FileOpenStatus openImage(RemoteFile source);
+ FileOpenStatus openSession(RemoteFile source);
+
bool saveSessionFile(QString path);
bool commitData(bool mayAskUser); // on session shutdown
@@ -429,16 +430,6 @@
virtual void closeEvent(QCloseEvent *e);
bool checkSaveModified();
- FileOpenStatus openSomeFile(QString path, QString location,
- AudioFileOpenMode = AskUser);
- FileOpenStatus openAudioFile(QString path, QString location,
- AudioFileOpenMode = AskUser);
- FileOpenStatus openPlaylistFile(QString path, QString location,
- AudioFileOpenMode = AskUser);
- FileOpenStatus openLayerFile(QString path, QString location);
- FileOpenStatus openImageFile(QString path, QString location);
- FileOpenStatus openSessionFile(QString path, QString location);
-
QString getOpenFileName(FileFinder::FileType type);
QString getSaveFileName(FileFinder::FileType type);
void registerLastOpenedFilePath(FileFinder::FileType type, QString path);
Modified: sonic-visualiser/trunk/sv/main/main.cpp
===================================================================
--- sonic-visualiser/trunk/sv/main/main.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/sv/main/main.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -300,17 +300,11 @@
if (i == args.begin()) continue;
if (i->startsWith('-')) continue;
- if (i->startsWith("http:") || i->startsWith("ftp:")) {
- std::cerr << "opening URL: \"" << i->toStdString() << "\"..." << std::endl;
- status = gui.openURL(*i);
- continue;
- }
-
QString path = *i;
if (path.endsWith("sv")) {
if (!haveSession) {
- status = gui.openSessionFile(path);
+ status = gui.openSession(path);
if (status == MainWindow::FileOpenSucceeded) {
haveSession = true;
haveMainModel = true;
@@ -322,25 +316,25 @@
}
if (status != MainWindow::FileOpenSucceeded) {
if (!haveMainModel) {
- status = gui.openSomeFile(path, MainWindow::ReplaceMainModel);
+ status = gui.open(path, MainWindow::ReplaceMainModel);
if (status == MainWindow::FileOpenSucceeded) {
haveMainModel = true;
}
} else {
if (haveSession && !havePriorCommandLineModel) {
- status = gui.openSomeFile(path, MainWindow::AskUser);
+ status = gui.open(path, MainWindow::AskUser);
if (status == MainWindow::FileOpenSucceeded) {
havePriorCommandLineModel = true;
}
} else {
- status = gui.openSomeFile(path, MainWindow::CreateAdditionalModel);
+ status = gui.open(path, MainWindow::CreateAdditionalModel);
}
}
}
if (status == MainWindow::FileOpenFailed) {
QMessageBox::critical
(&gui, QMessageBox::tr("Failed to open file"),
- QMessageBox::tr("File \"%1\" could not be opened").arg(path));
+ QMessageBox::tr("File or URL \"%1\" could not be opened").arg(path));
}
}
Modified: sonic-visualiser/trunk/widgets/ImageDialog.cpp
===================================================================
--- sonic-visualiser/trunk/widgets/ImageDialog.cpp 2007-10-18 10:24:26 UTC (rev 787)
+++ sonic-visualiser/trunk/widgets/ImageDialog.cpp 2007-10-18 15:31:20 UTC (rev 788)
@@ -187,7 +187,7 @@
.arg(url.scheme()));
} else {
m_remoteFile = new RemoteFile(url);
- m_remoteFile->wait();
+ m_remoteFile->waitForData();
if (!m_remoteFile->isOK()) {
QMessageBox::critical(this, tr("File download failed"),
tr("Failed to download URL \"%1\": %2")
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|