diff -r 89e065397ea6 -r e24348a560a6 src/multimedia/audio/qaudioinput_symbian_p.cpp --- a/src/multimedia/audio/qaudioinput_symbian_p.cpp Thu May 27 13:40:48 2010 +0300 +++ b/src/multimedia/audio/qaudioinput_symbian_p.cpp Fri Jun 11 14:24:45 2010 +0300 @@ -116,16 +116,16 @@ , m_pullMode(false) , m_sink(0) , m_pullTimer(new QTimer(this)) + , m_devSound(0) , m_devSoundBuffer(0) , m_devSoundBufferSize(0) , m_totalBytesReady(0) , m_devSoundBufferPos(0) , m_totalSamplesRecorded(0) { - connect(m_notifyTimer.data(), SIGNAL(timeout()), this, SIGNAL(notify())); + qRegisterMetaType("CMMFBuffer *"); - SymbianAudio::Utils::formatQtToNative(m_format, m_nativeFourCC, - m_nativeFormat); + connect(m_notifyTimer.data(), SIGNAL(timeout()), this, SIGNAL(notify())); m_pullTimer->setInterval(PushInterval); connect(m_pullTimer.data(), SIGNAL(timeout()), this, SLOT(pullData())); @@ -164,7 +164,7 @@ void QAudioInputPrivate::reset() { m_totalSamplesRecorded += getSamplesRecorded(); - m_devSound->Stop(); + m_devSound->stop(); startRecording(); } @@ -174,7 +174,7 @@ || SymbianAudio::IdleState == m_internalState) { m_notifyTimer->stop(); m_pullTimer->stop(); - m_devSound->Pause(); + m_devSound->pause(); const qint64 samplesRecorded = getSamplesRecorded(); m_totalSamplesRecorded += samplesRecorded; @@ -189,8 +189,11 @@ void QAudioInputPrivate::resume() { - if (SymbianAudio::SuspendedState == m_internalState) + if (SymbianAudio::SuspendedState == m_internalState) { + if (!m_pullMode && !bytesReady()) + m_devSound->start(); startDataTransfer(); + } } int QAudioInputPrivate::bytesReady() const @@ -224,11 +227,14 @@ void QAudioInputPrivate::setNotifyInterval(int ms) { - if (ms > 0) { + if (ms >= 0) { const int oldNotifyInterval = m_notifyInterval; m_notifyInterval = ms; - if (m_notifyTimer->isActive() && ms != oldNotifyInterval) + if (m_notifyInterval && (SymbianAudio::ActiveState == m_internalState || + SymbianAudio::IdleState == m_internalState)) m_notifyTimer->start(m_notifyInterval); + else + m_notifyTimer->stop(); } } @@ -275,88 +281,6 @@ return m_format; } -//----------------------------------------------------------------------------- -// MDevSoundObserver implementation -//----------------------------------------------------------------------------- - -void QAudioInputPrivate::InitializeComplete(TInt aError) -{ - Q_ASSERT_X(SymbianAudio::InitializingState == m_internalState, - Q_FUNC_INFO, "Invalid state"); - - if (KErrNone == aError) - startRecording(); -} - -void QAudioInputPrivate::ToneFinished(TInt aError) -{ - Q_UNUSED(aError) - // This class doesn't use DevSound's tone playback functions, so should - // never receive this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioInputPrivate::BufferToBeFilled(CMMFBuffer *aBuffer) -{ - Q_UNUSED(aBuffer) - // This class doesn't use DevSound in play mode, so should never receive - // this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioInputPrivate::PlayError(TInt aError) -{ - Q_UNUSED(aError) - // This class doesn't use DevSound in play mode, so should never receive - // this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioInputPrivate::BufferToBeEmptied(CMMFBuffer *aBuffer) -{ - // Following receipt of this callback, DevSound should not provide another - // buffer until we have returned the current one. - Q_ASSERT_X(!m_devSoundBuffer, Q_FUNC_INFO, "Buffer already held"); - - CMMFDataBuffer *const buffer = static_cast(aBuffer); - - if (!m_devSoundBufferSize) - m_devSoundBufferSize = buffer->Data().MaxLength(); - - m_totalBytesReady += buffer->Data().Length(); - - if (SymbianAudio::SuspendedState == m_internalState) { - m_devSoundBufferQ.append(buffer); - } else { - // Will be returned to DevSound by bufferEmptied(). - m_devSoundBuffer = buffer; - m_devSoundBufferPos = 0; - - if (bytesReady() && !m_pullMode) - pushData(); - } -} - -void QAudioInputPrivate::RecordError(TInt aError) -{ - Q_UNUSED(aError) - setError(QAudio::IOError); -} - -void QAudioInputPrivate::ConvertError(TInt aError) -{ - Q_UNUSED(aError) - // This class doesn't use DevSound's format conversion functions, so - // should never receive this callback. - Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback"); -} - -void QAudioInputPrivate::DeviceMessage(TUid aMessageType, const TDesC8 &aMsg) -{ - Q_UNUSED(aMessageType) - Q_UNUSED(aMsg) - // Ignore this callback. -} //----------------------------------------------------------------------------- // Private functions @@ -367,33 +291,30 @@ Q_ASSERT_X(SymbianAudio::ClosedState == m_internalState, Q_FUNC_INFO, "DevSound already opened"); - QT_TRAP_THROWING( m_devSound.reset(CMMFDevSound::NewL()) ) - - QScopedPointer caps( - new SymbianAudio::DevSoundCapabilities(*m_devSound, QAudio::AudioInput)); - - int err = SymbianAudio::Utils::isFormatSupported(m_format, *caps) ? - KErrNone : KErrNotSupported; + Q_ASSERT(!m_devSound); + m_devSound = new SymbianAudio::DevSoundWrapper(QAudio::AudioInput, this); - if (KErrNone == err) { - setState(SymbianAudio::InitializingState); - TRAP(err, m_devSound->InitializeL(*this, m_nativeFourCC, - EMMFStateRecording)); - } + connect(m_devSound, SIGNAL(initializeComplete(int)), + this, SLOT(devsoundInitializeComplete(int))); + connect(m_devSound, SIGNAL(bufferToBeProcessed(CMMFBuffer *)), + this, SLOT(devsoundBufferToBeEmptied(CMMFBuffer *))); + connect(m_devSound, SIGNAL(processingError(int)), + this, SLOT(devsoundRecordError(int))); - if (KErrNone != err) { - setError(QAudio::OpenError); - m_devSound.reset(); - } + setState(SymbianAudio::InitializingState); + m_devSound->initialize(m_format.codec()); } void QAudioInputPrivate::startRecording() { - const int samplesRecorded = m_devSound->SamplesRecorded(); + const int samplesRecorded = m_devSound->samplesProcessed(); Q_ASSERT(samplesRecorded == 0); - TRAPD(err, startDevSoundL()); - if (KErrNone == err) { + bool ok = m_devSound->setFormat(m_format); + if (ok) + ok = m_devSound->start(); + + if (ok) { startDataTransfer(); } else { setError(QAudio::OpenError); @@ -401,17 +322,10 @@ } } -void QAudioInputPrivate::startDevSoundL() -{ - TMMFCapabilities nativeFormat = m_devSound->Config(); - m_nativeFormat.iBufferSize = nativeFormat.iBufferSize; - m_devSound->SetConfigL(m_nativeFormat); - m_devSound->RecordInitL(); -} - void QAudioInputPrivate::startDataTransfer() { - m_notifyTimer->start(m_notifyInterval); + if (m_notifyInterval) + m_notifyTimer->start(m_notifyInterval); if (m_pullMode) m_pullTimer->start(); @@ -503,6 +417,48 @@ } } +void QAudioInputPrivate::devsoundInitializeComplete(int err) +{ + Q_ASSERT_X(SymbianAudio::InitializingState == m_internalState, + Q_FUNC_INFO, "Invalid state"); + + if (!err && m_devSound->isFormatSupported(m_format)) + startRecording(); + else + setError(QAudio::OpenError); +} + +void QAudioInputPrivate::devsoundBufferToBeEmptied(CMMFBuffer *baseBuffer) +{ + // Following receipt of this signal, DevSound should not provide another + // buffer until we have returned the current one. + Q_ASSERT_X(!m_devSoundBuffer, Q_FUNC_INFO, "Buffer already held"); + + CMMFDataBuffer *const buffer = static_cast(baseBuffer); + + if (!m_devSoundBufferSize) + m_devSoundBufferSize = buffer->Data().MaxLength(); + + m_totalBytesReady += buffer->Data().Length(); + + if (SymbianAudio::SuspendedState == m_internalState) { + m_devSoundBufferQ.append(buffer); + } else { + // Will be returned to DevSoundWrapper by bufferProcessed(). + m_devSoundBuffer = buffer; + m_devSoundBufferPos = 0; + + if (bytesReady() && !m_pullMode) + pushData(); + } +} + +void QAudioInputPrivate::devsoundRecordError(int err) +{ + Q_UNUSED(err) + setError(QAudio::IOError); +} + void QAudioInputPrivate::bufferEmptied() { m_devSoundBufferPos = 0; @@ -510,7 +466,7 @@ if (m_devSoundBuffer) { m_totalBytesReady -= m_devSoundBuffer->Data().Length(); m_devSoundBuffer = 0; - m_devSound->RecordData(); + m_devSound->bufferProcessed(); } else { Q_ASSERT(!m_devSoundBufferQ.empty()); m_totalBytesReady -= m_devSoundBufferQ.front()->Data().Length(); @@ -518,7 +474,8 @@ // If the queue has been emptied, resume transfer from the hardware if (m_devSoundBufferQ.empty()) - m_devSound->RecordInitL(); + if (!m_devSound->start()) + setError(QAudio::IOError); } Q_ASSERT(m_totalBytesReady >= 0); @@ -532,8 +489,10 @@ m_error = QAudio::NoError; if (m_devSound) - m_devSound->Stop(); - m_devSound.reset(); + m_devSound->stop(); + delete m_devSound; + m_devSound = 0; + m_devSoundBuffer = 0; m_devSoundBufferSize = 0; m_totalBytesReady = 0; @@ -554,7 +513,7 @@ { qint64 result = 0; if (m_devSound) - result = qint64(m_devSound->SamplesRecorded()); + result = qint64(m_devSound->samplesProcessed()); return result; } @@ -565,30 +524,28 @@ // Although no state transition actually occurs here, a stateChanged event // must be emitted to inform the client that the call to start() was // unsuccessful. - if (QAudio::OpenError == error) + if (QAudio::OpenError == error) { emit stateChanged(QAudio::StoppedState); - - // Close the DevSound instance. This causes a transition to StoppedState. - // This must be done asynchronously in case the current function was called - // from a DevSound event handler, in which case deleting the DevSound - // instance may cause an exception. - QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection); + } else { + if (QAudio::UnderrunError == error) + setState(SymbianAudio::IdleState); + else + // Close the DevSound instance. This causes a transition to + // StoppedState. This must be done asynchronously in case the + // current function was called from a DevSound event handler, in which + // case deleting the DevSound instance may cause an exception. + QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection); + } } void QAudioInputPrivate::setState(SymbianAudio::State newInternalState) { const QAudio::State oldExternalState = m_externalState; m_internalState = newInternalState; - m_externalState = SymbianAudio::Utils::stateNativeToQt( - m_internalState, initializingState()); + m_externalState = SymbianAudio::Utils::stateNativeToQt(m_internalState); if (m_externalState != oldExternalState) emit stateChanged(m_externalState); } -QAudio::State QAudioInputPrivate::initializingState() const -{ - return QAudio::IdleState; -} - QT_END_NAMESPACE