summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth Stockwell <ext-gareth.stockwell@nokia.com>2010-09-14 15:02:03 +0100
committerGareth Stockwell <ext-gareth.stockwell@nokia.com>2010-09-17 13:43:15 +0100
commit82a0342fa076b4872c439079822bad61023af7da (patch)
treeea44d44db729f4059c0a3719a65c03884b9f47a6
parent15f6338e3984e103728a66de2f25e09e19f9077e (diff)
downloadqt4-tools-82a0342fa076b4872c439079822bad61023af7da.tar.gz
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
-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 ae58b949d6..59fc05f764 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 58ef1925a4..84a93d1ee2 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 b837055b18..485c69507a 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 cc32f9ddcb..ea14e1946e 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