diff -r 000000000000 -r 71ca22bcf22a mmfenh/enhancedmediaclient/Plugins/ProgDLSource/src/ProgDLSource.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmfenh/enhancedmediaclient/Plugins/ProgDLSource/src/ProgDLSource.cpp Tue Feb 02 01:08:46 2010 +0200 @@ -0,0 +1,1803 @@ +/* +* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: Implementation of ProgDLSource. +* +*/ + + +#include +#include +#include +#include +#include +#include +#include "ProgDLDataSource.h" +#include "ProgDLMultimediaSource.h" +#include "MmffilePriv.h" +#include "FileAccess.h" +#include "SinkQueueItem.h" +#include "ProgDLSourceCustomCommands.h" +#include +#include "ProgDLSourceUid.h" +#include "AudioConfigurationPrivateCRKeys.h" + +#ifdef _DEBUG +#define DEBPRN1(str) RDebug::Print(str); +#define DEBPRN2(str, val1) RDebug::Print(str, val1); +#define DEBPRN3(str, val1, val2) RDebug::Print(str, val1, val2); +#define DEBPRN4(str, val1, val2, val3) RDebug::Print(str, val1, val2, val3); +#define DEBPRN5(str, val1, val2, val3, val4) RDebug::Print(str, val1, val2, val3, val4); +#else +#define DEBPRN1(str) +#define DEBPRN2(str, val1) +#define DEBPRN3(str, val1, val2) +#define DEBPRN4(str, val1, val2, val3) +#define DEBPRN5(str, val1, val2, val3, val4) +#endif // _DEBUG + +const TUint KMinPlaybackDuration = 15; // 15 second + +void Panic(TMMFFilePanicCode aPanicCode) + { + _LIT(KMMFFilePanicCategory, "MMFFile"); + User::Panic(KMMFFilePanicCategory, aPanicCode); + } + + /** + * Constructs a CTransferBufferCopy + * + * @return CTransferBufferCopy* +*/ +CTransferBufferCopy* CTransferBufferCopy::NewL(TInt aMaxLength) + { + CTransferBufferCopy* self = new (ELeave) CTransferBufferCopy(aMaxLength); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + /** + * Second phase constructor for CTransferBufferCopy + * + * @return void +*/ +void CTransferBufferCopy::ConstructL() + { + iBuffer = static_cast(User::AllocL(iMaxLength)); + iBufferDes.Set(iBuffer,0,iMaxLength); + } + +/************************/ +CProgDLSource* CProgDLSource::NewL(TUid aType ) + { + DEBPRN1(_L("CProgDLSource::NewL")); + CProgDLSource* self = new (ELeave) CProgDLSource(aType); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CProgDLSource::CProgDLSource(TUid aType) +: MDataSource(aType) + { + iInitData = NULL; + } + +CProgDLSource::~CProgDLSource(void) + { + delete iInitData; + iInitData = NULL; + } + +void CProgDLSource::ConstructL (void) + { + } + +// From MDataSource begins +TUid CProgDLSource::DataSourceType() const + { + return KMmfProgDLSource; + } + + +TFourCC CProgDLSource::SourceDataTypeCode(TMediaId /*aMediaId*/ ) + { + TFourCC fourCC; + return iMultiMediaSource->GetDataTypeCode(fourCC); + } + +TInt CProgDLSource::SetSourceDataTypeCode(TFourCC aSourceFourCC, + TMediaId /*aMediaId*/ ) + { + iMultiMediaSource->SetDataTypeCode(aSourceFourCC); + return KErrNone; + } + +void CProgDLSource::FillBufferL(CMMFBuffer* aBuffer, + MDataSink* aConsumer, + TMediaId aMediaId ) + { + iMultiMediaSource->FillBufferL(aBuffer,aConsumer,aMediaId); + } + +void CProgDLSource::BufferEmptiedL(CMMFBuffer* /*aBuffer*/ ) + { + User::Leave(KErrUnknown); + } + +TBool CProgDLSource::CanCreateSourceBuffer() + { + return EFalse; + } + +CMMFBuffer* CProgDLSource::CreateSourceBufferL(TMediaId /*aMediaId*/, + TBool &/*aReference*/ ) + { + return NULL; + } + +TInt CProgDLSource::SourceThreadLogon( MAsyncEventHandler& /*aEventHandler*/ ) + { + return iMultiMediaSource->Open(); + } + +void CProgDLSource::SourceThreadLogoff() + { + iMultiMediaSource->Close(); + } + +void CProgDLSource::SourcePrimeL() + { + DEBPRN1(_L("CProgDLSource::SourcePrimeL")); + User::LeaveIfError(iMultiMediaSource->Prime()); + } + +void CProgDLSource::SourcePlayL() + { + DEBPRN1(_L("CProgDLSource::SourcePlayL")); + User::LeaveIfError(iMultiMediaSource->Play()); + } + +void CProgDLSource::SourceStopL() + { + DEBPRN1(_L("CProgDLSource::SourceStopL")); + User::LeaveIfError(iMultiMediaSource->Stop()); + } + + +void CProgDLSource::ConstructSourceL(const TDesC8& aInitData ) + { + if(iInitData) + { + delete iInitData; + iInitData = NULL; + } + iInitData = aInitData.AllocL(); + } + +void CProgDLSource::SourceCustomCommand(TMMFMessage& aMessage) + { + iMultiMediaSource->SourceCustomCommand(aMessage); + } + +void CProgDLSource::SetMultimediaSource(CProgDLMultimediaSource& aMultimediaSource) + { + iMultiMediaSource = &aMultimediaSource; + } + +TDesC8& CProgDLSource::GetInitData() + { + return *iInitData; + } +/****************************/ + + +EXPORT_C CProgDLMultimediaSource* CProgDLMultimediaSource::NewL(MDataSource& aDataSource) + { + DEBPRN1(_L("CProgDLMultimediaSource::NewL")); + CProgDLMultimediaSource* self = new (ELeave) CProgDLMultimediaSource(aDataSource); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + /** + Destructor. +*/ +CProgDLMultimediaSource::~CProgDLMultimediaSource() + { + DEBPRN1(_L("CProgDLMultimediaSource::~CProgDLMultimediaSource() ")); + delete iInitData; + delete iFile; + EmptySinkQueue(); + iHandle.Close(); + iFsSession.Close(); + delete iFileName; + delete iFileExt; + delete iFilePath; + delete iFileDrive; + + + delete iCAFParameters; + delete iSinkQueue; + delete iAudioConfigRepository; + + if(iMessage) + { + if(!iMessage->IsCompleted()) + { + iMessage->Complete(KErrDied); + delete iMessage; + iMessage = NULL; + } + } + // Get rid of everything in RArray's & close them. + iRequests.ResetAndDestroy(); + iTransferBufferCopies.ResetAndDestroy(); + DEBPRN1(_L("CProgDLMultimediaSource::~CProgDLMultimediaSource() exit")); + } + + /** + Protected constructor. + + The default implementation is empty. +*/ +CProgDLMultimediaSource::CProgDLMultimediaSource(MDataSource& aDataSource) + : iSnkItemsCount(0), + iSnkBytes(0), + iDownloadSize(0), + iTransferRate(0), + //iConsumer(NULL), + iBufferedDataSize(0), + iDLFileSize(0), + isDownloadComplete(EFalse), + iFileSize(0), + iParentDataSource(&aDataSource) + { + iMessage = NULL; + iFile = NULL; + iState = ECLOSED; + iObserver = NULL; + iReadRequestPending = 0; + iReOpenCAF = EFalse; + iObserverBitRate = 0; + } + + /** + Constructs an CProgDLMultimediaSource MDataSource. + + @return A pointer to the new CProgDLMultimediaSource data source. +*/ +/*MDataSource* CProgDLMultimediaSource::NewSourceL() +{ +CProgDLMultimediaSource* self = new (ELeave) CProgDLMultimediaSource( KMmfProgDLSource ) ; +return STATIC_CAST( MDataSource*, self ) ; + }*/ + + + /** + Perform source construction dependant on the source construction + initialisation data aInitData. + + @param aInitData + The TPckg descriptor package containing the file name and full path. +*/ +void CProgDLMultimediaSource::ConstructL() + { + CProgDLSource* progDLSource = static_cast(iParentDataSource); + iInitData = (progDLSource->GetInitData()).AllocL(); + progDLSource->SetMultimediaSource(*this); + ConstructL(*iInitData, ESourceMode); + iSinkQueue = new(ELeave) TSglQue(_FOFF(CSinkQueueItem, iLink)); + } + + + /** + Protected constructor. + + Extracts the initialisation data provided by the calling functions: ConstructSourceL() and + ConstructSinkL(). Creates a file server session and sets up file name. If there is a file name and + it cannot be found this function leaves. If there is no file name the function leaves. Does not + attempt to open the file or check whether the file exists. + + If aInitData contains a TMMFFileHandleParams instead of TMMFFileParams, the source/sink is constructed from + the file handle provided by the caller + + @param aInitData + Initialisation data packaged in a TMMFFileParams or in a TMMFFileHandleParams (File Handle) +*/ +void CProgDLMultimediaSource::ConstructL(const TDesC8& aInitData,TMMFileMode aFileMode) + { + User::LeaveIfError(iFsSession.Connect()); + // on IPCv2 we auto attach + User::LeaveIfError(iFsSession.ShareAuto()); + + User::LeaveIfError(iFsSession.ShareProtected()); + + TBool fileInit = EFalse; + HBufC* filename = NULL; + TBool filenamePushed = EFalse; + + iCAFParameters = new (ELeave) CCAFParameters; + TBool drmContent = EFalse; + RDesReadStream stream(aInitData); + CleanupClosePushL(stream); + + iAudioConfigRepository = CRepository::NewL(KCRUidAudioConfiguration); + + // From Central Repository + GetAudioConfiguration(); + + TUid initUid; + + initUid = TUid::Uid(stream.ReadInt32L()); + + if (initUid == KMMFileHandleSourceUid) + { + TPckgBuf fileptr; + stream.ReadL(fileptr); + + iHandle.Duplicate(*fileptr()); + + TInt length; + length = stream.ReadInt32L(); + if (length>0) + { + iCAFParameters->iUniqueId = HBufC::NewL(length); + TPtr16 ptr = iCAFParameters->iUniqueId->Des(); + stream.ReadL(ptr, length); + } + iFileHandle = ETrue; + filename = HBufC::NewMaxL(KMaxFileName); + TPtr ptr = filename->Des(); + iHandle.Name(ptr); + fileInit = ETrue; + drmContent = ETrue; + + iCAFParameters->iEnableUI = stream.ReadInt32L(); + } + + else if (initUid == KMMFileSourceUid) + { + TInt length; + length = stream.ReadInt32L(); + filename = HBufC::NewMaxLC(length); + TPtr ptr = filename->Des(); + stream.ReadL(ptr, length); + + length = stream.ReadInt32L(); + if (length>0) + { + iCAFParameters->iUniqueId = HBufC::NewMaxL(length); + ptr.Set(iCAFParameters->iUniqueId->Des()); + stream.ReadL(ptr, length); + } + CleanupStack::Pop(filename); + + fileInit = ETrue; + drmContent = ETrue; + iFileHandle = EFalse; + iCAFParameters->iEnableUI = stream.ReadInt32L(); + } + else + { + // TODO If the UID is unknown we should reject, but currently + // code also used for older calls that just supply filename. + // User::Leave(KErrNotSupported); + } + + CleanupStack::PopAndDestroy(&stream); + + if (!fileInit && aInitData.Length() == sizeof(TMMFFileHandleParams)) + { + TMMFFileHandleParams params; + TPckgC config(params); + config.Set(aInitData); + params = config(); + + + if (params.iUid == KFileHandleUid) + { + fileInit = ETrue; + User::LeaveIfError(iHandle.Duplicate(*params.iFile)); + TInt pos = 0; + // make sure the duplicate handle is at the start of the file - the usage of the file handle really requires this + User::LeaveIfError(iHandle.Seek(ESeekStart, pos)); + iFileHandle = ETrue; + filename = HBufC::NewMaxLC(KMaxFileName); + filenamePushed = ETrue; + TPtr ptr = filename->Des(); + User::LeaveIfError(iHandle.Name(ptr)); + } + } + + if (!fileInit) // do old case as last resort + { + TMMFFileParams params; + TPckgC config(params); + config.Set(aInitData); + params = config(); + + filename = params.iPath.AllocL(); + fileInit = ETrue; + } + + if (!filenamePushed) + { + // from now on it is assumed pushed. + CleanupStack::PushL(filename); + } + + TParse parser ; + User::LeaveIfError(parser.Set(*filename, NULL, NULL)); + CleanupStack::PopAndDestroy(filename); + if ( !( parser.NamePresent() ) && !( parser.ExtPresent() ) ) + User::Leave( KErrBadName ) ; + + iFullFileName.Copy( parser.FullName() ) ; + iFileName = parser.Name().AllocL() ; + iFileExt = parser.Ext().AllocL() ; + iFilePath = parser.Path().AllocL() ; + iFileDrive = parser.Drive().AllocL() ; + + // in order to simulate old behaviour we are not passing error out + // but will try to create Content again during PrimeL() + if (fileInit && drmContent && aFileMode==ESourceMode) + { + TInt contentError; + if (iFileHandle) + { + TRAP(contentError, + iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI); + ); + } + else + { + // Open for read-only access + TRAP(contentError, + iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareAny, iCAFParameters->iEnableUI); + ); + } + } + } + + +/** +@deprecated + +Returns an RFile handle to the current file. + +If there is no current file, one is created. If the file exists then it is opened with read access +if it is read only, write access otherwise. If the file does not exist then it is opened with +write access. + +@leave KErrNotReady +The file is not open. + +@return A handle to the current file. +*/ +RFile& CProgDLMultimediaSource::FileL() + { + if (!iFile) + User::Leave(KErrNotReady); + if (iFileHandle) + return iHandle; + else + return iFile->FileL(); + } + +/** +Returns the file name of the current file. + + Note: This will give the wrong answer if the file is renamed! + + @return The FileName (without extension). +*/ +const TDesC& CProgDLMultimediaSource::FileName() const + { + return *iFileName ; + } + +/** +Returns the extension of the current file. + +Note: This will give the wrong answer if the file is renamed! + +@return The File Extension. +*/ +const TDesC& CProgDLMultimediaSource::Extension() const + { + return *iFileExt ; + } + +/** +Returns the path of the current file. + +Note: This will give the wrong answer if the file is renamed! + +@return The FilePath (without filename and extension) +*/ +const TDesC& CProgDLMultimediaSource::FilePath() const + { + return *iFilePath ; + } + +/** +Returns the drive on which the current file is located. + +Note: This will give the wrong answer if the file is renamed! + +@return The FileDrive (drive letter only, without path, filename and extension). +*/ +const TDesC& CProgDLMultimediaSource::FileDrive() const + { + return *iFileDrive ; + } + +/** +Returns the full name of the current file. + +Note: This will give the wrong answer if the file is renamed! + +@return The file name (full filename including drive letter, without path, filename and extension). +*/ +const TFileName CProgDLMultimediaSource::FullName() const + { + return iFullFileName; + } + +/** +Returns the uniqueID associated with this content. If no uniqueID has been provided, a null +descriptor will be provided + +@return The UniqueID +*/ +const TDesC& CProgDLMultimediaSource::UniqueId() const + { + if (iCAFParameters->iUniqueId) + return *(iCAFParameters->iUniqueId); + else + return KNullDesC; + } + +/** +Obtains a CTransferBufferCopy from iTransferBufferCopies that is +at least as big as that required. + +There is no need to put the pointer returned by this method onto the CleanupStack +as it will have already been placed into iTransferBufferCopies. + +@param aMaxLength +The size required. + +@return A pointer to a valid CTransferBufferCopy. +*/ +CTransferBufferCopy* CProgDLMultimediaSource::ObtainCopyOfTransferBufferL(TInt aMaxLength) + { + //find a free transfer buffer copy of the right size + TInt firstFree = -1; + CTransferBufferCopy* transBufCopyToUse = NULL; + + for(TInt cnt=0; cnt < iTransferBufferCopies.Count(); cnt++) + { + if(!iTransferBufferCopies[cnt]->InUse()) + { + //record the first free entry, we may remove this + //if entries in iTransferBufferCopies > KAcceptableTransferBufferCopiesSize + if(firstFree == -1) + firstFree = cnt; + + if(iTransferBufferCopies[cnt]->MaxLength() >= aMaxLength) + { + transBufCopyToUse = iTransferBufferCopies[cnt]; + + //Set the MaxLength. This will ensure that the copy acts the same as + //the original Transfer buffer, eg. file server will throw KErrOverflow + transBufCopyToUse->ReUse(aMaxLength); + break; + } + } + } + + //If we failed to find a suitable entry, we need to create a new one + if(!transBufCopyToUse) + { + //Firstly, should we re-cycle an existing entry? + //There must be entries in the array, a free entry must have been found, + //the size of the array must be beyond the water mark where we want to start + //cycling free entries. + if((iTransferBufferCopies.Count() > 0) && + (firstFree != -1) && + (iTransferBufferCopies.Count() > KAcceptableTransferBufferCopiesSize)) + { + delete iTransferBufferCopies[firstFree]; + iTransferBufferCopies.Remove(firstFree); + + transBufCopyToUse = CTransferBufferCopy::NewL(aMaxLength); + CleanupStack::PushL(transBufCopyToUse); + User::LeaveIfError(iTransferBufferCopies.Insert(transBufCopyToUse,firstFree)); + + CleanupStack::Pop(); + } + else + { + #ifdef _DEBUG + if(iTransferBufferCopies.Count() > KMaximumTransferBufferCopiesSize) + { + User::Panic(_L("iTransferBufferCopies grew too large in CProgDLMultimediaSource"),KErrTooBig); + } + #endif + + transBufCopyToUse = CTransferBufferCopy::NewL(aMaxLength); + CleanupStack::PushL(transBufCopyToUse); + User::LeaveIfError(iTransferBufferCopies.Append(transBufCopyToUse)); + + CleanupStack::Pop(); + } + } + + return transBufCopyToUse; + } + + + +/** +Loads aBuffer from iFile. + +The file must already be open for reading. File read is asynchronous. CReadRequest is created to +respond to completion. + +@param aBuffer +The buffer to be filled from the file. +@param aConsumer +The data sink consumer of the buffer. +*/ +void CProgDLMultimediaSource::FillBufferL( CMMFBuffer* aBuffer, MDataSink* aConsumer, TMediaId /*aMediaId*/ ) + { + // Requires that iFile is open for read. + // Reads data from iFile into aBuffer + TInt status(KErrNone); + DEBPRN2(_L("CProgDLMultimediaSource::FillBuffer[%x]]"), aBuffer ); + if ((!aConsumer) || (!aBuffer)) + User::Leave(KErrArgument); + + if (!iFile) + User::Leave(KErrNotReady); + + AppendBufferToSinkQueue(aBuffer,NULL,aConsumer,EFalse); + DEBPRN4(_L("CProgDLMultimediaSource::FillBuffer DLComplete[%d] ReOpenCAF[%d] RequestPending[%d]"), isDownloadComplete,iReOpenCAF,iReadRequestPending ); + if(isDownloadComplete && !iReOpenCAF) + { + if(!iReadRequestPending) + { + ReOpenCAF(); + status = ServiceFillBuffer(); + if(status == KErrUnderflow) + { + StateChanged(EBUFFERING); + } + } + } + else + { + status = ServiceFillBuffer(); + + if(status == KErrUnderflow) + { + StateChanged(EBUFFERING); + } + } + } + +/** +Stores a request in an array. + +CReadWriteRequests are stored in the array iRequests. +This function takes ownership and places the request in the array. +It also checks the array for completed requests and removes them. + +@param aRequest +The request to store. +*/ +void CProgDLMultimediaSource::StoreRequestL( CReadWriteRequest* aRequest ) + { + // add aRequest to iRequests + User::LeaveIfError( iRequests.Append( aRequest ) ) ; + + // Clear out any completed requests + for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ ) + { + if (iRequests[ii]->Completed()) + { + CReadWriteRequest* request = iRequests[ii]; + delete request; + + iRequests.Remove(ii); + ii--; + } + } + } + + +/** +Cancels outstanding requests. + +CReadWriteRequests are stored in the array iRequests. +This function cancels any outstanding requests and removes them +from iRequests. +*/ +void CProgDLMultimediaSource::CancelRequests() + { + // Clear out any completed requests + for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ ) + { + CReadWriteRequest* request = iRequests[ii]; + delete request; + iRequests.Remove(ii); + ii--; + } + } + + +/** +Evaluates a given intent against the rights associated with the file. + +The rights are not updated by this function call. + +@param aIntent +The intent to evaluate. + + @return An error code indicating if the function call was successful. KErrNone on success, otherwise + another of the system-wide error codes. +*/ +TInt CProgDLMultimediaSource::EvaluateIntent(ContentAccess::TIntent aIntent) const + { + if (!iFile) + { + return KErrNotReady; + } + + return iFile->EvaluateIntent(aIntent); + } + +/** +Evaluates and executes a given intent against the rights associated with the file. + +The rights object is updated after calling this function. + +@param aIntent +The intent to evaluate. + +@return An error code indicating if the function call was successful. KErrNone on success, otherwise +another of the system-wide error codes. +*/ +TInt CProgDLMultimediaSource::ExecuteIntent(ContentAccess::TIntent aIntent) + { + if (!iFile) + { + return KErrNotReady; + } + + return iFile->ExecuteIntent(aIntent); + } + +/** +Returns whether the file is protected. + +@return A boolean indicating if the file is protected. ETrue if the file is protected. +*/ +TInt CProgDLMultimediaSource::GetDRMProtection(TBool& aIsProtected) + { + TInt err(KErrNone); + if (!iFile) + { + return KErrNotReady; + } + + TRAP(err,aIsProtected = iFile->IsProtected()); + return err; + } + +TInt CProgDLMultimediaSource::SetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue) + { + if (!iFile) + { + return KErrNotReady; + } + + return iFile->SetAgentProperty(aProperty, aValue); + } + +/* +* Returns ETrue if the request can safely be deleted. +*/ +TBool CReadWriteRequest::Completed() + { + return iCompleted ; + } + +TInt CReadWriteRequest::SetStatus(TBool aStatus) + { + iCompleted = aStatus; + return KErrNone; + } + +TBool CReadWriteRequest::SourceType() + { + return iSourceType ; + } + + +/* +* Returns the data member of CMMFDataBuffer or CMMFTransferBuffer (as TPtr8) +* +*/ +TDes8& CReadWriteRequest::BufferDes() + { + if(iTransferBufferCopy) + return iTransferBufferCopy->Des(); + else + { + //reset iBufferDes in case iBuffer has changed... + iBufferDes = &(STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data()); + return *iBufferDes; + } + } + +const TDesC8& CReadWriteRequest::BufferDesC() + { + if(iTransferBufferCopy) + return iTransferBufferCopy->Des(); + else + return BufferDes(); + } + +CMMFBuffer* CReadWriteRequest::Buffer() + { + return iBuffer; + } + +TAny* CReadWriteRequest::GetSinkOrSource() + { + return iSinkOrSource; + } + +/* +* Destructor. +*/ +CReadWriteRequest::~CReadWriteRequest() + { + Cancel(); + if(iTransferBufferCopy) + iTransferBufferCopy->SetInUse(EFalse); + } + +/* +* Allows owning class access to SetActive() +*/ +void CReadWriteRequest::SetActive() + { + CActive::SetActive() ; + } + +/* +* For the moment at least... Canceled requests may be deleted +*/ +void CReadWriteRequest::DoCancel() + { + iCompleted = ETrue ; + } + +/* +* Called when errors in RunL force Leave. For the moment just mark the request deletable +*/ +TInt CReadWriteRequest::RunError( TInt aError ) + { + //RunL can leave. + iCompleted = ETrue ; + iError = aError; //keep this error internally for now + return KErrNone ; + } + +/* +* On completion of read request call back to the MDataSink +*/ +void CReadRequest::RunL() + { + //Copy the data from the normal buffer into the Transfer buffer + if(iTransferBufferCopy) + { + //must specify the size here as the dest may be smaller than the source. + TDes8& destDesc = STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data(); + destDesc.Copy(iTransferBufferCopy->Des().Left(destDesc.MaxLength())); + + iTransferBufferCopy->SetInUse(EFalse); + } + + STATIC_CAST(CProgDLMultimediaSource*,iParent)->ReadRequestStatus(STATIC_CAST(CReadWriteRequest*,this),iStatus); + } + + // From CMultimediaDataSource begins +TInt CProgDLMultimediaSource::SetObserver( MMultimediaDataSourceObserver& aObserver ) + { + TInt status(KErrNone); + iObserver = &aObserver; + return status; + } + +TInt CProgDLMultimediaSource::GetObserver( MMultimediaDataSourceObserver*& aObserver ) + { + TInt status(KErrNone); + aObserver = iObserver; + return status; + } + +void CProgDLMultimediaSource::Event( TUid aEvent ) + { + if( aEvent == KMultimediaDataSourceEventBitRateChanged ) + { + + if(iObserver) + { + iObserver->GetBitRate( iObserverBitRate ); + if(iState == EBUFFERING) + CalculateBufferedDataSize(); + } + } + + } + +TInt CProgDLMultimediaSource::SetDataTypeCode(TFourCC aSourceFourCC ) + { + TInt status(KErrNone); + iSourceFourCC = aSourceFourCC; + return status; + } + +TInt CProgDLMultimediaSource::GetDataTypeCode(TFourCC& aSourceFourCC ) + { + TInt status(KErrNone); + aSourceFourCC = iSourceFourCC; + return status; + } + +TInt CProgDLMultimediaSource::GetSize( TUint& aSize ) + { + TInt err = KErrNone; + if (iDLFileSize >=0) + { + aSize = iDLFileSize; + } + else + { + aSize = 0; + } + return err; + } + +TInt CProgDLMultimediaSource::Open() + { + TInt status(KErrNotReady); + DEBPRN1(_L("CProgDLMultimediaSource::Open")); + switch ( iState ) + { + case ECLOSED: + StateChanged(ESTOPPED); + status = KErrNone; + break; + case ESTOPPED: + case EPRIMED: + case EEXECUTING: + case EBUFFERING: + default: + DEBPRN2(_L("CProgDLMultimediaSource::Open[Illegal cmd on state[%d]]"), iState ); + break; + }; + return status; + } + +TInt CProgDLMultimediaSource::Close() + { + TInt status(KErrNone); + iHandle.Close(); + iFsSession.Close(); + + StateChanged(ECLOSED); + // Clear app buffers + EmptySinkQueue(); + iSnkBytes = 0; + // Clear observer buffers + return status; + } + +TInt CProgDLMultimediaSource::Prime() + { + TInt status(KErrNotReady); + DEBPRN1(_L("CProgDLMultimediaSource::Prime")); + switch ( iState ) + { + case ESTOPPED: + + // don't reopen file if already open + if (!iFile) + { + if (iFileHandle) + { + TRAPD(err,iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI)); + if(err) + return err; + } + else + { + // Open for read-only access + TRAPD(err,iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareAny, iCAFParameters->iEnableUI)); + if(err) + return err; + } + } + + if(iFile) + { + if(iFile->IsProtected()) + iFile->Size(iFileSize); + else + iFileSize = iDLFileSize; + } + + StateChanged(EPRIMED); + status = KErrNone; + break; + case EPRIMED: + status = KErrNone; + break; + case ECLOSED: + case EEXECUTING: + case EBUFFERING: + default: + DEBPRN2(_L("CProgDLMultimediaSource::Prime[Illegal cmd on state[%d]]"), iState ); + break; + } + return status; + } + +TInt CProgDLMultimediaSource::Play() + { + TInt status(KErrNotReady); + DEBPRN1(_L("CProgDLMultimediaSource::Play")); + switch ( iState ) + { + case EPRIMED: + CalculateBufferedDataSize(); + StateChanged(EEXECUTING); + + while ( !iSinkQueue->IsEmpty() ) + { + status = ServiceFillBuffer(); + } + + if(status == KErrUnderflow) + { + StateChanged(EBUFFERING); + } + + status = KErrNone; + break; + case EEXECUTING: + case EBUFFERING: + status = KErrNone; + // No op + break; + case ECLOSED: + case ESTOPPED: + default: + DEBPRN2(_L("CProgDLMultimediaSource::Play[Illegal cmd on state[%d]]"), iState ); + break; + }; + return status; + } + +TInt CProgDLMultimediaSource::Stop() + { + TInt status(KErrNotReady); + DEBPRN1(_L("CProgDLMultimediaSource::Stop")); + switch ( iState ) + { + case EPRIMED: + case EEXECUTING: + case EBUFFERING: + { + TInt pos = 0; + CancelRequests(); + delete iFile; + iFile = NULL; + //iDLFileSize = -1; + iSnkBytes=pos; + iBufferedDataSize = 0; + EmptySinkQueue(); + StateChanged(ESTOPPED); + status = KErrNone; + } + break; + case ECLOSED: + default: + DEBPRN2(_L("CProgDLMultimediaSource::Stop[Illegal cmd on state[%d]]"), iState ); + break; + }; + return status; + } + + +TInt CProgDLMultimediaSource::FillBuffer( CMMFBuffer* aBuffer ) + { + // Requires that iFile is open for read. + // Reads data from iFile into aBuffer + + TInt status(KErrNone); + DEBPRN2(_L("CProgDLMultimediaSource::FillBuffer[%x]]"), aBuffer ); + if (!aBuffer) + return KErrArgument; + + if (!iFile) + return KErrNotReady; + + AppendBufferToSinkQueue(aBuffer,iObserver,NULL,EFalse); + + DEBPRN4(_L("CProgDLMultimediaSource::FillBuffer DLComplete[%d] ReOpenCAF[%d] RequestPending[%d]"), isDownloadComplete,iReOpenCAF,iReadRequestPending ); + if(isDownloadComplete && !iReOpenCAF) + { + if(!iReadRequestPending) + { + ReOpenCAF(); + status = ServiceFillBuffer(); + if(status == KErrUnderflow) + { + StateChanged(EBUFFERING); + } + } + } + else + { + status = ServiceFillBuffer(); + + if(status == KErrUnderflow) + { + StateChanged(EBUFFERING); + } + } + return status; + } + + +TAny* CProgDLMultimediaSource::CustomInterface( TUid /*aInterfaceUid*/ ) + { + return NULL; + } + +TInt CProgDLMultimediaSource::AppendBufferToSinkQueue( CMMFBuffer* aBuffer, + MMultimediaDataSourceObserver* aObserver, + MDataSink* aConsumer,TBool aTop ) + { + TInt status(KErrNone); + + DEBPRN2(_L("CProgDLMultimediaSource::AppendBufferToSinkQueue() Buffer[%x]"), aBuffer ); + // Add observer buffer to queue + CMMFDataBuffer* dest = static_cast( aBuffer ); + TDes8& destBufferDes = dest->Data(); + + CSinkQueueItem* request(NULL); + + TRAP( status, request = CSinkQueueItem::NewL( aBuffer, aObserver,aConsumer) ); + if ( status == KErrNone ) + { + if(aTop) + iSinkQueue->AddFirst(*request); + else + iSinkQueue->AddLast(*request); + + iSnkItemsCount++; + + DEBPRN3(_L("CProgDLMultimediaSource::AppendBufferToQueue[ReqSize[%d]SnkItems[%d]]"), \ + aBuffer->RequestSize(), iSnkItemsCount ); + } + return status; + } + +void CProgDLMultimediaSource::SourceCustomCommand(TMMFMessage& aMessage) + { + TInt err(KErrNone); + switch ( aMessage.Function() ) + { + + case ESetUpdateFileName: + { + // Read size info + TPckgBuf sizePckg; + err = aMessage.ReadData1FromClient(sizePckg); + if ( err == KErrNone ) + { + iFullFileName = sizePckg(); + } + aMessage.Complete(KErrNone); + + } + break; + + case EDownloadRate: + { + + // Read size info + TPckgBuf sizePckg; + err = aMessage.ReadData1FromClient(sizePckg); + if ( err == KErrNone ) + { + iTransferRate = sizePckg(); + } + aMessage.Complete(KErrNone); + DEBPRN2(_L("CProgDLMultimediaSource::SourceCustomCommand EDownloadRate[%u] "),iTransferRate); + if(iState == EBUFFERING /*&& !iSinkQueue->IsEmpty()*/) + { + CalculateBufferedDataSize(); + } + } + break; + case ESetDownloadState: + { + isDownloadComplete = ETrue; + if(iFile) + iFile->Size(iFileSize); + + if(iFileSize != iDLFileSize) + iDLFileSize = iFileSize; + + iDownloadSize = iFileSize; + iBufferedDataSize = 0; + aMessage.Complete(KErrNone); + + if(iObserver) + iObserver->Event(KMultimediaDataSourceEventRandomSeekingSupportChanged); + + if(iState == EBUFFERING ) + { + if((iDownloadSize - iSnkBytes) > iBufferedDataSize) + { + StateChanged(EEXECUTING); + while ( !iSinkQueue->IsEmpty() ) + { + err = ServiceFillBuffer(); + if(err == KErrUnderflow) + { + StateChanged(EBUFFERING); + break; + } + } + } + } + } + break; + + case ESetDownloadSize: + { + // Read size info + TPckgBuf sizePckg; + err = aMessage.ReadData1FromClient(sizePckg); + if ( err == KErrNone ) + { + iDownloadSize = sizePckg(); + } + aMessage.Complete(KErrNone); + TInt size = 0; + + if(iFile) + iFile->Size(size); + + DEBPRN4(_L("CProgDLMultimediaSource::SourceCustomCommand ********BufferedDataSize[%u] DownloadSize[%d] iSnkbytes[%d]"), iBufferedDataSize ,iDownloadSize, iSnkBytes ); + DEBPRN4(_L("CProgDLMultimediaSource::SourceCustomCommand ********iDLFileSize[%d] iFileSize[%d]ActualSize[%d]"), iDLFileSize,iFileSize,size); + if(iState == EBUFFERING ) + { + if((iDownloadSize - iSnkBytes) > iBufferedDataSize) + { + StateChanged(EEXECUTING); + while ( !iSinkQueue->IsEmpty() ) + { + err = ServiceFillBuffer(); + if(err == KErrUnderflow) + { + StateChanged(EBUFFERING); + break; + } + } + } + } + } + break; + + case ESetActualSize: + { + // Read size info + TPckgBuf sizePckg; + err = aMessage.ReadData1FromClient(sizePckg); + if ( err == KErrNone ) + { + iDLFileSize = sizePckg(); + } + aMessage.Complete(KErrNone); + + if(iFile) + { + if(iFile->IsProtected()) + iFile->Size(iFileSize); + else + iFileSize = iDLFileSize; + } + DEBPRN3(_L("CProgDLMultimediaSource::SourceCustomCommand ActualSize********iDLFileSize[%d] iFileSize[%d]"), iDLFileSize,iFileSize); + + if(iObserver) + iObserver->Event(KMultimediaDataSourceObserverEventSourceSizeChanged); + + } + break; + + case EGetSourceState: + { + TPckgBuf statePckg; + aMessage.ReadData1FromClient(statePckg); + DEBPRN3(_L("CProgDLMultimediaSource::SourceCustomCommand() Client State[%d] SourceState[%d]"), statePckg(), iState); + + if(iState != statePckg()) + { + statePckg() = iState; + aMessage.WriteDataToClient(statePckg); + aMessage.Complete(KErrNone); + } + else + iMessage = new(ELeave) TMMFMessage(aMessage); + } + break; + + case EGetBitRate: + { + TPckgBuf bitRatePckg; + DEBPRN2(_L("CProgDLMultimediaSource::SourceCustomCommand() Client BitRateFromS[%d]"),iObserverBitRate); + bitRatePckg() = iObserverBitRate ; + aMessage.WriteDataToClient(bitRatePckg); + aMessage.Complete(KErrNone); + } + break; + + case EGetPercentageBuffered: + { + TPckgBuf perBufPckg; + TUint perBuf = 0; + if(iState == EBUFFERING && iBufferedDataSize != 0) + { + CalculateBufferedDataSize(); + if ( iBufferedDataSize == 0 ) + { + perBuf = 0; + } + else + { + perBuf = (iDownloadSize - iSnkBytes) * 100 / iBufferedDataSize; + } + } + + RDebug::Print(_L(" Percentage Buffered [%d]"),perBuf); + perBufPckg() = perBuf; + aMessage.WriteDataToClient(perBufPckg); + aMessage.Complete(KErrNone); + } + break; + + default: + err = KErrArgument; + break; + } + } + +TInt CProgDLMultimediaSource::ServiceFillBuffer() + { + + DEBPRN3(_L("CProgDLMultimediaSource::ServiceFillBuffer() state[%d] Download Size[%d]"), iState ,iDownloadSize ); + + TInt status(KErrNone); + if ( iSinkQueue->IsEmpty() ) + return KErrNone; + + CSinkQueueItem* tempsnkItem = iSinkQueue->First(); + CMMFBuffer* tempbuffer = tempsnkItem->Buffer(); + + TInt bufSize = tempbuffer->RequestSize(); + + DEBPRN5(_L("CProgDLMultimediaSource::ServiceFillBuffer() ********BufferedDataSize[%u] DownloadSize[%d] iSnkbytes[%d] BufSize[%d]"), iBufferedDataSize ,iDownloadSize, iSnkBytes,bufSize ); + if((((iDownloadSize - iSnkBytes) > bufSize) && + iState == EEXECUTING && + iDownloadSize > iBufferedDataSize && ((iReadRequestPending + 1)*bufSize < (iDownloadSize - iSnkBytes))) || (iFileSize == iDownloadSize)) + { + iReadRequestPending++; + CSinkQueueItem* snkItem = iSinkQueue->First(); + iSinkQueue->Remove(*snkItem); + iSnkItemsCount--; + CMMFBuffer* buffer = snkItem->Buffer(); + DEBPRN2(_L("CProgDLMultimediaSource::ServiceFillBuffer() Buffer[%x]"), buffer ); + MMultimediaDataSourceObserver* observer = snkItem->Observer(); + MDataSink* consumer = snkItem->Consumer(); + delete snkItem; + + if (CMMFBuffer::IsSupportedDataBuffer(buffer->Type())) + { + CTransferBufferCopy* transBufCopy = NULL; + CReadRequest* request = NULL; + + TDes8& bufferDes = STATIC_CAST( CMMFDataBuffer*, buffer )->Data(); + + TInt requestSize; + if(buffer->RequestSize()) + requestSize = buffer->RequestSize(); + else + requestSize = bufferDes.MaxLength(); + + //check whether buffer is safe to send to file server + //if not, eg for a transfer buffer, then it needs to be copied + if (!CMMFBuffer::IsFileServerSafe(buffer->Type())) + { + //NB: failure in this method will NOT cause transBufCopy to leak as it will be + //inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL. + TRAP(status,transBufCopy = ObtainCopyOfTransferBufferL(bufferDes.MaxLength())); + + if(consumer && !observer) + request = new(ELeave) CReadRequest(this,STATIC_CAST(TAny*, consumer), buffer, transBufCopy, iSnkBytes, iDownloadSize, ETrue); + else + request = new(ELeave) CReadRequest(this,STATIC_CAST(TAny*, observer), buffer, transBufCopy, iSnkBytes, iDownloadSize, EFalse); + + } + else + { + if(consumer && !observer) + request = new(ELeave) CReadRequest(this,STATIC_CAST(TAny*, consumer), buffer, iSnkBytes, iDownloadSize, ETrue); + else + request = new(ELeave) CReadRequest(this,STATIC_CAST(TAny*, observer), buffer, iSnkBytes, iDownloadSize, EFalse); + } + + CleanupStack::PushL( request ); + + TRAP_IGNORE(StoreRequestL(request)); // transfers ownership + CleanupStack::Pop() ; // request + + request->SetActive(); + + // iSnkBytes += requestSize; + + if ((iSnkBytes + request->Buffer()->RequestSize()) >= iDownloadSize && isDownloadComplete) + { + request->Buffer()->SetLastBuffer(ETrue); + DEBPRN1(_L("CProgDLMultimediaSource::ServiceFillBuffer() LastBuffer$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$")); + } + + iFile->Read(request->BufferDes(), requestSize, request->iStatus); + + } + else // if (CMMFBuffer::IsSupportedDataBuffer(buffer->Type())) + return KErrNotSupported; + } + /*else if(iDownloadSize == iSnkBytes) + { + Stop(); + }*/ + else + { + + //StateChanged(EBUFFERING); + return KErrUnderflow; + } + return status; + } + +TInt CProgDLMultimediaSource::EmptySinkQueue() + { + TInt status(KErrNone); + // Empty sink queue + CSinkQueueItem* snkItem; + while ( !iSinkQueue->IsEmpty() ) + { + snkItem = iSinkQueue->First(); + iSinkQueue->Remove(*snkItem); + delete snkItem; + } + + iSnkItemsCount = 0; + return status; + } + +void CProgDLMultimediaSource::CalculateBufferedDataSize() + { + DEBPRN1(_L("CProgDLMultimediaSource::CalculateBufferedDataSize()")); + iBufferedDataSize = 0; + + // Get the bit rate from observer + if(iObserver) + iObserver->GetBitRate( iObserverBitRate ); + + // If we don't know observer bit rate + if(iDownloadSize == iDLFileSize) + { + iBufferedDataSize = 0; + return; + } + + if(iObserverBitRate == 0 && (iSinkQueue->First() != NULL)) + { + if(iPrimaryBufferingConfig.iType == TBufferingConfig::FIXEDDURATION + || iPrimaryBufferingConfig.iType == TBufferingConfig::DYNAMICDURATION) + { + if(iSecondaryBufferingConfig.iType == TBufferingConfig::FIXEDDURATION + || iSecondaryBufferingConfig.iType == TBufferingConfig::DYNAMICDURATION) + { + iBufferedDataSize = iDLFileSize * iInitialBufferingPercentage / 100; + } + else + { + if(iDLFileSize < iSecondaryBufferingConfig.iAmount) + { + iBufferedDataSize = iDLFileSize; + } + else + { + iBufferedDataSize = iSecondaryBufferingConfig.iAmount; + } + } + } + else + { + if(iDLFileSize < iPrimaryBufferingConfig.iAmount) + { + iBufferedDataSize = iDLFileSize; + } + else + { + iBufferedDataSize = iPrimaryBufferingConfig.iAmount; + } + } + + } + else + { + if(iPrimaryBufferingConfig.iType == TBufferingConfig::FIXEDDURATION + || iPrimaryBufferingConfig.iType == TBufferingConfig::DYNAMICDURATION) + { + TUint constantC = KMinPlaybackDuration * iObserverBitRate / 8; + + // calculate time remaining + //TInt64 timeRemaining = ( iDLFileSize - iSnkBytes ) * 8 / iObserverBitRate; + TUint bytesRemaining = iDLFileSize - iSnkBytes; + iBufferedDataSize = bytesRemaining < constantC ? bytesRemaining : constantC; + +// timeRemaining = timeRemaining < 0 ? 0 : timeRemaining; + + // calculate the value in a temporary variable +// TInt64 bufferedDataSize = ((TInt64(iObserverBitRate)) - (TInt64(iTransferRate))) * timeRemaining / 8; +// bufferedDataSize = bufferedDataSize < constantC ? bufferedDataSize : constantC; + +// iBufferedDataSize = bufferedDataSize > KMaxTUint ? KMaxTUint : I64LOW(bufferedDataSize); + } + else + { + iBufferedDataSize = iPrimaryBufferingConfig.iAmount; + } + } + + DEBPRN5(_L("CProgDLMultimediaSource::CalculateBufferdDataSize[%u] ObserverBitRate[%d] SnkBytes[%u] TransferRate[%d]"), iBufferedDataSize,iObserverBitRate,iSnkBytes,iTransferRate ); + } + +void CProgDLMultimediaSource::StateChanged(TState newState) + { + DEBPRN3(_L("CProgDLMultimediaSource::StateChanged OLD[%d] NEW[%d]"),iState, newState); + if(iState != newState) + { + if(iMessage) + { + if(!iMessage->IsCompleted()) + { + TPckgBuf statePckg(newState); + iMessage->WriteDataToClient(statePckg); + iMessage->Complete(KErrNone); + delete iMessage; + iMessage = NULL; + } + } + iState = newState; + } + } + +TInt CProgDLMultimediaSource::ReadRequestStatus(CReadWriteRequest* aRequest, TRequestStatus& aStatus) + { + + if(aStatus != KErrNone) + { + TMMFEvent event(KMMFErrorCategoryControllerGeneralError, aStatus.Int()); + iEventHandler->SendEventToClient(event); + return KErrNone; + } + else + { + + DEBPRN4(_L("CProgDLMultimediaSource::ReadRequestStatus Buffer[%x] BufferSize[%d] RequestSize[%d]"),aRequest->Buffer(),aRequest->Buffer()->BufferSize(),aRequest->Buffer()->RequestSize()); + DEBPRN3(_L("CProgDLMultimediaSource::ReadRequestStatus Buffer[%x] LastBuffer[%d]"),aRequest->Buffer(),aRequest->Buffer()->LastBuffer()); + + TBool lastBuffer = aRequest->Buffer()->LastBuffer(); + + if((aRequest->Buffer()->BufferSize() != aRequest->Buffer()->RequestSize()) && !lastBuffer) + { + if(aRequest->SourceType()) + { + MDataSink* sinkOrSource = REINTERPRET_CAST(MDataSink*,aRequest->GetSinkOrSource()); + TUint position = aRequest->Buffer()->Position(); + TUint newPos = position - aRequest->Buffer()->BufferSize(); + aRequest->Buffer()->SetPosition(newPos); + AppendBufferToSinkQueue(aRequest->Buffer(),(MMultimediaDataSourceObserver*)NULL,sinkOrSource,ETrue); + //iSnkBytes -= aRequest->Buffer()->BufferSize(); + iFile->Seek(ESeekStart,iSnkBytes); + StateChanged(EBUFFERING); + } + else + { + MMultimediaDataSourceObserver* sinkOrSource = REINTERPRET_CAST(MMultimediaDataSourceObserver*,aRequest->GetSinkOrSource()); + TInt position = aRequest->Buffer()->Position(); + TInt newPos = position - aRequest->Buffer()->BufferSize(); + aRequest->Buffer()->SetPosition(newPos); + AppendBufferToSinkQueue(aRequest->Buffer(),sinkOrSource,(MDataSink*)NULL,ETrue); + //iSnkBytes -= aRequest->Buffer()->BufferSize(); + iFile->Seek(ESeekStart,iSnkBytes); + StateChanged(EBUFFERING); + } + } + else + { + iSnkBytes += aRequest->Buffer()->BufferSize(); + + + if(aRequest->SourceType()) + REINTERPRET_CAST(MDataSink*, aRequest->GetSinkOrSource())->BufferFilledL(aRequest->Buffer()) ; // callback to MDataSource/Sink + else + REINTERPRET_CAST(MMultimediaDataSourceObserver*, aRequest->GetSinkOrSource())->BufferFilled(aRequest->Buffer()) ; // callback to MDataSource/Sink + + + } + + iReadRequestPending--; + DEBPRN4(_L("CProgDLMultimediaSource::ReadRequestStatus iReadRequestPending[%d] isDownloadComplete[%d] iReOpenCAF[%d]"),iReadRequestPending,isDownloadComplete,iReOpenCAF); + if(!iReadRequestPending && isDownloadComplete && !iReOpenCAF) + { + ReOpenCAF(); + while ( !iSinkQueue->IsEmpty() ) + { + TInt err = ServiceFillBuffer(); + if(err == KErrUnderflow) + { + StateChanged(EBUFFERING); + break; + } + } + } + + aRequest->SetStatus(ETrue); + return KErrNone; + } + } + + +TInt CProgDLMultimediaSource::ReOpenCAF() + { + TInt status(KErrNone); + DEBPRN2(_L("CProgDLMultimediaSource::StateChanged ReOpenCAF[%d]"),iSnkBytes); + delete iFile; + iFile = NULL; + + if (!iFile) + { + if (iFileHandle) + { + TRAPD(status,iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI)); + if(status) + return status; + } + else + { + // Open for read-only access + TRAPD(status,iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareAny, iCAFParameters->iEnableUI)); + if(status) + return status; + } + + if(!status) + iFile->Seek(ESeekCurrent,iSnkBytes); + } + + if(iFile) + { + if(iFile->IsProtected()) + { + iFile->Size(iFileSize); + iDownloadSize = iFileSize; + iDLFileSize = iFileSize; + + if(iObserver) + { + iObserver->Event(KMultimediaDataSourceObserverEventSourceSizeChanged); + } + } + else + { + iFileSize = iDLFileSize; + } + } + + iReOpenCAF = ETrue; + DEBPRN3(_L("CProgDLMultimediaSource::StateChanged Exit status[%d] iFileSize[%d]"),status,iFileSize); + return status; + } + +void CProgDLMultimediaSource::GetAudioConfiguration() + { + TInt bufType = 0; + TInt bufAmount = 0; + TInt bufPer = 0; + + iAudioConfigRepository->Get(KPDLPrimaryBufferingType,bufType); + iAudioConfigRepository->Get(KPDLPrimaryBufferingAmount,bufAmount); + + iPrimaryBufferingConfig.iType = TBufferingConfig::TBufferingType(bufType); + iPrimaryBufferingConfig.iAmount = bufAmount; + + iAudioConfigRepository->Get(KPDLSecondaryBufferingType,bufType); + iAudioConfigRepository->Get(KPDLSecondaryBufferingAmount,bufAmount); + + iSecondaryBufferingConfig.iType = TBufferingConfig::TBufferingType(bufType); + iSecondaryBufferingConfig.iAmount = bufAmount; + + iAudioConfigRepository->Get(KPDLInitialBufferingPercentage,bufPer); + iInitialBufferingPercentage = bufPer; + } + +TInt CProgDLMultimediaSource::Seek(TUint aPosInBytes) + { + DEBPRN2(_L("CProgDLMultimediaSource::Seek[%d]]"), aPosInBytes ); + TInt status(KErrNone); + if(aPosInBytes <= iFileSize) + { + iSnkBytes = aPosInBytes; + status = iFile->Seek(ESeekStart,iSnkBytes); + } + else + { + status = KErrNotReady; + } + return status; + } + +TInt CProgDLMultimediaSource::GetSeekingSupport( TBool& aSeekSupport ) + { + aSeekSupport = ETrue; + return KErrNone; + } + +TInt CProgDLMultimediaSource::GetRandomSeekingSupport( TBool& aSeekSupport ) + { + aSeekSupport = ETrue; + return KErrNone; + } +//End of File +