mmfenh/enhancedmediaclient/Plugins/ProgDLSource/src/ProgDLSource.cpp
changeset 0 71ca22bcf22a
child 30 ab526b8cacfb
--- /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 <f32file.h>
+#include <e32std.h>
+#include <mmfdatabuffer.h>
+#include <mmfutilities.h>
+#include <mmf/common/mmfcontroller.h>
+#include <mmfpaniccodes.h>
+#include "ProgDLDataSource.h"
+#include "ProgDLMultimediaSource.h"
+#include "MmffilePriv.h"
+#include "FileAccess.h"
+#include "SinkQueueItem.h"
+#include "ProgDLSourceCustomCommands.h"
+#include <MultimediaDataSourceEvents.h>
+#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<TUint8*>(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<TMMFFileParams> descriptor package containing the file name and full path.
+*/
+void CProgDLMultimediaSource::ConstructL() 
+    {
+    CProgDLSource* progDLSource = static_cast<CProgDLSource*>(iParentDataSource);    
+    iInitData = (progDLSource->GetInitData()).AllocL();
+    progDLSource->SetMultimediaSource(*this);
+    ConstructL(*iInitData, ESourceMode);
+    iSinkQueue = new(ELeave) TSglQue<CSinkQueueItem>(_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<RFile*> 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<TMMFFileHandleParams> 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<TMMFFileParams> 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<CMMFDataBuffer*>( 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<TFileName> sizePckg;
+            err = aMessage.ReadData1FromClient(sizePckg);
+            if ( err == KErrNone )
+                {
+                iFullFileName = sizePckg();
+                }
+            aMessage.Complete(KErrNone);			            
+            
+            }   
+            break;
+
+        case EDownloadRate:
+            {
+            
+            // Read size info
+            TPckgBuf<TUint> 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<TInt> 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<TInt> 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<TState> 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<TUint> bitRatePckg;	 
+            DEBPRN2(_L("CProgDLMultimediaSource::SourceCustomCommand() Client BitRateFromS[%d]"),iObserverBitRate);
+            bitRatePckg() = iObserverBitRate ;	
+            aMessage.WriteDataToClient(bitRatePckg);
+            aMessage.Complete(KErrNone);
+            }            
+            break;   
+
+        case EGetPercentageBuffered:
+            {
+            TPckgBuf<TUint> 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<TState> 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
+