os/mm/mmlibs/mmfw/src/Plugin/StdSourceAndSink/Mmffile.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 //		XXX 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 	    {
  1036 	    __ASSERT_DEBUG(iFile != NULL,Panic(EMMFFileHandleNULL));
  1037 		err = iFile->Size(size);
  1038 	    }
  1039 	if (err)
  1040 		{
  1041 		size = 0;
  1042 		iFileSize = -1; //reset cached size
  1043 		}
  1044 	else 
  1045 		iFileSize = size; //cache the filesize
  1046 
  1047 	if (fileOpened)
  1048 		{
  1049 		__ASSERT_DEBUG(iFile != NULL,Panic(EMMFFileHandleNULL));
  1050 		delete iFile;
  1051 		iFile = NULL;
  1052 		iFileSize = -1;
  1053 		}
  1054 
  1055 	return size;
  1056 	}
  1057 
  1058 /**
  1059 Source thread logon.
  1060 
  1061 Shares fsSession between threads
  1062 
  1063 @param  aEventHandler
  1064         This is an MAsyncEventHandler to handle asynchronous events that occur during the
  1065         transfer of multimedia data.
  1066 
  1067 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
  1068         another of the system-wide error codes.
  1069 */
  1070 TInt CMMFFile::SourceThreadLogon(MAsyncEventHandler& aEventHandler)
  1071 	{
  1072 	iEventHandler = &aEventHandler;
  1073 	if(!iMmfFileEventHandler)
  1074 		{
  1075 		iMmfFileEventHandler = new CMMFFileAsyncEventHandler(this);
  1076 		if(!iMmfFileEventHandler)
  1077 			return KErrNoMemory;
  1078 		}
  1079 #ifdef __IPC_V2_PRESENT__
  1080 	return KErrNone; // nothing to do
  1081 #else
  1082 	return iFsSession.Attach();
  1083 #endif // __HIDE_IPC_V1__
  1084 	}
  1085 
  1086 /** 
  1087 Logs off source thread.
  1088 */
  1089 void CMMFFile::SourceThreadLogoff()
  1090 	{
  1091 	delete iMmfFileEventHandler;
  1092 	iMmfFileEventHandler = NULL;
  1093 	iEventHandler = NULL;
  1094 	}
  1095 
  1096 
  1097 /**
  1098 Sink thread logon.
  1099 
  1100 Shares fsSession between threads.
  1101 
  1102 @param  aEventHandler
  1103         This is an MAsyncEventHandler to handle asynchronous events that occur during the
  1104         transfer of multimedia data.
  1105 
  1106 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
  1107         another of the system-wide error codes.
  1108 */
  1109 TInt CMMFFile::SinkThreadLogon(MAsyncEventHandler& aEventHandler)
  1110 	{
  1111 	iEventHandler = &aEventHandler;
  1112 	if(!iMmfFileEventHandler)
  1113 		{
  1114 		iMmfFileEventHandler = new CMMFFileAsyncEventHandler(this);
  1115 		if(!iMmfFileEventHandler)
  1116 			return KErrNoMemory;
  1117 		}
  1118 #ifdef __IPC_V2_PRESENT__
  1119 	return KErrNone;
  1120 #else
  1121 	return iFsSession.Attach();
  1122 #endif // __HIDE_IPC_V1__
  1123 	}
  1124 
  1125 /** 
  1126 Sink thread log off.
  1127 */
  1128 void CMMFFile::SinkThreadLogoff() 
  1129 	{
  1130 	delete iMmfFileEventHandler;
  1131 	iMmfFileEventHandler = NULL;
  1132 	iEventHandler = NULL;
  1133 	}
  1134 
  1135 /**
  1136 Stores a request in an array.
  1137 
  1138 CReadWriteRequests are stored in the array iRequests.
  1139 This function takes ownership and places the request in the array.
  1140 It also checks the array for completed requests and removes them.
  1141 
  1142 @param  aRequest
  1143         The request to store.
  1144 */
  1145 void CMMFFile::StoreRequestL( CReadWriteRequest* aRequest )
  1146 	{
  1147 	// add aRequest to iRequests
  1148 	User::LeaveIfError( iRequests.Append( aRequest ) ) ;
  1149 
  1150 	// Clear out any completed requests
  1151 	for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ )
  1152 		{
  1153 		if (iRequests[ii]->Completed())
  1154 			{
  1155 			CReadWriteRequest* request = iRequests[ii];
  1156 			delete request;
  1157 
  1158 			iRequests.Remove(ii);
  1159 			ii--;
  1160 			}
  1161 		}
  1162 	}
  1163 
  1164 
  1165 /**
  1166 Cancels outstanding requests.
  1167 
  1168 CReadWriteRequests are stored in the array iRequests.
  1169 This function cancels any outstanding requests and removes them
  1170 from iRequests.
  1171 */
  1172 void CMMFFile::CancelRequests()
  1173 	{
  1174 	// Clear out any completed requests
  1175 	for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ )
  1176 		{
  1177 		CReadWriteRequest* request = iRequests[ii];
  1178 		delete request;
  1179 		iRequests.Remove(ii);
  1180 		ii--;
  1181 		}
  1182 	}
  1183 
  1184 
  1185 
  1186 /**
  1187 Returns the data type as a fourCC code of CMMFFile as a data source.
  1188 
  1189 @return The data type fourCC code.
  1190 */
  1191 TFourCC CMMFFile::SourceDataTypeCode(TMediaId /*aMediaId*/) 
  1192 	{
  1193 	return  iSourceFourCC ;
  1194 	}
  1195 
  1196 /**
  1197 Returns the data type as a fourCC code of CMMFFile as a data sink.
  1198 
  1199 @return The data type fourCC code
  1200 */
  1201 TFourCC CMMFFile::SinkDataTypeCode(TMediaId /*aMediaId*/) 
  1202 	{
  1203 	return  iSinkFourCC ;
  1204 	}
  1205 
  1206 
  1207 /**
  1208 CMMFFile as a source is always passive so this function is not supported.
  1209 
  1210 @param  aBuffer
  1211         The emptied buffer.
  1212 */
  1213 void CMMFFile::BufferEmptiedL(CMMFBuffer* /* aBuffer */)
  1214 	{
  1215 	Panic(EMMFFilePanicBufferEmptiedLNotSupported);
  1216 	}
  1217 
  1218 /**
  1219 Tests whether a source buffer can be created.
  1220 
  1221 @return	A boolean indicating if if CMMFFile can create its own buffer. EFalse if CMMFFile cannot 
  1222         create it's own buffer.
  1223 */
  1224 TBool CMMFFile::CanCreateSourceBuffer()
  1225 	{
  1226 	return EFalse ;
  1227 	}
  1228 
  1229 /**
  1230 Creates a source buffer.
  1231 
  1232 @param  aMediaId
  1233         The Media ID.
  1234 @param  aReference
  1235         A boolean indicating if MDataSource owns the buffer. ETrue if it does, EFalse if the caller
  1236         owns the buffer.
  1237 
  1238 @return	NULL as a CMMFFile cannot create it's own buffer
  1239 */
  1240 CMMFBuffer* CMMFFile::CreateSourceBufferL( TMediaId /*aMediaId*/ , TBool& /*aReference*/)
  1241 	{
  1242 	User::Leave(KErrNotSupported);
  1243 	return NULL ;
  1244 	}
  1245 
  1246 /**
  1247 CMMFFile as a sink is always passive so this function is not supported.
  1248 
  1249 @param  aBuffer
  1250         The buffer.
  1251 */
  1252 void CMMFFile::BufferFilledL(CMMFBuffer* /* aBuffer */)
  1253 	{
  1254 	Panic(EMMFFilePanicBufferFilledLNotSupported);
  1255 	}
  1256 
  1257 /**
  1258 Tests whether a sink buffer can be created.
  1259 
  1260 @return	A boolean indicating if the sink buffer can be created. EFalse if CMMFFile cannot create 
  1261         it's own buffer
  1262 */
  1263 TBool CMMFFile::CanCreateSinkBuffer() 
  1264 	{
  1265 	return EFalse ;
  1266 	}
  1267 
  1268 /**
  1269 Creates a sink buffer.
  1270 
  1271 @param  aMediaId
  1272         The Media ID.
  1273 @param  aReference 
  1274         A boolean indicating if MDataSource owns the buffer. ETrue if MDataSource owns the buffer,
  1275         EFalse if the caller owns the buffer.
  1276 
  1277 @return	NULL as a CMMFFile cannot create it's own buffer
  1278 */
  1279 CMMFBuffer* CMMFFile::CreateSinkBufferL(TMediaId /*aMediaId*/ , TBool& /*aReference*/) 
  1280 	{
  1281 	User::Leave(KErrNotSupported);
  1282 	return NULL ;
  1283 	}
  1284 
  1285 /**
  1286 Primes the source.
  1287 
  1288 When used as a source, the file prime opens the file as read only.
  1289 */
  1290 void CMMFFile::SourcePrimeL()
  1291 	{
  1292 	// don't reopen file if already open
  1293 	if (!iFile)
  1294 		{
  1295 		if (iFileHandle)
  1296 			{
  1297 			iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI);
  1298 			}
  1299 		else
  1300 			{
  1301 			// Open for read-only access
  1302 			iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareReadersOnly, iCAFParameters->iEnableUI);
  1303 			}
  1304 		}
  1305 	}
  1306 
  1307 /**
  1308 Primes the sink.
  1309 
  1310 When used as a sink, the file prime opens the file for read/write access.
  1311 */
  1312 void CMMFFile::SinkPrimeL() 
  1313 	{
  1314 	// don't reopen file if already open
  1315 	if (!iFile)
  1316 		{
  1317 		if (iFileHandle)
  1318 			iFile = CF32File::NewL(iHandle);
  1319 		else
  1320 			iFile = CF32File::NewL(iFsSession, iFullFileName, EFileRead | EFileWrite);
  1321 		}
  1322 		iSinkNotStopped = ETrue;
  1323 	}
  1324 
  1325 /**
  1326 Stops the file source. When stopping close the file. If the source is a file handle, the position is reset, but the 
  1327 file handle remains open.
  1328 */
  1329 void CMMFFile::SourceStopL()
  1330 	{
  1331 	TInt pos = 0;
  1332 
  1333 	CancelRequests();
  1334 	
  1335 	// It is possible the file could have disappeared at this point (MMC/SD Card)
  1336 	//
  1337 	if (!iFile)
  1338 		{
  1339 		iPosition=pos;
  1340 		return;
  1341 		}
  1342 
  1343 	if (!iFileHandle && !iFile->IsProtected())
  1344 		{
  1345 		delete iFile;
  1346 		iFile = NULL;
  1347 		iFileSize = -1;
  1348 		}
  1349 	else
  1350 		{
  1351 		User::LeaveIfError(iFile->Seek(ESeekStart, pos));
  1352 		}
  1353 	iPosition=pos;
  1354 	}
  1355 
  1356 /**
  1357 Stops the file sink. 
  1358 
  1359 When stopping close the file. When the file sink is a file handle, the position is reset, but the file handle
  1360 remains open
  1361 */
  1362 void CMMFFile::SinkStopL()
  1363 	{
  1364 	iFileSize = -1;
  1365 	iPosition=0;
  1366 
  1367 	CancelRequests();
  1368 	iSinkNotStopped = EFalse;
  1369 	if (!iFileHandle)
  1370 		{		
  1371 		delete iFile;
  1372 		iFile = NULL;
  1373 		}
  1374 	else
  1375 		{
  1376 		TInt pos = 0;
  1377 		User::LeaveIfError(iFile->Seek(ESeekStart, pos));
  1378 		}
  1379 	}
  1380 
  1381 /**
  1382 Pauses the file source
  1383 */
  1384 void CMMFFile::SourcePauseL()
  1385 	{
  1386 	CancelRequests();
  1387 	}
  1388 
  1389 /**
  1390 Returns a boolean indicating if the sink has been stopped.
  1391 
  1392 @return A boolean indicating if the sink has stopped.
  1393  */
  1394 TBool CMMFFile::SinkStopped()
  1395 	{
  1396 	if(iSinkNotStopped == EFalse)
  1397 		return ETrue;
  1398 	else
  1399 		return EFalse;
  1400 	}
  1401 
  1402 /**
  1403 Evaluates a given intent against the rights associated with the file.
  1404 
  1405 The rights are not updated by this function call.
  1406 
  1407 @param  aIntent
  1408         The intent to evaluate.
  1409 
  1410 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
  1411         another of the system-wide error codes.
  1412 */
  1413 TInt CMMFFile::EvaluateIntent(ContentAccess::TIntent aIntent) const
  1414 	{
  1415 	if (iFile==NULL)
  1416 		{
  1417 		return KErrNotReady;
  1418 		}
  1419 
  1420 	return iFile->EvaluateIntent(aIntent);
  1421 	}
  1422 
  1423 /**
  1424 Evaluates and executes a given intent against the rights associated with the file.
  1425 
  1426 The rights object is updated after calling this function.
  1427 
  1428 @param  aIntent
  1429         The intent to evaluate.
  1430 
  1431 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
  1432         another of the system-wide error codes.
  1433 */
  1434 TInt CMMFFile::ExecuteIntent(ContentAccess::TIntent aIntent)
  1435 	{
  1436 	if (iFile==NULL)
  1437 		{
  1438 		return KErrNotReady;
  1439 		}
  1440 
  1441 	return iFile->ExecuteIntent(aIntent);
  1442 	}
  1443 
  1444 /**
  1445 Returns whether the file is protected.
  1446 
  1447 @return A boolean indicating if the file is protected. ETrue if the file is protected.
  1448 */
  1449 TBool CMMFFile::IsProtectedL() const
  1450 	{
  1451 	if (iFile==NULL)
  1452 		{
  1453 		User::Leave(KErrNotReady);
  1454 		}
  1455 
  1456 	return iFile->IsProtected();
  1457 	}
  1458 
  1459 TInt CMMFFile::SetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
  1460 	{
  1461 	if (iFile==NULL)
  1462 		{
  1463 		return KErrNotReady;
  1464 		}
  1465 
  1466 	return iFile->SetAgentProperty(aProperty, aValue);
  1467 	}
  1468 
  1469 /*
  1470  *	Returns ETrue if the request can safely be deleted.
  1471  */
  1472 TBool CReadWriteRequest::Completed() 
  1473 	{
  1474 	return iCompleted ;
  1475 	}
  1476 
  1477 /*
  1478  *	Returns the data member of CMMFDataBuffer or CMMFTransferBuffer (as TPtr8)
  1479  *  
  1480  */
  1481 TDes8& CReadWriteRequest::BufferDes()
  1482 	{
  1483 	if(iTransferBufferCopy)
  1484 		return iTransferBufferCopy->Des();
  1485 	else
  1486 		{
  1487 		//reset iBufferDes in case iBuffer has changed...
  1488 		iBufferDes = &(STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data());
  1489 		return *iBufferDes;
  1490 		}
  1491 	}
  1492 	
  1493 const TDesC8& CReadWriteRequest::BufferDesC()
  1494 	{
  1495 	if(iTransferBufferCopy)
  1496 		return iTransferBufferCopy->Des();
  1497 	else
  1498 		return BufferDes();
  1499 	}
  1500 
  1501 
  1502 /*
  1503  *	Destructor.
  1504  */
  1505 CReadWriteRequest::~CReadWriteRequest() 
  1506 	{
  1507 	Cancel();
  1508 	if(iTransferBufferCopy)
  1509 		iTransferBufferCopy->SetInUse(EFalse);
  1510 	}
  1511 
  1512 /*
  1513  *	Allows owning class access to SetActive()
  1514  */
  1515 void CReadWriteRequest::SetActive() 
  1516 	{
  1517 	CActive::SetActive() ;
  1518 	}
  1519 
  1520 /*
  1521  *  For the moment at least...    Canceled requests may be deleted
  1522  */
  1523 void CReadWriteRequest::DoCancel() 
  1524 	{
  1525 	iCompleted = ETrue ;
  1526 	}
  1527 
  1528 /*
  1529  *	Called when errors in RunL force Leave.  For the moment just mark the request deletable
  1530  */
  1531 TInt CReadWriteRequest::RunError( TInt aError ) 
  1532 	{
  1533 	//RunL can leave.
  1534 	iCompleted = ETrue ;
  1535 	iError = aError; //keep this error internally for now
  1536 	return KErrNone ;
  1537 	}
  1538 
  1539 /*
  1540  *	On completion of read request call back to the MDataSink
  1541  */
  1542 void CReadRequest::RunL() 
  1543 	{
  1544 	if (iStatus != KErrNone)
  1545 		{
  1546 		TMMFEvent event(KMMFErrorCategoryControllerGeneralError, iStatus.Int());
  1547 		iEventHandler->SendEventToClient(event);
  1548 		}
  1549 	else
  1550 		{
  1551 		//Copy the data from the normal buffer into the Transfer buffer
  1552 		if(iTransferBufferCopy)
  1553 			{
  1554 			//must specify the size here as the dest may be smaller than the source.
  1555 			TDes8& destDesc = STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data();
  1556 			destDesc.Copy(iTransferBufferCopy->Des().Left(destDesc.MaxLength()));
  1557 
  1558 			iTransferBufferCopy->SetInUse(EFalse);
  1559 			}
  1560 
  1561 		// removed checking EOF from here, it should be checked in CMMFFile
  1562 
  1563 		REINTERPRET_CAST(MDataSink*, iSinkOrSource)->BufferFilledL(iBuffer) ; // callback to MDataSource/Sink
  1564 		}
  1565 	
  1566 	iCompleted = ETrue ;
  1567 	}
  1568 
  1569 /* 
  1570  *  On completion of write request call back to the MDataSource
  1571  */
  1572 void CWriteRequest::RunL() 
  1573 	{
  1574 	if(iTransferBufferCopy)
  1575 		iTransferBufferCopy->SetInUse(EFalse);
  1576 
  1577 	if (iStatus != KErrNone)
  1578 		{
  1579 		TMMFEvent event(KMMFErrorCategoryControllerGeneralError, iStatus.Int());
  1580 		iEventHandler->SendEventToClient(event);
  1581 		}
  1582 	else
  1583 		REINTERPRET_CAST(MDataSource*, iSinkOrSource)->BufferEmptiedL(iBuffer) ; // callback to MDataSource/Sink
  1584 
  1585 	iCompleted = ETrue ;
  1586 	}
  1587 
  1588 CMMFFile::CMMFFileAsyncEventHandler::CMMFFileAsyncEventHandler(CMMFFile* aParent)
  1589 	{
  1590 	iParent = aParent;
  1591 	}
  1592 
  1593 CMMFFile::CMMFFileAsyncEventHandler::~CMMFFileAsyncEventHandler()
  1594 	{
  1595 	}
  1596 
  1597 TInt CMMFFile::CMMFFileAsyncEventHandler::SendEventToClient(const TMMFEvent& aEvent)
  1598 	{
  1599 	if(aEvent.iErrorCode == KErrNotReady)//i.e. MMC removed while recording
  1600 		{
  1601 		TRAPD(err, iParent->SinkStopL() );
  1602 		if (err != KErrNone)
  1603 			{
  1604 			return err;	
  1605 			}
  1606 		}
  1607 	return iParent->iEventHandler->SendEventToClient(aEvent);
  1608 	}
  1609 
  1610 /**
  1611 Returns access to internal CData property
  1612 
  1613 @param aData
  1614        On return, set to the internal CData property used to access file for reading.
  1615 
  1616 Returns:
  1617   * KErrNotReady if the file is not open/data object has not been created. 
  1618   * KErrNotSupported if not supported (e.g. on data sink)
  1619 
  1620 @return Standard error code
  1621 */
  1622 TInt CMMFFile::Data(ContentAccess::CData*& aData)
  1623 	{
  1624 	if (!iFile)
  1625 		{
  1626 		return KErrNotReady;
  1627 		}
  1628 	else
  1629 		{
  1630 		return iFile->Data(aData);
  1631 		}
  1632 	}
  1633