# HG changeset patch # User Chris Cannam # Date 1227879373 0 # Node ID b6dc6c7f402cd2bfd6de62d4b066b1a53d3c1419 # Parent 05383ee78f3e0591a91f5d0dc680a1975c121828 Various fixes: * Fix handling of HTTP redirects (avoiding crashes... I hope) * Fix failure to delete FFT models when a feature extraction model transformer was abandoned (also a cause of crashes in the past) * Fix deadlock when said transform was abandoned before its source model was ready because the session was being cleared (and so the source model would never be ready) diff -r 05383ee78f3e -r b6dc6c7f402c data/fft/FFTDataServer.cpp --- a/data/fft/FFTDataServer.cpp Thu Nov 27 22:09:58 2008 +0000 +++ b/data/fft/FFTDataServer.cpp Fri Nov 28 13:36:13 2008 +0000 @@ -451,6 +451,7 @@ if (i->second.second > 0) { std::cerr << "WARNING: FFTDataServer::modelAboutToBeDeleted: Model " << model << " (\"" << model->objectName().toStdString() << "\") is about to be deleted, but is still being referred to by FFT server " << server << " with non-zero refcount " << i->second.second << std::endl; + server->suspendWrites(); return; } for (ServerQueue::iterator j = m_releasedServers.begin(); diff -r 05383ee78f3e -r b6dc6c7f402c data/fileio/FileSource.cpp --- a/data/fileio/FileSource.cpp Thu Nov 27 22:09:58 2008 +0000 +++ b/data/fileio/FileSource.cpp Fri Nov 28 13:36:13 2008 +0000 @@ -29,7 +29,7 @@ #include #include -#define DEBUG_FILE_SOURCE 1 +//#define DEBUG_FILE_SOURCE 1 int FileSource::m_count = 0; @@ -108,6 +108,8 @@ emit statusAvailable(); emit ready(); } + + std::cerr << "FileSource::FileSource(string) exiting" << std::endl; } FileSource::FileSource(QUrl url, ProgressReporter *reporter) : @@ -134,6 +136,8 @@ } init(); + + std::cerr << "FileSource::FileSource(url) exiting" << std::endl; } FileSource::FileSource(const FileSource &rf) : @@ -182,6 +186,8 @@ } m_done = true; + + std::cerr << "FileSource::FileSource(copy ctor) exiting" << std::endl; } FileSource::~FileSource() @@ -311,7 +317,8 @@ FileSource::initHttp() { m_ok = true; - m_http = new QHttp(m_url.host(), m_url.port(80)); + int port = m_url.port(); + m_http = new QHttp(m_url.host(), port < 0 ? 80 : port); connect(m_http, SIGNAL(done(bool)), this, SLOT(done(bool))); connect(m_http, SIGNAL(dataReadProgress(int, int)), this, SLOT(dataReadProgress(int, int))); @@ -475,6 +482,7 @@ while (m_ok && !m_done) { // std::cerr << "FileSource::waitForData: calling QApplication::processEvents" << std::endl; QCoreApplication::processEvents(); + usleep(10000); } } @@ -545,8 +553,9 @@ void FileSource::httpResponseHeaderReceived(const QHttpResponseHeader &resp) { - m_lastStatus = resp.statusCode(); - if (m_lastStatus / 100 == 3) { + std::cerr << "FileSource::httpResponseHeaderReceived" << std::endl; + + if (resp.statusCode() / 100 == 3) { QString location = resp.value("Location"); #ifdef DEBUG_FILE_SOURCE std::cerr << "FileSource::responseHeaderReceived: redirect to \"" @@ -555,19 +564,20 @@ if (location != "") { QUrl newUrl(location); if (newUrl != m_url) { + cleanup(); + deleteCacheFile(); m_url = newUrl; + m_localFile = 0; m_lastStatus = 0; - disconnect(m_http, SIGNAL(done(bool)), this, SLOT(done(bool))); - disconnect(m_http, SIGNAL(dataReadProgress(int, int)), - this, SLOT(dataReadProgress(int, int))); - m_http->abort(); - m_http->deleteLater(); - m_http = 0; + m_done = false; + m_refCounted = false; init(); return; } } } + + m_lastStatus = resp.statusCode(); if (m_lastStatus / 100 >= 4) { m_errorString = QString("%1 %2") .arg(resp.statusCode()).arg(resp.reasonPhrase()); diff -r 05383ee78f3e -r b6dc6c7f402c data/model/FFTModel.h --- a/data/model/FFTModel.h Thu Nov 27 22:09:58 2008 +0000 +++ b/data/model/FFTModel.h Fri Nov 28 13:36:13 2008 +0000 @@ -66,43 +66,43 @@ size_t fillFromColumn = 0); ~FFTModel(); - float getMagnitudeAt(size_t x, size_t y) { + inline float getMagnitudeAt(size_t x, size_t y) { return m_server->getMagnitudeAt(x << m_xshift, y << m_yshift); } - float getNormalizedMagnitudeAt(size_t x, size_t y) { + inline float getNormalizedMagnitudeAt(size_t x, size_t y) { return m_server->getNormalizedMagnitudeAt(x << m_xshift, y << m_yshift); } - float getMaximumMagnitudeAt(size_t x) { + inline float getMaximumMagnitudeAt(size_t x) { return m_server->getMaximumMagnitudeAt(x << m_xshift); } - float getPhaseAt(size_t x, size_t y) { + inline float getPhaseAt(size_t x, size_t y) { return m_server->getPhaseAt(x << m_xshift, y << m_yshift); } - void getValuesAt(size_t x, size_t y, float &real, float &imaginary) { + inline void getValuesAt(size_t x, size_t y, float &real, float &imaginary) { m_server->getValuesAt(x << m_xshift, y << m_yshift, real, imaginary); } - bool isColumnAvailable(size_t x) const { + inline bool isColumnAvailable(size_t x) const { return m_server->isColumnReady(x << m_xshift); } - float getMagnitudesAt(size_t x, float *values, size_t minbin = 0, size_t count = 0) { + inline float getMagnitudesAt(size_t x, float *values, size_t minbin = 0, size_t count = 0) { return m_server->getMagnitudesAt(x << m_xshift, values, minbin << m_yshift, count, getYRatio()); } - float getNormalizedMagnitudesAt(size_t x, float *values, size_t minbin = 0, size_t count = 0) { + inline float getNormalizedMagnitudesAt(size_t x, float *values, size_t minbin = 0, size_t count = 0) { return m_server->getNormalizedMagnitudesAt(x << m_xshift, values, minbin << m_yshift, count, getYRatio()); } - float getPhasesAt(size_t x, float *values, size_t minbin = 0, size_t count = 0) { + inline float getPhasesAt(size_t x, float *values, size_t minbin = 0, size_t count = 0) { return m_server->getPhasesAt(x << m_xshift, values, minbin << m_yshift, count, getYRatio()); } - size_t getFillExtent() const { return m_server->getFillExtent(); } + inline size_t getFillExtent() const { return m_server->getFillExtent(); } // DenseThreeDimensionalModel and Model methods: // - virtual size_t getWidth() const { + inline virtual size_t getWidth() const { return m_server->getWidth() >> m_xshift; } - virtual size_t getHeight() const { + inline virtual size_t getHeight() const { // If there is no y-shift, the server's height (based on its // fftsize/2 + 1) is correct. If there is a shift, then the // server is using a larger fft size than we want, so we shift diff -r 05383ee78f3e -r b6dc6c7f402c transform/FeatureExtractionModelTransformer.cpp --- a/transform/FeatureExtractionModelTransformer.cpp Thu Nov 27 22:09:58 2008 +0000 +++ b/transform/FeatureExtractionModelTransformer.cpp Fri Nov 28 13:36:13 2008 +0000 @@ -371,10 +371,11 @@ if (!m_output) return; - while (!input->isReady()) { + while (!input->isReady() && !m_abandoned) { std::cerr << "FeatureExtractionModelTransformer::run: Waiting for input model to be ready..." << std::endl; - sleep(1); + usleep(500000); } + if (m_abandoned) return; size_t sampleRate = input->getSampleRate(); @@ -478,9 +479,13 @@ getFrames(channelCount, blockFrame, blockSize, buffers); } + if (m_abandoned) break; + Vamp::Plugin::FeatureSet features = m_plugin->process (buffers, Vamp::RealTime::frame2RealTime(blockFrame, sampleRate)); + if (m_abandoned) break; + for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) { Vamp::Plugin::Feature feature = features[m_outputFeatureNo][fi]; @@ -495,23 +500,23 @@ blockFrame += stepSize; } - if (m_abandoned) return; + if (!m_abandoned) { + Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures(); - Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures(); + for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) { + Vamp::Plugin::Feature feature = + features[m_outputFeatureNo][fi]; + addFeature(blockFrame, feature); + } + } - for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) { - Vamp::Plugin::Feature feature = - features[m_outputFeatureNo][fi]; - addFeature(blockFrame, feature); - } + setCompletion(100); if (frequencyDomain) { for (size_t ch = 0; ch < channelCount; ++ch) { delete fftModels[ch]; } } - - setCompletion(100); } void diff -r 05383ee78f3e -r b6dc6c7f402c transform/RealTimeEffectModelTransformer.cpp --- a/transform/RealTimeEffectModelTransformer.cpp Thu Nov 27 22:09:58 2008 +0000 +++ b/transform/RealTimeEffectModelTransformer.cpp Fri Nov 28 13:36:13 2008 +0000 @@ -121,10 +121,11 @@ DenseTimeValueModel *input = getConformingInput(); if (!input) return; - while (!input->isReady()) { + while (!input->isReady() && !m_abandoned) { std::cerr << "RealTimeEffectModelTransformer::run: Waiting for input model to be ready..." << std::endl; - sleep(1); + usleep(500000); } + if (m_abandoned) return; SparseTimeValueModel *stvm = dynamic_cast(m_output); WritableWaveFileModel *wwfm = dynamic_cast(m_output);