# HG changeset patch # User Chris Cannam # Date 1483530483 0 # Node ID 6f54789f312790a9d17deec2988b0435a2b78065 # Parent 1cc23cee4ebfd7a2601adcd8469128110aa5e447 Fix race condition in first-time recording, where adding the recording wave model would prompt the audio play source to note that its channel count had increased (from 0 to, say, 2) and thus to cause the audio device to be reopened, stopping recording. Fix is to make this only happen if channel count increases beyond that of the device, which shouldn't happen in the recording case diff -r 1cc23cee4ebf -r 6f54789f3127 audio/AudioCallbackPlaySource.cpp --- a/audio/AudioCallbackPlaySource.cpp Wed Jan 04 09:57:13 2017 +0000 +++ b/audio/AudioCallbackPlaySource.cpp Wed Jan 04 11:48:03 2017 +0000 @@ -235,6 +235,8 @@ } if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) { + cerr << "m_writeBuffers size = " << (m_writeBuffers ? m_writeBuffers->size() : 0) << endl; + cerr << "target channel count = " << (getTargetChannelCount()) << endl; clearRingBuffers(true, getTargetChannelCount()); buffersIncreased = true; } else { @@ -270,8 +272,13 @@ m_audioGenerator->setTargetChannelCount(getTargetChannelCount()); if (buffersIncreased) { - SVDEBUG << "AudioCallbackPlaySource::addModel: Number of buffers increased, signalling channelCountIncreased" << endl; - emit channelCountIncreased(); + SVDEBUG << "AudioCallbackPlaySource::addModel: Number of buffers increased to " << getTargetChannelCount() << endl; + if (getTargetChannelCount() > getDeviceChannelCount()) { + SVDEBUG << "AudioCallbackPlaySource::addModel: This is more than the device channel count, signalling channelCountIncreased" << endl; + emit channelCountIncreased(getTargetChannelCount()); + } else { + SVDEBUG << "AudioCallbackPlaySource::addModel: This is no more than the device channel count (" << getDeviceChannelCount() << "), so taking no action" << endl; + } } if (!m_fillThread) { diff -r 1cc23cee4ebf -r 6f54789f3127 audio/AudioCallbackPlaySource.h --- a/audio/AudioCallbackPlaySource.h Wed Jan 04 09:57:13 2017 +0000 +++ b/audio/AudioCallbackPlaySource.h Wed Jan 04 11:48:03 2017 +0000 @@ -304,7 +304,7 @@ sv_samplerate_t available, bool willResample); - void channelCountIncreased(); + void channelCountIncreased(int count); // target channel count (see getTargetChannelCount()) void audioOverloadPluginDisabled(); void audioTimeStretchMultiChannelDisabled(); diff -r 1cc23cee4ebf -r 6f54789f3127 audio/AudioRecordTarget.cpp --- a/audio/AudioRecordTarget.cpp Wed Jan 04 09:57:13 2017 +0000 +++ b/audio/AudioRecordTarget.cpp Wed Jan 04 11:48:03 2017 +0000 @@ -102,8 +102,10 @@ } void -AudioRecordTarget::setInputLevels(float, float) +AudioRecordTarget::setInputLevels(float left, float right) { + cerr << "AudioRecordTarget::setInputLevels(" << left << "," << right << ")" + << endl; } void @@ -123,7 +125,7 @@ QString subdirname("recorded"); if (!parent.mkpath(subdirname)) { - cerr << "ERROR: AudioRecordTarget::getRecordContainerFolder: Failed to create recorded dir in \"" << parent.canonicalPath() << "\"" << endl; + SVCERR << "ERROR: AudioRecordTarget::getRecordContainerFolder: Failed to create recorded dir in \"" << parent.canonicalPath() << "\"" << endl; return ""; } else { return parent.filePath(subdirname); @@ -138,7 +140,7 @@ QString subdirname = QString("%1").arg(now.toString("yyyyMMdd")); if (!parent.mkpath(subdirname)) { - cerr << "ERROR: AudioRecordTarget::getRecordFolder: Failed to create recorded dir in \"" << parent.canonicalPath() << "\"" << endl; + SVCERR << "ERROR: AudioRecordTarget::getRecordFolder: Failed to create recorded dir in \"" << parent.canonicalPath() << "\"" << endl; return ""; } else { return parent.filePath(subdirname); @@ -149,43 +151,46 @@ AudioRecordTarget::startRecording() { { - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - if (m_recording) { - cerr << "WARNING: AudioRecordTarget::startRecording: We are already recording" << endl; - return 0; - } + if (m_recording) { + SVCERR << "WARNING: AudioRecordTarget::startRecording: We are already recording" << endl; + return 0; + } - m_model = 0; - m_frameCount = 0; + m_model = 0; + m_frameCount = 0; - QString folder = getRecordFolder(); - if (folder == "") return 0; - QDir recordedDir(folder); + QString folder = getRecordFolder(); + if (folder == "") return 0; + QDir recordedDir(folder); - QDateTime now = QDateTime::currentDateTime(); + QDateTime now = QDateTime::currentDateTime(); - // Don't use QDateTime::toString(Qt::ISODate) as the ":" character - // isn't permitted in filenames on Windows - QString filename = QString("recorded-%1.wav") - .arg(now.toString("yyyyMMdd-HHmmss-zzz")); + // Don't use QDateTime::toString(Qt::ISODate) as the ":" character + // isn't permitted in filenames on Windows + QString nowString = now.toString("yyyyMMdd-HHmmss-zzz"); + + QString filename = tr("recorded-%1.wav").arg(nowString); + QString label = tr("Recorded %1").arg(nowString); - m_audioFileName = recordedDir.filePath(filename); + m_audioFileName = recordedDir.filePath(filename); - m_model = new WritableWaveFileModel(m_recordSampleRate, - m_recordChannelCount, - m_audioFileName); + m_model = new WritableWaveFileModel(m_recordSampleRate, + m_recordChannelCount, + m_audioFileName); - if (!m_model->isOK()) { - cerr << "ERROR: AudioRecordTarget::startRecording: Recording failed" - << endl; - //!!! and throw? - delete m_model; - m_model = 0; - return 0; - } + if (!m_model->isOK()) { + SVCERR << "ERROR: AudioRecordTarget::startRecording: Recording failed" + << endl; + //!!! and throw? + delete m_model; + m_model = 0; + return 0; + } - m_recording = true; + m_model->setObjectName(label); + m_recording = true; } emit recordStatusChanged(true); @@ -196,15 +201,15 @@ AudioRecordTarget::stopRecording() { { - QMutexLocker locker(&m_mutex); - if (!m_recording) { - cerr << "WARNING: AudioRecordTarget::startRecording: Not recording" << endl; - return; - } + QMutexLocker locker(&m_mutex); + if (!m_recording) { + SVCERR << "WARNING: AudioRecordTarget::startRecording: Not recording" << endl; + return; + } - m_model->writeComplete(); - m_model = 0; - m_recording = false; + m_model->writeComplete(); + m_model = 0; + m_recording = false; } emit recordStatusChanged(false); diff -r 1cc23cee4ebf -r 6f54789f3127 framework/MainWindowBase.cpp --- a/framework/MainWindowBase.cpp Wed Jan 04 09:57:13 2017 +0000 +++ b/framework/MainWindowBase.cpp Wed Jan 04 11:48:03 2017 +0000 @@ -242,8 +242,8 @@ connect(m_playSource, SIGNAL(sampleRateMismatch(sv_samplerate_t, sv_samplerate_t, bool)), this, SLOT(sampleRateMismatch(sv_samplerate_t, sv_samplerate_t, bool))); - connect(m_playSource, SIGNAL(channelCountIncreased()), - this, SLOT(recreateAudioIO())); + connect(m_playSource, SIGNAL(channelCountIncreased(int)), + this, SLOT(audioChannelCountIncreased(int))); connect(m_playSource, SIGNAL(audioOverloadPluginDisabled()), this, SLOT(audioOverloadPluginDisabled())); connect(m_playSource, SIGNAL(audioTimeStretchMultiChannelDisabled()), @@ -2386,6 +2386,8 @@ secondBit = tr("
Audio playback will not be available during this session.
"); } } + SVDEBUG << "createAudioIO: ERROR: Failed to open audio device \"" + << implementation << "\": error is: " << error << endl; QMessageBox::warning(this, tr("Couldn't open audio device"), firstBit + secondBit, QMessageBox::Ok); } @@ -2422,6 +2424,12 @@ createAudioIO(); } +void +MainWindowBase::audioChannelCountIncreased(int) +{ + recreateAudioIO(); +} + WaveFileModel * MainWindowBase::getMainModel() { @@ -2878,11 +2886,12 @@ } if (!m_audioIO) { + cerr << "MainWindowBase::record: about to create audio IO" << endl; createAudioIO(); } if (!m_audioIO) { - //!!! report + // don't need to report this, createAudioIO already should have return; } @@ -2902,6 +2911,7 @@ if (m_viewManager) m_viewManager->setGlobalCentreFrame(0); + cerr << "MainWindowBase::record: about to resume" << endl; m_audioIO->resume(); WritableWaveFileModel *model = m_recordTarget->startRecording(); diff -r 1cc23cee4ebf -r 6f54789f3127 framework/MainWindowBase.h --- a/framework/MainWindowBase.h Wed Jan 04 09:57:13 2017 +0000 +++ b/framework/MainWindowBase.h Wed Jan 04 11:48:03 2017 +0000 @@ -248,6 +248,8 @@ virtual void playSelectionToggled(); virtual void playSoloToggled(); + virtual void audioChannelCountIncreased(int count); + virtual void sampleRateMismatch(sv_samplerate_t, sv_samplerate_t, bool) = 0; virtual void audioOverloadPluginDisabled() = 0; virtual void audioTimeStretchMultiChannelDisabled() = 0;