summaryrefslogtreecommitdiffstats
path: root/src/multimedia/audio
diff options
context:
space:
mode:
authorGareth Stockwell <ext-gareth.stockwell@nokia.com>2010-09-14 14:02:03 (GMT)
committerGareth Stockwell <ext-gareth.stockwell@nokia.com>2010-09-17 13:21:06 (GMT)
commit737b75e19b7206cb9888e87930cb37b1906a6345 (patch)
tree3cb777f81837eb1f59a90e8e27fe961533463d74 /src/multimedia/audio
parent9fd8589c9d4574c04a989a6c5e1d335779d2b244 (diff)
downloadQt-737b75e19b7206cb9888e87930cb37b1906a6345.zip
Qt-737b75e19b7206cb9888e87930cb37b1906a6345.tar.gz
Qt-737b75e19b7206cb9888e87930cb37b1906a6345.tar.bz2
Implement QAudioInput::suspend() using CMMFDevSound::Stop()
As with playback mode, lack of support for CMMFDevSound::Pause() in DevSound's recording mode causes problems on some devices. Specifically, while QAudioInput works fine on the Nokia 5800, this bug was observed on the Nokia N8. This fix means that suspending and resuming audio input will work correctly on all devices. Task-number: QTBUG-13506 Reviewed-by: Derick Hawcroft
Diffstat (limited to 'src/multimedia/audio')
-rw-r--r--src/multimedia/audio/qaudio_symbian_p.cpp25
-rw-r--r--src/multimedia/audio/qaudio_symbian_p.h15
-rw-r--r--src/multimedia/audio/qaudioinput_symbian_p.cpp30
-rw-r--r--src/multimedia/audio/qaudiooutput_symbian_p.cpp45
4 files changed, 73 insertions, 42 deletions
diff --git a/src/multimedia/audio/qaudio_symbian_p.cpp b/src/multimedia/audio/qaudio_symbian_p.cpp
index ae58b94..59fc05f 100644
--- a/src/multimedia/audio/qaudio_symbian_p.cpp
+++ b/src/multimedia/audio/qaudio_symbian_p.cpp
@@ -313,7 +313,8 @@ QAudio::State stateNativeToQt(State nativeState)
return QAudio::ActiveState;
case IdleState:
return QAudio::IdleState;
- case SuspendedState:
+ case SuspendedPausedState:
+ case SuspendedStoppedState:
return QAudio::SuspendedState;
default:
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid state");
@@ -476,10 +477,22 @@ bool DevSoundWrapper::start()
return (KErrNone == err);
}
-void DevSoundWrapper::pause()
+bool DevSoundWrapper::pause()
{
Q_ASSERT(StateInitialized == m_state);
- m_devsound->Pause();
+ const bool canPause = isResumeSupported();
+ if (canPause)
+ m_devsound->Pause();
+ else
+ stop();
+ return canPause;
+}
+
+void DevSoundWrapper::resume()
+{
+ Q_ASSERT(StateInitialized == m_state);
+ Q_ASSERT(isResumeSupported());
+ // TODO: QTBUG-13625
}
void DevSoundWrapper::stop()
@@ -558,6 +571,12 @@ void DevSoundWrapper::populateCapabilities()
}
}
+bool DevSoundWrapper::isResumeSupported() const
+{
+ // TODO: QTBUG-13625
+ return false;
+}
+
void DevSoundWrapper::InitializeComplete(TInt aError)
{
Q_ASSERT(StateInitializing == m_state);
diff --git a/src/multimedia/audio/qaudio_symbian_p.h b/src/multimedia/audio/qaudio_symbian_p.h
index 58ef192..84a93d1 100644
--- a/src/multimedia/audio/qaudio_symbian_p.h
+++ b/src/multimedia/audio/qaudio_symbian_p.h
@@ -81,7 +81,10 @@ enum State {
, InitializingState
, ActiveState
, IdleState
- , SuspendedState
+ // QAudio is suspended; DevSound is paused
+ , SuspendedPausedState
+ // QAudio is suspended; DevSound is stopped
+ , SuspendedStoppedState
};
/**
@@ -117,7 +120,14 @@ public:
int samplesProcessed() const;
bool setFormat(const QAudioFormat &format);
bool start();
- void pause();
+
+ // If DevSound implementation supports pause, calls pause and returns true.
+ // Otherwise calls stop and returns false. In this case, all DevSound buffers
+ // currently held by the backend must be discarded.
+ bool pause();
+
+ void resume();
+
void stop();
void bufferProcessed();
@@ -140,6 +150,7 @@ signals:
private:
void getSupportedCodecs();
void populateCapabilities();
+ bool isResumeSupported() const;
private:
const QAudio::Mode m_mode;
diff --git a/src/multimedia/audio/qaudioinput_symbian_p.cpp b/src/multimedia/audio/qaudioinput_symbian_p.cpp
index b837055..485c695 100644
--- a/src/multimedia/audio/qaudioinput_symbian_p.cpp
+++ b/src/multimedia/audio/qaudioinput_symbian_p.cpp
@@ -174,22 +174,30 @@ void QAudioInputPrivate::suspend()
|| SymbianAudio::IdleState == m_internalState) {
m_notifyTimer->stop();
m_pullTimer->stop();
- m_devSound->pause();
const qint64 samplesRecorded = getSamplesRecorded();
m_totalSamplesRecorded += samplesRecorded;
- m_devSoundBuffer = 0;
- m_devSoundBufferQ.clear();
- m_devSoundBufferPos = 0;
-
- setState(SymbianAudio::SuspendedState);
+ const bool paused = m_devSound->pause();
+ if (paused) {
+ if (m_devSoundBuffer)
+ m_devSoundBufferQ.append(m_devSoundBuffer);
+ m_devSoundBuffer = 0;
+ setState(SymbianAudio::SuspendedPausedState);
+ } else {
+ m_devSoundBuffer = 0;
+ m_devSoundBufferQ.clear();
+ m_devSoundBufferPos = 0;
+ setState(SymbianAudio::SuspendedStoppedState);
+ }
}
}
void QAudioInputPrivate::resume()
{
- if (SymbianAudio::SuspendedState == m_internalState) {
- if (!m_pullMode && !bytesReady())
+ if (QAudio::SuspendedState == m_externalState) {
+ if (SymbianAudio::SuspendedPausedState == m_internalState)
+ m_devSound->resume();
+ else
m_devSound->start();
startDataTransfer();
}
@@ -245,7 +253,7 @@ int QAudioInputPrivate::notifyInterval() const
qint64 QAudioInputPrivate::processedUSecs() const
{
int samplesPlayed = 0;
- if (m_devSound && SymbianAudio::SuspendedState != m_internalState)
+ if (m_devSound && QAudio::SuspendedState != m_externalState)
samplesPlayed = getSamplesRecorded();
// Protect against division by zero
@@ -334,7 +342,7 @@ void QAudioInputPrivate::startDataTransfer()
if (!m_pullMode)
pushData();
} else {
- if (SymbianAudio::SuspendedState == m_internalState)
+ if (QAudio::SuspendedState == m_externalState)
setState(SymbianAudio::ActiveState);
else
setState(SymbianAudio::IdleState);
@@ -442,7 +450,7 @@ void QAudioInputPrivate::devsoundBufferToBeEmptied(CMMFBuffer *baseBuffer)
m_totalBytesReady += buffer->Data().Length();
- if (SymbianAudio::SuspendedState == m_internalState) {
+ if (SymbianAudio::SuspendedPausedState == m_internalState) {
m_devSoundBufferQ.append(buffer);
} else {
// Will be returned to DevSoundWrapper by bufferProcessed().
diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp
index cc32f9d..ea14e19 100644
--- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp
+++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp
@@ -180,40 +180,33 @@ void QAudioOutputPrivate::suspend()
|| SymbianAudio::IdleState == m_internalState) {
m_notifyTimer->stop();
m_underflowTimer->stop();
-
const qint64 samplesWritten = SymbianAudio::Utils::bytesToSamples(
m_format, m_bytesWritten);
-
const qint64 samplesPlayed = getSamplesPlayed();
-
- m_bytesWritten = 0;
-
- // CMMFDevSound::Pause() is not guaranteed to work correctly in all
- // implementations, for play-mode DevSound sessions. We therefore
- // have to implement suspend() by calling CMMFDevSound::Stop().
- // Because this causes buffered data to be dropped, we replace the
- // lost data with silence following a call to resume(), in order to
- // ensure that processedUSecs() returns the correct value.
- m_devSound->stop();
- m_devSoundBuffer = 0;
m_totalSamplesPlayed += samplesPlayed;
-
- // Calculate the amount of data dropped
- const qint64 paddingSamples = samplesWritten - samplesPlayed;
- Q_ASSERT(paddingSamples >= 0);
- m_bytesPadding = SymbianAudio::Utils::samplesToBytes(m_format,
- paddingSamples);
-
- setState(SymbianAudio::SuspendedState);
+ m_bytesWritten = 0;
+ const bool paused = m_devSound->pause();
+ if (paused) {
+ setState(SymbianAudio::SuspendedPausedState);
+ } else {
+ m_devSoundBuffer = 0;
+ // Calculate the amount of data dropped
+ const qint64 paddingSamples = samplesWritten - samplesPlayed;
+ Q_ASSERT(paddingSamples >= 0);
+ m_bytesPadding = SymbianAudio::Utils::samplesToBytes(m_format,
+ paddingSamples);
+ setState(SymbianAudio::SuspendedStoppedState);
+ }
}
}
void QAudioOutputPrivate::resume()
{
- if (SymbianAudio::SuspendedState == m_internalState) {
- if (!m_pullMode && m_devSoundBuffer)
- bufferFilled();
- startPlayback();
+ if (QAudio::SuspendedState == m_externalState) {
+ if (SymbianAudio::SuspendedPausedState == m_internalState)
+ m_devSound->resume();
+ else
+ startPlayback();
}
}
@@ -271,7 +264,7 @@ int QAudioOutputPrivate::notifyInterval() const
qint64 QAudioOutputPrivate::processedUSecs() const
{
int samplesPlayed = 0;
- if (m_devSound && SymbianAudio::SuspendedState != m_internalState)
+ if (m_devSound && QAudio::SuspendedState != m_externalState)
samplesPlayed = getSamplesPlayed();
// Protect against division by zero