sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: sl@0: #include <f32file.h> sl@0: #include <e32std.h> sl@0: #include <mmf/server/mmfdes.h> sl@0: #include <mmf/server/mmfdatabuffer.h> sl@0: #include <mmf/common/mmfpaniccodes.h> sl@0: sl@0: void Panic(TMMFDescriptorPanicCode aPanicCode) sl@0: { sl@0: _LIT(KMMFDescriptorPanicCategory, "MMFDescriptor"); sl@0: User::Panic(KMMFDescriptorPanicCategory, aPanicCode); sl@0: } sl@0: sl@0: /** sl@0: Protected constructor. sl@0: sl@0: Sets the offset to zero. sl@0: */ sl@0: CMMFDescriptor::CMMFDescriptor( ) : CMMFClip( KUidMmfDescriptorSource, KUidMmfDescriptorSink ) sl@0: { sl@0: } sl@0: sl@0: /** sl@0: Destructor. sl@0: sl@0: The default implementation closes the descriptor thread. sl@0: */ sl@0: CMMFDescriptor::~CMMFDescriptor() sl@0: { sl@0: iDesThread.Close() ; sl@0: } sl@0: sl@0: /** sl@0: Constructs a CMMFDescriptor MDataSource. sl@0: sl@0: @return A pointer to a new CMMFDescriptor. sl@0: */ sl@0: MDataSource* CMMFDescriptor::NewSourceL( ) sl@0: { sl@0: CMMFDescriptor* self = new (ELeave) CMMFDescriptor( ) ; sl@0: return STATIC_CAST( MDataSource*, self ) ; sl@0: } sl@0: sl@0: /** sl@0: Constructs a CMMFDescriptor MDataSink. sl@0: sl@0: @return A pointer to a new CMMFDescriptor. sl@0: */ sl@0: MDataSink* CMMFDescriptor::NewSinkL( ) sl@0: { sl@0: CMMFDescriptor* self = new (ELeave) CMMFDescriptor( ) ; sl@0: return STATIC_CAST( MDataSink*, self ) ; sl@0: } sl@0: sl@0: /** sl@0: Performs source construction dependant on the source construction sl@0: initialisation data aInitData. sl@0: sl@0: @param aInitData sl@0: The TPckgC<TMMFDescriptorParams> descriptor package containing the descriptor and the thread sl@0: ID for the descriptor. sl@0: */ sl@0: void CMMFDescriptor::ConstructSourceL( const TDesC8& aInitData ) sl@0: { sl@0: ConstructL( aInitData ) ; sl@0: } sl@0: sl@0: sl@0: /*** sl@0: Sets how much of the underlying descriptor will be used, up to the underlying descriptor's maximum sl@0: length. sl@0: sl@0: @param aSize sl@0: The size of the descriptor. sl@0: sl@0: @return An error code indicating if the function call was successful. KErrNone on success, otherwise sl@0: another of the system-wide error codes. sl@0: */ sl@0: TInt CMMFDescriptor::SetSize( TInt aSize ) sl@0: { sl@0: //[ precondition aSize >= 0 sl@0: // precondition sSize < MaxSize() sl@0: // iDes is not null] sl@0: if(!iDes ) sl@0: return KErrNotReady; sl@0: sl@0: if( aSize > MaxLength() ) sl@0: return KErrOverflow; sl@0: sl@0: if( aSize < 0 ) sl@0: return KErrUnderflow; sl@0: sl@0: // [ actually do the work ] sl@0: iDes->SetLength( aSize ); sl@0: sl@0: //[ assert the post condition sl@0: // aSize == Length() sl@0: // descriptor is still ok] sl@0: ASSERT( aSize == iDes->Length()); sl@0: ASSERT( iDes ); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Performs sink construction dependant on the sink construction initialisation data aInitData. sl@0: sl@0: @param aInitData sl@0: The TPckgC<TMMFDescriptorParams> descriptor package containing sl@0: the descriptor and the thread ID for the descriptor. sl@0: */ sl@0: void CMMFDescriptor::ConstructSinkL( const TDesC8& aInitData ) sl@0: { sl@0: ConstructL( aInitData ) ; sl@0: } sl@0: sl@0: void CMMFDescriptor::ConstructL( const TDesC8& aInitData ) sl@0: { sl@0: TMMFDescriptorParams params; sl@0: TPckgC<TMMFDescriptorParams> config(params); sl@0: if (aInitData.Length() < config.Length()) sl@0: User::Leave(KErrGeneral); sl@0: config.Set(aInitData); sl@0: iDes = STATIC_CAST( TDes8*, config().iDes); sl@0: User::LeaveIfError( iDesThread.Open( config().iDesThreadId ) ); sl@0: } sl@0: sl@0: sl@0: /** sl@0: Loads aBuffer from iDes. sl@0: sl@0: File read is asynchronous. CReadRequest is created to respond to completion. sl@0: sl@0: @param aBuffer sl@0: The buffer to be filled from the descriptor. sl@0: @param aConsumer sl@0: The data sink consumer of the buffer. sl@0: @param aMediaId sl@0: Not used. sl@0: */ sl@0: void CMMFDescriptor::FillBufferL( CMMFBuffer* aBuffer, MDataSink* aConsumer, TMediaId /*aMediaId*/ ) sl@0: { sl@0: // Current position in Descriptor is iOffset. sl@0: sl@0: // Read from iDes in iDesThread into Des in aBuffer. sl@0: sl@0: // Assume that the amount to be read is the size of the buffer descriptor sl@0: // Should check that there is sufficient data in the source buffer sl@0: // If there is not enough to fill the target then copy what there is sl@0: // How should the function deal with no data in the source buffer? sl@0: sl@0: // Use of a single iOffset will preclude use by more than one client (use ReadBufferL()) sl@0: if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) sl@0: { sl@0: TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); sl@0: sl@0: //if request size is set, use it, else use max length of buffer sl@0: TInt targetMaxLength = aBuffer->RequestSize() ? aBuffer->RequestSize() : bufferDes.MaxLength(); sl@0: sl@0: //ensure RequestSize was within bounds sl@0: if(targetMaxLength > bufferDes.MaxLength()) sl@0: targetMaxLength = bufferDes.MaxLength(); sl@0: sl@0: TInt sourceLengthRemaining = iDes->Length() - iOffset; sl@0: if ( ( sourceLengthRemaining - targetMaxLength ) > 0 ) sl@0: { sl@0: bufferDes = iDes->Mid(iOffset,targetMaxLength); sl@0: iOffset += targetMaxLength; sl@0: } sl@0: else if (sourceLengthRemaining > 0) sl@0: { sl@0: bufferDes = iDes->Mid(iOffset,sourceLengthRemaining); sl@0: iOffset += sourceLengthRemaining; sl@0: aBuffer->SetLastBuffer(ETrue); sl@0: } sl@0: else sl@0: { sl@0: bufferDes.SetLength(0); sl@0: aBuffer->SetLastBuffer(ETrue); sl@0: } sl@0: sl@0: aConsumer->BufferFilledL( aBuffer ) ; sl@0: } sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: Empties aBuffer into iDes. sl@0: sl@0: @param aBuffer sl@0: The buffer to be written to the descriptor. sl@0: @param aSupplier sl@0: The data source supplier of the buffer. sl@0: @param aMediaId sl@0: The Media ID. sl@0: */ sl@0: void CMMFDescriptor::EmptyBufferL( CMMFBuffer* aBuffer, MDataSource* aSupplier, TMediaId /*aMediaId*/ ) sl@0: { sl@0: // Does the buffer type need to be checked? sl@0: sl@0: // Assume that the amount to be read is the size of the buffer descriptor sl@0: // Should check that there is sufficient data in the source buffer sl@0: // If there is not enough to fill the target then copy what there is sl@0: // How should the function deal with no data in the source buffer? sl@0: if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) sl@0: { sl@0: TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); sl@0: sl@0: TInt sourceLength = bufferDes.Length() ; sl@0: TInt targetLength = iDes->MaxLength() - iDes->Length(); sl@0: if ( targetLength>0 ) sl@0: { sl@0: if (sourceLength>targetLength) sl@0: { sl@0: sourceLength = targetLength; sl@0: bufferDes.SetLength(targetLength); sl@0: } sl@0: sl@0: iDes->Append(bufferDes) ; sl@0: } sl@0: else sl@0: bufferDes.SetLength(0); sl@0: sl@0: aSupplier->BufferEmptiedL( aBuffer ) ; sl@0: } sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: Loads aLength number of bytes into aBuffer from specified point in iDes. sl@0: sl@0: @param aLength sl@0: The number of bytes to be read into buffer. sl@0: @param aBuffer sl@0: The buffer to be filled from the descriptor. sl@0: @param aPosition sl@0: The offset into the descriptor at which to start reading. sl@0: @param aConsumer sl@0: The data sink consumer of the buffer sl@0: */ sl@0: void CMMFDescriptor::ReadBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer) sl@0: { sl@0: if (!aBuffer) sl@0: User::Leave(KErrArgument); sl@0: sl@0: if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) sl@0: { sl@0: TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); sl@0: sl@0: if (aLength>bufferDes.MaxLength()) sl@0: User::Leave(KErrOverflow); sl@0: sl@0: if ((aLength<0) || (aPosition<0)) sl@0: User::Leave(KErrArgument); sl@0: sl@0: TInt sourceLength = iDes->Length() ; sl@0: sl@0: //ensure not trying to read more than is available sl@0: if(aPosition + aLength > sourceLength) sl@0: aLength = sourceLength - aPosition; sl@0: sl@0: if (aLength>0) sl@0: { sl@0: TPtrC8 srcPtr(iDes->Mid(aPosition,aLength)); sl@0: bufferDes.Copy(srcPtr.Ptr(),aLength); sl@0: } sl@0: else sl@0: bufferDes.SetLength(0); sl@0: sl@0: //have we read all the available data sl@0: if(aPosition + aLength >= sourceLength) sl@0: aBuffer->SetLastBuffer(ETrue); sl@0: sl@0: if (aConsumer) sl@0: aConsumer->BufferFilledL(aBuffer); sl@0: } sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: Loads aBuffer from specified point in iDes sl@0: sl@0: @param aBuffer sl@0: The buffer to be filled from the descriptor. sl@0: @param aPosition sl@0: The offset into the descriptor at which to start reading. sl@0: @param aConsumer sl@0: The data sink consumer of the buffer. sl@0: */ sl@0: void CMMFDescriptor::ReadBufferL(CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer) sl@0: { sl@0: if (!aBuffer) sl@0: User::Leave(KErrArgument); sl@0: sl@0: if (aPosition<0) sl@0: User::Leave(KErrArgument); sl@0: sl@0: if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) sl@0: { sl@0: TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); sl@0: //if request size is set, use it, else use max length of buffer sl@0: TUint copyLength = aBuffer->RequestSize() ? aBuffer->RequestSize() : bufferDes.MaxLength(); sl@0: sl@0: ReadBufferL(copyLength, aBuffer, aPosition, aConsumer); sl@0: } sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: Loads aBuffer from specified point in iDes. Note that this is a synchronous read. sl@0: sl@0: @param aBuffer sl@0: The buffer to be filled from the descriptor. sl@0: @param aPosition sl@0: The offset into the descriptor at which to start reading. sl@0: */ sl@0: void CMMFDescriptor::ReadBufferL(CMMFBuffer* aBuffer, TInt aPosition) sl@0: { sl@0: ReadBufferL(aBuffer, aPosition, NULL); sl@0: } sl@0: sl@0: /** sl@0: Empties aBuffer into iDes at specified location. sl@0: sl@0: @param aBuffer sl@0: The data buffer containing bytes to be written. sl@0: @param aPosition sl@0: The offset into the descriptor at which to start writing. sl@0: @param aSupplier sl@0: The data source to be notified when the write has been completed. sl@0: */ sl@0: void CMMFDescriptor::WriteBufferL(CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier) sl@0: { sl@0: if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) sl@0: { sl@0: TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); sl@0: sl@0: WriteBufferL(bufferDes.Length(), aBuffer, aPosition, aSupplier); sl@0: } sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: Empties aLength bytes from aBuffer into iDes at specified location. sl@0: sl@0: @param aLength sl@0: The number of bytes to be emptied from buffer. sl@0: @param aBuffer sl@0: The data buffer containing bytes to be written. sl@0: @param aPosition sl@0: The offset into the descriptor at which to start writing. sl@0: @param aSupplier sl@0: The data source to be notified when the write has been completed. sl@0: sl@0: @leave KErrNotReady sl@0: If SinkPrimeL() and SinkThreadLogon() have not been called. sl@0: @leave KErrArgument sl@0: If aLength<0 or aPosition<0 or aSupplier is NULL. sl@0: @leave KErrNotSupported sl@0: If aBuffer is not of type KMMFDataBuffer. sl@0: */ sl@0: void CMMFDescriptor::WriteBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier) sl@0: { sl@0: if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) sl@0: { sl@0: TDes8& bufferDes = STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data(); sl@0: sl@0: if (aLength>bufferDes.Length() || (aLength<0) || (aPosition<0)) sl@0: User::Leave(KErrArgument); sl@0: sl@0: TInt sourceLength = aLength; sl@0: TPtr8 bufferPtr(((sourceLength) ? &bufferDes[0] : NULL), sourceLength, sourceLength); sl@0: TInt targetLength = iDes->MaxLength() - aPosition; sl@0: if (targetLength>0 && sourceLength > 0) sl@0: { sl@0: if (sourceLength>targetLength) sl@0: User::Leave(KErrOverflow); sl@0: sl@0: if ((iDes->Length() - aPosition) > 0) sl@0: { sl@0: TInt bytesToReplace = iDes->Length() - aPosition; sl@0: if (sourceLength > bytesToReplace) sl@0: { sl@0: TPtrC8 replaceBuf = bufferPtr.Left(bytesToReplace); sl@0: TPtrC8 appendBuf = bufferPtr.Right(sourceLength-bytesToReplace); sl@0: iDes->Replace(aPosition, bytesToReplace, replaceBuf); sl@0: iDes->Append(appendBuf); sl@0: } sl@0: else sl@0: iDes->Replace(aPosition, sourceLength, bufferPtr); sl@0: sl@0: } sl@0: else sl@0: iDes->Append(bufferPtr.Ptr(),sourceLength); sl@0: } sl@0: else if (targetLength<0) sl@0: User::Leave(KErrArgument); sl@0: else if (aLength != 0) sl@0: User::Leave(KErrOverflow); sl@0: sl@0: if (aSupplier) sl@0: aSupplier->BufferEmptiedL(aBuffer); sl@0: } sl@0: else sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: /** sl@0: Empties aBuffer into iFile at specified location. Note that this is a synchronous write sl@0: sl@0: @param aBuffer sl@0: The data buffer containing bytes to be written. sl@0: @param aPosition sl@0: The offset into file at which to start writing. sl@0: */ sl@0: void CMMFDescriptor::WriteBufferL( CMMFBuffer* aBuffer, TInt aPosition) sl@0: { sl@0: WriteBufferL( aBuffer, aPosition, NULL ); sl@0: } sl@0: sl@0: /** sl@0: Returns the amount of space available for the clip. sl@0: sl@0: @return The space available in descriptor (difference between length and maxlength). sl@0: */ sl@0: TInt64 CMMFDescriptor::BytesFree() sl@0: { sl@0: TInt64 length = iDes->Length() ; sl@0: TInt64 maxLength = iDes->MaxLength() ; sl@0: return( maxLength - length ) ; sl@0: } sl@0: sl@0: /** sl@0: Returns the length of the clip. sl@0: sl@0: @return The length (not max length) of the descriptor. sl@0: */ sl@0: TInt CMMFDescriptor::Size() sl@0: { sl@0: TInt length = iDes->Length(); sl@0: return(length); sl@0: } sl@0: sl@0: /** sl@0: Returns the data type as a fourCC code for the CMMFDescriptor data source. sl@0: sl@0: @param aMediaId sl@0: The ID of the media for which the codec is obtained. sl@0: sl@0: @return The data type fourCC code. sl@0: */ sl@0: TFourCC CMMFDescriptor::SourceDataTypeCode(TMediaId /*aMediaId*/) sl@0: { sl@0: return iSourceFourCC ; sl@0: } sl@0: sl@0: /** sl@0: Returns the data type as a fourCC code of the CMMFDescriptor data sink. sl@0: sl@0: Used by MDataSource and MDataSink. sl@0: sl@0: @return The data type fourCC code. sl@0: */ sl@0: TFourCC CMMFDescriptor::SinkDataTypeCode(TMediaId /*aMediaId*/) sl@0: { sl@0: return iSinkFourCC ; sl@0: } sl@0: sl@0: /** sl@0: CMMFDescriptor as a source is always passive so this function is not supported. sl@0: sl@0: @param aBuffer sl@0: The emptied buffer. sl@0: */ sl@0: void CMMFDescriptor::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ ) sl@0: { sl@0: Panic(EMMFDescriptorPanicBufferEmptiedLNotSupported); sl@0: } sl@0: sl@0: /** sl@0: Tests whether a source buffer can be created. sl@0: sl@0: @return A boolean indicating if the buffer can be created. EFalse if a CMMFDescriptor cannot create sl@0: it's own buffer sl@0: */ sl@0: TBool CMMFDescriptor::CanCreateSourceBuffer() sl@0: { sl@0: return EFalse ; sl@0: } sl@0: sl@0: /** sl@0: Creates a source buffer. sl@0: sl@0: @param aMediaId sl@0: The Media ID. sl@0: @param aReference sl@0: A boolean indicating if MDataSource owns the buffer. ETrue if MDataSource owns the buffer, sl@0: EFalse if the caller owns the buffer. sl@0: sl@0: @return NULL as a CMMFFile cannot create it's own buffer sl@0: */ sl@0: CMMFBuffer* CMMFDescriptor::CreateSourceBufferL( TMediaId /*aMediaId*/, TBool& /*aReference*/ ) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: return NULL; sl@0: } sl@0: sl@0: /** sl@0: CMMFDescriptor as a sink is always passive so this function is not supported. sl@0: sl@0: @param aBuffer sl@0: The filled buffer. sl@0: */ sl@0: void CMMFDescriptor::BufferFilledL( CMMFBuffer* /*aBuffer*/ ) sl@0: { sl@0: Panic(EMMFDescriptorPanicBufferFilledLNotSupported); sl@0: } sl@0: sl@0: /** sl@0: Tests whether a sink buffer can be created. sl@0: sl@0: @return A boolean indicating if the sink buffer can be created. EFalse if a CMMFDescriptor cannot sl@0: create it's own buffer. sl@0: */ sl@0: TBool CMMFDescriptor::CanCreateSinkBuffer() sl@0: { sl@0: return EFalse ; sl@0: } sl@0: sl@0: /** sl@0: Creates a sink buffer. sl@0: sl@0: @param aMediaId sl@0: The Media ID. sl@0: @param aReference sl@0: A boolean indicating if MDataSource owns the buffer. ETrue if MDataSource owns the buffer, sl@0: EFalse if the caller owns the buffer. sl@0: sl@0: @return NULL as a CMMFDescriptor cannot create it's own buffer sl@0: */ sl@0: CMMFBuffer* CMMFDescriptor::CreateSinkBufferL( TMediaId /*aMediaId*/ , TBool& /*aReference*/) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: return NULL; sl@0: }