diff -r e6ebb7730c4b -r 5fca9e46c6fa baseport/syborg/soundsc/shared_txsound.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/baseport/syborg/soundsc/shared_txsound.cpp Wed Oct 21 10:29:21 2009 +0100 @@ -0,0 +1,312 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +#include "shared_sound.h" +#include "variant_sound.h" + +void TimerCallback(TAny* aData) + { + DDriverSyborgSoundScPdd * soundscpdd = (DDriverSyborgSoundScPdd*) aData; + + soundscpdd->Callback(soundscpdd->iTransferArray[0].iTransferID, KErrNone, soundscpdd->iTransferArray[0].iNumBytes); + + } + + +DDriverSyborgSoundScPdd::DDriverSyborgSoundScPdd() : iTimer(TimerCallback,this) + { + + } + +DDriverSyborgSoundScPdd::~DDriverSyborgSoundScPdd() + { + iTimer.Cancel(); + } + + +TInt DDriverSyborgSoundScPdd::DoCreate() + { + + SetCaps(); + + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::DoCreate TxPdd"); + + return KErrNone; + } + +void DDriverSyborgSoundScPdd::GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo) + { + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::GetChunkCreateInfo TxPdd"); + + aChunkCreateInfo.iType = TChunkCreateInfo::ESharedKernelMultiple; + aChunkCreateInfo.iMapAttr = EMapAttrFullyBlocking; // No caching + aChunkCreateInfo.iOwnsMemory = ETrue; // Using RAM pages + aChunkCreateInfo.iDestroyedDfc = NULL; // No chunk destroy DFC + } + +void DDriverSyborgSoundScPdd::Caps(TDes8& aCapsBuf) const + { + + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::Caps TxPdd"); + + // Fill the structure with zeros in case it is a newer version than we know about + aCapsBuf.FillZ(aCapsBuf.MaxLength()); + + // And copy the capabilities into the packaged structure + TPtrC8 ptr((const TUint8*) &iCaps, sizeof(iCaps)); + aCapsBuf = ptr.Left(Min(ptr.Length(), aCapsBuf.MaxLength())); + } + +TInt DDriverSyborgSoundScPdd::SetConfig(const TDesC8& aConfigBuf) + { + + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::SetConfig TxPdd"); + + // Read the new configuration from the LDD + TCurrentSoundFormatV02 config; + TPtr8 ptr((TUint8*) &config, sizeof(config)); + Kern::InfoCopy(ptr, aConfigBuf); + + iConfig = config; + + return KErrNone; + } + + +TInt DDriverSyborgSoundScPdd::SetVolume(TInt aVolume) + { + + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::Setvolume TxPdd"); + + return KErrNone; + } + + +TInt DDriverSyborgSoundScPdd::StartTransfer() + { + + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::starttransfer TxPdd"); + + //Prepare for transfer + return KErrNone; + + } + +TInt DDriverSyborgSoundScPdd::CalculateBufferTime(TInt aNumBytes) + { + + TUint samplerate=0; + + // Let the compiler perform an integer division of rates + switch(iConfig.iRate) + { + case ESoundRate7350Hz: samplerate = 7350; break; + case ESoundRate8000Hz: samplerate = 8000; break; + case ESoundRate8820Hz: samplerate = 8820; break; + case ESoundRate9600Hz: samplerate = 9600; break; + case ESoundRate11025Hz: samplerate = 11025; break; + case ESoundRate12000Hz: samplerate = 12000; break; + case ESoundRate14700Hz: samplerate = 14700; break; + case ESoundRate16000Hz: samplerate = 16000; break; + case ESoundRate22050Hz: samplerate = 22050; break; + case ESoundRate24000Hz: samplerate = 24000; break; + case ESoundRate29400Hz: samplerate = 29400; break; + case ESoundRate32000Hz: samplerate = 32000; break; + case ESoundRate44100Hz: samplerate = 44100; break; + case ESoundRate48000Hz: samplerate = 48000; break; + } + + + // integer division by number of channels + aNumBytes /= iConfig.iChannels; + + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::iChannels =%d", iConfig.iChannels); + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::iEncoding =%d", iConfig.iEncoding); + + // integer division by bytes per sample + switch(iConfig.iEncoding) + { + case ESoundEncoding8BitPCM: break; + case ESoundEncoding16BitPCM: aNumBytes /= 2; break; + case ESoundEncoding24BitPCM: aNumBytes /= 3; break; + } + + return (aNumBytes * 1000) / samplerate; //return time in milliseconds + + + } + +TInt DDriverSyborgSoundScPdd::TransferData(TUint aTransferID, TLinAddr aLinAddr, TPhysAddr /*aPhysAddr*/, TInt aNumBytes) + { + + //function wil get called multiple times while transfer is in progress therefore keep fifo queue of requests + TTransferArrayInfo transfer; + + transfer.iTransferID = aTransferID; + transfer.iLinAddr = aLinAddr; + transfer.iNumBytes = aNumBytes; + + //calculate the amount of time required to play/record buffer + TInt buffer_play_time = CalculateBufferTime(aNumBytes); + TInt timerticks = NKern::TimerTicks(buffer_play_time); + transfer.iPlayTime = timerticks; + + iTransferArray.Append(transfer); + + //Timer will callback when correct time has elapsed, will return KErrInUse if transfer + //already active, this is ok becuase will be started again in callback + TInt err = iTimer.OneShot(timerticks, ETrue); + + + return KErrNone; + } + +void DDriverSyborgSoundScPdd::StopTransfer() + { + // Stop transfer + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::stoptransfer TxPdd"); + + //If timer is currently active then cancel it and call back buffer + if(iTimer.Cancel()) + { + Callback(iTransferArray[0].iTransferID, KErrNone, iTransferArray[0].iNumBytes); + } + + + } + + +TInt DDriverSyborgSoundScPdd::PauseTransfer() + { + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::pausetransfer TxPdd"); + //Pause Transfer + + return KErrNone; + } + + +TInt DDriverSyborgSoundScPdd::ResumeTransfer() + { + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::resumetransfer TxPdd"); + //Resume Transfer + + return KErrNone; + } + +TInt DDriverSyborgSoundScPdd::PowerUp() + { + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::PowerUp TxPdd"); + return KErrNone; + } + +void DDriverSyborgSoundScPdd::PowerDown() + { + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::Powerdown TxPdd"); + } + +TInt DDriverSyborgSoundScPdd::CustomConfig(TInt /*aFunction*/,TAny* /*aParam*/) + { + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::customconfig TxPdd"); + return KErrNotSupported; + } + + +void DDriverSyborgSoundScPdd::Callback(TUint aTransferID, TInt aTransferResult, TInt aBytesTransferred) + { + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::playcallback TxPdd"); + //Callback when Transfer completes or is stopped + + iTransferArray.Remove(0); + + if(iUnitType == KSoundScTxUnit0) + { + Ldd()->PlayCallback(aTransferID, aTransferResult, aBytesTransferred); + } + else if(iUnitType == KSoundScRxUnit0) + { + Ldd()->RecordCallback(aTransferID, aTransferResult, aBytesTransferred); + } + + if( iTransferArray.Count()>0) + { + iTimer.OneShot(iTransferArray[0].iPlayTime, ETrue); + } + + } + +TDfcQue*DDriverSyborgSoundScPdd::DfcQ() + { + return iPhysicalDevice->iDfcQ; + } + + +TInt DDriverSyborgSoundScPdd::MaxTransferLen() const + { + + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::MaxTransferLen TxPdd"); + + TInt maxlength = 200*1024; + return maxlength; + } + + +void DDriverSyborgSoundScPdd::SetCaps() + { + SYBORG_SOUND_DEBUG("DDriverSyborgSoundScPdd::SetCaps TxPdd"); + + if(iUnitType == KSoundScTxUnit0) + { + // The data transfer direction for this unit is play + iCaps.iDirection = ESoundDirPlayback; + } + else if(iUnitType == KSoundScTxUnit0) + { + // The data transfer direction for this unit is play + iCaps.iDirection = ESoundDirRecord; + } + + // This unit supports both mono and stereo + iCaps.iChannels = (KSoundMonoChannel | KSoundStereoChannel); + + // This unit supports only some of the sample rates offered by Symbian OS + iCaps.iRates = (KSoundRate8000Hz | KSoundRate11025Hz | KSoundRate12000Hz | KSoundRate16000Hz | + KSoundRate22050Hz | KSoundRate24000Hz | KSoundRate32000Hz | KSoundRate44100Hz | + KSoundRate48000Hz); + + // This unit only supports 16bit PCM encoding + iCaps.iEncodings = KSoundEncoding16BitPCM; + + // This unit only supports interleaved data format when playing stereo; that is, a PCM data + // stream where the left and right channel samples are interleaved as L-R-L-R-L-R etc. + iCaps.iDataFormats = KSoundDataFormatInterleaved; + + // The iRequestMinSize member is named badly. It is actually the value of which the length samples + // must be a multiple of. ie. The sample length % iRequestMinSize must == 0. This value must always + // be a power of 2 + iCaps.iRequestMinSize = 4; + + // The logarithm to base 2 of the alignment required for request arguments. DMA requests must be + // aligned to a 32 bit boundary + iCaps.iRequestAlignment = 2; + + // This unit is not capable of detecting changes in hardware configuration + iCaps.iHwConfigNotificationSupport = EFalse; + } + + + +