mmlibs/mmfw/src/Plugin/StdSourceAndSink/Mmffile.cpp
changeset 0 b8ed18f6c07b
equal deleted inserted replaced
-1:000000000000 0:b8ed18f6c07b
       
     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 		if(!request->Processing())
       
  1179 			{
       
  1180 			delete request;
       
  1181 			iRequests.Remove(ii);
       
  1182 			ii--;
       
  1183 			}
       
  1184 		}
       
  1185 	}
       
  1186 
       
  1187 
       
  1188 
       
  1189 /**
       
  1190 Returns the data type as a fourCC code of CMMFFile as a data source.
       
  1191 
       
  1192 @return The data type fourCC code.
       
  1193 */
       
  1194 TFourCC CMMFFile::SourceDataTypeCode(TMediaId /*aMediaId*/) 
       
  1195 	{
       
  1196 	return  iSourceFourCC ;
       
  1197 	}
       
  1198 
       
  1199 /**
       
  1200 Returns the data type as a fourCC code of CMMFFile as a data sink.
       
  1201 
       
  1202 @return The data type fourCC code
       
  1203 */
       
  1204 TFourCC CMMFFile::SinkDataTypeCode(TMediaId /*aMediaId*/) 
       
  1205 	{
       
  1206 	return  iSinkFourCC ;
       
  1207 	}
       
  1208 
       
  1209 
       
  1210 /**
       
  1211 CMMFFile as a source is always passive so this function is not supported.
       
  1212 
       
  1213 @param  aBuffer
       
  1214         The emptied buffer.
       
  1215 */
       
  1216 void CMMFFile::BufferEmptiedL(CMMFBuffer* /* aBuffer */)
       
  1217 	{
       
  1218 	Panic(EMMFFilePanicBufferEmptiedLNotSupported);
       
  1219 	}
       
  1220 
       
  1221 /**
       
  1222 Tests whether a source buffer can be created.
       
  1223 
       
  1224 @return	A boolean indicating if if CMMFFile can create its own buffer. EFalse if CMMFFile cannot 
       
  1225         create it's own buffer.
       
  1226 */
       
  1227 TBool CMMFFile::CanCreateSourceBuffer()
       
  1228 	{
       
  1229 	return EFalse ;
       
  1230 	}
       
  1231 
       
  1232 /**
       
  1233 Creates a source buffer.
       
  1234 
       
  1235 @param  aMediaId
       
  1236         The Media ID.
       
  1237 @param  aReference
       
  1238         A boolean indicating if MDataSource owns the buffer. ETrue if it does, EFalse if the caller
       
  1239         owns the buffer.
       
  1240 
       
  1241 @return	NULL as a CMMFFile cannot create it's own buffer
       
  1242 */
       
  1243 CMMFBuffer* CMMFFile::CreateSourceBufferL( TMediaId /*aMediaId*/ , TBool& /*aReference*/)
       
  1244 	{
       
  1245 	User::Leave(KErrNotSupported);
       
  1246 	return NULL ;
       
  1247 	}
       
  1248 
       
  1249 /**
       
  1250 CMMFFile as a sink is always passive so this function is not supported.
       
  1251 
       
  1252 @param  aBuffer
       
  1253         The buffer.
       
  1254 */
       
  1255 void CMMFFile::BufferFilledL(CMMFBuffer* /* aBuffer */)
       
  1256 	{
       
  1257 	Panic(EMMFFilePanicBufferFilledLNotSupported);
       
  1258 	}
       
  1259 
       
  1260 /**
       
  1261 Tests whether a sink buffer can be created.
       
  1262 
       
  1263 @return	A boolean indicating if the sink buffer can be created. EFalse if CMMFFile cannot create 
       
  1264         it's own buffer
       
  1265 */
       
  1266 TBool CMMFFile::CanCreateSinkBuffer() 
       
  1267 	{
       
  1268 	return EFalse ;
       
  1269 	}
       
  1270 
       
  1271 /**
       
  1272 Creates a sink buffer.
       
  1273 
       
  1274 @param  aMediaId
       
  1275         The Media ID.
       
  1276 @param  aReference 
       
  1277         A boolean indicating if MDataSource owns the buffer. ETrue if MDataSource owns the buffer,
       
  1278         EFalse if the caller owns the buffer.
       
  1279 
       
  1280 @return	NULL as a CMMFFile cannot create it's own buffer
       
  1281 */
       
  1282 CMMFBuffer* CMMFFile::CreateSinkBufferL(TMediaId /*aMediaId*/ , TBool& /*aReference*/) 
       
  1283 	{
       
  1284 	User::Leave(KErrNotSupported);
       
  1285 	return NULL ;
       
  1286 	}
       
  1287 
       
  1288 /**
       
  1289 Primes the source.
       
  1290 
       
  1291 When used as a source, the file prime opens the file as read only.
       
  1292 */
       
  1293 void CMMFFile::SourcePrimeL()
       
  1294 	{
       
  1295 	// don't reopen file if already open
       
  1296 	if (!iFile)
       
  1297 		{
       
  1298 		if (iFileHandle)
       
  1299 			{
       
  1300 			iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI);
       
  1301 			}
       
  1302 		else
       
  1303 			{
       
  1304 			// Open for read-only access
       
  1305 			iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareReadersOnly, iCAFParameters->iEnableUI);
       
  1306 			}
       
  1307 		}
       
  1308 	}
       
  1309 
       
  1310 /**
       
  1311 Primes the sink.
       
  1312 
       
  1313 When used as a sink, the file prime opens the file for read/write access.
       
  1314 */
       
  1315 void CMMFFile::SinkPrimeL() 
       
  1316 	{
       
  1317 	// don't reopen file if already open
       
  1318 	if (!iFile)
       
  1319 		{
       
  1320 		if (iFileHandle)
       
  1321 			iFile = CF32File::NewL(iHandle);
       
  1322 		else
       
  1323 			iFile = CF32File::NewL(iFsSession, iFullFileName, EFileRead | EFileWrite);
       
  1324 		}
       
  1325 		iSinkNotStopped = ETrue;
       
  1326 	}
       
  1327 
       
  1328 /**
       
  1329 Stops the file source. When stopping close the file. If the source is a file handle, the position is reset, but the 
       
  1330 file handle remains open.
       
  1331 */
       
  1332 void CMMFFile::SourceStopL()
       
  1333 	{
       
  1334 	TInt pos = 0;
       
  1335 
       
  1336 	CancelRequests();
       
  1337 	
       
  1338 	// It is possible the file could have disappeared at this point (MMC/SD Card)
       
  1339 	//
       
  1340 	if (!iFile)
       
  1341 		{
       
  1342 		iPosition=pos;
       
  1343 		return;
       
  1344 		}
       
  1345 
       
  1346 	if (!iFileHandle && !iFile->IsProtected())
       
  1347 		{
       
  1348 		delete iFile;
       
  1349 		iFile = NULL;
       
  1350 		iFileSize = -1;
       
  1351 		}
       
  1352 	else
       
  1353 		{
       
  1354 		User::LeaveIfError(iFile->Seek(ESeekStart, pos));
       
  1355 		}
       
  1356 	iPosition=pos;
       
  1357 	}
       
  1358 
       
  1359 /**
       
  1360 Stops the file sink. 
       
  1361 
       
  1362 When stopping close the file. When the file sink is a file handle, the position is reset, but the file handle
       
  1363 remains open
       
  1364 */
       
  1365 void CMMFFile::SinkStopL()
       
  1366 	{
       
  1367 	iFileSize = -1;
       
  1368 	iPosition=0;
       
  1369 
       
  1370 	CancelRequests();
       
  1371 	iSinkNotStopped = EFalse;
       
  1372 	if (!iFileHandle)
       
  1373 		{		
       
  1374 		delete iFile;
       
  1375 		iFile = NULL;
       
  1376 		}
       
  1377 	else
       
  1378 		{
       
  1379 		TInt pos = 0;
       
  1380 		User::LeaveIfError(iFile->Seek(ESeekStart, pos));
       
  1381 		}
       
  1382 	}
       
  1383 
       
  1384 /**
       
  1385 Pauses the file source
       
  1386 */
       
  1387 void CMMFFile::SourcePauseL()
       
  1388 	{
       
  1389 	CancelRequests();
       
  1390 	}
       
  1391 
       
  1392 /**
       
  1393 Returns a boolean indicating if the sink has been stopped.
       
  1394 
       
  1395 @return A boolean indicating if the sink has stopped.
       
  1396  */
       
  1397 TBool CMMFFile::SinkStopped()
       
  1398 	{
       
  1399 	if(iSinkNotStopped == EFalse)
       
  1400 		return ETrue;
       
  1401 	else
       
  1402 		return EFalse;
       
  1403 	}
       
  1404 
       
  1405 /**
       
  1406 Evaluates a given intent against the rights associated with the file.
       
  1407 
       
  1408 The rights are not updated by this function call.
       
  1409 
       
  1410 @param  aIntent
       
  1411         The intent to evaluate.
       
  1412 
       
  1413 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
  1414         another of the system-wide error codes.
       
  1415 */
       
  1416 TInt CMMFFile::EvaluateIntent(ContentAccess::TIntent aIntent) const
       
  1417 	{
       
  1418 	if (iFile==NULL)
       
  1419 		{
       
  1420 		return KErrNotReady;
       
  1421 		}
       
  1422 
       
  1423 	return iFile->EvaluateIntent(aIntent);
       
  1424 	}
       
  1425 
       
  1426 /**
       
  1427 Evaluates and executes a given intent against the rights associated with the file.
       
  1428 
       
  1429 The rights object is updated after calling this function.
       
  1430 
       
  1431 @param  aIntent
       
  1432         The intent to evaluate.
       
  1433 
       
  1434 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
  1435         another of the system-wide error codes.
       
  1436 */
       
  1437 TInt CMMFFile::ExecuteIntent(ContentAccess::TIntent aIntent)
       
  1438 	{
       
  1439 	if (iFile==NULL)
       
  1440 		{
       
  1441 		return KErrNotReady;
       
  1442 		}
       
  1443 
       
  1444 	return iFile->ExecuteIntent(aIntent);
       
  1445 	}
       
  1446 
       
  1447 /**
       
  1448 Returns whether the file is protected.
       
  1449 
       
  1450 @return A boolean indicating if the file is protected. ETrue if the file is protected.
       
  1451 */
       
  1452 TBool CMMFFile::IsProtectedL() const
       
  1453 	{
       
  1454 	if (iFile==NULL)
       
  1455 		{
       
  1456 		User::Leave(KErrNotReady);
       
  1457 		}
       
  1458 
       
  1459 	return iFile->IsProtected();
       
  1460 	}
       
  1461 
       
  1462 TInt CMMFFile::SetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
       
  1463 	{
       
  1464 	if (iFile==NULL)
       
  1465 		{
       
  1466 		return KErrNotReady;
       
  1467 		}
       
  1468 
       
  1469 	return iFile->SetAgentProperty(aProperty, aValue);
       
  1470 	}
       
  1471 
       
  1472 /*
       
  1473  *	Returns the data member of CMMFDataBuffer or CMMFTransferBuffer (as TPtr8)
       
  1474  *  
       
  1475  */
       
  1476 TDes8& CReadWriteRequest::BufferDes()
       
  1477 	{
       
  1478 	if(iTransferBufferCopy)
       
  1479 		return iTransferBufferCopy->Des();
       
  1480 	else
       
  1481 		{
       
  1482 		//reset iBufferDes in case iBuffer has changed...
       
  1483 		iBufferDes = &(STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data());
       
  1484 		return *iBufferDes;
       
  1485 		}
       
  1486 	}
       
  1487 	
       
  1488 const TDesC8& CReadWriteRequest::BufferDesC()
       
  1489 	{
       
  1490 	if(iTransferBufferCopy)
       
  1491 		return iTransferBufferCopy->Des();
       
  1492 	else
       
  1493 		return BufferDes();
       
  1494 	}
       
  1495 
       
  1496 
       
  1497 /*
       
  1498  *	Destructor.
       
  1499  */
       
  1500 CReadWriteRequest::~CReadWriteRequest() 
       
  1501 	{
       
  1502 	Cancel();
       
  1503 	if(iTransferBufferCopy)
       
  1504 		iTransferBufferCopy->SetInUse(EFalse);
       
  1505 	}
       
  1506 
       
  1507 /*
       
  1508  *	Allows owning class access to SetActive()
       
  1509  */
       
  1510 void CReadWriteRequest::SetActive() 
       
  1511 	{
       
  1512 	CActive::SetActive() ;
       
  1513 	}
       
  1514 
       
  1515 /*
       
  1516  *  For the moment at least...    Canceled requests may be deleted
       
  1517  */
       
  1518 void CReadWriteRequest::DoCancel() 
       
  1519 	{
       
  1520 	iState = ECompleted;
       
  1521 	}
       
  1522 
       
  1523 /*
       
  1524  *	Called when errors in RunL force Leave.  For the moment just mark the request deletable
       
  1525  */
       
  1526 TInt CReadWriteRequest::RunError( TInt aError ) 
       
  1527 	{
       
  1528 	//RunL can leave.
       
  1529 	iState = ECompleted;
       
  1530 	iError = aError; //keep this error internally for now
       
  1531 	return KErrNone ;
       
  1532 	}
       
  1533 
       
  1534 /*
       
  1535  *	On completion of read request call back to the MDataSink
       
  1536  */
       
  1537 void CReadRequest::RunL() 
       
  1538 	{
       
  1539 	// This prevents the request from deletion during the execution of RunL
       
  1540 	iState = EProcessing;
       
  1541 	if (iStatus != KErrNone)
       
  1542 		{
       
  1543 		TMMFEvent event(KMMFErrorCategoryControllerGeneralError, iStatus.Int());
       
  1544 		iEventHandler->SendEventToClient(event);
       
  1545 		}
       
  1546 	else
       
  1547 		{
       
  1548 		//Copy the data from the normal buffer into the Transfer buffer
       
  1549 		if(iTransferBufferCopy)
       
  1550 			{
       
  1551 			//must specify the size here as the dest may be smaller than the source.
       
  1552 			TDes8& destDesc = STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data();
       
  1553 			destDesc.Copy(iTransferBufferCopy->Des().Left(destDesc.MaxLength()));
       
  1554 
       
  1555 			iTransferBufferCopy->SetInUse(EFalse);
       
  1556 			}
       
  1557 
       
  1558 		// removed checking EOF from here, it should be checked in CMMFFile
       
  1559 
       
  1560 		REINTERPRET_CAST(MDataSink*, iSinkOrSource)->BufferFilledL(iBuffer) ; // callback to MDataSource/Sink
       
  1561 		}
       
  1562 	
       
  1563 	iState = ECompleted;
       
  1564 	
       
  1565 	}
       
  1566 
       
  1567 /* 
       
  1568  *  On completion of write request call back to the MDataSource
       
  1569  */
       
  1570 void CWriteRequest::RunL() 
       
  1571 	{
       
  1572 	iState = EProcessing;
       
  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 	iState = ECompleted;
       
  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