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: 	}