diff -r 000000000000 -r 71ca22bcf22a mmfenh/enhancedmediaclient/Plugins/CacheSource/src/CacheSource.cpp --- /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 +#include "ReadWriteRequestAO.h" +#include + +#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(_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( 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( 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( 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(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