mmlibs/mmfw/src/Plugin/StdSourceAndSink/Mmffile.cpp
changeset 0 40261b775718
child 8 bc06d8566074
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <f32file.h>
       
    17 #include <e32std.h>
       
    18 #include <mmf/server/mmfdatabuffer.h>
       
    19 #include <mmf/common/mmfutilities.h>
       
    20 #include <mmf/common/mmfcontroller.h>
       
    21 #include <mmf/common/mmfpaniccodes.h>
       
    22 #include <mmf/server/MmfFile.h>
       
    23 #include "MmffilePriv.h"
       
    24 #include "FileAccess.h"
       
    25 
       
    26 void Panic(TMMFFilePanicCode aPanicCode)
       
    27 	{
       
    28 	_LIT(KMMFFilePanicCategory, "MMFFile");
       
    29 	User::Panic(KMMFFilePanicCategory, aPanicCode);
       
    30 	}
       
    31 
       
    32 /**
       
    33  * Constructs a CTransferBufferCopy
       
    34  *
       
    35  * @return CTransferBufferCopy*
       
    36  */
       
    37 CTransferBufferCopy* CTransferBufferCopy::NewL(TInt aMaxLength)
       
    38 	{
       
    39 	CTransferBufferCopy* self = new (ELeave) CTransferBufferCopy(aMaxLength);
       
    40 	CleanupStack::PushL(self);
       
    41 	self->ConstructL();
       
    42 	CleanupStack::Pop(self);
       
    43 	return self;
       
    44 	}
       
    45 
       
    46 /**
       
    47  * Second phase constructor for CTransferBufferCopy
       
    48  *
       
    49  * @return void
       
    50  */
       
    51 void CTransferBufferCopy::ConstructL()
       
    52 	{
       
    53 	iBuffer = static_cast<TUint8*>(User::AllocL(iMaxLength));
       
    54 	iBufferDes.Set(iBuffer,0,iMaxLength);
       
    55 	}
       
    56 
       
    57 /**
       
    58 Destructor.
       
    59 */
       
    60 CMMFFile::~CMMFFile() 
       
    61 	{
       
    62 	delete iFile;
       
    63 	
       
    64 	
       
    65 	iHandle.Close();
       
    66 	iFsSession.Close();
       
    67 	delete iFileName;
       
    68 	delete iFileExt;
       
    69 	delete iFilePath;
       
    70 	delete iFileDrive;
       
    71 	delete iMmfFileEventHandler;
       
    72 	delete iCAFParameters;
       
    73 
       
    74 	// Get rid of everything in RArray's & close them.
       
    75 	iRequests.ResetAndDestroy();
       
    76 	iTransferBufferCopies.ResetAndDestroy();
       
    77 	}
       
    78 
       
    79 /**
       
    80 Protected constructor.
       
    81 
       
    82 The default implementation is empty.
       
    83 */
       
    84 CMMFFile::CMMFFile() : CMMFClip( KUidMmfFileSource, KUidMmfFileSink ), iFileSize(-1)
       
    85 	{
       
    86 	iSinkNotStopped = EFalse;
       
    87 	}
       
    88 
       
    89 /**
       
    90 Constructs an CMMFFile MDataSource.
       
    91 
       
    92 @return A pointer to the new CMMFFile data source.
       
    93 */
       
    94 MDataSource* CMMFFile::NewSourceL() 
       
    95 	{
       
    96 	CMMFFile* self = new (ELeave) CMMFFile ;
       
    97 	return STATIC_CAST( MDataSource*, self ) ;
       
    98 	}
       
    99 
       
   100 /**
       
   101 Constructs a CMMFFile MDataSink
       
   102 
       
   103 @return A pointer to the new CMMFFile data sink.
       
   104 */
       
   105 MDataSink* CMMFFile::NewSinkL()
       
   106 	{
       
   107 	CMMFFile* self = new (ELeave) CMMFFile ;
       
   108 	return STATIC_CAST( MDataSink*, self ) ;
       
   109 	}
       
   110 
       
   111 /**
       
   112 Perform source construction dependant on the source construction
       
   113 initialisation data aInitData.
       
   114 
       
   115 @param  aInitData
       
   116         The TPckg<TMMFFileParams> descriptor package containing the file name and full path.
       
   117 */
       
   118 void CMMFFile::ConstructSourceL(const TDesC8& aInitData ) 
       
   119 	{
       
   120 	ConstructL(aInitData, ESourceMode);
       
   121 	}
       
   122 	
       
   123 /**
       
   124 Performs sink construction dependant on the sink construction
       
   125 initialisation data aInitData.
       
   126 
       
   127 @param  aInitData
       
   128         The TPckg<TMMFFileParams> descriptor package containing the file name and full path.
       
   129 */
       
   130 void CMMFFile::ConstructSinkL(const TDesC8& aInitData)
       
   131 	{
       
   132 	ConstructL(aInitData, ESinkMode);
       
   133 	}
       
   134 
       
   135 /**
       
   136 Protected constructor.
       
   137 
       
   138 Extracts the initialisation data provided by the calling functions: ConstructSourceL() and 
       
   139 ConstructSinkL(). Creates a file server session and sets up file name. If there is a file name and 
       
   140 it cannot be found this function leaves. If there is no file name the function leaves. Does not 
       
   141 attempt to open the file or check whether the file exists.
       
   142 
       
   143 If aInitData contains a TMMFFileHandleParams instead of TMMFFileParams, the source/sink is constructed from 
       
   144 the file handle provided by the caller
       
   145 
       
   146 @param  aInitData
       
   147         Initialisation data packaged in a TMMFFileParams or in a TMMFFileHandleParams (File Handle)
       
   148 */
       
   149 void CMMFFile::ConstructL(const TDesC8& aInitData,TMMFileMode aFileMode)
       
   150 	{
       
   151 	User::LeaveIfError(iFsSession.Connect());
       
   152 #ifdef __IPC_V2_PRESENT__
       
   153 	// on IPCv2 we auto attach
       
   154 	User::LeaveIfError(iFsSession.ShareAuto());
       
   155 #else
       
   156 	// on IPCv1 we use explicit - more efficient
       
   157 	User::LeaveIfError(iFsSession.Share(RSessionBase::EExplicitAttach));
       
   158 #endif
       
   159 
       
   160 	User::LeaveIfError(iFsSession.ShareProtected());
       
   161 	
       
   162 	HBufC* filename = NULL; 
       
   163 	
       
   164 	iCAFParameters = new (ELeave) CCAFParameters;
       
   165 	TBool drmContent = EFalse;
       
   166 	RDesReadStream stream(aInitData);
       
   167 	CleanupClosePushL(stream);
       
   168 	
       
   169 	TUid initUid = TUid::Uid(stream.ReadInt32L());
       
   170 
       
   171 	if (initUid == KMMFileHandleSourceUid)
       
   172 		{
       
   173 		TPckgBuf<RFile*> fileptr;
       
   174 		stream.ReadL(fileptr);
       
   175 		
       
   176 		iHandle.Duplicate(*fileptr());
       
   177 
       
   178 		TInt length = stream.ReadInt32L();
       
   179 		if (length>0)
       
   180 			{
       
   181 			iCAFParameters->iUniqueId = HBufC::NewL(length);
       
   182 			TPtr16 ptr = iCAFParameters->iUniqueId->Des();
       
   183 			stream.ReadL(ptr, length);
       
   184 			}
       
   185 		iFileHandle = ETrue;
       
   186 
       
   187 		filename = HBufC::NewMaxLC(KMaxFileName);
       
   188 		TPtr ptr = filename->Des();
       
   189 		User::LeaveIfError(iHandle.FullName(ptr));
       
   190 		drmContent = ETrue;
       
   191 		
       
   192 		iCAFParameters->iEnableUI = stream.ReadInt32L();
       
   193 		}
       
   194 		
       
   195 	else if (initUid == KMMFileSourceUid)
       
   196 		{
       
   197 		TInt length = stream.ReadInt32L();
       
   198 		filename = HBufC::NewMaxLC(length);
       
   199 		TPtr ptr = filename->Des();
       
   200 		stream.ReadL(ptr, length);
       
   201 
       
   202 		length = stream.ReadInt32L();
       
   203 		if (length>0)
       
   204 			{
       
   205 			iCAFParameters->iUniqueId = HBufC::NewMaxL(length);
       
   206 			ptr.Set(iCAFParameters->iUniqueId->Des());
       
   207 			stream.ReadL(ptr, length);
       
   208 			}
       
   209 		drmContent = ETrue;
       
   210 		iCAFParameters->iEnableUI = stream.ReadInt32L();
       
   211 		}
       
   212 	else
       
   213 		{
       
   214 //		TODO If the UID is unknown we should reject, but  currently
       
   215 //		code also used for older calls that just supply filename.
       
   216 //		User::Leave(KErrNotSupported);
       
   217 		}
       
   218 	
       
   219 	if ((filename == NULL) && aInitData.Length() == sizeof(TMMFFileHandleParams))
       
   220 		{
       
   221 		TMMFFileHandleParams params;
       
   222 		TPckgC<TMMFFileHandleParams> config(params);
       
   223 		config.Set(aInitData);
       
   224 		params = config();
       
   225 
       
   226 		
       
   227 		if (params.iUid == KFileHandleUid)
       
   228 			{
       
   229 			User::LeaveIfError(iHandle.Duplicate(*params.iFile));
       
   230 			TInt pos = 0;
       
   231 			// make sure the duplicate handle is at the start of the file - the usage of the file handle really requires this
       
   232 			User::LeaveIfError(iHandle.Seek(ESeekStart, pos));
       
   233 			iFileHandle = ETrue;
       
   234 			ASSERT(filename == NULL);
       
   235 			filename = HBufC::NewMaxLC(KMaxFileName);
       
   236 			TPtr ptr = filename->Des();
       
   237 			User::LeaveIfError(iHandle.FullName(ptr));
       
   238 			}
       
   239 		}
       
   240 
       
   241 	if (filename == NULL) // do old case as last resort
       
   242 		{
       
   243 		TMMFFileParams params;
       
   244 		TPckgC<TMMFFileParams> config(params);
       
   245 		config.Set(aInitData);
       
   246 		params = config();
       
   247 		
       
   248 		filename = params.iPath.AllocLC();
       
   249 		}
       
   250 	
       
   251 	ASSERT(filename != NULL);
       
   252 	
       
   253 	TParse parser ;
       
   254 	User::LeaveIfError(parser.Set(*filename, NULL, NULL));
       
   255 	CleanupStack::PopAndDestroy(2, &stream); //filename, stream
       
   256 	if ( !( parser.NamePresent() ) && !( parser.ExtPresent() ) )
       
   257 		{
       
   258 		User::Leave( KErrBadName ) ;
       
   259 		}
       
   260 	
       
   261 	iFullFileName.Copy( parser.FullName() ) ;	
       
   262 	iFileName = parser.Name().AllocL() ;
       
   263 	iFileExt = parser.Ext().AllocL() ;
       
   264 	iFilePath = parser.Path().AllocL() ;
       
   265 	iFileDrive = parser.Drive().AllocL() ;
       
   266 	
       
   267 	// in order to simulate old behaviour we are not passing error out
       
   268 	// but will try to create Content again during PrimeL()
       
   269 	if (drmContent && aFileMode==ESourceMode)
       
   270 		{
       
   271 		TInt contentError;
       
   272 		if (iFileHandle)
       
   273 			{
       
   274 			TRAP(contentError, 
       
   275 				iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI);
       
   276 				);
       
   277 			}
       
   278 		else
       
   279 			{
       
   280 			// Open for read-only access
       
   281 			TRAP(contentError,
       
   282 				iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareReadersOnly, iCAFParameters->iEnableUI);
       
   283 			);
       
   284 			}
       
   285 		}
       
   286 	}
       
   287 	
       
   288 
       
   289 /**
       
   290 @deprecated - Replaced by CMMFFile::Data()
       
   291 
       
   292 Returns an RFile handle to the current file.
       
   293 
       
   294 If there is no current file, one is created. If the file exists then it is opened with read access 
       
   295 if it is read only, write access otherwise. If the file does not exist then it is opened with
       
   296 write access.
       
   297 
       
   298 @leave KErrNotReady
       
   299        The file is not open.
       
   300 
       
   301 @return A handle to the current file.
       
   302 @see CMMFFile::Data()
       
   303 */
       
   304 RFile& CMMFFile::FileL()
       
   305 	{
       
   306 	if (!iFile)
       
   307 		User::Leave(KErrNotReady);
       
   308 	if (iFileHandle)
       
   309 		return iHandle;
       
   310 	else
       
   311 		return iFile->FileL();
       
   312 	}
       
   313 
       
   314 /** 
       
   315 Returns the file name of the current file.
       
   316 
       
   317 Note: This will give the wrong answer if the file is renamed!
       
   318 
       
   319 @return The FileName (without extension).
       
   320 */
       
   321 const TDesC& CMMFFile::FileName() const
       
   322 	{
       
   323 	return *iFileName ;
       
   324 	}
       
   325 
       
   326 /**
       
   327 Returns the extension of the current file.
       
   328 
       
   329 Note: This will give the wrong answer if the file is renamed!
       
   330 
       
   331 @return The File Extension.
       
   332 */
       
   333 const TDesC& CMMFFile::Extension() const 
       
   334 	{
       
   335 	return *iFileExt ;
       
   336 	}
       
   337 
       
   338 /** 
       
   339 Returns the path of the current file.
       
   340 
       
   341 Note: This will give the wrong answer if the file is renamed!
       
   342 
       
   343 @return The FilePath (without filename and extension)
       
   344 */
       
   345 const TDesC& CMMFFile::FilePath() const 
       
   346 	{
       
   347 	return *iFilePath ;
       
   348 	}
       
   349 
       
   350 /** 
       
   351 Returns the drive on which the current file is located.
       
   352 
       
   353 Note: This will give the wrong answer if the file is renamed!
       
   354 
       
   355 @return The FileDrive (drive letter only, without path, filename and extension).
       
   356 */
       
   357 const TDesC& CMMFFile::FileDrive() const 
       
   358 	{
       
   359 	return *iFileDrive ;
       
   360 	}
       
   361 
       
   362 /** 
       
   363 Returns the full name of the current file.
       
   364 
       
   365 Note: This will give the wrong answer if the file is renamed!
       
   366 
       
   367 @return The file name (full filename including drive letter, without path, filename and extension).
       
   368 */
       
   369 const TFileName CMMFFile::FullName() const
       
   370 	{
       
   371 	return iFullFileName;
       
   372 	}
       
   373 	
       
   374 /** 
       
   375 Returns the uniqueID associated with this content. If no uniqueID has been provided, a null
       
   376 descriptor will be provided
       
   377 
       
   378 @return The UniqueID
       
   379 */
       
   380 const TDesC& CMMFFile::UniqueId() const
       
   381 	{
       
   382 	if (iCAFParameters->iUniqueId)
       
   383 		return *(iCAFParameters->iUniqueId);
       
   384 	else
       
   385 		return KNullDesC;
       
   386 	}
       
   387 
       
   388 
       
   389 /**
       
   390 Deletes the file.
       
   391 
       
   392 Closes the currently open file, then deletes it. If the file source is accessing a file handle, 
       
   393 the file is truncated to 0 bytes instead.
       
   394 
       
   395 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
   396         another of the system-wide error codes.
       
   397 */
       
   398 TInt CMMFFile::Delete()				
       
   399 	{
       
   400 	TInt result = KErrNone;
       
   401 	if (!iFileHandle)
       
   402 		{
       
   403 		delete iFile;
       
   404 		iFile = NULL;
       
   405 		iFileSize=-1;
       
   406 		iPosition=0;
       
   407 
       
   408 		result = iFsSession.Delete(iFullFileName);
       
   409 		}
       
   410 	else
       
   411 		{
       
   412 		iFileSize=-1;
       
   413 		iPosition=0;
       
   414 		
       
   415 		if (iFile)
       
   416 			{
       
   417 			result = iFile->SetSize(0);
       
   418 			}
       
   419 		}
       
   420 
       
   421 	return result;
       
   422 	}
       
   423 
       
   424 /** 
       
   425 Sets the file size.
       
   426 
       
   427 @param  aSize
       
   428         The size of the file.
       
   429 
       
   430 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
   431         another of the system-wide error codes.
       
   432 */
       
   433 TInt CMMFFile::SetSize(TInt aSize)
       
   434 	{
       
   435 	if ( !iFile )
       
   436 		return KErrNotReady;
       
   437 	TInt err =  iFile->SetSize(aSize);
       
   438 	if(err == KErrNone)
       
   439 		iFileSize = aSize;
       
   440 	else
       
   441 		iFileSize = -1;
       
   442 
       
   443 	return err;
       
   444 	}
       
   445 	
       
   446 /**
       
   447 Obtains a CTransferBufferCopy from iTransferBufferCopies that is
       
   448 at least as big as that required.
       
   449 
       
   450 There is no need to put the pointer returned by this method onto the CleanupStack
       
   451 as it will have already been placed into iTransferBufferCopies.
       
   452 
       
   453 @param  aMaxLength
       
   454         The size required.
       
   455 
       
   456 @return A pointer to a valid CTransferBufferCopy.
       
   457 */
       
   458 CTransferBufferCopy* CMMFFile::ObtainCopyOfTransferBufferL(TInt aMaxLength)
       
   459 	{
       
   460 	//find a free transfer buffer copy of the right size
       
   461 	TInt firstFree = -1;
       
   462 	CTransferBufferCopy* transBufCopyToUse = NULL;
       
   463 
       
   464 	for(TInt cnt=0; cnt < iTransferBufferCopies.Count(); cnt++)
       
   465 		{
       
   466 		if(!iTransferBufferCopies[cnt]->InUse())
       
   467 			{
       
   468 			//record the first free entry, we may remove this
       
   469 			//if entries in iTransferBufferCopies > KAcceptableTransferBufferCopiesSize
       
   470 			if(firstFree == -1) 
       
   471 				firstFree = cnt;
       
   472 
       
   473 			if(iTransferBufferCopies[cnt]->MaxLength() >= aMaxLength)
       
   474 				{
       
   475 				transBufCopyToUse = iTransferBufferCopies[cnt];
       
   476 
       
   477 				//Set the MaxLength. This will ensure that the copy acts the same as
       
   478 				//the original Transfer buffer, eg. file server will throw KErrOverflow
       
   479 				transBufCopyToUse->ReUse(aMaxLength);
       
   480 				break;
       
   481 				}
       
   482 			}
       
   483 		}
       
   484 
       
   485 	//If we failed to find a suitable entry, we need to create a new one
       
   486 	if(!transBufCopyToUse)
       
   487 		{
       
   488 		//Firstly, should we re-cycle an existing entry?
       
   489 		//There must be entries in the array, a free entry must have been found,
       
   490 		//the size of the array must be beyond the water mark where we want to start
       
   491 		//cycling free entries.
       
   492 		if((iTransferBufferCopies.Count() > 0) &&
       
   493 			(firstFree != -1) &&
       
   494 			(iTransferBufferCopies.Count() > KAcceptableTransferBufferCopiesSize))
       
   495 			{
       
   496 			delete iTransferBufferCopies[firstFree];
       
   497 			iTransferBufferCopies.Remove(firstFree);
       
   498 
       
   499 			transBufCopyToUse = CTransferBufferCopy::NewL(aMaxLength);
       
   500 			CleanupStack::PushL(transBufCopyToUse);
       
   501 			User::LeaveIfError(iTransferBufferCopies.Insert(transBufCopyToUse,firstFree));
       
   502 				
       
   503 			CleanupStack::Pop();
       
   504 			}
       
   505 		else
       
   506 			{
       
   507 #ifdef _DEBUG
       
   508 			if(iTransferBufferCopies.Count() > KMaximumTransferBufferCopiesSize)
       
   509 				{
       
   510 				User::Panic(_L("iTransferBufferCopies grew too large in CMMFFile"),KErrTooBig);
       
   511 				}
       
   512 #endif
       
   513 
       
   514 			transBufCopyToUse = CTransferBufferCopy::NewL(aMaxLength);
       
   515 			CleanupStack::PushL(transBufCopyToUse);
       
   516 			User::LeaveIfError(iTransferBufferCopies.Append(transBufCopyToUse));
       
   517 
       
   518 			CleanupStack::Pop();
       
   519 			}
       
   520 		}
       
   521 
       
   522 	return transBufCopyToUse;
       
   523 	}
       
   524 
       
   525 
       
   526 
       
   527 /** 
       
   528 Loads aBuffer from iFile.
       
   529 
       
   530 The file must already be open for reading. File read is asynchronous. CReadRequest is created to 
       
   531 respond to completion.
       
   532 
       
   533 @param  aBuffer
       
   534         The buffer to be filled from the file.
       
   535 @param  aConsumer
       
   536         The data sink consumer of the buffer.
       
   537 */
       
   538 void CMMFFile::FillBufferL( CMMFBuffer* aBuffer, MDataSink* aConsumer, TMediaId /*aMediaId*/ )
       
   539 	{
       
   540 	// Requires that iFile is open for read.
       
   541 	// Reads data from iFile into aBuffer
       
   542 	if ((aConsumer == NULL) || (aBuffer == NULL))
       
   543 		User::Leave(KErrArgument);
       
   544 
       
   545 	if (!iFile || (iMmfFileEventHandler == NULL))
       
   546 		User::Leave(KErrNotReady);
       
   547 
       
   548 	if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   549 		{
       
   550 		CTransferBufferCopy* transBufCopy = NULL;
       
   551 		CReadRequest* request = NULL;
       
   552 
       
   553 		TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
       
   554 
       
   555 		TInt requestSize;
       
   556 		if(aBuffer->RequestSize())
       
   557 			requestSize = aBuffer->RequestSize();
       
   558 		else
       
   559 			requestSize = aBufferDes.MaxLength();
       
   560 
       
   561 		//check whether buffer is safe to send to file server
       
   562 		//if not, eg for a transfer buffer, then it needs to be copied
       
   563 		if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
       
   564 			{
       
   565 			//NB: failure in this method will NOT cause transBufCopy to leak as it will be 
       
   566 			//inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
       
   567 			transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
       
   568 			request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, transBufCopy, iPosition, Size(), iMmfFileEventHandler);
       
   569 			}
       
   570 		else
       
   571 			{
       
   572 			request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, iPosition, Size(), iMmfFileEventHandler);
       
   573 			}
       
   574 
       
   575 		CleanupStack::PushL( request );
       
   576 
       
   577 		StoreRequestL(request); // transfers ownership
       
   578 		CleanupStack::Pop() ; // request
       
   579 
       
   580 		iFile->Read(request->BufferDes(), requestSize, request->iStatus);
       
   581 		iPosition += requestSize;
       
   582 		
       
   583 		if (iPosition >= iFileSize)
       
   584 			{
       
   585 			aBuffer->SetLastBuffer(ETrue);
       
   586 			}
       
   587 
       
   588 		request->SetActive();
       
   589 		}
       
   590 	else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   591 		User::Leave( KErrNotSupported ) ;
       
   592 	}
       
   593 
       
   594 /** 
       
   595 Empties aBuffer into iFile. The file must be already open for writing.
       
   596 
       
   597 @param  aBuffer
       
   598         The buffer to be written to the file.
       
   599 @param  aSupplier
       
   600         The data source supplier of the buffer.
       
   601 */
       
   602 void CMMFFile::EmptyBufferL( CMMFBuffer* aBuffer, MDataSource* aSupplier, TMediaId /*aMediaId*/ )
       
   603 	{
       
   604 	// Requires that iFile is open for write.
       
   605 	// Writes data from iFile into aBuffer
       
   606 	if ((aSupplier == NULL) || (aBuffer == NULL))
       
   607 		User::Leave(KErrArgument);
       
   608 
       
   609 	if (!iFile || (iMmfFileEventHandler == NULL))
       
   610 		User::Leave(KErrNotReady);
       
   611 
       
   612 	CTransferBufferCopy* transBufCopy = NULL;
       
   613 	
       
   614 	if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   615 		{
       
   616 		CWriteRequest* request = NULL;
       
   617 		TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
       
   618 
       
   619 		//check whether buffer is safe to send to file server
       
   620 		//if not, eg for a transfer buffer, then it needs to be copied
       
   621 		if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
       
   622 			{
       
   623 			//Obtain a normal buffer to send to the file server
       
   624 			//NB: failure in this method will NOT cause transBufCopy to leak as it will be 
       
   625 			//inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
       
   626 			transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
       
   627 
       
   628 			//Copy the data into the buffer we will send to the file server
       
   629 			transBufCopy->Des().Copy(aBufferDes);
       
   630 
       
   631 			request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, transBufCopy, iMmfFileEventHandler);
       
   632 			}
       
   633 		else
       
   634 			{
       
   635 			request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, iMmfFileEventHandler);
       
   636 			}
       
   637 
       
   638 		CleanupStack::PushL( request );
       
   639 
       
   640 		StoreRequestL(request);  // transfers ownership
       
   641 		CleanupStack::Pop(); // request
       
   642 
       
   643 		iFile->Write(request->BufferDes(), request->BufferDes().Length(), request->iStatus);
       
   644 		request->SetActive();
       
   645 		}
       
   646 	else  // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   647 		{
       
   648 		User::Leave( KErrNotSupported ) ;
       
   649 		}
       
   650 	}
       
   651 
       
   652 /** 
       
   653 Loads aLength number of bytes into aBuffer from specified point in iFile.
       
   654 
       
   655 @param  aLength
       
   656         The number of bytes to be read into buffer.
       
   657 @param  aBuffer
       
   658         The buffer to be filled from the file.
       
   659 @param  aPosition
       
   660         The offset into the file at which to start reading.
       
   661 @param  aConsumer
       
   662         The data sink consumer of the buffer.
       
   663 */
       
   664 void CMMFFile::ReadBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer)
       
   665 	{
       
   666 	// Requires that iFile is open for read.
       
   667 	// Reads data from iFile into aBuffer
       
   668 	if ((aLength < 0) || (aPosition<0) || (aConsumer == NULL) || (aBuffer == NULL))
       
   669 		User::Leave(KErrArgument);
       
   670 
       
   671 	if (!iFile || (iMmfFileEventHandler == NULL))
       
   672 		User::Leave(KErrNotReady);
       
   673 
       
   674 	CTransferBufferCopy* transBufCopy = NULL;
       
   675 
       
   676 	if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   677 		{
       
   678 		CReadRequest* request = NULL;
       
   679 		TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
       
   680 		
       
   681 		//check whether buffer is safe to send to file server
       
   682 		//if not, eg for a transfer buffer, then it needs to be copied
       
   683 		if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
       
   684 			{
       
   685 			//Obtain a normal buffer to send to the file server
       
   686 			//NB: failure in this method will NOT cause transBufCopy to leak as it will be 
       
   687 			//inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
       
   688 			transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
       
   689 
       
   690 			request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, transBufCopy, aPosition, Size(), iMmfFileEventHandler);
       
   691 			}
       
   692 		else
       
   693 			{
       
   694 			request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, aPosition, Size(), iMmfFileEventHandler);
       
   695 			}
       
   696 
       
   697 		CleanupStack::PushL( request );
       
   698 
       
   699 		StoreRequestL(request) ;  //transfers ownership
       
   700 		CleanupStack::Pop() ; //request
       
   701 
       
   702 		TInt err = iFile->Read(aPosition, request->BufferDes(), aLength, request->iStatus);
       
   703 		if (err == KErrCANotSupported)
       
   704 			{
       
   705 			err = KErrNone;
       
   706 			if (aPosition != iPosition)
       
   707 				{
       
   708 				err = iFile->Seek(ESeekStart, aPosition);
       
   709 				}
       
   710 			if (err==KErrNone)
       
   711 				{
       
   712 				iFile->Read(request->BufferDes(), aLength, request->iStatus);
       
   713 				}
       
   714 			}
       
   715 		
       
   716 		if (err != KErrNone)
       
   717 			{
       
   718 			TRequestStatus* status = &request->iStatus;
       
   719 			User::RequestComplete(status, err);
       
   720 			}
       
   721 
       
   722 		iPosition = aPosition + aLength;
       
   723 		
       
   724 		if (iPosition >= iFileSize)
       
   725 			{
       
   726 			aBuffer->SetLastBuffer(ETrue);
       
   727 			}
       
   728 
       
   729 		request->SetActive();
       
   730 		}
       
   731 	else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   732 		User::Leave( KErrNotSupported ) ;
       
   733 	}
       
   734 	
       
   735 	
       
   736 /**
       
   737 Loads aBuffer from specified point in iFile.
       
   738 
       
   739 The file must already be open for reading.
       
   740 
       
   741 @param  aBuffer
       
   742         The buffer to be filled from the file.
       
   743 @param  aPosition
       
   744         The offset into file at which to start reading.
       
   745 @param  aConsumer
       
   746         The data sink consumer of the buffer.
       
   747 */
       
   748 void CMMFFile::ReadBufferL(CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer)
       
   749 	{
       
   750 	// Requires that iFile is open for read.
       
   751 	// Reads data from iFile into aBuffer
       
   752 	if ((aPosition<0) || (aConsumer == NULL) || (aBuffer == NULL))
       
   753 		User::Leave(KErrArgument);
       
   754 
       
   755 	if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   756 		{
       
   757 		TInt requestSize;
       
   758 		if(aBuffer->RequestSize())
       
   759 			requestSize = aBuffer->RequestSize();
       
   760 		else
       
   761 			requestSize = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data().MaxLength();
       
   762 
       
   763 		ReadBufferL(requestSize, aBuffer, aPosition, aConsumer);
       
   764 		}
       
   765 	else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   766 		User::Leave(KErrNotSupported);
       
   767 	}
       
   768 
       
   769 
       
   770 /**
       
   771 Loads aBuffer from specified point in iFile.  Note that this is a synchronous read.
       
   772 
       
   773 @param  aBuffer
       
   774         The buffer to be filled from the file.
       
   775 @param  aPosition
       
   776         The offset into file at which to start reading.
       
   777 */
       
   778 void CMMFFile::ReadBufferL( CMMFBuffer* aBuffer, TInt aPosition)
       
   779 	{
       
   780 	// Requires that iFile is open for read.
       
   781 	// Reads data from iFile into aBuffer
       
   782 	if ((aPosition<0) || (aBuffer == NULL))
       
   783 		User::Leave(KErrArgument);
       
   784 
       
   785 	if (!iFile)
       
   786 		User::Leave(KErrNotReady);
       
   787 
       
   788 	if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   789 		{
       
   790 		TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
       
   791 
       
   792 		TInt requestSize;
       
   793 		if(aBuffer->RequestSize())
       
   794 			requestSize = aBuffer->RequestSize();
       
   795 		else
       
   796 			requestSize = aBufferDes.MaxLength();
       
   797 
       
   798 		//check whether buffer is safe to send to file server
       
   799 		//if not, eg for a transfer buffer, then it needs to be copied
       
   800 		if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
       
   801 			{
       
   802 			//NB: failure in this method will NOT cause transBufCopy to leak as it will be 
       
   803 			//inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
       
   804 			CTransferBufferCopy* transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
       
   805 
       
   806 			User::LeaveIfError(iFile->Seek(ESeekStart, aPosition));
       
   807 			User::LeaveIfError(iFile->Read(transBufCopy->Des(), requestSize));
       
   808 			aBufferDes.Copy(transBufCopy->Des().Left(aBufferDes.MaxLength()));
       
   809 			}
       
   810 		else
       
   811 			{
       
   812 			User::LeaveIfError(iFile->Seek(ESeekStart, aPosition));
       
   813 			User::LeaveIfError(iFile->Read(aBufferDes, requestSize));
       
   814 			}
       
   815 
       
   816 		iPosition = aPosition + aBufferDes.Length();
       
   817 		
       
   818 		//check if the buffer is the last buffer and if so set the last buffer flag on the CMMFDataBuffer
       
   819 		//NB: setting last buffer is the done by the formatter, but this is a hang over to account for 
       
   820 		//existing formatters that may fail if this is removed.
       
   821 		if (iPosition >= Size())
       
   822 			{
       
   823 			aBuffer->SetLastBuffer(ETrue);
       
   824 			}
       
   825 		}
       
   826 	else  // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   827 		User::Leave(KErrNotSupported); 
       
   828 	}
       
   829 
       
   830 /** 
       
   831 Empties aLength bytes from aBuffer into iFile at specified location.
       
   832 
       
   833 @param  aLength
       
   834         The number of bytes to be emptied from buffer.
       
   835 @param  aBuffer
       
   836         The data buffer containing bytes to be written.
       
   837 @param  aPosition
       
   838         The offset into file at which to start writing.
       
   839 @param  aSupplier
       
   840         The data source to be notified when the write has been completed.
       
   841 
       
   842 @leave  KErrNotReady 
       
   843         SinkPrimeL() and SinkThreadLogon() have not been called.
       
   844 @leave  KErrArgument 
       
   845         aLength<0 or aPosition<0 or aSupplier is NULL.
       
   846 @leave  KErrNotSupported 
       
   847         aBuffer is not a supported CMMFDataBuffer
       
   848 */
       
   849 void CMMFFile::WriteBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier)
       
   850 	{
       
   851 	if ((aLength<0) || (aPosition<0) || (aSupplier == NULL) || (aBuffer == NULL))
       
   852 		User::Leave(KErrArgument);
       
   853 
       
   854 	if (!iFile || (iMmfFileEventHandler == NULL))
       
   855 		User::Leave(KErrNotReady);
       
   856 	
       
   857 	if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   858 		{
       
   859 		CWriteRequest* request = NULL;
       
   860 		TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
       
   861 
       
   862 		//check whether buffer is safe to send to file server
       
   863 		//if not, eg for a transfer buffer, then it needs to be copied
       
   864 		if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
       
   865 			{
       
   866 			//NB: failure in this method will NOT cause transBufCopy to leak as it will be 
       
   867 			//inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
       
   868 			CTransferBufferCopy* transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
       
   869 
       
   870 			transBufCopy->Des().Copy(aBufferDes);
       
   871 
       
   872 			request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, transBufCopy, iMmfFileEventHandler);
       
   873 			}
       
   874 		else
       
   875 			{
       
   876 			request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, iMmfFileEventHandler);
       
   877 			}
       
   878 
       
   879 		CleanupStack::PushL( request );
       
   880 
       
   881 		StoreRequestL(request);  // transfers ownership
       
   882 		CleanupStack::Pop(); // request
       
   883 
       
   884 		User::LeaveIfError(iFile->Seek(ESeekStart, aPosition));		
       
   885 		iFile->Write(request->BufferDes(), aLength, request->iStatus);
       
   886 		iFileSize = -1; //reset cached size
       
   887 
       
   888 		request->SetActive();
       
   889 		}
       
   890 	else // if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
       
   891 		{
       
   892 		//write bitmap to file
       
   893 		User::Leave(KErrNotSupported);
       
   894 		}
       
   895 	}
       
   896 
       
   897 /**
       
   898 Empties aBuffer into iFile at the specified location.
       
   899 
       
   900 @param  aBuffer
       
   901         The data buffer containing bytes to be written.
       
   902 @param  aPosition
       
   903         The offset into file at which to start writing.
       
   904 @param  aSupplier
       
   905         The data source to be notified when the write has been completed.
       
   906 
       
   907 @leave  KErrNotReady 
       
   908         SinkPrimeL() and SinkThreadLogon() have not been called.
       
   909 @leave  KErrArgument 
       
   910         aSupplier is NULL.
       
   911 @leave  KErrNotSupported 
       
   912         The aBuffer is not of type KMMFDataBuffer.
       
   913 */
       
   914 void CMMFFile::WriteBufferL( CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier)
       
   915 	{
       
   916 	// Requires that iFile is open for write.
       
   917 	// Writes data from iFile into aBuffer
       
   918 	if ((aPosition<0) || (aSupplier == NULL) || (aBuffer == NULL))
       
   919 		User::Leave(KErrArgument);
       
   920 
       
   921 	if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   922 		{
       
   923 		TUint requestSize = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data().Length();
       
   924 
       
   925 		WriteBufferL(requestSize, aBuffer, aPosition, aSupplier);
       
   926 		}
       
   927 	else  // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   928 		{
       
   929 		//write bitmap to file
       
   930 		User::Leave( KErrNotSupported ) ;
       
   931 		}
       
   932 	}
       
   933 
       
   934 /**
       
   935 Empties aBuffer into iFile at specified location.  Note that this is a synchronous write.
       
   936 
       
   937 @param  aBuffer
       
   938         The data buffer containing bytes to be written.
       
   939 @param  aPosition
       
   940         The offset into file at which to start writing.
       
   941 
       
   942 @return The error code from RFile.
       
   943 */
       
   944 void CMMFFile::WriteBufferL( CMMFBuffer* aBuffer, TInt aPosition ) 
       
   945 	{
       
   946 	if ((aPosition<0) || (aBuffer == NULL))
       
   947 		User::Leave(KErrArgument);
       
   948 
       
   949 	if (!iFile)
       
   950 		User::Leave(KErrNotReady);
       
   951 
       
   952 	TInt err(KErrNone) ;
       
   953 
       
   954 	//check whether buffer is safe to send to file server
       
   955 	//if not, eg for a transfer buffer, then it needs to be copied
       
   956 	if ((!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
       
   957 		&& (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())))
       
   958 		{
       
   959 		TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
       
   960 
       
   961 		//NB: failure in this method will NOT cause transBufCopy to leak as it will be 
       
   962 		//inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
       
   963 		CTransferBufferCopy* transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
       
   964 
       
   965 		transBufCopy->Des().Copy(aBufferDes);
       
   966 		err = iFile->Seek(ESeekStart, aPosition);
       
   967 		if (err==KErrNone)
       
   968 			err = iFile->Write(transBufCopy->Des(),transBufCopy->Des().Length()); 
       
   969 		iFileSize = -1; //reset cached size
       
   970 		}
       
   971 	else if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   972 		{
       
   973 		TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
       
   974 
       
   975 		err = iFile->Seek(ESeekStart, aPosition);
       
   976 		if (err==KErrNone)
       
   977 			err = iFile->Write(aBufferDes, aBufferDes.Length()); 
       
   978 		iFileSize = -1; //reset cached size
       
   979 		}
       
   980 	else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
       
   981 		{
       
   982 		User::Leave(KErrNotSupported);
       
   983 		}
       
   984 
       
   985 	User::LeaveIfError(err);
       
   986 	}
       
   987 
       
   988 /**
       
   989 Gets the number of free bytes in the device's file system.
       
   990 
       
   991 @return The number of free bytes.
       
   992 */
       
   993 TInt64 CMMFFile::BytesFree()
       
   994 	{
       
   995 	TInt driveNumber = KDefaultDrive;
       
   996 	
       
   997 	if (FileDrive().Length() > 0)
       
   998  		{
       
   999  		TChar driveLetter = FileDrive()[0];
       
  1000  		RFs::CharToDrive(driveLetter, driveNumber);
       
  1001  		}
       
  1002 	
       
  1003 	TVolumeInfo volInfo;
       
  1004 	if (iFsSession.Volume(volInfo, driveNumber) == KErrNone)
       
  1005 		{
       
  1006 		return volInfo.iFree;
       
  1007 		}
       
  1008 	return TInt64(0);
       
  1009 	}
       
  1010 
       
  1011 /** 
       
  1012 Returns the size of the file in bytes.
       
  1013 
       
  1014 Note: This is not the maximum length.
       
  1015 
       
  1016 @return The size of the file in bytes.
       
  1017 */
       
  1018 TInt CMMFFile::Size()
       
  1019 	{
       
  1020 	TInt size = 0;
       
  1021 	TInt err = KErrNone;
       
  1022 	TBool fileOpened = EFalse;
       
  1023 
       
  1024 	if(iFileSize != -1)
       
  1025 		return iFileSize;
       
  1026 
       
  1027 	if (!iFile)
       
  1028 		{
       
  1029 		// Open the file. We only need read access, so SourcePrimeL will open the file with read flag
       
  1030 		TRAP(err, SourcePrimeL());
       
  1031 		if (iFile)
       
  1032 			fileOpened = ETrue;
       
  1033 		}
       
  1034 	if (err == KErrNone)
       
  1035 		err = iFile->Size(size);
       
  1036 	if (err)
       
  1037 		{
       
  1038 		size = 0;
       
  1039 		iFileSize = -1; //reset cached size
       
  1040 		}
       
  1041 	else 
       
  1042 		iFileSize = size; //cache the filesize
       
  1043 
       
  1044 	if (fileOpened)
       
  1045 		{
       
  1046 		delete iFile;
       
  1047 		iFile = NULL;
       
  1048 		iFileSize = -1;
       
  1049 		}
       
  1050 
       
  1051 	return size;
       
  1052 	}
       
  1053 
       
  1054 /**
       
  1055 Source thread logon.
       
  1056 
       
  1057 Shares fsSession between threads
       
  1058 
       
  1059 @param  aEventHandler
       
  1060         This is an MAsyncEventHandler to handle asynchronous events that occur during the
       
  1061         transfer of multimedia data.
       
  1062 
       
  1063 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
  1064         another of the system-wide error codes.
       
  1065 */
       
  1066 TInt CMMFFile::SourceThreadLogon(MAsyncEventHandler& aEventHandler)
       
  1067 	{
       
  1068 	iEventHandler = &aEventHandler;
       
  1069 	if(!iMmfFileEventHandler)
       
  1070 		{
       
  1071 		iMmfFileEventHandler = new CMMFFileAsyncEventHandler(this);
       
  1072 		if(!iMmfFileEventHandler)
       
  1073 			return KErrNoMemory;
       
  1074 		}
       
  1075 #ifdef __IPC_V2_PRESENT__
       
  1076 	return KErrNone; // nothing to do
       
  1077 #else
       
  1078 	return iFsSession.Attach();
       
  1079 #endif // __HIDE_IPC_V1__
       
  1080 	}
       
  1081 
       
  1082 /** 
       
  1083 Logs off source thread.
       
  1084 */
       
  1085 void CMMFFile::SourceThreadLogoff()
       
  1086 	{
       
  1087 	delete iMmfFileEventHandler;
       
  1088 	iMmfFileEventHandler = NULL;
       
  1089 	iEventHandler = NULL;
       
  1090 	}
       
  1091 
       
  1092 
       
  1093 /**
       
  1094 Sink thread logon.
       
  1095 
       
  1096 Shares fsSession between threads.
       
  1097 
       
  1098 @param  aEventHandler
       
  1099         This is an MAsyncEventHandler to handle asynchronous events that occur during the
       
  1100         transfer of multimedia data.
       
  1101 
       
  1102 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
  1103         another of the system-wide error codes.
       
  1104 */
       
  1105 TInt CMMFFile::SinkThreadLogon(MAsyncEventHandler& aEventHandler)
       
  1106 	{
       
  1107 	iEventHandler = &aEventHandler;
       
  1108 	if(!iMmfFileEventHandler)
       
  1109 		{
       
  1110 		iMmfFileEventHandler = new CMMFFileAsyncEventHandler(this);
       
  1111 		if(!iMmfFileEventHandler)
       
  1112 			return KErrNoMemory;
       
  1113 		}
       
  1114 #ifdef __IPC_V2_PRESENT__
       
  1115 	return KErrNone;
       
  1116 #else
       
  1117 	return iFsSession.Attach();
       
  1118 #endif // __HIDE_IPC_V1__
       
  1119 	}
       
  1120 
       
  1121 /** 
       
  1122 Sink thread log off.
       
  1123 */
       
  1124 void CMMFFile::SinkThreadLogoff() 
       
  1125 	{
       
  1126 	delete iMmfFileEventHandler;
       
  1127 	iMmfFileEventHandler = NULL;
       
  1128 	iEventHandler = NULL;
       
  1129 	}
       
  1130 
       
  1131 /**
       
  1132 Stores a request in an array.
       
  1133 
       
  1134 CReadWriteRequests are stored in the array iRequests.
       
  1135 This function takes ownership and places the request in the array.
       
  1136 It also checks the array for completed requests and removes them.
       
  1137 
       
  1138 @param  aRequest
       
  1139         The request to store.
       
  1140 */
       
  1141 void CMMFFile::StoreRequestL( CReadWriteRequest* aRequest )
       
  1142 	{
       
  1143 	// add aRequest to iRequests
       
  1144 	User::LeaveIfError( iRequests.Append( aRequest ) ) ;
       
  1145 
       
  1146 	// Clear out any completed requests
       
  1147 	for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ )
       
  1148 		{
       
  1149 		if (iRequests[ii]->Completed())
       
  1150 			{
       
  1151 			CReadWriteRequest* request = iRequests[ii];
       
  1152 			delete request;
       
  1153 
       
  1154 			iRequests.Remove(ii);
       
  1155 			ii--;
       
  1156 			}
       
  1157 		}
       
  1158 	}
       
  1159 
       
  1160 
       
  1161 /**
       
  1162 Cancels outstanding requests.
       
  1163 
       
  1164 CReadWriteRequests are stored in the array iRequests.
       
  1165 This function cancels any outstanding requests and removes them
       
  1166 from iRequests.
       
  1167 */
       
  1168 void CMMFFile::CancelRequests()
       
  1169 	{
       
  1170 	// Clear out any completed requests
       
  1171 	for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ )
       
  1172 		{
       
  1173 		CReadWriteRequest* request = iRequests[ii];
       
  1174 		delete request;
       
  1175 		iRequests.Remove(ii);
       
  1176 		ii--;
       
  1177 		}
       
  1178 	}
       
  1179 
       
  1180 
       
  1181 
       
  1182 /**
       
  1183 Returns the data type as a fourCC code of CMMFFile as a data source.
       
  1184 
       
  1185 @return The data type fourCC code.
       
  1186 */
       
  1187 TFourCC CMMFFile::SourceDataTypeCode(TMediaId /*aMediaId*/) 
       
  1188 	{
       
  1189 	return  iSourceFourCC ;
       
  1190 	}
       
  1191 
       
  1192 /**
       
  1193 Returns the data type as a fourCC code of CMMFFile as a data sink.
       
  1194 
       
  1195 @return The data type fourCC code
       
  1196 */
       
  1197 TFourCC CMMFFile::SinkDataTypeCode(TMediaId /*aMediaId*/) 
       
  1198 	{
       
  1199 	return  iSinkFourCC ;
       
  1200 	}
       
  1201 
       
  1202 
       
  1203 /**
       
  1204 CMMFFile as a source is always passive so this function is not supported.
       
  1205 
       
  1206 @param  aBuffer
       
  1207         The emptied buffer.
       
  1208 */
       
  1209 void CMMFFile::BufferEmptiedL(CMMFBuffer* /* aBuffer */)
       
  1210 	{
       
  1211 	Panic(EMMFFilePanicBufferEmptiedLNotSupported);
       
  1212 	}
       
  1213 
       
  1214 /**
       
  1215 Tests whether a source buffer can be created.
       
  1216 
       
  1217 @return	A boolean indicating if if CMMFFile can create its own buffer. EFalse if CMMFFile cannot 
       
  1218         create it's own buffer.
       
  1219 */
       
  1220 TBool CMMFFile::CanCreateSourceBuffer()
       
  1221 	{
       
  1222 	return EFalse ;
       
  1223 	}
       
  1224 
       
  1225 /**
       
  1226 Creates a source buffer.
       
  1227 
       
  1228 @param  aMediaId
       
  1229         The Media ID.
       
  1230 @param  aReference
       
  1231         A boolean indicating if MDataSource owns the buffer. ETrue if it does, EFalse if the caller
       
  1232         owns the buffer.
       
  1233 
       
  1234 @return	NULL as a CMMFFile cannot create it's own buffer
       
  1235 */
       
  1236 CMMFBuffer* CMMFFile::CreateSourceBufferL( TMediaId /*aMediaId*/ , TBool& /*aReference*/)
       
  1237 	{
       
  1238 	User::Leave(KErrNotSupported);
       
  1239 	return NULL ;
       
  1240 	}
       
  1241 
       
  1242 /**
       
  1243 CMMFFile as a sink is always passive so this function is not supported.
       
  1244 
       
  1245 @param  aBuffer
       
  1246         The buffer.
       
  1247 */
       
  1248 void CMMFFile::BufferFilledL(CMMFBuffer* /* aBuffer */)
       
  1249 	{
       
  1250 	Panic(EMMFFilePanicBufferFilledLNotSupported);
       
  1251 	}
       
  1252 
       
  1253 /**
       
  1254 Tests whether a sink buffer can be created.
       
  1255 
       
  1256 @return	A boolean indicating if the sink buffer can be created. EFalse if CMMFFile cannot create 
       
  1257         it's own buffer
       
  1258 */
       
  1259 TBool CMMFFile::CanCreateSinkBuffer() 
       
  1260 	{
       
  1261 	return EFalse ;
       
  1262 	}
       
  1263 
       
  1264 /**
       
  1265 Creates a sink buffer.
       
  1266 
       
  1267 @param  aMediaId
       
  1268         The Media ID.
       
  1269 @param  aReference 
       
  1270         A boolean indicating if MDataSource owns the buffer. ETrue if MDataSource owns the buffer,
       
  1271         EFalse if the caller owns the buffer.
       
  1272 
       
  1273 @return	NULL as a CMMFFile cannot create it's own buffer
       
  1274 */
       
  1275 CMMFBuffer* CMMFFile::CreateSinkBufferL(TMediaId /*aMediaId*/ , TBool& /*aReference*/) 
       
  1276 	{
       
  1277 	User::Leave(KErrNotSupported);
       
  1278 	return NULL ;
       
  1279 	}
       
  1280 
       
  1281 /**
       
  1282 Primes the source.
       
  1283 
       
  1284 When used as a source, the file prime opens the file as read only.
       
  1285 */
       
  1286 void CMMFFile::SourcePrimeL()
       
  1287 	{
       
  1288 	// don't reopen file if already open
       
  1289 	if (!iFile)
       
  1290 		{
       
  1291 		if (iFileHandle)
       
  1292 			{
       
  1293 			iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI);
       
  1294 			}
       
  1295 		else
       
  1296 			{
       
  1297 			// Open for read-only access
       
  1298 			iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareReadersOnly, iCAFParameters->iEnableUI);
       
  1299 			}
       
  1300 		}
       
  1301 	}
       
  1302 
       
  1303 /**
       
  1304 Primes the sink.
       
  1305 
       
  1306 When used as a sink, the file prime opens the file for read/write access.
       
  1307 */
       
  1308 void CMMFFile::SinkPrimeL() 
       
  1309 	{
       
  1310 	// don't reopen file if already open
       
  1311 	if (!iFile)
       
  1312 		{
       
  1313 		if (iFileHandle)
       
  1314 			iFile = CF32File::NewL(iHandle);
       
  1315 		else
       
  1316 			iFile = CF32File::NewL(iFsSession, iFullFileName, EFileRead | EFileWrite);
       
  1317 		}
       
  1318 		iSinkNotStopped = ETrue;
       
  1319 	}
       
  1320 
       
  1321 /**
       
  1322 Stops the file source. When stopping close the file. If the source is a file handle, the position is reset, but the 
       
  1323 file handle remains open.
       
  1324 */
       
  1325 void CMMFFile::SourceStopL()
       
  1326 	{
       
  1327 	TInt pos = 0;
       
  1328 
       
  1329 	CancelRequests();
       
  1330 	
       
  1331 	// It is possible the file could have disappeared at this point (MMC/SD Card)
       
  1332 	//
       
  1333 	if (!iFile)
       
  1334 		{
       
  1335 		iPosition=pos;
       
  1336 		return;
       
  1337 		}
       
  1338 
       
  1339 	if (!iFileHandle && !iFile->IsProtected())
       
  1340 		{
       
  1341 		delete iFile;
       
  1342 		iFile = NULL;
       
  1343 		iFileSize = -1;
       
  1344 		}
       
  1345 	else
       
  1346 		{
       
  1347 		User::LeaveIfError(iFile->Seek(ESeekStart, pos));
       
  1348 		}
       
  1349 	iPosition=pos;
       
  1350 	}
       
  1351 
       
  1352 /**
       
  1353 Stops the file sink. 
       
  1354 
       
  1355 When stopping close the file. When the file sink is a file handle, the position is reset, but the file handle
       
  1356 remains open
       
  1357 */
       
  1358 void CMMFFile::SinkStopL()
       
  1359 	{
       
  1360 	iFileSize = -1;
       
  1361 	iPosition=0;
       
  1362 
       
  1363 	CancelRequests();
       
  1364 	iSinkNotStopped = EFalse;
       
  1365 	if (!iFileHandle)
       
  1366 		{		
       
  1367 		delete iFile;
       
  1368 		iFile = NULL;
       
  1369 		}
       
  1370 	else
       
  1371 		{
       
  1372 		TInt pos = 0;
       
  1373 		User::LeaveIfError(iFile->Seek(ESeekStart, pos));
       
  1374 		}
       
  1375 	}
       
  1376 
       
  1377 /**
       
  1378 Pauses the file source
       
  1379 */
       
  1380 void CMMFFile::SourcePauseL()
       
  1381 	{
       
  1382 	CancelRequests();
       
  1383 	}
       
  1384 
       
  1385 /**
       
  1386 Returns a boolean indicating if the sink has been stopped.
       
  1387 
       
  1388 @return A boolean indicating if the sink has stopped.
       
  1389  */
       
  1390 TBool CMMFFile::SinkStopped()
       
  1391 	{
       
  1392 	if(iSinkNotStopped == EFalse)
       
  1393 		return ETrue;
       
  1394 	else
       
  1395 		return EFalse;
       
  1396 	}
       
  1397 
       
  1398 /**
       
  1399 Evaluates a given intent against the rights associated with the file.
       
  1400 
       
  1401 The rights are not updated by this function call.
       
  1402 
       
  1403 @param  aIntent
       
  1404         The intent to evaluate.
       
  1405 
       
  1406 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
  1407         another of the system-wide error codes.
       
  1408 */
       
  1409 TInt CMMFFile::EvaluateIntent(ContentAccess::TIntent aIntent) const
       
  1410 	{
       
  1411 	if (iFile==NULL)
       
  1412 		{
       
  1413 		return KErrNotReady;
       
  1414 		}
       
  1415 
       
  1416 	return iFile->EvaluateIntent(aIntent);
       
  1417 	}
       
  1418 
       
  1419 /**
       
  1420 Evaluates and executes a given intent against the rights associated with the file.
       
  1421 
       
  1422 The rights object is updated after calling this function.
       
  1423 
       
  1424 @param  aIntent
       
  1425         The intent to evaluate.
       
  1426 
       
  1427 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
  1428         another of the system-wide error codes.
       
  1429 */
       
  1430 TInt CMMFFile::ExecuteIntent(ContentAccess::TIntent aIntent)
       
  1431 	{
       
  1432 	if (iFile==NULL)
       
  1433 		{
       
  1434 		return KErrNotReady;
       
  1435 		}
       
  1436 
       
  1437 	return iFile->ExecuteIntent(aIntent);
       
  1438 	}
       
  1439 
       
  1440 /**
       
  1441 Returns whether the file is protected.
       
  1442 
       
  1443 @return A boolean indicating if the file is protected. ETrue if the file is protected.
       
  1444 */
       
  1445 TBool CMMFFile::IsProtectedL() const
       
  1446 	{
       
  1447 	if (iFile==NULL)
       
  1448 		{
       
  1449 		User::Leave(KErrNotReady);
       
  1450 		}
       
  1451 
       
  1452 	return iFile->IsProtected();
       
  1453 	}
       
  1454 
       
  1455 TInt CMMFFile::SetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
       
  1456 	{
       
  1457 	if (iFile==NULL)
       
  1458 		{
       
  1459 		return KErrNotReady;
       
  1460 		}
       
  1461 
       
  1462 	return iFile->SetAgentProperty(aProperty, aValue);
       
  1463 	}
       
  1464 
       
  1465 /*
       
  1466  *	Returns ETrue if the request can safely be deleted.
       
  1467  */
       
  1468 TBool CReadWriteRequest::Completed() 
       
  1469 	{
       
  1470 	return iCompleted ;
       
  1471 	}
       
  1472 
       
  1473 /*
       
  1474  *	Returns the data member of CMMFDataBuffer or CMMFTransferBuffer (as TPtr8)
       
  1475  *  
       
  1476  */
       
  1477 TDes8& CReadWriteRequest::BufferDes()
       
  1478 	{
       
  1479 	if(iTransferBufferCopy)
       
  1480 		return iTransferBufferCopy->Des();
       
  1481 	else
       
  1482 		{
       
  1483 		//reset iBufferDes in case iBuffer has changed...
       
  1484 		iBufferDes = &(STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data());
       
  1485 		return *iBufferDes;
       
  1486 		}
       
  1487 	}
       
  1488 	
       
  1489 const TDesC8& CReadWriteRequest::BufferDesC()
       
  1490 	{
       
  1491 	if(iTransferBufferCopy)
       
  1492 		return iTransferBufferCopy->Des();
       
  1493 	else
       
  1494 		return BufferDes();
       
  1495 	}
       
  1496 
       
  1497 
       
  1498 /*
       
  1499  *	Destructor.
       
  1500  */
       
  1501 CReadWriteRequest::~CReadWriteRequest() 
       
  1502 	{
       
  1503 	Cancel();
       
  1504 	if(iTransferBufferCopy)
       
  1505 		iTransferBufferCopy->SetInUse(EFalse);
       
  1506 	}
       
  1507 
       
  1508 /*
       
  1509  *	Allows owning class access to SetActive()
       
  1510  */
       
  1511 void CReadWriteRequest::SetActive() 
       
  1512 	{
       
  1513 	CActive::SetActive() ;
       
  1514 	}
       
  1515 
       
  1516 /*
       
  1517  *  For the moment at least...    Canceled requests may be deleted
       
  1518  */
       
  1519 void CReadWriteRequest::DoCancel() 
       
  1520 	{
       
  1521 	iCompleted = ETrue ;
       
  1522 	}
       
  1523 
       
  1524 /*
       
  1525  *	Called when errors in RunL force Leave.  For the moment just mark the request deletable
       
  1526  */
       
  1527 TInt CReadWriteRequest::RunError( TInt aError ) 
       
  1528 	{
       
  1529 	//RunL can leave.
       
  1530 	iCompleted = ETrue ;
       
  1531 	iError = aError; //keep this error internally for now
       
  1532 	return KErrNone ;
       
  1533 	}
       
  1534 
       
  1535 /*
       
  1536  *	On completion of read request call back to the MDataSink
       
  1537  */
       
  1538 void CReadRequest::RunL() 
       
  1539 	{
       
  1540 	if (iStatus != KErrNone)
       
  1541 		{
       
  1542 		TMMFEvent event(KMMFErrorCategoryControllerGeneralError, iStatus.Int());
       
  1543 		iEventHandler->SendEventToClient(event);
       
  1544 		}
       
  1545 	else
       
  1546 		{
       
  1547 		//Copy the data from the normal buffer into the Transfer buffer
       
  1548 		if(iTransferBufferCopy)
       
  1549 			{
       
  1550 			//must specify the size here as the dest may be smaller than the source.
       
  1551 			TDes8& destDesc = STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data();
       
  1552 			destDesc.Copy(iTransferBufferCopy->Des().Left(destDesc.MaxLength()));
       
  1553 
       
  1554 			iTransferBufferCopy->SetInUse(EFalse);
       
  1555 			}
       
  1556 
       
  1557 		// removed checking EOF from here, it should be checked in CMMFFile
       
  1558 
       
  1559 		REINTERPRET_CAST(MDataSink*, iSinkOrSource)->BufferFilledL(iBuffer) ; // callback to MDataSource/Sink
       
  1560 		}
       
  1561 	
       
  1562 	iCompleted = ETrue ;
       
  1563 	}
       
  1564 
       
  1565 /* 
       
  1566  *  On completion of write request call back to the MDataSource
       
  1567  */
       
  1568 void CWriteRequest::RunL() 
       
  1569 	{
       
  1570 	if(iTransferBufferCopy)
       
  1571 		iTransferBufferCopy->SetInUse(EFalse);
       
  1572 
       
  1573 	if (iStatus != KErrNone)
       
  1574 		{
       
  1575 		TMMFEvent event(KMMFErrorCategoryControllerGeneralError, iStatus.Int());
       
  1576 		iEventHandler->SendEventToClient(event);
       
  1577 		}
       
  1578 	else
       
  1579 		REINTERPRET_CAST(MDataSource*, iSinkOrSource)->BufferEmptiedL(iBuffer) ; // callback to MDataSource/Sink
       
  1580 
       
  1581 	iCompleted = ETrue ;
       
  1582 	}
       
  1583 
       
  1584 CMMFFile::CMMFFileAsyncEventHandler::CMMFFileAsyncEventHandler(CMMFFile* aParent)
       
  1585 	{
       
  1586 	iParent = aParent;
       
  1587 	}
       
  1588 
       
  1589 CMMFFile::CMMFFileAsyncEventHandler::~CMMFFileAsyncEventHandler()
       
  1590 	{
       
  1591 	}
       
  1592 
       
  1593 TInt CMMFFile::CMMFFileAsyncEventHandler::SendEventToClient(const TMMFEvent& aEvent)
       
  1594 	{
       
  1595 	if(aEvent.iErrorCode == KErrNotReady)//i.e. MMC removed while recording
       
  1596 		{
       
  1597 		TRAPD(err, iParent->SinkStopL() );
       
  1598 		if (err != KErrNone)
       
  1599 			{
       
  1600 			return err;	
       
  1601 			}
       
  1602 		}
       
  1603 	return iParent->iEventHandler->SendEventToClient(aEvent);
       
  1604 	}
       
  1605 
       
  1606 /**
       
  1607 Returns access to internal CData property
       
  1608 
       
  1609 @param aData
       
  1610        On return, set to the internal CData property used to access file for reading.
       
  1611 
       
  1612 Returns:
       
  1613   * KErrNotReady if the file is not open/data object has not been created. 
       
  1614   * KErrNotSupported if not supported (e.g. on data sink)
       
  1615 
       
  1616 @return Standard error code
       
  1617 */
       
  1618 TInt CMMFFile::Data(ContentAccess::CData*& aData)
       
  1619 	{
       
  1620 	if (!iFile)
       
  1621 		{
       
  1622 		return KErrNotReady;
       
  1623 		}
       
  1624 	else
       
  1625 		{
       
  1626 		return iFile->Data(aData);
       
  1627 		}
       
  1628 	}
       
  1629