--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmfenh/enhancedmediaclient/Plugins/CacheSource/src/CacheSource.cpp Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,615 @@
+/*
+* 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: S60 Cache Data Source Plugin implementation
+*
+*/
+
+#include "CacheSource.h"
+#include "SinkQueueItem.h"
+#include "CacheSourceUid.h"
+#include <MultimediaDataSourceEvents.h>
+#include "ReadWriteRequestAO.h"
+#include <mmfdatabuffer.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 KTransferBufferSize = 8192;
+
+EXPORT_C CCacheSource* CCacheSource::NewL(CMultimediaDataSource* aDataSource, CDataSourceConfigIntfc* aDataSourceConfig )
+ {
+ DEBPRN1(_L("CCacheSource::NewL"));
+ CCacheSource* self = new (ELeave) CCacheSource(aDataSource,aDataSourceConfig);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CCacheSource::CCacheSource(CMultimediaDataSource* aDataSource,CDataSourceConfigIntfc* aDataSourceConfig )
+: iDataSource(aDataSource),iDataSourceConfig(aDataSourceConfig)
+ {
+ // iState from Base
+ iState = ECLOSED;
+ iFileSize = 0;
+ iLastBufferWritten = false;
+ iAbsBufferStart = 0;
+ iAbsBufferEnd = 0;
+ iBufferReadPos = 0;
+ iSeekStart = 0;
+ iSeekEnd = 0;
+ iSnkBytes = 0;
+ iDataBuffer = NULL;
+ iCacheLocation = NULL;
+ }
+
+CCacheSource::~CCacheSource()
+ {
+ DEBPRN1(_L("CCacheSource::~CCacheSource"));
+ iState = ECLOSED;
+ EmptySinkQueue();
+ // Empty sink queue
+ delete iSinkQueue;
+ delete iDataSourceObserver;
+ delete iTransferBuffer;
+ delete iReadRequest;
+ delete iWriteRequest;
+ delete iDataSource;
+
+ if(iCacheType == CDataSourceConfigIntfc::EFILE)
+ {
+ if(iCacheLocation)
+ {
+ delete iCacheLocation;
+ }
+ iFile.Close();
+ iFs.Delete(iFileName);
+ iFs.Close();
+ }
+ else
+ {
+ delete iDataBuffer;
+ }
+ }
+
+void CCacheSource::ConstructL (void)
+ {
+ DEBPRN1(_L("CCacheSource::ConstructL ENTER"));
+ iSinkQueue = new(ELeave) TSglQue<CSinkQueueItem>(_FOFF(CSinkQueueItem, iLink));
+ iDataSourceObserver = CMDataSourceObserver::NewL(iDataSource,this);
+ iTransferBuffer = CMMFDataBuffer::NewL(KTransferBufferSize);
+ iTransferBuffer->SetRequestSizeL(KTransferBufferSize);
+ iWriteRequest = CReadWriteRequestAO::NewL(*this,CReadWriteRequestAO::EWriteRequest);
+ iWriteRequest->SetBuffer(iTransferBuffer);
+ iReadRequest = CReadWriteRequestAO::NewL(*this,CReadWriteRequestAO::EReadRequest);
+ iReadRequest->SetBuffer(iTransferBuffer);
+ iDataSourceConfig->GetCacheType(iCacheType);
+ DEBPRN1(_L("CCacheSource::ConstructL EXIT"));
+ }
+
+
+
+// From CMultimediaDataSource begins
+TInt CCacheSource::SetObserver( MMultimediaDataSourceObserver& aObserver )
+ {
+ TInt status(KErrNone);
+ iObserver = &aObserver;
+ return status;
+ }
+
+TInt CCacheSource::GetObserver( MMultimediaDataSourceObserver*& aObserver )
+ {
+ aObserver = iObserver;
+ return KErrNone;
+ }
+
+void CCacheSource::Event( TUid aEvent )
+ {
+ // CAll the Parent DataSource
+ iDataSource->Event(aEvent);
+ }
+
+TInt CCacheSource::SetDataTypeCode(TFourCC aSourceFourCC )
+ {
+ TInt status(KErrNone);
+ status = iDataSource->SetDataTypeCode(aSourceFourCC);
+ return status;
+ }
+
+TInt CCacheSource::GetDataTypeCode(TFourCC& aSourceFourCC )
+ {
+ TInt status(KErrNone);
+ status = iDataSource->GetDataTypeCode(aSourceFourCC);
+ return status;
+ }
+
+TInt CCacheSource::GetSize( TUint& aSize )
+ {
+ TInt status(KErrNone);
+ status = iDataSource->GetSize(aSize);
+ return status;
+ }
+
+TInt CCacheSource::Open()
+ {
+ TInt status(KErrNone);
+ DEBPRN1(_L("CCacheSource::Open"));
+ status = iDataSource->Open();
+ return status;
+ }
+
+TInt CCacheSource::Close()
+ {
+ TInt status(KErrNone);
+ DEBPRN1(_L("CCacheSource::Close"));
+ status = iDataSource->Close();
+ return status;
+ }
+
+TInt CCacheSource::Prime()
+ {
+ TInt status(KErrNone);
+ DEBPRN1(_L("CCacheSource::Prime"));
+ status = iDataSource->Prime();
+
+ iDataSourceConfig->GetCacheType(iCacheType);
+ if(iCacheType == CDataSourceConfigIntfc::EFILE)
+ {
+ status = iFs.Connect();
+ if(status == KErrNone)
+ {
+ if(iCacheLocation)
+ {
+ delete iCacheLocation;
+ iCacheLocation = NULL;
+ }
+ iCacheLocation = HBufC16::NewL(KMaxFileName);
+ TPtr des = iCacheLocation->Des();
+ iDataSourceConfig->GetCacheLocation(des);
+
+ TInt err = iFile.Temp(iFs,des,iFileName,EFileWrite);
+ status = err;
+ }
+ }
+ else
+ {
+ TUint cacheSize = 0;
+ iDataSourceConfig->GetCacheSize(cacheSize);
+
+ if(iDataBuffer)
+ {
+ delete iDataBuffer;
+ iDataBuffer = NULL;
+ }
+ TRAP(status,iDataBuffer = CMMFDataBuffer::NewL( cacheSize ));
+ if(status == KErrNone)
+ {
+ iDataBuffer->Data().SetLength(cacheSize);
+ }
+ }
+
+ //status = iDataSource->FillBuffer(iTransferBuffer);
+ return status;
+ }
+
+TInt CCacheSource::Play()
+ {
+ TInt status(KErrNone);
+ DEBPRN1(_L("CCacheSource::Play"));
+ status = iDataSource->Play();
+ return status;
+ }
+
+TInt CCacheSource::Stop()
+ {
+ TInt status(KErrNone);
+ DEBPRN1(_L("CCacheSource::Stop"));
+ status = iDataSource->Stop();
+ iFileSize = 0;
+ iLastBufferWritten = false;
+ iAbsBufferStart = 0;
+ iAbsBufferEnd = 0;
+ iBufferReadPos = 0;
+ iSeekStart = 0;
+ iSeekEnd = 0;
+ iSnkBytes = 0;
+ iTransferBuffer->SetLastBuffer(EFalse);
+ if(iCacheType == CDataSourceConfigIntfc::EFILE)
+ {
+ iFile.Close();
+ iFs.Delete(iFileName);
+ }
+ return status;
+ }
+
+TInt CCacheSource::FillBuffer( CMMFBuffer* aBuffer )
+ {
+ TInt status(KErrNone);
+ ASSERT(aBuffer);
+ CMMFDataBuffer* dest = static_cast<CMMFDataBuffer*>( aBuffer );
+ TDes8& destBufferDes = dest->Data();
+
+ DEBPRN4(_L("CCacheSource::FillBuffer RequestSize[%d] AbsBufEnd[%d] SnkBytes[%d]"),aBuffer->RequestSize(),iAbsBufferEnd,iSnkBytes);
+
+ AppendBufferToSinkQueue(dest);
+
+ if(iCacheType == CDataSourceConfigIntfc::EFILE)
+ {
+ if(((iSnkBytes + aBuffer->RequestSize()) < iFileSize) || iLastBufferWritten)
+ {
+ status = ServiceFillBuffer();
+ }
+ else
+ {
+ if(!iLastBufferWritten)
+ {
+ iTransferBuffer->Data().FillZ();
+ iTransferBuffer->Data().SetLength(0);
+ iDataSource->FillBuffer(iTransferBuffer);
+ }
+
+ status = KErrUnderflow;
+ }
+ }
+ else
+ {
+ if((aBuffer->RequestSize() < (iAbsBufferEnd - iAbsBufferReadPos)) || iLastBufferWritten)
+ {
+ status = ServiceFillBuffer();
+ }
+ else
+ {
+ if(!iLastBufferWritten)
+ {
+ iTransferBuffer->Data().FillZ();
+ iTransferBuffer->Data().SetLength(0);
+ iDataSource->FillBuffer(iTransferBuffer);
+ }
+
+ status = KErrUnderflow;
+ }
+ }
+ return status;
+ }
+
+TInt CCacheSource::ServiceFillBuffer()
+ {
+ TInt status(KErrNone);
+ if ( iSinkQueue->IsEmpty() )
+ return status;
+
+ CSinkQueueItem* snkItem = iSinkQueue->First();
+ iSinkQueue->Remove(*snkItem);
+ iSnkItemsCount--;
+ CMMFBuffer* buffer = snkItem->Buffer();
+ delete snkItem;
+
+ if(iCacheType == CDataSourceConfigIntfc::EFILE)
+ {
+ iReadRequest->SetBuffer(buffer);
+ iReadRequest->SetActive();
+ if((iSnkBytes + iReadRequest->Buffer()->RequestSize()) > iFileSize)
+ {
+ iReadRequest->Buffer()->SetLastBuffer(ETrue);
+ }
+
+ iFile.Read(iSnkBytes,iReadRequest->Buffer()->Data(),iReadRequest->iStatus);
+ iSnkBytes += iReadRequest->Buffer()->RequestSize();
+ }
+ else
+ {
+ iReadRequest->SetBuffer(buffer);
+
+ DEBPRN4(_L("CCacheSource::ServiceFillBuffer DataSize[%d] iBufferReadPos[%d] SnkBytes[%d]"),iDataBuffer->Data().Size(),iBufferReadPos,iSnkBytes);
+ if((iBufferReadPos + iReadRequest->Buffer()->RequestSize()) > iAbsBufferEnd)
+ {
+ iReadRequest->Buffer()->SetLastBuffer(ETrue);
+ }
+
+ iDataBuffer->SetPosition(iBufferReadPos);
+
+ if((iBufferReadPos + iReadRequest->Buffer()->RequestSize()) <= iDataBuffer->Data().Size())
+ {
+ iReadRequest->Buffer()->Data().Copy(iDataBuffer->Data().MidTPtr(iBufferReadPos,iReadRequest->Buffer()->RequestSize()));
+ iBufferReadPos += iReadRequest->Buffer()->RequestSize();
+ }
+ else
+ {
+ TInt dataToCopy = iDataBuffer->Data().Size() - iBufferReadPos;
+ iReadRequest->Buffer()->Data().Append(iDataBuffer->Data().MidTPtr(iBufferReadPos,dataToCopy));
+ iBufferReadPos = 0;
+ TInt dataLeftToCopy = iReadRequest->Buffer()->RequestSize() - dataToCopy;
+ iReadRequest->Buffer()->Data().Append(iDataBuffer->Data().MidTPtr(iBufferReadPos,dataLeftToCopy));
+ iBufferReadPos += dataLeftToCopy;
+ DEBPRN4(_L("CCacheSource::ServiceFillBuffer dataToCopy[%d] dataLeftToCopy[%d] SnkBytes[%d]"),dataToCopy,dataLeftToCopy,iBufferReadPos);
+ }
+
+ iSnkBytes += iReadRequest->Buffer()->Data().Length();
+ DEBPRN4(_L("CCacheSource::ServiceFillBuffer RequestSize[%d] iBufferReadPos[%d] SnkBytes[%d]"),iReadRequest->Buffer()->RequestSize(),iBufferReadPos,iSnkBytes);
+ iReadRequest->SetActive();
+ TRequestStatus* status = &(iReadRequest->iStatus);
+ User::RequestComplete(status,KErrNone);
+ }
+ return status;
+ }
+
+TAny* CCacheSource::CustomInterface( TUid /*aInterfaceUid*/ )
+ {
+ return NULL;
+ }
+
+TInt CCacheSource::GetSeekingSupport( TBool& aSeekSupport )
+ {
+ aSeekSupport = ETrue;
+ return KErrNone;
+ };
+
+TInt CCacheSource::GetRandomSeekingSupport( TBool& aSeekSupport )
+ {
+ aSeekSupport = EFalse;
+ return KErrNone;
+ };
+
+// Seek Implementation
+
+TInt CCacheSource::Seek(TUint aPosInBytes)
+ {
+ TInt status(KErrNone);
+ DEBPRN2(_L("CCacheSource::Seek[%d]"),aPosInBytes);
+
+ if(iCacheType == CDataSourceConfigIntfc::EFILE)
+ {
+ // This is File Seek so the SeekPosition has to be less
+ // then the File Size otherwise we leave
+ if(aPosInBytes <= iFileSize)
+ {
+ iSnkBytes = aPosInBytes;
+ }
+ else
+ {
+ status = KErrNotReady;
+ }
+ }
+ else
+ {
+ DEBPRN3(_L("CCacheSource::Seek AbsBufStart[%d] AbsBufEnd[%d]"),iAbsBufferStart,iAbsBufferEnd);
+ // Here we seek in the Buffer, so we can only seek from the begining of the
+ // buffer window. which is iAbsBufferStart
+ if(aPosInBytes >= iAbsBufferStart)
+ {
+ iAbsBufferReadPos = aPosInBytes;
+ TInt seekDelta = aPosInBytes - iAbsBufferStart;
+ if(seekDelta <= (iDataBuffer->Data().MaxLength() - iSeekStart))
+ {
+ iBufferReadPos = iSeekStart + seekDelta;
+ }
+ else
+ {
+ iBufferReadPos = seekDelta - (iDataBuffer->Data().MaxLength() - iSeekStart);
+ }
+ }
+ else
+ {
+ status = KErrNotReady;
+ }
+ }
+ return status;
+ }
+
+// From CMultimediaDataSource ends
+
+TInt CCacheSource::ServiceBufferFilled( CMMFBuffer* aBuffer )
+ {
+ TInt status(KErrNone);
+ CMMFDataBuffer* dest = static_cast<CMMFDataBuffer*>( aBuffer );
+ TDes8& destBufferDes = dest->Data();
+
+ if(iCacheType == CDataSourceConfigIntfc::EFILE)
+ {
+ iWriteRequest->SetActive();
+ iFile.Write(iFileSize,destBufferDes,iWriteRequest->iStatus);
+ iFileSize = iFileSize + dest->BufferSize();
+ DEBPRN3(_L("CCacheSource::ServiceBufferFilled FileSize[%d] LastBuffer[%d]"),iFileSize,dest->LastBuffer());
+ if(dest->LastBuffer())
+ {
+ iLastBufferWritten = ETrue;
+ dest->SetLastBuffer(EFalse);
+ }
+ }
+ else
+ {
+ iWriteRequest->SetActive();
+
+ iDataBuffer->SetPosition(iSeekEnd);
+
+ if((iSeekEnd + dest->BufferSize()) <= iDataBuffer->Data().MaxLength())
+ {
+ iDataBuffer->Data().Replace(iSeekEnd,dest->Data().Size(),dest->Data());
+ iSeekEnd += dest->Data().Size();
+ }
+ else
+ {
+ TInt copyEndData = iDataBuffer->Data().MaxLength() - iSeekEnd;
+ iDataBuffer->Data().Replace(iSeekEnd,copyEndData,dest->Data().MidTPtr(0,copyEndData));
+ TInt dataLeftToCopy = dest->Data().Size() - copyEndData;
+ iSeekEnd = 0;
+ iDataBuffer->Data().Replace(iSeekEnd,dataLeftToCopy,dest->Data().MidTPtr(copyEndData,dataLeftToCopy));
+ iSeekEnd = dataLeftToCopy;
+ }
+
+ iAbsBufferEnd += dest->BufferSize();
+ if(iAbsBufferEnd < iDataBuffer->Data().MaxLength())
+ {
+ iAbsBufferStart = 0;
+ }
+ else
+ {
+ iAbsBufferStart = iAbsBufferEnd - iDataBuffer->Data().MaxLength();
+ }
+
+ if(iAbsBufferEnd < iDataBuffer->Data().MaxLength())
+ {
+ iSeekStart = 0;
+ }
+ else
+ {
+ iSeekStart = iSeekEnd;
+ }
+
+ DEBPRN4(_L("CCacheSource::ServiceBufferFilled DataSize[%d] AbsBufferEnd[%d] LastBuffer[%d]"),iDataBuffer->Data().Size(),iAbsBufferEnd,dest->LastBuffer());
+ if(dest->LastBuffer())
+ iLastBufferWritten = ETrue;
+
+ TRequestStatus* status = &(iWriteRequest->iStatus);
+ User::RequestComplete(status,KErrNone);
+ }
+ return status;
+ }
+
+void CCacheSource::ReadRequestComplete(CReadWriteRequestAO* aRequest,TRequestStatus& aStatus)
+ {
+ if(aStatus != KErrNone)
+ {
+ }
+ else
+ {
+ if(aRequest->RequestType() == CReadWriteRequestAO::EReadRequest)
+ {
+ DEBPRN3(_L("CCacheSource::ReadRequestComplete [%d] [%d]"),aRequest->Buffer()->Data().Size(),aRequest->Buffer()->RequestSize());
+ iObserver->BufferFilled(aRequest->Buffer());
+ }
+ else
+ {
+ CSinkQueueItem* snkItem = iSinkQueue->First();
+ iSinkQueue->Remove(*snkItem);
+ iSnkItemsCount--;
+ CMMFBuffer* buffer = snkItem->Buffer();
+ delete snkItem;
+ FillBuffer(buffer);
+ }
+ }
+ }
+
+
+TInt CCacheSource::AppendBufferToSinkQueue( CMMFBuffer* aBuffer )
+ {
+ TInt status(KErrNone);
+ // Add observer buffer to queue
+ CMMFDataBuffer* dest = static_cast<CMMFDataBuffer*>( aBuffer );
+ TDes8& destBufferDes = dest->Data();
+
+ CSinkQueueItem* request(NULL);
+
+ TRAP( status, request = CSinkQueueItem::NewL( aBuffer ) );
+ if ( status == KErrNone )
+ {
+ iSinkQueue->AddLast(*request);
+ iSnkItemsCount++;
+ }
+ return status;
+ }
+
+TInt CCacheSource::EmptySinkQueue()
+ {
+ TInt status(KErrNone);
+ // Empty sink queue
+ CSinkQueueItem* snkItem;
+ while ( !iSinkQueue->IsEmpty() )
+ {
+ snkItem = iSinkQueue->First();
+ iSinkQueue->Remove(*snkItem);
+ delete snkItem;
+ }
+
+ iSnkItemsCount = 0;
+ return status;
+ }
+
+//From MMultimediaDataSourceObserver
+
+
+CMDataSourceObserver::CMDataSourceObserver(CMultimediaDataSource* aDataSource ,CMultimediaDataSource* aParent)
+ :iDataSource(aDataSource)
+ ,iParent(aParent)
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CSinkQueueItem::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CMDataSourceObserver::ConstructL()
+ {
+ iDataSource->SetObserver(*this);
+ }
+
+// -----------------------------------------------------------------------------
+// CSinkQueueItem::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMDataSourceObserver* CMDataSourceObserver::NewL(CMultimediaDataSource* aDataSource ,CMultimediaDataSource* aParent)
+ {
+ CMDataSourceObserver* self = new(ELeave) CMDataSourceObserver( aDataSource, aParent );
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CSinkQueueItem::~CSinkQueueItem
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CMDataSourceObserver::~CMDataSourceObserver()
+ {
+ }
+
+void CMDataSourceObserver::BufferFilled( CMMFBuffer* aBuffer )
+ {
+ (static_cast<CCacheSource*>(iParent))->ServiceBufferFilled(aBuffer);
+ }
+
+void CMDataSourceObserver::Event( TUid aEvent )
+ {
+ MMultimediaDataSourceObserver* obsvr(NULL);
+ iParent->GetObserver(obsvr);
+ obsvr->Event(aEvent);
+ }
+
+TInt CMDataSourceObserver::GetBitRate( TUint& aBitRate )
+ {
+ TInt status(KErrNone);
+ MMultimediaDataSourceObserver* obsvr(NULL);
+ iParent->GetObserver(obsvr);
+ status = obsvr->GetBitRate(aBitRate);
+ return status;
+ }
+
+// End of file