src/multimedia/audio/qaudio_symbian_p.cpp
changeset 25 e24348a560a6
parent 22 79de32ba3296
equal deleted inserted replaced
23:89e065397ea6 25:e24348a560a6
    43 #include <mmffourcc.h>
    43 #include <mmffourcc.h>
    44 
    44 
    45 QT_BEGIN_NAMESPACE
    45 QT_BEGIN_NAMESPACE
    46 
    46 
    47 namespace SymbianAudio {
    47 namespace SymbianAudio {
    48 
       
    49 DevSoundCapabilities::DevSoundCapabilities(CMMFDevSound &devsound,
       
    50                                            QAudio::Mode mode)
       
    51 {
       
    52     QT_TRAP_THROWING(constructL(devsound, mode));
       
    53 }
       
    54 
       
    55 DevSoundCapabilities::~DevSoundCapabilities()
       
    56 {
       
    57     m_fourCC.Close();
       
    58 }
       
    59 
       
    60 void DevSoundCapabilities::constructL(CMMFDevSound &devsound,
       
    61                                       QAudio::Mode mode)
       
    62 {
       
    63     m_caps = devsound.Capabilities();
       
    64 
       
    65     TMMFPrioritySettings settings;
       
    66 
       
    67     switch (mode) {
       
    68     case QAudio::AudioOutput:
       
    69         settings.iState = EMMFStatePlaying;
       
    70         devsound.GetSupportedInputDataTypesL(m_fourCC, settings);
       
    71         break;
       
    72 
       
    73     case QAudio::AudioInput:
       
    74         settings.iState = EMMFStateRecording;
       
    75         devsound.GetSupportedInputDataTypesL(m_fourCC, settings);
       
    76         break;
       
    77 
       
    78     default:
       
    79         Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
       
    80     }
       
    81 }
       
    82 
       
    83 namespace Utils {
    48 namespace Utils {
    84 
    49 
    85 //-----------------------------------------------------------------------------
    50 //-----------------------------------------------------------------------------
    86 // Static data
    51 // Static data
    87 //-----------------------------------------------------------------------------
    52 //-----------------------------------------------------------------------------
   272     }
   237     }
   273 
   238 
   274     return found;
   239     return found;
   275 }
   240 }
   276 
   241 
   277 //-----------------------------------------------------------------------------
   242 void capabilitiesNativeToQt(const TMMFCapabilities &caps,
   278 // Public functions
   243                             const TFourCC &fourcc,
   279 //-----------------------------------------------------------------------------
       
   280 
       
   281 void capabilitiesNativeToQt(const DevSoundCapabilities &caps,
       
   282                             QList<int> &frequencies,
   244                             QList<int> &frequencies,
   283                             QList<int> &channels,
   245                             QList<int> &channels,
   284                             QList<int> &sampleSizes,
   246                             QList<int> &sampleSizes,
   285                             QList<QAudioFormat::Endian> &byteOrders,
   247                             QList<QAudioFormat::Endian> &byteOrders,
   286                             QList<QAudioFormat::SampleType> &sampleTypes) {
   248                             QList<QAudioFormat::SampleType> &sampleTypes) {
   290     byteOrders.clear();
   252     byteOrders.clear();
   291     sampleTypes.clear();
   253     sampleTypes.clear();
   292     channels.clear();
   254     channels.clear();
   293 
   255 
   294     for (int i=0; i<SampleRateCount; ++i)
   256     for (int i=0; i<SampleRateCount; ++i)
   295         if (caps.caps().iRate & SampleRateListNative[i])
   257         if (caps.iRate & SampleRateListNative[i])
   296             frequencies += SampleRateListQt[i];
   258             frequencies += SampleRateListQt[i];
   297 
   259 
   298     for (int i=0; i<ChannelsCount; ++i)
   260     for (int i=0; i<ChannelsCount; ++i)
   299         if (caps.caps().iChannels & ChannelsListNative[i])
   261         if (caps.iChannels & ChannelsListNative[i])
   300             channels += ChannelsListQt[i];
   262             channels += ChannelsListQt[i];
   301 
   263 
   302     for (int i=0; i<EncodingCount; ++i) {
   264     for (int i=0; i<EncodingCount; ++i) {
   303         if (caps.fourCC().Find(EncodingFourCC[i]) != KErrNotFound) {
   265         if (fourcc == EncodingFourCC[i]) {
   304             sampleSizes += EncodingSampleSize[i];
   266             sampleSizes += EncodingSampleSize[i];
   305             byteOrders += EncodingByteOrder[i];
   267             byteOrders += EncodingByteOrder[i];
   306             sampleTypes += EncodingSampleType[i];
   268             sampleTypes += EncodingSampleType[i];
   307         }
   269         }
   308     }
   270     }
   309 
       
   310 }
       
   311 
       
   312 bool isFormatSupported(const QAudioFormat &formatQt,
       
   313                        const DevSoundCapabilities &caps) {
       
   314     TMMFCapabilities formatNative;
       
   315     TUint32 fourCC;
       
   316 
       
   317     bool result = false;
       
   318     if (formatQt.codec() == QString::fromAscii("audio/pcm") &&
       
   319         formatQtToNative(formatQt, fourCC, formatNative)) {
       
   320         result =
       
   321                 (formatNative.iRate & caps.caps().iRate)
       
   322             &&  (formatNative.iChannels & caps.caps().iChannels)
       
   323             &&  (caps.fourCC().Find(fourCC) != KErrNotFound);
       
   324     }
       
   325     return result;
       
   326 }
   271 }
   327 
   272 
   328 bool formatQtToNative(const QAudioFormat &inputFormat,
   273 bool formatQtToNative(const QAudioFormat &inputFormat,
   329                       TUint32 &outputFourCC,
   274                       TUint32 &outputFourCC,
   330                       TMMFCapabilities &outputFormat) {
   275                       TMMFCapabilities &outputFormat) {
   335     // TInt, rather than MMF enumerated types.
   280     // TInt, rather than MMF enumerated types.
   336     TMMFSampleRate outputSampleRate;
   281     TMMFSampleRate outputSampleRate;
   337     TMMFMonoStereo outputChannels;
   282     TMMFMonoStereo outputChannels;
   338     TMMFSoundEncoding outputEncoding;
   283     TMMFSoundEncoding outputEncoding;
   339 
   284 
   340     if (inputFormat.codec() == QString::fromAscii("audio/pcm")) {
   285     if (inputFormat.codec() == QLatin1String("audio/pcm")) {
   341         result =
   286         result =
   342                 sampleRateQtToNative(inputFormat.frequency(), outputSampleRate)
   287                 sampleRateQtToNative(inputFormat.frequency(), outputSampleRate)
   343             &&  channelsQtToNative(inputFormat.channels(), outputChannels)
   288             &&  channelsQtToNative(inputFormat.channels(), outputChannels)
   344             &&  sampleInfoQtToNative(inputFormat.sampleSize(),
   289             &&  sampleInfoQtToNative(inputFormat.sampleSize(),
   345                                      inputFormat.byteOrder(),
   290                                      inputFormat.byteOrder(),
   355     }
   300     }
   356 
   301 
   357     return result;
   302     return result;
   358 }
   303 }
   359 
   304 
   360 QAudio::State stateNativeToQt(State nativeState,
   305 QAudio::State stateNativeToQt(State nativeState)
   361                               QAudio::State initializingState)
       
   362 {
   306 {
   363     switch (nativeState) {
   307     switch (nativeState) {
   364     case ClosedState:
   308     case ClosedState:
   365         return QAudio::StoppedState;
   309         return QAudio::StoppedState;
   366     case InitializingState:
   310     case InitializingState:
   367         return initializingState;
   311         return QAudio::StoppedState;
   368     case ActiveState:
   312     case ActiveState:
   369         return QAudio::ActiveState;
   313         return QAudio::ActiveState;
   370     case IdleState:
   314     case IdleState:
   371         return QAudio::IdleState;
   315         return QAudio::IdleState;
   372     case SuspendedState:
   316     case SuspendedState:
   386 {
   330 {
   387     return samples * (format.sampleSize() / 8) * format.channels();
   331     return samples * (format.sampleSize() / 8) * format.channels();
   388 }
   332 }
   389 
   333 
   390 } // namespace Utils
   334 } // namespace Utils
       
   335 
       
   336 
       
   337 //-----------------------------------------------------------------------------
       
   338 // DevSoundWrapper
       
   339 //-----------------------------------------------------------------------------
       
   340 
       
   341 DevSoundWrapper::DevSoundWrapper(QAudio::Mode mode, QObject *parent)
       
   342     :   QObject(parent)
       
   343     ,   m_mode(mode)
       
   344     ,   m_state(StateIdle)
       
   345     ,   m_devsound(0)
       
   346     ,   m_fourcc(0)
       
   347 {
       
   348     QT_TRAP_THROWING(m_devsound = CMMFDevSound::NewL());
       
   349 
       
   350     switch (mode) {
       
   351     case QAudio::AudioOutput:
       
   352         m_nativeMode = EMMFStatePlaying;
       
   353         break;
       
   354 
       
   355     case QAudio::AudioInput:
       
   356         m_nativeMode = EMMFStateRecording;
       
   357         break;
       
   358 
       
   359     default:
       
   360         Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
       
   361     }
       
   362 
       
   363     getSupportedCodecs();
       
   364 }
       
   365 
       
   366 DevSoundWrapper::~DevSoundWrapper()
       
   367 {
       
   368     delete m_devsound;
       
   369 }
       
   370 
       
   371 const QList<QString>& DevSoundWrapper::supportedCodecs() const
       
   372 {
       
   373     return m_supportedCodecs;
       
   374 }
       
   375 
       
   376 void DevSoundWrapper::initialize(const QString& codec)
       
   377 {
       
   378     Q_ASSERT(StateInitializing != m_state);
       
   379     m_state = StateInitializing;
       
   380     if (QLatin1String("audio/pcm") == codec) {
       
   381         m_fourcc = KMMFFourCCCodePCM16;
       
   382         TRAPD(err, m_devsound->InitializeL(*this, m_fourcc, m_nativeMode));
       
   383         if (KErrNone != err) {
       
   384             m_state = StateIdle;
       
   385             emit initializeComplete(err);
       
   386         }
       
   387     } else {
       
   388         emit initializeComplete(KErrNotSupported);
       
   389     }
       
   390 }
       
   391 
       
   392 const QList<int>& DevSoundWrapper::supportedFrequencies() const
       
   393 {
       
   394     Q_ASSERT(StateInitialized == m_state);
       
   395     return m_supportedFrequencies;
       
   396 }
       
   397 
       
   398 const QList<int>& DevSoundWrapper::supportedChannels() const
       
   399 {
       
   400     Q_ASSERT(StateInitialized == m_state);
       
   401     return m_supportedChannels;
       
   402 }
       
   403 
       
   404 const QList<int>& DevSoundWrapper::supportedSampleSizes() const
       
   405 {
       
   406     Q_ASSERT(StateInitialized == m_state);
       
   407     return m_supportedSampleSizes;
       
   408 }
       
   409 
       
   410 const QList<QAudioFormat::Endian>& DevSoundWrapper::supportedByteOrders() const
       
   411 {
       
   412     Q_ASSERT(StateInitialized == m_state);
       
   413     return m_supportedByteOrders;
       
   414 }
       
   415 
       
   416 const QList<QAudioFormat::SampleType>& DevSoundWrapper::supportedSampleTypes() const
       
   417 {
       
   418     Q_ASSERT(StateInitialized == m_state);
       
   419     return m_supportedSampleTypes;
       
   420 }
       
   421 
       
   422 bool DevSoundWrapper::isFormatSupported(const QAudioFormat &format) const
       
   423 {
       
   424     Q_ASSERT(StateInitialized == m_state);
       
   425     return m_supportedCodecs.contains(format.codec())
       
   426         && m_supportedFrequencies.contains(format.frequency())
       
   427         && m_supportedChannels.contains(format.channels())
       
   428         && m_supportedSampleSizes.contains(format.sampleSize())
       
   429         && m_supportedSampleTypes.contains(format.sampleType())
       
   430         && m_supportedByteOrders.contains(format.byteOrder());
       
   431 }
       
   432 
       
   433 int DevSoundWrapper::samplesProcessed() const
       
   434 {
       
   435     Q_ASSERT(StateInitialized == m_state);
       
   436     int result = 0;
       
   437     switch (m_mode) {
       
   438     case QAudio::AudioInput:
       
   439         result = m_devsound->SamplesRecorded();
       
   440         break;
       
   441     case QAudio::AudioOutput:
       
   442         result = m_devsound->SamplesPlayed();
       
   443         break;
       
   444     }
       
   445     return result;
       
   446 }
       
   447 
       
   448 bool DevSoundWrapper::setFormat(const QAudioFormat &format)
       
   449 {
       
   450     Q_ASSERT(StateInitialized == m_state);
       
   451     bool result = false;
       
   452     TUint32 fourcc;
       
   453     TMMFCapabilities nativeFormat;
       
   454     if (Utils::formatQtToNative(format, fourcc, nativeFormat)) {
       
   455         TMMFCapabilities currentNativeFormat = m_devsound->Config();
       
   456         nativeFormat.iBufferSize = currentNativeFormat.iBufferSize;
       
   457         TRAPD(err, m_devsound->SetConfigL(nativeFormat));
       
   458         result = (KErrNone == err);
       
   459     }
       
   460     return result;
       
   461 }
       
   462 
       
   463 bool DevSoundWrapper::start()
       
   464 {
       
   465     Q_ASSERT(StateInitialized == m_state);
       
   466     int err = KErrArgument;
       
   467     switch (m_mode) {
       
   468     case QAudio::AudioInput:
       
   469         TRAP(err, m_devsound->RecordInitL());
       
   470         break;
       
   471     case QAudio::AudioOutput:
       
   472         TRAP(err, m_devsound->PlayInitL());
       
   473         break;
       
   474     }
       
   475     return (KErrNone == err);
       
   476 }
       
   477 
       
   478 void DevSoundWrapper::pause()
       
   479 {
       
   480     Q_ASSERT(StateInitialized == m_state);
       
   481     m_devsound->Pause();
       
   482 }
       
   483 
       
   484 void DevSoundWrapper::stop()
       
   485 {
       
   486     m_devsound->Stop();
       
   487 }
       
   488 
       
   489 void DevSoundWrapper::bufferProcessed()
       
   490 {
       
   491     Q_ASSERT(StateInitialized == m_state);
       
   492     switch (m_mode) {
       
   493     case QAudio::AudioInput:
       
   494         m_devsound->RecordData();
       
   495         break;
       
   496     case QAudio::AudioOutput:
       
   497         m_devsound->PlayData();
       
   498         break;
       
   499     }
       
   500 }
       
   501 
       
   502 void DevSoundWrapper::getSupportedCodecs()
       
   503 {
       
   504 /*
       
   505  * TODO: once we support formats other than PCM, this function should
       
   506  * convert the array of FourCC codes into MIME types for each codec.
       
   507  *
       
   508     RArray<TFourCC> fourcc;
       
   509     QT_TRAP_THROWING(CleanupClosePushL(&fourcc));
       
   510 
       
   511     TMMFPrioritySettings settings;
       
   512     switch (mode) {
       
   513     case QAudio::AudioOutput:
       
   514         settings.iState = EMMFStatePlaying;
       
   515         m_devsound->GetSupportedInputDataTypesL(fourcc, settings);
       
   516         break;
       
   517 
       
   518     case QAudio::AudioInput:
       
   519         settings.iState = EMMFStateRecording;
       
   520         m_devsound->GetSupportedInputDataTypesL(fourcc, settings);
       
   521         break;
       
   522 
       
   523     default:
       
   524         Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid mode");
       
   525     }
       
   526 
       
   527     CleanupStack::PopAndDestroy(); // fourcc
       
   528 */
       
   529 
       
   530     m_supportedCodecs.append(QLatin1String("audio/pcm"));
       
   531 }
       
   532 
       
   533 void DevSoundWrapper::populateCapabilities()
       
   534 {
       
   535     m_supportedFrequencies.clear();
       
   536     m_supportedChannels.clear();
       
   537     m_supportedSampleSizes.clear();
       
   538     m_supportedByteOrders.clear();
       
   539     m_supportedSampleTypes.clear();
       
   540 
       
   541     const TMMFCapabilities caps = m_devsound->Capabilities();
       
   542 
       
   543     for (int i=0; i<Utils::SampleRateCount; ++i)
       
   544         if (caps.iRate & Utils::SampleRateListNative[i])
       
   545             m_supportedFrequencies += Utils::SampleRateListQt[i];
       
   546 
       
   547     for (int i=0; i<Utils::ChannelsCount; ++i)
       
   548         if (caps.iChannels & Utils::ChannelsListNative[i])
       
   549             m_supportedChannels += Utils::ChannelsListQt[i];
       
   550 
       
   551     for (int i=0; i<Utils::EncodingCount; ++i) {
       
   552         if (m_fourcc == Utils::EncodingFourCC[i]) {
       
   553             m_supportedSampleSizes += Utils::EncodingSampleSize[i];
       
   554             m_supportedByteOrders += Utils::EncodingByteOrder[i];
       
   555             m_supportedSampleTypes += Utils::EncodingSampleType[i];
       
   556         }
       
   557     }
       
   558 }
       
   559 
       
   560 void DevSoundWrapper::InitializeComplete(TInt aError)
       
   561 {
       
   562     Q_ASSERT(StateInitializing == m_state);
       
   563     if (KErrNone == aError) {
       
   564         m_state = StateInitialized;
       
   565         populateCapabilities();
       
   566     } else {
       
   567         m_state = StateIdle;
       
   568     }
       
   569     emit initializeComplete(aError);
       
   570 }
       
   571 
       
   572 void DevSoundWrapper::ToneFinished(TInt aError)
       
   573 {
       
   574     Q_UNUSED(aError)
       
   575     // This class doesn't use DevSound's tone playback functions, so should
       
   576     // never receive this callback.
       
   577     Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback");
       
   578 }
       
   579 
       
   580 void DevSoundWrapper::BufferToBeFilled(CMMFBuffer *aBuffer)
       
   581 {
       
   582     Q_ASSERT(QAudio::AudioOutput == m_mode);
       
   583     emit bufferToBeProcessed(aBuffer);
       
   584 }
       
   585 
       
   586 void DevSoundWrapper::PlayError(TInt aError)
       
   587 {
       
   588     Q_ASSERT(QAudio::AudioOutput == m_mode);
       
   589     emit processingError(aError);
       
   590 }
       
   591 
       
   592 void DevSoundWrapper::BufferToBeEmptied(CMMFBuffer *aBuffer)
       
   593 {
       
   594     Q_ASSERT(QAudio::AudioInput == m_mode);
       
   595     emit bufferToBeProcessed(aBuffer);
       
   596 }
       
   597 
       
   598 void DevSoundWrapper::RecordError(TInt aError)
       
   599 {
       
   600     Q_ASSERT(QAudio::AudioInput == m_mode);
       
   601     emit processingError(aError);
       
   602 }
       
   603 
       
   604 void DevSoundWrapper::ConvertError(TInt aError)
       
   605 {
       
   606     Q_UNUSED(aError)
       
   607     // This class doesn't use DevSound's format conversion functions, so
       
   608     // should never receive this callback.
       
   609     Q_ASSERT_X(false, Q_FUNC_INFO, "Unexpected callback");
       
   610 }
       
   611 
       
   612 void DevSoundWrapper::DeviceMessage(TUid aMessageType, const TDesC8 &aMsg)
       
   613 {
       
   614     Q_UNUSED(aMessageType)
       
   615     Q_UNUSED(aMsg)
       
   616     // Ignore this callback.
       
   617 }
       
   618 
       
   619 
   391 } // namespace SymbianAudio
   620 } // namespace SymbianAudio
   392 
   621 
   393 QT_END_NAMESPACE
   622 QT_END_NAMESPACE
   394 
   623 
   395 
   624