src/multimedia/audio/qaudio_symbian_p.cpp
changeset 25 e24348a560a6
parent 22 79de32ba3296
--- a/src/multimedia/audio/qaudio_symbian_p.cpp	Thu May 27 13:40:48 2010 +0300
+++ b/src/multimedia/audio/qaudio_symbian_p.cpp	Fri Jun 11 14:24:45 2010 +0300
@@ -45,41 +45,6 @@
 QT_BEGIN_NAMESPACE
 
 namespace SymbianAudio {
-
-DevSoundCapabilities::DevSoundCapabilities(CMMFDevSound &devsound,
-                                           QAudio::Mode mode)
-{
-    QT_TRAP_THROWING(constructL(devsound, mode));
-}
-
-DevSoundCapabilities::~DevSoundCapabilities()
-{
-    m_fourCC.Close();
-}
-
-void DevSoundCapabilities::constructL(CMMFDevSound &devsound,
-                                      QAudio::Mode mode)
-{
-    m_caps = devsound.Capabilities();
-
-    TMMFPrioritySettings settings;
-
-    switch (mode) {
-    case QAudio::AudioOutput:
-        settings.iState = EMMFStatePlaying;
-        devsound.GetSupportedInputDataTypesL(m_fourCC, settings);
-        break;
-
-    case QAudio::AudioInput:
-        settings.iState = EMMFStateRecording;
-        devsound.GetSupportedInputDataTypesL(m_fourCC, settings);
-        break;
-
-    default:
-        Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
-    }
-}
-
 namespace Utils {
 
 //-----------------------------------------------------------------------------
@@ -274,11 +239,8 @@
     return found;
 }
 
-//-----------------------------------------------------------------------------
-// Public functions
-//-----------------------------------------------------------------------------
-
-void capabilitiesNativeToQt(const DevSoundCapabilities &caps,
+void capabilitiesNativeToQt(const TMMFCapabilities &caps,
+                            const TFourCC &fourcc,
                             QList<int> &frequencies,
                             QList<int> &channels,
                             QList<int> &sampleSizes,
@@ -292,37 +254,20 @@
     channels.clear();
 
     for (int i=0; i<SampleRateCount; ++i)
-        if (caps.caps().iRate & SampleRateListNative[i])
+        if (caps.iRate & SampleRateListNative[i])
             frequencies += SampleRateListQt[i];
 
     for (int i=0; i<ChannelsCount; ++i)
-        if (caps.caps().iChannels & ChannelsListNative[i])
+        if (caps.iChannels & ChannelsListNative[i])
             channels += ChannelsListQt[i];
 
     for (int i=0; i<EncodingCount; ++i) {
-        if (caps.fourCC().Find(EncodingFourCC[i]) != KErrNotFound) {
+        if (fourcc == EncodingFourCC[i]) {
             sampleSizes += EncodingSampleSize[i];
             byteOrders += EncodingByteOrder[i];
             sampleTypes += EncodingSampleType[i];
         }
     }
-
-}
-
-bool isFormatSupported(const QAudioFormat &formatQt,
-                       const DevSoundCapabilities &caps) {
-    TMMFCapabilities formatNative;
-    TUint32 fourCC;
-
-    bool result = false;
-    if (formatQt.codec() == QString::fromAscii("audio/pcm") &&
-        formatQtToNative(formatQt, fourCC, formatNative)) {
-        result =
-                (formatNative.iRate & caps.caps().iRate)
-            &&  (formatNative.iChannels & caps.caps().iChannels)
-            &&  (caps.fourCC().Find(fourCC) != KErrNotFound);
-    }
-    return result;
 }
 
 bool formatQtToNative(const QAudioFormat &inputFormat,
@@ -337,7 +282,7 @@
     TMMFMonoStereo outputChannels;
     TMMFSoundEncoding outputEncoding;
 
-    if (inputFormat.codec() == QString::fromAscii("audio/pcm")) {
+    if (inputFormat.codec() == QLatin1String("audio/pcm")) {
         result =
                 sampleRateQtToNative(inputFormat.frequency(), outputSampleRate)
             &&  channelsQtToNative(inputFormat.channels(), outputChannels)
@@ -357,14 +302,13 @@
     return result;
 }
 
-QAudio::State stateNativeToQt(State nativeState,
-                              QAudio::State initializingState)
+QAudio::State stateNativeToQt(State nativeState)
 {
     switch (nativeState) {
     case ClosedState:
         return QAudio::StoppedState;
     case InitializingState:
-        return initializingState;
+        return QAudio::StoppedState;
     case ActiveState:
         return QAudio::ActiveState;
     case IdleState:
@@ -388,6 +332,291 @@
 }
 
 } // namespace Utils
+
+
+//-----------------------------------------------------------------------------
+// DevSoundWrapper
+//-----------------------------------------------------------------------------
+
+DevSoundWrapper::DevSoundWrapper(QAudio::Mode mode, QObject *parent)
+    :   QObject(parent)
+    ,   m_mode(mode)
+    ,   m_state(StateIdle)
+    ,   m_devsound(0)
+    ,   m_fourcc(0)
+{
+    QT_TRAP_THROWING(m_devsound = CMMFDevSound::NewL());
+
+    switch (mode) {
+    case QAudio::AudioOutput:
+        m_nativeMode = EMMFStatePlaying;
+        break;
+
+    case QAudio::AudioInput:
+        m_nativeMode = EMMFStateRecording;
+        break;
+
+    default:
+        Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
+    }
+
+    getSupportedCodecs();
+}
+
+DevSoundWrapper::~DevSoundWrapper()
+{
+    delete m_devsound;
+}
+
+const QList<QString>& DevSoundWrapper::supportedCodecs() const
+{
+    return m_supportedCodecs;
+}
+
+void DevSoundWrapper::initialize(const QString& codec)
+{
+    Q_ASSERT(StateInitializing != m_state);
+    m_state = StateInitializing;
+    if (QLatin1String("audio/pcm") == codec) {
+        m_fourcc = KMMFFourCCCodePCM16;
+        TRAPD(err, m_devsound->InitializeL(*this, m_fourcc, m_nativeMode));
+        if (KErrNone != err) {
+            m_state = StateIdle;
+            emit initializeComplete(err);
+        }
+    } else {
+        emit initializeComplete(KErrNotSupported);
+    }
+}
+
+const QList<int>& DevSoundWrapper::supportedFrequencies() const
+{
+    Q_ASSERT(StateInitialized == m_state);
+    return m_supportedFrequencies;
+}
+
+const QList<int>& DevSoundWrapper::supportedChannels() const
+{
+    Q_ASSERT(StateInitialized == m_state);
+    return m_supportedChannels;
+}
+
+const QList<int>& DevSoundWrapper::supportedSampleSizes() const
+{
+    Q_ASSERT(StateInitialized == m_state);
+    return m_supportedSampleSizes;
+}
+
+const QList<QAudioFormat::Endian>& DevSoundWrapper::supportedByteOrders() const
+{
+    Q_ASSERT(StateInitialized == m_state);
+    return m_supportedByteOrders;
+}
+
+const QList<QAudioFormat::SampleType>& DevSoundWrapper::supportedSampleTypes() const
+{
+    Q_ASSERT(StateInitialized == m_state);
+    return m_supportedSampleTypes;
+}
+
+bool DevSoundWrapper::isFormatSupported(const QAudioFormat &format) const
+{
+    Q_ASSERT(StateInitialized == m_state);
+    return m_supportedCodecs.contains(format.codec())
+        && m_supportedFrequencies.contains(format.frequency())
+        && m_supportedChannels.contains(format.channels())
+        && m_supportedSampleSizes.contains(format.sampleSize())
+        && m_supportedSampleTypes.contains(format.sampleType())
+        && m_supportedByteOrders.contains(format.byteOrder());
+}
+
+int DevSoundWrapper::samplesProcessed() const
+{
+    Q_ASSERT(StateInitialized == m_state);
+    int result = 0;
+    switch (m_mode) {
+    case QAudio::AudioInput:
+        result = m_devsound->SamplesRecorded();
+        break;
+    case QAudio::AudioOutput:
+        result = m_devsound->SamplesPlayed();
+        break;
+    }
+    return result;
+}
+
+bool DevSoundWrapper::setFormat(const QAudioFormat &format)
+{
+    Q_ASSERT(StateInitialized == m_state);
+    bool result = false;
+    TUint32 fourcc;
+    TMMFCapabilities nativeFormat;
+    if (Utils::formatQtToNative(format, fourcc, nativeFormat)) {
+        TMMFCapabilities currentNativeFormat = m_devsound->Config();
+        nativeFormat.iBufferSize = currentNativeFormat.iBufferSize;
+        TRAPD(err, m_devsound->SetConfigL(nativeFormat));
+        result = (KErrNone == err);
+    }
+    return result;
+}
+
+bool DevSoundWrapper::start()
+{
+    Q_ASSERT(StateInitialized == m_state);
+    int err = KErrArgument;
+    switch (m_mode) {
+    case QAudio::AudioInput:
+        TRAP(err, m_devsound->RecordInitL());
+        break;
+    case QAudio::AudioOutput:
+        TRAP(err, m_devsound->PlayInitL());
+        break;
+    }
+    return (KErrNone == err);
+}
+
+void DevSoundWrapper::pause()
+{
+    Q_ASSERT(StateInitialized == m_state);
+    m_devsound->Pause();
+}
+
+void DevSoundWrapper::stop()
+{
+    m_devsound->Stop();
+}
+
+void DevSoundWrapper::bufferProcessed()
+{
+    Q_ASSERT(StateInitialized == m_state);
+    switch (m_mode) {
+    case QAudio::AudioInput:
+        m_devsound->RecordData();
+        break;
+    case QAudio::AudioOutput:
+        m_devsound->PlayData();
+        break;
+    }
+}
+
+void DevSoundWrapper::getSupportedCodecs()
+{
+/*
+ * TODO: once we support formats other than PCM, this function should
+ * convert the array of FourCC codes into MIME types for each codec.
+ *
+    RArray<TFourCC> fourcc;
+    QT_TRAP_THROWING(CleanupClosePushL(&fourcc));
+
+    TMMFPrioritySettings settings;
+    switch (mode) {
+    case QAudio::AudioOutput:
+        settings.iState = EMMFStatePlaying;
+        m_devsound->GetSupportedInputDataTypesL(fourcc, settings);
+        break;
+
+    case QAudio::AudioInput:
+        settings.iState = EMMFStateRecording;
+        m_devsound->GetSupportedInputDataTypesL(fourcc, settings);
+        break;
+
+    default:
+        Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
+    }
+
+    CleanupStack::PopAndDestroy(); // fourcc
+*/
+
+    m_supportedCodecs.append(QLatin1String("audio/pcm"));
+}
+
+void DevSoundWrapper::populateCapabilities()
+{
+    m_supportedFrequencies.clear();
+    m_supportedChannels.clear();
+    m_supportedSampleSizes.clear();
+    m_supportedByteOrders.clear();
+    m_supportedSampleTypes.clear();
+
+    const TMMFCapabilities caps = m_devsound->Capabilities();
+
+    for (int i=0; i<Utils::SampleRateCount; ++i)
+        if (caps.iRate & Utils::SampleRateListNative[i])
+            m_supportedFrequencies += Utils::SampleRateListQt[i];
+
+    for (int i=0; i<Utils::ChannelsCount; ++i)
+        if (caps.iChannels & Utils::ChannelsListNative[i])
+            m_supportedChannels += Utils::ChannelsListQt[i];
+
+    for (int i=0; i<Utils::EncodingCount; ++i) {
+        if (m_fourcc == Utils::EncodingFourCC[i]) {
+            m_supportedSampleSizes += Utils::EncodingSampleSize[i];
+            m_supportedByteOrders += Utils::EncodingByteOrder[i];
+            m_supportedSampleTypes += Utils::EncodingSampleType[i];
+        }
+    }
+}
+
+void DevSoundWrapper::InitializeComplete(TInt aError)
+{
+    Q_ASSERT(StateInitializing == m_state);
+    if (KErrNone == aError) {
+        m_state = StateInitialized;
+        populateCapabilities();
+    } else {
+        m_state = StateIdle;
+    }
+    emit initializeComplete(aError);
+}
+
+void DevSoundWrapper::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 DevSoundWrapper::BufferToBeFilled(CMMFBuffer *aBuffer)
+{
+    Q_ASSERT(QAudio::AudioOutput == m_mode);
+    emit bufferToBeProcessed(aBuffer);
+}
+
+void DevSoundWrapper::PlayError(TInt aError)
+{
+    Q_ASSERT(QAudio::AudioOutput == m_mode);
+    emit processingError(aError);
+}
+
+void DevSoundWrapper::BufferToBeEmptied(CMMFBuffer *aBuffer)
+{
+    Q_ASSERT(QAudio::AudioInput == m_mode);
+    emit bufferToBeProcessed(aBuffer);
+}
+
+void DevSoundWrapper::RecordError(TInt aError)
+{
+    Q_ASSERT(QAudio::AudioInput == m_mode);
+    emit processingError(aError);
+}
+
+void DevSoundWrapper::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 DevSoundWrapper::DeviceMessage(TUid aMessageType, const TDesC8 &aMsg)
+{
+    Q_UNUSED(aMessageType)
+    Q_UNUSED(aMsg)
+    // Ignore this callback.
+}
+
+
 } // namespace SymbianAudio
 
 QT_END_NAMESPACE