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) { |
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 |