sl@0: // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include //for SwCodecWrapper CustomInterfaces sl@0: #include sl@0: #ifdef SYMBIAN_MULTIMEDIA_CODEC_API sl@0: #include sl@0: #endif // SYMBIAN_MULTIMEDIA_CODEC_API sl@0: #include "MmfDevSoundServer.h" sl@0: #include "MmfDevSoundSessionBody.h" sl@0: /* sl@0: * sl@0: * Initializes DevSound object for the mode aMode for processing audio data sl@0: * with hardware device aHWDev. sl@0: * sl@0: * On completion of Initialization, the observer will be notified via call back sl@0: * InitializeComplete(). sl@0: * sl@0: * Leaves on failure. sl@0: * sl@0: * @param "MDevSoundObserver& aDevSoundObserver" sl@0: * A reference to DevSound Observer instance. sl@0: * sl@0: * @param "TUid aHWDev" sl@0: * CMMFHwDevice implementation identifier. sl@0: * sl@0: * @param "TMMFState aMode" sl@0: * Mode for which this object will be used. sl@0: * sl@0: */ sl@0: sl@0: #ifdef _DEBUG sl@0: _LIT(KMMFDevSoundSessionCategory, "MMFDevSoundSessionCategory"); sl@0: inline void Panic(TInt aError) sl@0: { sl@0: User::Panic(KMMFDevSoundSessionCategory, aError); sl@0: } sl@0: enum TMMFDevSoundSessionPanics sl@0: { sl@0: TMMFDevSoundSessionPolicyNotInvalidated sl@0: }; sl@0: #endif sl@0: sl@0: inline void CMMFDevSoundSvrImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TUid aHWDev, TMMFState aMode) sl@0: { sl@0: TInt initError = KErrNone; sl@0: iDevSoundObserver = &aDevSoundObserver; sl@0: sl@0: if (aMode == EMMFStateIdle) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: iMode= static_cast (aMode); sl@0: iHasPolicy = EFalse; sl@0: sl@0: if (iMode == EMMFDevSoundStateRecording) sl@0: {//DEF037912 incase the recording capabilities differ from play sl@0: User::LeaveIfError(InitializeFormat(iRecordFormatsSupported, iRecordFormat)); sl@0: } sl@0: sl@0: sl@0: iDevSoundObserver = &aDevSoundObserver; sl@0: iHwDeviceID.iUid = aHWDev.iUid; sl@0: if(iCMMFHwDevice) sl@0: { sl@0: delete iCMMFHwDevice; sl@0: iHwDeviceBuffer = NULL; // buffer is deleted by HwDevice delete sl@0: iPlayCustomInterface = NULL; //custom interfaces are also invalid sl@0: iRecordCustomInterface = NULL; sl@0: iTimePlayedCustomInterface = NULL; sl@0: } sl@0: sl@0: iCMMFHwDevice = NULL; sl@0: sl@0: // Load the HwDevice implementation from ECom sl@0: TRAP(initError,iCMMFHwDevice = CMMFHwDevice::NewL(aHWDev));//trap it to get debug print sl@0: sl@0: if (initError == KErrNone) sl@0: { sl@0: #ifdef SYMBIAN_MULTIMEDIA_CODEC_API sl@0: if (iFourCCSet) sl@0: { sl@0: MMdfHwDeviceSetup* setup = reinterpret_cast(iCMMFHwDevice->CustomInterface(KUidHwDeviceSetupInterface)); sl@0: if (setup!=NULL) sl@0: { sl@0: setup->SetDataTypesL(iSrcFourCC, iDestFourCC); sl@0: } sl@0: } sl@0: #endif // SYMBIAN_MULTIMEDIA_CODEC_API sl@0: iDevInfo.iHwDeviceObserver = this; sl@0: initError = iCMMFHwDevice->Init(iDevInfo); sl@0: if (initError == KErrNone) sl@0: { sl@0: TUid playCustomInterfaceUid; sl@0: playCustomInterfaceUid.iUid = KMmfPlaySettingsCustomInterface; sl@0: TUid recordCustomInterfaceUid; sl@0: recordCustomInterfaceUid.iUid = KMmfRecordSettingsCustomInterface; sl@0: iPlayCustomInterface = sl@0: (MPlayCustomInterface*)iCMMFHwDevice->CustomInterface(playCustomInterfaceUid); sl@0: if (!iPlayCustomInterface) sl@0: {//DEF40443 need to check custom interface has been created sl@0: initError = KErrNoMemory;//it won't if there is no memory sl@0: } sl@0: else sl@0: { sl@0: iRecordCustomInterface = sl@0: (MRecordCustomInterface*)iCMMFHwDevice->CustomInterface(recordCustomInterfaceUid); sl@0: if (!iRecordCustomInterface) sl@0: initError = KErrNoMemory; sl@0: } sl@0: } sl@0: } sl@0: sl@0: // in the InitializeComplete() call we will signal the observer that the sl@0: // custom interface may have changed sl@0: iDevSoundObserver->InitializeComplete(initError); sl@0: sl@0: if (initError) sl@0: { sl@0: User::Leave(initError); sl@0: } sl@0: __ASSERT_DEBUG(!(iHasPolicy&&(iMode == EMMFDevSoundStatePlaying)), Panic(TMMFDevSoundSessionPolicyNotInvalidated)); sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Initializes DevSound object for the mode aMode for processing audio data sl@0: * with hardware device supporting FourCC aDesiredFourCC. sl@0: * sl@0: * On completion of Initialization, the observer will be notified via call back sl@0: * InitializeComplete(). sl@0: * sl@0: * Leaves on failure. sl@0: * sl@0: * @param "MDevSoundObserver& aDevSoundObserver" sl@0: * A reference to DevSound Observer instance. sl@0: * sl@0: * @param "TFourCC aDesiredFourCC" sl@0: * CMMFHwDevice implementation FourCC. sl@0: * sl@0: * @param "TMMFState aMode" sl@0: * Mode for which this object will be used. sl@0: * sl@0: */ sl@0: inline void CMMFDevSoundSvrImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TFourCC aDesiredFourCC, TMMFState aMode) sl@0: { sl@0: // to get HW Uid from the FourCC sl@0: RImplInfoPtrArray plugInArray; sl@0: TFourCC KPCM16FourCC(' ','P','1','6'); sl@0: _LIT(KNullString, ""); sl@0: sl@0: TUid hwDevicePluginInterface = {KMmfUidPluginInterfaceHwDevice}; sl@0: TUid implUid = {0}; sl@0: sl@0: CleanupResetAndDestroyPushL( plugInArray ); sl@0: // Get the implementation UID based on the FourCC and mode. sl@0: #ifdef SYMBIAN_MULTIMEDIA_CODEC_API sl@0: TInt err = KErrNone; sl@0: RArray dataTypes; sl@0: CleanupClosePushL(dataTypes); sl@0: sl@0: TRAP(err, iDevSoundUtil->SeekCodecPluginsL(dataTypes, aMode, EFalse)); sl@0: // if we find a new codec plugin sl@0: TBool found = EFalse; sl@0: if (!err && dataTypes.Find(aDesiredFourCC)!=KErrNotFound) sl@0: { sl@0: TRAP(err, iDevSoundUtil->FindHwDeviceAdapterL(hwDevicePluginInterface, plugInArray)); sl@0: if (err == KErrNone) sl@0: { sl@0: if (aMode == EMMFDevSoundStatePlaying) sl@0: {//destination four CC is pcm16 sl@0: iFourCCSet = ETrue; sl@0: iSrcFourCC = aDesiredFourCC; sl@0: iDestFourCC = KPCM16FourCC; sl@0: } sl@0: else if (aMode == EMMFDevSoundStateRecording) sl@0: {//source fourCC is pcm16 sl@0: iFourCCSet = ETrue; sl@0: iSrcFourCC = KPCM16FourCC; sl@0: iDestFourCC = aDesiredFourCC; sl@0: } sl@0: found = ETrue; sl@0: } sl@0: } sl@0: if (!found) sl@0: #endif // SYMBIAN_MULTIMEDIA_CODEC_API sl@0: { sl@0: plugInArray.ResetAndDestroy(); sl@0: if (aMode == EMMFDevSoundStatePlaying) sl@0: {//destination four CC is pcm16 sl@0: iFourCCSet = ETrue; sl@0: iSrcFourCC = aDesiredFourCC; sl@0: iDestFourCC = KPCM16FourCC; sl@0: iDevSoundUtil->SeekUsingFourCCL(hwDevicePluginInterface, plugInArray, aDesiredFourCC, KPCM16FourCC, KNullString); sl@0: } sl@0: else if (aMode == EMMFDevSoundStateRecording) sl@0: {//source fourCC is pcm16 sl@0: iFourCCSet = ETrue; sl@0: iSrcFourCC = KPCM16FourCC; sl@0: iDestFourCC = aDesiredFourCC; sl@0: iDevSoundUtil->SeekUsingFourCCL(hwDevicePluginInterface, plugInArray, KPCM16FourCC, aDesiredFourCC, KNullString); sl@0: } sl@0: else sl@0: { sl@0: User::Leave(KErrNotSupported);//invalid aMode cant set 4CC for tone sl@0: } sl@0: } sl@0: sl@0: sl@0: if(plugInArray.Count() == 0) sl@0: { // couldn't find Decoder only implementation, try to get Decoder/Encoder sl@0: iDevSoundUtil->SeekUsingFourCCL(hwDevicePluginInterface, plugInArray, aDesiredFourCC, aDesiredFourCC, KNullString); sl@0: if(plugInArray.Count() == 0) sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: implUid = plugInArray[0]->ImplementationUid(); // Just pick the first in the list sl@0: sl@0: #ifdef SYMBIAN_MULTIMEDIA_CODEC_API sl@0: CleanupStack::PopAndDestroy(2, &plugInArray) ; //pluginArray, dataTypes sl@0: #else sl@0: CleanupStack::PopAndDestroy() ; //pluginArray sl@0: #endif // SYMBIAN_MULTIMEDIA_CODEC_API sl@0: // If we made it here, there we have found implementation UID sl@0: InitializeL(aDevSoundObserver, implUid, aMode); sl@0: __ASSERT_DEBUG(!(iHasPolicy&&(iMode == EMMFDevSoundStatePlaying)), Panic(TMMFDevSoundSessionPolicyNotInvalidated)); sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns the supported Audio settings. sl@0: * sl@0: * @return "TMMFCapabilities" sl@0: * Device settings. sl@0: * sl@0: */ sl@0: inline TMMFCapabilities CMMFDevSoundSvrImp::Capabilities() sl@0: { sl@0: return iDeviceCapabilities; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns the current audio settings. sl@0: * sl@0: * @return "TMMFCapabilities" sl@0: * Device settings. sl@0: * sl@0: */ sl@0: inline TMMFCapabilities CMMFDevSoundSvrImp::Config() const sl@0: { sl@0: return iDeviceConfig; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns an integer representing the maximum volume. sl@0: * sl@0: * This is the maximum value which can be passed to CMMFDevSoundProxy::SetVolume. sl@0: * sl@0: * @return "TInt" sl@0: * The maximum volume. This value is platform dependent but is always sl@0: * greater than or equal to one. sl@0: * sl@0: */ sl@0: inline TInt CMMFDevSoundSvrImp::MaxVolume() sl@0: { sl@0: return iPlayFormatsSupported().iMaxVolume; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns an integer representing the current volume. sl@0: * sl@0: * @return "TInt" sl@0: * The current volume level. sl@0: * sl@0: */ sl@0: inline TInt CMMFDevSoundSvrImp::Volume() sl@0: { sl@0: return iVolume; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns an integer representing the maximum gain. sl@0: * sl@0: * This is the maximum value which can be passed to CMMFDevSoundProxy::SetGain. sl@0: * sl@0: * @return "TInt" sl@0: * The maximum gain. This value is platform dependent but is always sl@0: * greater than or equal to one. sl@0: * sl@0: */ sl@0: inline TInt CMMFDevSoundSvrImp::MaxGain() sl@0: { sl@0: return iRecordFormatsSupported().iMaxVolume;//uses iMaxVolume for iMaxGain sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns an integer representing the current gain. sl@0: * sl@0: * @return "TInt" sl@0: * The current gain level. sl@0: * sl@0: */ sl@0: inline TInt CMMFDevSoundSvrImp::Gain() sl@0: { sl@0: return iGain; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns the speaker balance set for playing. sl@0: * sl@0: * Leaves on failure. sl@0: * sl@0: * @param "TInt& aLeftPrecentage" sl@0: * On return contains the left speaker volume percentage. sl@0: * sl@0: * @param "TInt& aRightPercentage" sl@0: * On return contains the right speaker volume percentage. sl@0: * sl@0: */ sl@0: inline void CMMFDevSoundSvrImp::GetPlayBalanceL(TInt& aLeftPercentage, TInt& aRightPercentage) sl@0: { sl@0: aLeftPercentage = iLeftPlayBalance; sl@0: aRightPercentage = iRightPlayBalance; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns the microphone gain balance set for recording. sl@0: * sl@0: * Leaves on failure. sl@0: * sl@0: * @param "TInt& aLeftPercentage" sl@0: * On return contains the left microphone gain percentage. sl@0: * sl@0: * @param "TInt& aRightPercentage" sl@0: * On return contains the right microphone gain percentage. sl@0: * sl@0: */ sl@0: inline void CMMFDevSoundSvrImp::GetRecordBalanceL(TInt& aLeftPercentage, TInt& aRightPercentage) sl@0: { sl@0: aLeftPercentage = iLeftRecordBalance; sl@0: aRightPercentage = iRightRecordBalance; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Contine the process of recording. Once the buffer is filled with recorded sl@0: * data, the Observer gets reference to buffer along with callback sl@0: * BufferToBeEmptied(). After processing the buffer (copying over to a sl@0: * different buffer or writing to file) the client should call this sl@0: * method to continue recording process. sl@0: * sl@0: */ sl@0: inline TBool CMMFDevSoundSvrImp::RecordData(const RMmfIpcMessage& aMessage) sl@0: { sl@0: ASSERT(iDevSoundObserver); sl@0: if(iAudioPolicyPrioritySettings.iState != EMMFStateRecordData) sl@0: { sl@0: PanicClient(aMessage, EMMFDevSoundRecordDataWithoutInitialize); sl@0: return EFalse; sl@0: } sl@0: // Checkes if the client has a UserEnvironment capability sl@0: if (!aMessage.HasCapability(ECapabilityUserEnvironment)) sl@0: { sl@0: iDevSoundObserver->RecordError(KErrPermissionDenied); sl@0: return ETrue; sl@0: } sl@0: if(iCMMFHwDevice) sl@0: { sl@0: if ((iMode == EMMFDevSoundStateRecording) && iHasPolicy) sl@0: { sl@0: iHwDeviceBuffer->Data().SetLength(iHwDeviceBuffer->RequestSize()); sl@0: TInt error = iCMMFHwDevice->ThisHwBufferEmptied(*iHwDeviceBuffer); sl@0: if(error != KErrNone) sl@0: { sl@0: Error(error); sl@0: iCMMFHwDevice->Stop(); sl@0: } sl@0: sl@0: } sl@0: } sl@0: return ETrue; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Defines the number of times the audio is to be repeated during the tone sl@0: * playback operation. sl@0: * sl@0: * A period of silence can follow each playing of tone. The tone playing can sl@0: * be repeated indefinitely. sl@0: * sl@0: * @param "TInt aRepeatCount" sl@0: * The number of times the tone, together with the trailing silence, sl@0: * is to be repeated. If this is set to KMdaRepeatForever, then the sl@0: * tone, together with the trailing silence, is repeated indefinitely sl@0: * or until Stop() is called. If this is set to zero, then the tone is sl@0: * not repeated. sl@0: * sl@0: * Supported only during tone playing. sl@0: * sl@0: */ sl@0: inline void CMMFDevSoundSvrImp::SetToneRepeats(TInt aRepeatCount, sl@0: const TTimeIntervalMicroSeconds& aRepeatTrailingSilence) sl@0: { sl@0: iRepeatCount = aRepeatCount; sl@0: iRepeatTrailingSilence = aRepeatTrailingSilence; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Defines the priority settings that should be used for this instance. sl@0: * sl@0: * @param "const TMMFPrioritySettings& aPrioritySettings" sl@0: * An class type representing the client's priority, priority sl@0: * preference and state. sl@0: * sl@0: */ sl@0: inline void CMMFDevSoundSvrImp::SetPrioritySettings(const TMMFPrioritySettings& aPrioritySettings) sl@0: { sl@0: iAudioPolicyPrioritySettings.iPref = aPrioritySettings.iPref; sl@0: iAudioPolicyPrioritySettings.iPriority = aPrioritySettings.iPriority; sl@0: } sl@0: sl@0: // Currently only support bitrate custom interface sl@0: inline TAny* CMMFDevSoundSvrImp::CustomInterface(TUid aInterfaceId) sl@0: { sl@0: TAny* ptr = NULL; sl@0: if (iCMMFHwDevice) sl@0: { sl@0: ptr = iCMMFHwDevice->CustomInterface(aInterfaceId); sl@0: } sl@0: sl@0: return ptr; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns the number of available pre-defined tone sequences. sl@0: * sl@0: * This is the number of fixed sequence supported by DevSound by default. sl@0: * sl@0: * @return "TInt" sl@0: * The fixed sequence count. This value is implementation dependent sl@0: * but is always greater than or equal to zero. sl@0: * sl@0: */ sl@0: inline TInt CMMFDevSoundSvrImp::FixedSequenceCount() sl@0: { sl@0: return iFixedSequences->Count(); sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns the name assigned to a specific pre-defined tone sequence. sl@0: * sl@0: * This is the number of fixed sequence supported by DevSound by default. sl@0: * sl@0: * The function raises a panic if sequence number specified invalid. sl@0: * sl@0: * @return "TDesC&" sl@0: * A reference to a Descriptor containing the fixed sequence sl@0: * name indexed by aSequenceNumber. sl@0: * sl@0: * @param "TInt aSequenceNumber" sl@0: * The index identifying the specific pre-defined tone sequence. Index sl@0: * values are relative to zero. sl@0: * This can be any value from zero to the value returned by a call to sl@0: * FixedSequenceCount() - 1. sl@0: * The function raises a panic if sequence number is not within this sl@0: * range. sl@0: * sl@0: * @see FixedSequenceCount() sl@0: * sl@0: */ sl@0: inline const TDesC& CMMFDevSoundSvrImp::FixedSequenceName(TInt aSequenceNumber) sl@0: { sl@0: ASSERT((aSequenceNumber >= 0)&&(aSequenceNumber < iFixedSequences->Count())); sl@0: return iDevSoundUtil->FixedSequenceName(aSequenceNumber); sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Sets Id for this instance of DevSound sl@0: * sl@0: * @param "TInt aDevSoundId" sl@0: * Integer value assigned by Audio Policy Server sl@0: * sl@0: */ sl@0: inline void CMMFDevSoundSvrImp::SetDevSoundId(TInt aDevSoundId) sl@0: { sl@0: iDevSoundInfo.iDevSoundId = aDevSoundId; sl@0: } sl@0: sl@0: /* sl@0: * sl@0: * Returns information about this DevSound instance. sl@0: * sl@0: * This method is used by Audio Policy Server to make audio policy decisions. sl@0: * sl@0: * @return "TMMFDevSoundinfo" sl@0: * A reference to TMMFDevSoundinfo object holding the current settings sl@0: * of this DevSound instance. sl@0: * sl@0: */ sl@0: inline TMMFDevSoundInfo CMMFDevSoundSvrImp::DevSoundInfo() sl@0: { sl@0: return iDevSoundInfo; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Updates the total bytes played. sl@0: * sl@0: */ sl@0: inline void CMMFDevSoundSvrImp::UpdateBytesPlayed() sl@0: { sl@0: if (iPlayCustomInterface) sl@0: iPlayedBytesCount = iPlayCustomInterface->BytesPlayed(); sl@0: }