1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmlibs/mmfw/src/Plugin/StdSourceAndSink/Mmffile.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1633 @@
1.4 +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <f32file.h>
1.20 +#include <e32std.h>
1.21 +#include <mmf/server/mmfdatabuffer.h>
1.22 +#include <mmf/common/mmfutilities.h>
1.23 +#include <mmf/common/mmfcontroller.h>
1.24 +#include <mmf/common/mmfpaniccodes.h>
1.25 +#include <mmf/server/mmffile.h>
1.26 +#include "MmffilePriv.h"
1.27 +#include "FileAccess.h"
1.28 +
1.29 +void Panic(TMMFFilePanicCode aPanicCode)
1.30 + {
1.31 + _LIT(KMMFFilePanicCategory, "MMFFile");
1.32 + User::Panic(KMMFFilePanicCategory, aPanicCode);
1.33 + }
1.34 +
1.35 +/**
1.36 + * Constructs a CTransferBufferCopy
1.37 + *
1.38 + * @return CTransferBufferCopy*
1.39 + */
1.40 +CTransferBufferCopy* CTransferBufferCopy::NewL(TInt aMaxLength)
1.41 + {
1.42 + CTransferBufferCopy* self = new (ELeave) CTransferBufferCopy(aMaxLength);
1.43 + CleanupStack::PushL(self);
1.44 + self->ConstructL();
1.45 + CleanupStack::Pop(self);
1.46 + return self;
1.47 + }
1.48 +
1.49 +/**
1.50 + * Second phase constructor for CTransferBufferCopy
1.51 + *
1.52 + * @return void
1.53 + */
1.54 +void CTransferBufferCopy::ConstructL()
1.55 + {
1.56 + iBuffer = static_cast<TUint8*>(User::AllocL(iMaxLength));
1.57 + iBufferDes.Set(iBuffer,0,iMaxLength);
1.58 + }
1.59 +
1.60 +/**
1.61 +Destructor.
1.62 +*/
1.63 +CMMFFile::~CMMFFile()
1.64 + {
1.65 + delete iFile;
1.66 +
1.67 +
1.68 + iHandle.Close();
1.69 + iFsSession.Close();
1.70 + delete iFileName;
1.71 + delete iFileExt;
1.72 + delete iFilePath;
1.73 + delete iFileDrive;
1.74 + delete iMmfFileEventHandler;
1.75 + delete iCAFParameters;
1.76 +
1.77 + // Get rid of everything in RArray's & close them.
1.78 + iRequests.ResetAndDestroy();
1.79 + iTransferBufferCopies.ResetAndDestroy();
1.80 + }
1.81 +
1.82 +/**
1.83 +Protected constructor.
1.84 +
1.85 +The default implementation is empty.
1.86 +*/
1.87 +CMMFFile::CMMFFile() : CMMFClip( KUidMmfFileSource, KUidMmfFileSink ), iFileSize(-1)
1.88 + {
1.89 + iSinkNotStopped = EFalse;
1.90 + }
1.91 +
1.92 +/**
1.93 +Constructs an CMMFFile MDataSource.
1.94 +
1.95 +@return A pointer to the new CMMFFile data source.
1.96 +*/
1.97 +MDataSource* CMMFFile::NewSourceL()
1.98 + {
1.99 + CMMFFile* self = new (ELeave) CMMFFile ;
1.100 + return STATIC_CAST( MDataSource*, self ) ;
1.101 + }
1.102 +
1.103 +/**
1.104 +Constructs a CMMFFile MDataSink
1.105 +
1.106 +@return A pointer to the new CMMFFile data sink.
1.107 +*/
1.108 +MDataSink* CMMFFile::NewSinkL()
1.109 + {
1.110 + CMMFFile* self = new (ELeave) CMMFFile ;
1.111 + return STATIC_CAST( MDataSink*, self ) ;
1.112 + }
1.113 +
1.114 +/**
1.115 +Perform source construction dependant on the source construction
1.116 +initialisation data aInitData.
1.117 +
1.118 +@param aInitData
1.119 + The TPckg<TMMFFileParams> descriptor package containing the file name and full path.
1.120 +*/
1.121 +void CMMFFile::ConstructSourceL(const TDesC8& aInitData )
1.122 + {
1.123 + ConstructL(aInitData, ESourceMode);
1.124 + }
1.125 +
1.126 +/**
1.127 +Performs sink construction dependant on the sink construction
1.128 +initialisation data aInitData.
1.129 +
1.130 +@param aInitData
1.131 + The TPckg<TMMFFileParams> descriptor package containing the file name and full path.
1.132 +*/
1.133 +void CMMFFile::ConstructSinkL(const TDesC8& aInitData)
1.134 + {
1.135 + ConstructL(aInitData, ESinkMode);
1.136 + }
1.137 +
1.138 +/**
1.139 +Protected constructor.
1.140 +
1.141 +Extracts the initialisation data provided by the calling functions: ConstructSourceL() and
1.142 +ConstructSinkL(). Creates a file server session and sets up file name. If there is a file name and
1.143 +it cannot be found this function leaves. If there is no file name the function leaves. Does not
1.144 +attempt to open the file or check whether the file exists.
1.145 +
1.146 +If aInitData contains a TMMFFileHandleParams instead of TMMFFileParams, the source/sink is constructed from
1.147 +the file handle provided by the caller
1.148 +
1.149 +@param aInitData
1.150 + Initialisation data packaged in a TMMFFileParams or in a TMMFFileHandleParams (File Handle)
1.151 +*/
1.152 +void CMMFFile::ConstructL(const TDesC8& aInitData,TMMFileMode aFileMode)
1.153 + {
1.154 + User::LeaveIfError(iFsSession.Connect());
1.155 +#ifdef __IPC_V2_PRESENT__
1.156 + // on IPCv2 we auto attach
1.157 + User::LeaveIfError(iFsSession.ShareAuto());
1.158 +#else
1.159 + // on IPCv1 we use explicit - more efficient
1.160 + User::LeaveIfError(iFsSession.Share(RSessionBase::EExplicitAttach));
1.161 +#endif
1.162 +
1.163 + User::LeaveIfError(iFsSession.ShareProtected());
1.164 +
1.165 + HBufC* filename = NULL;
1.166 +
1.167 + iCAFParameters = new (ELeave) CCAFParameters;
1.168 + TBool drmContent = EFalse;
1.169 + RDesReadStream stream(aInitData);
1.170 + CleanupClosePushL(stream);
1.171 +
1.172 + TUid initUid = TUid::Uid(stream.ReadInt32L());
1.173 +
1.174 + if (initUid == KMMFileHandleSourceUid)
1.175 + {
1.176 + TPckgBuf<RFile*> fileptr;
1.177 + stream.ReadL(fileptr);
1.178 +
1.179 + iHandle.Duplicate(*fileptr());
1.180 +
1.181 + TInt length = stream.ReadInt32L();
1.182 + if (length>0)
1.183 + {
1.184 + iCAFParameters->iUniqueId = HBufC::NewL(length);
1.185 + TPtr16 ptr = iCAFParameters->iUniqueId->Des();
1.186 + stream.ReadL(ptr, length);
1.187 + }
1.188 + iFileHandle = ETrue;
1.189 +
1.190 + filename = HBufC::NewMaxLC(KMaxFileName);
1.191 + TPtr ptr = filename->Des();
1.192 + User::LeaveIfError(iHandle.FullName(ptr));
1.193 + drmContent = ETrue;
1.194 +
1.195 + iCAFParameters->iEnableUI = stream.ReadInt32L();
1.196 + }
1.197 +
1.198 + else if (initUid == KMMFileSourceUid)
1.199 + {
1.200 + TInt length = stream.ReadInt32L();
1.201 + filename = HBufC::NewMaxLC(length);
1.202 + TPtr ptr = filename->Des();
1.203 + stream.ReadL(ptr, length);
1.204 +
1.205 + length = stream.ReadInt32L();
1.206 + if (length>0)
1.207 + {
1.208 + iCAFParameters->iUniqueId = HBufC::NewMaxL(length);
1.209 + ptr.Set(iCAFParameters->iUniqueId->Des());
1.210 + stream.ReadL(ptr, length);
1.211 + }
1.212 + drmContent = ETrue;
1.213 + iCAFParameters->iEnableUI = stream.ReadInt32L();
1.214 + }
1.215 + else
1.216 + {
1.217 +// XXX If the UID is unknown we should reject, but currently
1.218 +// code also used for older calls that just supply filename.
1.219 +// User::Leave(KErrNotSupported);
1.220 + }
1.221 +
1.222 + if ((filename == NULL) && aInitData.Length() == sizeof(TMMFFileHandleParams))
1.223 + {
1.224 + TMMFFileHandleParams params;
1.225 + TPckgC<TMMFFileHandleParams> config(params);
1.226 + config.Set(aInitData);
1.227 + params = config();
1.228 +
1.229 +
1.230 + if (params.iUid == KFileHandleUid)
1.231 + {
1.232 + User::LeaveIfError(iHandle.Duplicate(*params.iFile));
1.233 + TInt pos = 0;
1.234 + // make sure the duplicate handle is at the start of the file - the usage of the file handle really requires this
1.235 + User::LeaveIfError(iHandle.Seek(ESeekStart, pos));
1.236 + iFileHandle = ETrue;
1.237 + ASSERT(filename == NULL);
1.238 + filename = HBufC::NewMaxLC(KMaxFileName);
1.239 + TPtr ptr = filename->Des();
1.240 + User::LeaveIfError(iHandle.FullName(ptr));
1.241 + }
1.242 + }
1.243 +
1.244 + if (filename == NULL) // do old case as last resort
1.245 + {
1.246 + TMMFFileParams params;
1.247 + TPckgC<TMMFFileParams> config(params);
1.248 + config.Set(aInitData);
1.249 + params = config();
1.250 +
1.251 + filename = params.iPath.AllocLC();
1.252 + }
1.253 +
1.254 + ASSERT(filename != NULL);
1.255 +
1.256 + TParse parser ;
1.257 + User::LeaveIfError(parser.Set(*filename, NULL, NULL));
1.258 + CleanupStack::PopAndDestroy(2, &stream); //filename, stream
1.259 + if ( !( parser.NamePresent() ) && !( parser.ExtPresent() ) )
1.260 + {
1.261 + User::Leave( KErrBadName ) ;
1.262 + }
1.263 +
1.264 + iFullFileName.Copy( parser.FullName() ) ;
1.265 + iFileName = parser.Name().AllocL() ;
1.266 + iFileExt = parser.Ext().AllocL() ;
1.267 + iFilePath = parser.Path().AllocL() ;
1.268 + iFileDrive = parser.Drive().AllocL() ;
1.269 +
1.270 + // in order to simulate old behaviour we are not passing error out
1.271 + // but will try to create Content again during PrimeL()
1.272 + if (drmContent && aFileMode==ESourceMode)
1.273 + {
1.274 + TInt contentError;
1.275 + if (iFileHandle)
1.276 + {
1.277 + TRAP(contentError,
1.278 + iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI);
1.279 + );
1.280 + }
1.281 + else
1.282 + {
1.283 + // Open for read-only access
1.284 + TRAP(contentError,
1.285 + iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareReadersOnly, iCAFParameters->iEnableUI);
1.286 + );
1.287 + }
1.288 + }
1.289 + }
1.290 +
1.291 +
1.292 +/**
1.293 +@deprecated - Replaced by CMMFFile::Data()
1.294 +
1.295 +Returns an RFile handle to the current file.
1.296 +
1.297 +If there is no current file, one is created. If the file exists then it is opened with read access
1.298 +if it is read only, write access otherwise. If the file does not exist then it is opened with
1.299 +write access.
1.300 +
1.301 +@leave KErrNotReady
1.302 + The file is not open.
1.303 +
1.304 +@return A handle to the current file.
1.305 +@see CMMFFile::Data()
1.306 +*/
1.307 +RFile& CMMFFile::FileL()
1.308 + {
1.309 + if (!iFile)
1.310 + User::Leave(KErrNotReady);
1.311 + if (iFileHandle)
1.312 + return iHandle;
1.313 + else
1.314 + return iFile->FileL();
1.315 + }
1.316 +
1.317 +/**
1.318 +Returns the file name of the current file.
1.319 +
1.320 +Note: This will give the wrong answer if the file is renamed!
1.321 +
1.322 +@return The FileName (without extension).
1.323 +*/
1.324 +const TDesC& CMMFFile::FileName() const
1.325 + {
1.326 + return *iFileName ;
1.327 + }
1.328 +
1.329 +/**
1.330 +Returns the extension of the current file.
1.331 +
1.332 +Note: This will give the wrong answer if the file is renamed!
1.333 +
1.334 +@return The File Extension.
1.335 +*/
1.336 +const TDesC& CMMFFile::Extension() const
1.337 + {
1.338 + return *iFileExt ;
1.339 + }
1.340 +
1.341 +/**
1.342 +Returns the path of the current file.
1.343 +
1.344 +Note: This will give the wrong answer if the file is renamed!
1.345 +
1.346 +@return The FilePath (without filename and extension)
1.347 +*/
1.348 +const TDesC& CMMFFile::FilePath() const
1.349 + {
1.350 + return *iFilePath ;
1.351 + }
1.352 +
1.353 +/**
1.354 +Returns the drive on which the current file is located.
1.355 +
1.356 +Note: This will give the wrong answer if the file is renamed!
1.357 +
1.358 +@return The FileDrive (drive letter only, without path, filename and extension).
1.359 +*/
1.360 +const TDesC& CMMFFile::FileDrive() const
1.361 + {
1.362 + return *iFileDrive ;
1.363 + }
1.364 +
1.365 +/**
1.366 +Returns the full name of the current file.
1.367 +
1.368 +Note: This will give the wrong answer if the file is renamed!
1.369 +
1.370 +@return The file name (full filename including drive letter, without path, filename and extension).
1.371 +*/
1.372 +const TFileName CMMFFile::FullName() const
1.373 + {
1.374 + return iFullFileName;
1.375 + }
1.376 +
1.377 +/**
1.378 +Returns the uniqueID associated with this content. If no uniqueID has been provided, a null
1.379 +descriptor will be provided
1.380 +
1.381 +@return The UniqueID
1.382 +*/
1.383 +const TDesC& CMMFFile::UniqueId() const
1.384 + {
1.385 + if (iCAFParameters->iUniqueId)
1.386 + return *(iCAFParameters->iUniqueId);
1.387 + else
1.388 + return KNullDesC;
1.389 + }
1.390 +
1.391 +
1.392 +/**
1.393 +Deletes the file.
1.394 +
1.395 +Closes the currently open file, then deletes it. If the file source is accessing a file handle,
1.396 +the file is truncated to 0 bytes instead.
1.397 +
1.398 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
1.399 + another of the system-wide error codes.
1.400 +*/
1.401 +TInt CMMFFile::Delete()
1.402 + {
1.403 + TInt result = KErrNone;
1.404 + if (!iFileHandle)
1.405 + {
1.406 + delete iFile;
1.407 + iFile = NULL;
1.408 + iFileSize=-1;
1.409 + iPosition=0;
1.410 +
1.411 + result = iFsSession.Delete(iFullFileName);
1.412 + }
1.413 + else
1.414 + {
1.415 + iFileSize=-1;
1.416 + iPosition=0;
1.417 +
1.418 + if (iFile)
1.419 + {
1.420 + result = iFile->SetSize(0);
1.421 + }
1.422 + }
1.423 +
1.424 + return result;
1.425 + }
1.426 +
1.427 +/**
1.428 +Sets the file size.
1.429 +
1.430 +@param aSize
1.431 + The size of the file.
1.432 +
1.433 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
1.434 + another of the system-wide error codes.
1.435 +*/
1.436 +TInt CMMFFile::SetSize(TInt aSize)
1.437 + {
1.438 + if ( !iFile )
1.439 + return KErrNotReady;
1.440 + TInt err = iFile->SetSize(aSize);
1.441 + if(err == KErrNone)
1.442 + iFileSize = aSize;
1.443 + else
1.444 + iFileSize = -1;
1.445 +
1.446 + return err;
1.447 + }
1.448 +
1.449 +/**
1.450 +Obtains a CTransferBufferCopy from iTransferBufferCopies that is
1.451 +at least as big as that required.
1.452 +
1.453 +There is no need to put the pointer returned by this method onto the CleanupStack
1.454 +as it will have already been placed into iTransferBufferCopies.
1.455 +
1.456 +@param aMaxLength
1.457 + The size required.
1.458 +
1.459 +@return A pointer to a valid CTransferBufferCopy.
1.460 +*/
1.461 +CTransferBufferCopy* CMMFFile::ObtainCopyOfTransferBufferL(TInt aMaxLength)
1.462 + {
1.463 + //find a free transfer buffer copy of the right size
1.464 + TInt firstFree = -1;
1.465 + CTransferBufferCopy* transBufCopyToUse = NULL;
1.466 +
1.467 + for(TInt cnt=0; cnt < iTransferBufferCopies.Count(); cnt++)
1.468 + {
1.469 + if(!iTransferBufferCopies[cnt]->InUse())
1.470 + {
1.471 + //record the first free entry, we may remove this
1.472 + //if entries in iTransferBufferCopies > KAcceptableTransferBufferCopiesSize
1.473 + if(firstFree == -1)
1.474 + firstFree = cnt;
1.475 +
1.476 + if(iTransferBufferCopies[cnt]->MaxLength() >= aMaxLength)
1.477 + {
1.478 + transBufCopyToUse = iTransferBufferCopies[cnt];
1.479 +
1.480 + //Set the MaxLength. This will ensure that the copy acts the same as
1.481 + //the original Transfer buffer, eg. file server will throw KErrOverflow
1.482 + transBufCopyToUse->ReUse(aMaxLength);
1.483 + break;
1.484 + }
1.485 + }
1.486 + }
1.487 +
1.488 + //If we failed to find a suitable entry, we need to create a new one
1.489 + if(!transBufCopyToUse)
1.490 + {
1.491 + //Firstly, should we re-cycle an existing entry?
1.492 + //There must be entries in the array, a free entry must have been found,
1.493 + //the size of the array must be beyond the water mark where we want to start
1.494 + //cycling free entries.
1.495 + if((iTransferBufferCopies.Count() > 0) &&
1.496 + (firstFree != -1) &&
1.497 + (iTransferBufferCopies.Count() > KAcceptableTransferBufferCopiesSize))
1.498 + {
1.499 + delete iTransferBufferCopies[firstFree];
1.500 + iTransferBufferCopies.Remove(firstFree);
1.501 +
1.502 + transBufCopyToUse = CTransferBufferCopy::NewL(aMaxLength);
1.503 + CleanupStack::PushL(transBufCopyToUse);
1.504 + User::LeaveIfError(iTransferBufferCopies.Insert(transBufCopyToUse,firstFree));
1.505 +
1.506 + CleanupStack::Pop();
1.507 + }
1.508 + else
1.509 + {
1.510 +#ifdef _DEBUG
1.511 + if(iTransferBufferCopies.Count() > KMaximumTransferBufferCopiesSize)
1.512 + {
1.513 + User::Panic(_L("iTransferBufferCopies grew too large in CMMFFile"),KErrTooBig);
1.514 + }
1.515 +#endif
1.516 +
1.517 + transBufCopyToUse = CTransferBufferCopy::NewL(aMaxLength);
1.518 + CleanupStack::PushL(transBufCopyToUse);
1.519 + User::LeaveIfError(iTransferBufferCopies.Append(transBufCopyToUse));
1.520 +
1.521 + CleanupStack::Pop();
1.522 + }
1.523 + }
1.524 +
1.525 + return transBufCopyToUse;
1.526 + }
1.527 +
1.528 +
1.529 +
1.530 +/**
1.531 +Loads aBuffer from iFile.
1.532 +
1.533 +The file must already be open for reading. File read is asynchronous. CReadRequest is created to
1.534 +respond to completion.
1.535 +
1.536 +@param aBuffer
1.537 + The buffer to be filled from the file.
1.538 +@param aConsumer
1.539 + The data sink consumer of the buffer.
1.540 +*/
1.541 +void CMMFFile::FillBufferL( CMMFBuffer* aBuffer, MDataSink* aConsumer, TMediaId /*aMediaId*/ )
1.542 + {
1.543 + // Requires that iFile is open for read.
1.544 + // Reads data from iFile into aBuffer
1.545 + if ((aConsumer == NULL) || (aBuffer == NULL))
1.546 + User::Leave(KErrArgument);
1.547 +
1.548 + if (!iFile || (iMmfFileEventHandler == NULL))
1.549 + User::Leave(KErrNotReady);
1.550 +
1.551 + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.552 + {
1.553 + CTransferBufferCopy* transBufCopy = NULL;
1.554 + CReadRequest* request = NULL;
1.555 +
1.556 + TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
1.557 +
1.558 + TInt requestSize;
1.559 + if(aBuffer->RequestSize())
1.560 + requestSize = aBuffer->RequestSize();
1.561 + else
1.562 + requestSize = aBufferDes.MaxLength();
1.563 +
1.564 + //check whether buffer is safe to send to file server
1.565 + //if not, eg for a transfer buffer, then it needs to be copied
1.566 + if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
1.567 + {
1.568 + //NB: failure in this method will NOT cause transBufCopy to leak as it will be
1.569 + //inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
1.570 + transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
1.571 + request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, transBufCopy, iPosition, Size(), iMmfFileEventHandler);
1.572 + }
1.573 + else
1.574 + {
1.575 + request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, iPosition, Size(), iMmfFileEventHandler);
1.576 + }
1.577 +
1.578 + CleanupStack::PushL( request );
1.579 +
1.580 + StoreRequestL(request); // transfers ownership
1.581 + CleanupStack::Pop() ; // request
1.582 +
1.583 + iFile->Read(request->BufferDes(), requestSize, request->iStatus);
1.584 + iPosition += requestSize;
1.585 +
1.586 + if (iPosition >= iFileSize)
1.587 + {
1.588 + aBuffer->SetLastBuffer(ETrue);
1.589 + }
1.590 +
1.591 + request->SetActive();
1.592 + }
1.593 + else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.594 + User::Leave( KErrNotSupported ) ;
1.595 + }
1.596 +
1.597 +/**
1.598 +Empties aBuffer into iFile. The file must be already open for writing.
1.599 +
1.600 +@param aBuffer
1.601 + The buffer to be written to the file.
1.602 +@param aSupplier
1.603 + The data source supplier of the buffer.
1.604 +*/
1.605 +void CMMFFile::EmptyBufferL( CMMFBuffer* aBuffer, MDataSource* aSupplier, TMediaId /*aMediaId*/ )
1.606 + {
1.607 + // Requires that iFile is open for write.
1.608 + // Writes data from iFile into aBuffer
1.609 + if ((aSupplier == NULL) || (aBuffer == NULL))
1.610 + User::Leave(KErrArgument);
1.611 +
1.612 + if (!iFile || (iMmfFileEventHandler == NULL))
1.613 + User::Leave(KErrNotReady);
1.614 +
1.615 + CTransferBufferCopy* transBufCopy = NULL;
1.616 +
1.617 + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.618 + {
1.619 + CWriteRequest* request = NULL;
1.620 + TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
1.621 +
1.622 + //check whether buffer is safe to send to file server
1.623 + //if not, eg for a transfer buffer, then it needs to be copied
1.624 + if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
1.625 + {
1.626 + //Obtain a normal buffer to send to the file server
1.627 + //NB: failure in this method will NOT cause transBufCopy to leak as it will be
1.628 + //inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
1.629 + transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
1.630 +
1.631 + //Copy the data into the buffer we will send to the file server
1.632 + transBufCopy->Des().Copy(aBufferDes);
1.633 +
1.634 + request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, transBufCopy, iMmfFileEventHandler);
1.635 + }
1.636 + else
1.637 + {
1.638 + request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, iMmfFileEventHandler);
1.639 + }
1.640 +
1.641 + CleanupStack::PushL( request );
1.642 +
1.643 + StoreRequestL(request); // transfers ownership
1.644 + CleanupStack::Pop(); // request
1.645 +
1.646 + iFile->Write(request->BufferDes(), request->BufferDes().Length(), request->iStatus);
1.647 + request->SetActive();
1.648 + }
1.649 + else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.650 + {
1.651 + User::Leave( KErrNotSupported ) ;
1.652 + }
1.653 + }
1.654 +
1.655 +/**
1.656 +Loads aLength number of bytes into aBuffer from specified point in iFile.
1.657 +
1.658 +@param aLength
1.659 + The number of bytes to be read into buffer.
1.660 +@param aBuffer
1.661 + The buffer to be filled from the file.
1.662 +@param aPosition
1.663 + The offset into the file at which to start reading.
1.664 +@param aConsumer
1.665 + The data sink consumer of the buffer.
1.666 +*/
1.667 +void CMMFFile::ReadBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer)
1.668 + {
1.669 + // Requires that iFile is open for read.
1.670 + // Reads data from iFile into aBuffer
1.671 + if ((aLength < 0) || (aPosition<0) || (aConsumer == NULL) || (aBuffer == NULL))
1.672 + User::Leave(KErrArgument);
1.673 +
1.674 + if (!iFile || (iMmfFileEventHandler == NULL))
1.675 + User::Leave(KErrNotReady);
1.676 +
1.677 + CTransferBufferCopy* transBufCopy = NULL;
1.678 +
1.679 + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.680 + {
1.681 + CReadRequest* request = NULL;
1.682 + TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
1.683 +
1.684 + //check whether buffer is safe to send to file server
1.685 + //if not, eg for a transfer buffer, then it needs to be copied
1.686 + if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
1.687 + {
1.688 + //Obtain a normal buffer to send to the file server
1.689 + //NB: failure in this method will NOT cause transBufCopy to leak as it will be
1.690 + //inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
1.691 + transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
1.692 +
1.693 + request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, transBufCopy, aPosition, Size(), iMmfFileEventHandler);
1.694 + }
1.695 + else
1.696 + {
1.697 + request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, aPosition, Size(), iMmfFileEventHandler);
1.698 + }
1.699 +
1.700 + CleanupStack::PushL( request );
1.701 +
1.702 + StoreRequestL(request) ; //transfers ownership
1.703 + CleanupStack::Pop() ; //request
1.704 +
1.705 + TInt err = iFile->Read(aPosition, request->BufferDes(), aLength, request->iStatus);
1.706 + if (err == KErrCANotSupported)
1.707 + {
1.708 + err = KErrNone;
1.709 + if (aPosition != iPosition)
1.710 + {
1.711 + err = iFile->Seek(ESeekStart, aPosition);
1.712 + }
1.713 + if (err==KErrNone)
1.714 + {
1.715 + iFile->Read(request->BufferDes(), aLength, request->iStatus);
1.716 + }
1.717 + }
1.718 +
1.719 + if (err != KErrNone)
1.720 + {
1.721 + TRequestStatus* status = &request->iStatus;
1.722 + User::RequestComplete(status, err);
1.723 + }
1.724 +
1.725 + iPosition = aPosition + aLength;
1.726 +
1.727 + if (iPosition >= iFileSize)
1.728 + {
1.729 + aBuffer->SetLastBuffer(ETrue);
1.730 + }
1.731 +
1.732 + request->SetActive();
1.733 + }
1.734 + else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.735 + User::Leave( KErrNotSupported ) ;
1.736 + }
1.737 +
1.738 +
1.739 +/**
1.740 +Loads aBuffer from specified point in iFile.
1.741 +
1.742 +The file must already be open for reading.
1.743 +
1.744 +@param aBuffer
1.745 + The buffer to be filled from the file.
1.746 +@param aPosition
1.747 + The offset into file at which to start reading.
1.748 +@param aConsumer
1.749 + The data sink consumer of the buffer.
1.750 +*/
1.751 +void CMMFFile::ReadBufferL(CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer)
1.752 + {
1.753 + // Requires that iFile is open for read.
1.754 + // Reads data from iFile into aBuffer
1.755 + if ((aPosition<0) || (aConsumer == NULL) || (aBuffer == NULL))
1.756 + User::Leave(KErrArgument);
1.757 +
1.758 + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.759 + {
1.760 + TInt requestSize;
1.761 + if(aBuffer->RequestSize())
1.762 + requestSize = aBuffer->RequestSize();
1.763 + else
1.764 + requestSize = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data().MaxLength();
1.765 +
1.766 + ReadBufferL(requestSize, aBuffer, aPosition, aConsumer);
1.767 + }
1.768 + else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.769 + User::Leave(KErrNotSupported);
1.770 + }
1.771 +
1.772 +
1.773 +/**
1.774 +Loads aBuffer from specified point in iFile. Note that this is a synchronous read.
1.775 +
1.776 +@param aBuffer
1.777 + The buffer to be filled from the file.
1.778 +@param aPosition
1.779 + The offset into file at which to start reading.
1.780 +*/
1.781 +void CMMFFile::ReadBufferL( CMMFBuffer* aBuffer, TInt aPosition)
1.782 + {
1.783 + // Requires that iFile is open for read.
1.784 + // Reads data from iFile into aBuffer
1.785 + if ((aPosition<0) || (aBuffer == NULL))
1.786 + User::Leave(KErrArgument);
1.787 +
1.788 + if (!iFile)
1.789 + User::Leave(KErrNotReady);
1.790 +
1.791 + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.792 + {
1.793 + TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
1.794 +
1.795 + TInt requestSize;
1.796 + if(aBuffer->RequestSize())
1.797 + requestSize = aBuffer->RequestSize();
1.798 + else
1.799 + requestSize = aBufferDes.MaxLength();
1.800 +
1.801 + //check whether buffer is safe to send to file server
1.802 + //if not, eg for a transfer buffer, then it needs to be copied
1.803 + if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
1.804 + {
1.805 + //NB: failure in this method will NOT cause transBufCopy to leak as it will be
1.806 + //inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
1.807 + CTransferBufferCopy* transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
1.808 +
1.809 + User::LeaveIfError(iFile->Seek(ESeekStart, aPosition));
1.810 + User::LeaveIfError(iFile->Read(transBufCopy->Des(), requestSize));
1.811 + aBufferDes.Copy(transBufCopy->Des().Left(aBufferDes.MaxLength()));
1.812 + }
1.813 + else
1.814 + {
1.815 + User::LeaveIfError(iFile->Seek(ESeekStart, aPosition));
1.816 + User::LeaveIfError(iFile->Read(aBufferDes, requestSize));
1.817 + }
1.818 +
1.819 + iPosition = aPosition + aBufferDes.Length();
1.820 +
1.821 + //check if the buffer is the last buffer and if so set the last buffer flag on the CMMFDataBuffer
1.822 + //NB: setting last buffer is the done by the formatter, but this is a hang over to account for
1.823 + //existing formatters that may fail if this is removed.
1.824 + if (iPosition >= Size())
1.825 + {
1.826 + aBuffer->SetLastBuffer(ETrue);
1.827 + }
1.828 + }
1.829 + else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.830 + User::Leave(KErrNotSupported);
1.831 + }
1.832 +
1.833 +/**
1.834 +Empties aLength bytes from aBuffer into iFile at specified location.
1.835 +
1.836 +@param aLength
1.837 + The number of bytes to be emptied from buffer.
1.838 +@param aBuffer
1.839 + The data buffer containing bytes to be written.
1.840 +@param aPosition
1.841 + The offset into file at which to start writing.
1.842 +@param aSupplier
1.843 + The data source to be notified when the write has been completed.
1.844 +
1.845 +@leave KErrNotReady
1.846 + SinkPrimeL() and SinkThreadLogon() have not been called.
1.847 +@leave KErrArgument
1.848 + aLength<0 or aPosition<0 or aSupplier is NULL.
1.849 +@leave KErrNotSupported
1.850 + aBuffer is not a supported CMMFDataBuffer
1.851 +*/
1.852 +void CMMFFile::WriteBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier)
1.853 + {
1.854 + if ((aLength<0) || (aPosition<0) || (aSupplier == NULL) || (aBuffer == NULL))
1.855 + User::Leave(KErrArgument);
1.856 +
1.857 + if (!iFile || (iMmfFileEventHandler == NULL))
1.858 + User::Leave(KErrNotReady);
1.859 +
1.860 + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.861 + {
1.862 + CWriteRequest* request = NULL;
1.863 + TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
1.864 +
1.865 + //check whether buffer is safe to send to file server
1.866 + //if not, eg for a transfer buffer, then it needs to be copied
1.867 + if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
1.868 + {
1.869 + //NB: failure in this method will NOT cause transBufCopy to leak as it will be
1.870 + //inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
1.871 + CTransferBufferCopy* transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
1.872 +
1.873 + transBufCopy->Des().Copy(aBufferDes);
1.874 +
1.875 + request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, transBufCopy, iMmfFileEventHandler);
1.876 + }
1.877 + else
1.878 + {
1.879 + request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, iMmfFileEventHandler);
1.880 + }
1.881 +
1.882 + CleanupStack::PushL( request );
1.883 +
1.884 + StoreRequestL(request); // transfers ownership
1.885 + CleanupStack::Pop(); // request
1.886 +
1.887 + User::LeaveIfError(iFile->Seek(ESeekStart, aPosition));
1.888 + iFile->Write(request->BufferDes(), aLength, request->iStatus);
1.889 + iFileSize = -1; //reset cached size
1.890 +
1.891 + request->SetActive();
1.892 + }
1.893 + else // if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
1.894 + {
1.895 + //write bitmap to file
1.896 + User::Leave(KErrNotSupported);
1.897 + }
1.898 + }
1.899 +
1.900 +/**
1.901 +Empties aBuffer into iFile at the specified location.
1.902 +
1.903 +@param aBuffer
1.904 + The data buffer containing bytes to be written.
1.905 +@param aPosition
1.906 + The offset into file at which to start writing.
1.907 +@param aSupplier
1.908 + The data source to be notified when the write has been completed.
1.909 +
1.910 +@leave KErrNotReady
1.911 + SinkPrimeL() and SinkThreadLogon() have not been called.
1.912 +@leave KErrArgument
1.913 + aSupplier is NULL.
1.914 +@leave KErrNotSupported
1.915 + The aBuffer is not of type KMMFDataBuffer.
1.916 +*/
1.917 +void CMMFFile::WriteBufferL( CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier)
1.918 + {
1.919 + // Requires that iFile is open for write.
1.920 + // Writes data from iFile into aBuffer
1.921 + if ((aPosition<0) || (aSupplier == NULL) || (aBuffer == NULL))
1.922 + User::Leave(KErrArgument);
1.923 +
1.924 + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.925 + {
1.926 + TUint requestSize = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data().Length();
1.927 +
1.928 + WriteBufferL(requestSize, aBuffer, aPosition, aSupplier);
1.929 + }
1.930 + else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.931 + {
1.932 + //write bitmap to file
1.933 + User::Leave( KErrNotSupported ) ;
1.934 + }
1.935 + }
1.936 +
1.937 +/**
1.938 +Empties aBuffer into iFile at specified location. Note that this is a synchronous write.
1.939 +
1.940 +@param aBuffer
1.941 + The data buffer containing bytes to be written.
1.942 +@param aPosition
1.943 + The offset into file at which to start writing.
1.944 +
1.945 +@return The error code from RFile.
1.946 +*/
1.947 +void CMMFFile::WriteBufferL( CMMFBuffer* aBuffer, TInt aPosition )
1.948 + {
1.949 + if ((aPosition<0) || (aBuffer == NULL))
1.950 + User::Leave(KErrArgument);
1.951 +
1.952 + if (!iFile)
1.953 + User::Leave(KErrNotReady);
1.954 +
1.955 + TInt err(KErrNone) ;
1.956 +
1.957 + //check whether buffer is safe to send to file server
1.958 + //if not, eg for a transfer buffer, then it needs to be copied
1.959 + if ((!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
1.960 + && (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())))
1.961 + {
1.962 + TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
1.963 +
1.964 + //NB: failure in this method will NOT cause transBufCopy to leak as it will be
1.965 + //inserted into iTransferBufferCopies by ObtainCopyOfTransferBufferL.
1.966 + CTransferBufferCopy* transBufCopy = ObtainCopyOfTransferBufferL(aBufferDes.MaxLength());
1.967 +
1.968 + transBufCopy->Des().Copy(aBufferDes);
1.969 + err = iFile->Seek(ESeekStart, aPosition);
1.970 + if (err==KErrNone)
1.971 + err = iFile->Write(transBufCopy->Des(),transBufCopy->Des().Length());
1.972 + iFileSize = -1; //reset cached size
1.973 + }
1.974 + else if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.975 + {
1.976 + TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
1.977 +
1.978 + err = iFile->Seek(ESeekStart, aPosition);
1.979 + if (err==KErrNone)
1.980 + err = iFile->Write(aBufferDes, aBufferDes.Length());
1.981 + iFileSize = -1; //reset cached size
1.982 + }
1.983 + else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
1.984 + {
1.985 + User::Leave(KErrNotSupported);
1.986 + }
1.987 +
1.988 + User::LeaveIfError(err);
1.989 + }
1.990 +
1.991 +/**
1.992 +Gets the number of free bytes in the device's file system.
1.993 +
1.994 +@return The number of free bytes.
1.995 +*/
1.996 +TInt64 CMMFFile::BytesFree()
1.997 + {
1.998 + TInt driveNumber = KDefaultDrive;
1.999 +
1.1000 + if (FileDrive().Length() > 0)
1.1001 + {
1.1002 + TChar driveLetter = FileDrive()[0];
1.1003 + RFs::CharToDrive(driveLetter, driveNumber);
1.1004 + }
1.1005 +
1.1006 + TVolumeInfo volInfo;
1.1007 + if (iFsSession.Volume(volInfo, driveNumber) == KErrNone)
1.1008 + {
1.1009 + return volInfo.iFree;
1.1010 + }
1.1011 + return TInt64(0);
1.1012 + }
1.1013 +
1.1014 +/**
1.1015 +Returns the size of the file in bytes.
1.1016 +
1.1017 +Note: This is not the maximum length.
1.1018 +
1.1019 +@return The size of the file in bytes.
1.1020 +*/
1.1021 +TInt CMMFFile::Size()
1.1022 + {
1.1023 + TInt size = 0;
1.1024 + TInt err = KErrNone;
1.1025 + TBool fileOpened = EFalse;
1.1026 +
1.1027 + if(iFileSize != -1)
1.1028 + return iFileSize;
1.1029 +
1.1030 + if (!iFile)
1.1031 + {
1.1032 + // Open the file. We only need read access, so SourcePrimeL will open the file with read flag
1.1033 + TRAP(err, SourcePrimeL());
1.1034 + if (iFile)
1.1035 + fileOpened = ETrue;
1.1036 + }
1.1037 + if (err == KErrNone)
1.1038 + {
1.1039 + __ASSERT_DEBUG(iFile != NULL,Panic(EMMFFileHandleNULL));
1.1040 + err = iFile->Size(size);
1.1041 + }
1.1042 + if (err)
1.1043 + {
1.1044 + size = 0;
1.1045 + iFileSize = -1; //reset cached size
1.1046 + }
1.1047 + else
1.1048 + iFileSize = size; //cache the filesize
1.1049 +
1.1050 + if (fileOpened)
1.1051 + {
1.1052 + __ASSERT_DEBUG(iFile != NULL,Panic(EMMFFileHandleNULL));
1.1053 + delete iFile;
1.1054 + iFile = NULL;
1.1055 + iFileSize = -1;
1.1056 + }
1.1057 +
1.1058 + return size;
1.1059 + }
1.1060 +
1.1061 +/**
1.1062 +Source thread logon.
1.1063 +
1.1064 +Shares fsSession between threads
1.1065 +
1.1066 +@param aEventHandler
1.1067 + This is an MAsyncEventHandler to handle asynchronous events that occur during the
1.1068 + transfer of multimedia data.
1.1069 +
1.1070 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
1.1071 + another of the system-wide error codes.
1.1072 +*/
1.1073 +TInt CMMFFile::SourceThreadLogon(MAsyncEventHandler& aEventHandler)
1.1074 + {
1.1075 + iEventHandler = &aEventHandler;
1.1076 + if(!iMmfFileEventHandler)
1.1077 + {
1.1078 + iMmfFileEventHandler = new CMMFFileAsyncEventHandler(this);
1.1079 + if(!iMmfFileEventHandler)
1.1080 + return KErrNoMemory;
1.1081 + }
1.1082 +#ifdef __IPC_V2_PRESENT__
1.1083 + return KErrNone; // nothing to do
1.1084 +#else
1.1085 + return iFsSession.Attach();
1.1086 +#endif // __HIDE_IPC_V1__
1.1087 + }
1.1088 +
1.1089 +/**
1.1090 +Logs off source thread.
1.1091 +*/
1.1092 +void CMMFFile::SourceThreadLogoff()
1.1093 + {
1.1094 + delete iMmfFileEventHandler;
1.1095 + iMmfFileEventHandler = NULL;
1.1096 + iEventHandler = NULL;
1.1097 + }
1.1098 +
1.1099 +
1.1100 +/**
1.1101 +Sink thread logon.
1.1102 +
1.1103 +Shares fsSession between threads.
1.1104 +
1.1105 +@param aEventHandler
1.1106 + This is an MAsyncEventHandler to handle asynchronous events that occur during the
1.1107 + transfer of multimedia data.
1.1108 +
1.1109 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
1.1110 + another of the system-wide error codes.
1.1111 +*/
1.1112 +TInt CMMFFile::SinkThreadLogon(MAsyncEventHandler& aEventHandler)
1.1113 + {
1.1114 + iEventHandler = &aEventHandler;
1.1115 + if(!iMmfFileEventHandler)
1.1116 + {
1.1117 + iMmfFileEventHandler = new CMMFFileAsyncEventHandler(this);
1.1118 + if(!iMmfFileEventHandler)
1.1119 + return KErrNoMemory;
1.1120 + }
1.1121 +#ifdef __IPC_V2_PRESENT__
1.1122 + return KErrNone;
1.1123 +#else
1.1124 + return iFsSession.Attach();
1.1125 +#endif // __HIDE_IPC_V1__
1.1126 + }
1.1127 +
1.1128 +/**
1.1129 +Sink thread log off.
1.1130 +*/
1.1131 +void CMMFFile::SinkThreadLogoff()
1.1132 + {
1.1133 + delete iMmfFileEventHandler;
1.1134 + iMmfFileEventHandler = NULL;
1.1135 + iEventHandler = NULL;
1.1136 + }
1.1137 +
1.1138 +/**
1.1139 +Stores a request in an array.
1.1140 +
1.1141 +CReadWriteRequests are stored in the array iRequests.
1.1142 +This function takes ownership and places the request in the array.
1.1143 +It also checks the array for completed requests and removes them.
1.1144 +
1.1145 +@param aRequest
1.1146 + The request to store.
1.1147 +*/
1.1148 +void CMMFFile::StoreRequestL( CReadWriteRequest* aRequest )
1.1149 + {
1.1150 + // add aRequest to iRequests
1.1151 + User::LeaveIfError( iRequests.Append( aRequest ) ) ;
1.1152 +
1.1153 + // Clear out any completed requests
1.1154 + for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ )
1.1155 + {
1.1156 + if (iRequests[ii]->Completed())
1.1157 + {
1.1158 + CReadWriteRequest* request = iRequests[ii];
1.1159 + delete request;
1.1160 +
1.1161 + iRequests.Remove(ii);
1.1162 + ii--;
1.1163 + }
1.1164 + }
1.1165 + }
1.1166 +
1.1167 +
1.1168 +/**
1.1169 +Cancels outstanding requests.
1.1170 +
1.1171 +CReadWriteRequests are stored in the array iRequests.
1.1172 +This function cancels any outstanding requests and removes them
1.1173 +from iRequests.
1.1174 +*/
1.1175 +void CMMFFile::CancelRequests()
1.1176 + {
1.1177 + // Clear out any completed requests
1.1178 + for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ )
1.1179 + {
1.1180 + CReadWriteRequest* request = iRequests[ii];
1.1181 + delete request;
1.1182 + iRequests.Remove(ii);
1.1183 + ii--;
1.1184 + }
1.1185 + }
1.1186 +
1.1187 +
1.1188 +
1.1189 +/**
1.1190 +Returns the data type as a fourCC code of CMMFFile as a data source.
1.1191 +
1.1192 +@return The data type fourCC code.
1.1193 +*/
1.1194 +TFourCC CMMFFile::SourceDataTypeCode(TMediaId /*aMediaId*/)
1.1195 + {
1.1196 + return iSourceFourCC ;
1.1197 + }
1.1198 +
1.1199 +/**
1.1200 +Returns the data type as a fourCC code of CMMFFile as a data sink.
1.1201 +
1.1202 +@return The data type fourCC code
1.1203 +*/
1.1204 +TFourCC CMMFFile::SinkDataTypeCode(TMediaId /*aMediaId*/)
1.1205 + {
1.1206 + return iSinkFourCC ;
1.1207 + }
1.1208 +
1.1209 +
1.1210 +/**
1.1211 +CMMFFile as a source is always passive so this function is not supported.
1.1212 +
1.1213 +@param aBuffer
1.1214 + The emptied buffer.
1.1215 +*/
1.1216 +void CMMFFile::BufferEmptiedL(CMMFBuffer* /* aBuffer */)
1.1217 + {
1.1218 + Panic(EMMFFilePanicBufferEmptiedLNotSupported);
1.1219 + }
1.1220 +
1.1221 +/**
1.1222 +Tests whether a source buffer can be created.
1.1223 +
1.1224 +@return A boolean indicating if if CMMFFile can create its own buffer. EFalse if CMMFFile cannot
1.1225 + create it's own buffer.
1.1226 +*/
1.1227 +TBool CMMFFile::CanCreateSourceBuffer()
1.1228 + {
1.1229 + return EFalse ;
1.1230 + }
1.1231 +
1.1232 +/**
1.1233 +Creates a source buffer.
1.1234 +
1.1235 +@param aMediaId
1.1236 + The Media ID.
1.1237 +@param aReference
1.1238 + A boolean indicating if MDataSource owns the buffer. ETrue if it does, EFalse if the caller
1.1239 + owns the buffer.
1.1240 +
1.1241 +@return NULL as a CMMFFile cannot create it's own buffer
1.1242 +*/
1.1243 +CMMFBuffer* CMMFFile::CreateSourceBufferL( TMediaId /*aMediaId*/ , TBool& /*aReference*/)
1.1244 + {
1.1245 + User::Leave(KErrNotSupported);
1.1246 + return NULL ;
1.1247 + }
1.1248 +
1.1249 +/**
1.1250 +CMMFFile as a sink is always passive so this function is not supported.
1.1251 +
1.1252 +@param aBuffer
1.1253 + The buffer.
1.1254 +*/
1.1255 +void CMMFFile::BufferFilledL(CMMFBuffer* /* aBuffer */)
1.1256 + {
1.1257 + Panic(EMMFFilePanicBufferFilledLNotSupported);
1.1258 + }
1.1259 +
1.1260 +/**
1.1261 +Tests whether a sink buffer can be created.
1.1262 +
1.1263 +@return A boolean indicating if the sink buffer can be created. EFalse if CMMFFile cannot create
1.1264 + it's own buffer
1.1265 +*/
1.1266 +TBool CMMFFile::CanCreateSinkBuffer()
1.1267 + {
1.1268 + return EFalse ;
1.1269 + }
1.1270 +
1.1271 +/**
1.1272 +Creates a sink buffer.
1.1273 +
1.1274 +@param aMediaId
1.1275 + The Media ID.
1.1276 +@param aReference
1.1277 + A boolean indicating if MDataSource owns the buffer. ETrue if MDataSource owns the buffer,
1.1278 + EFalse if the caller owns the buffer.
1.1279 +
1.1280 +@return NULL as a CMMFFile cannot create it's own buffer
1.1281 +*/
1.1282 +CMMFBuffer* CMMFFile::CreateSinkBufferL(TMediaId /*aMediaId*/ , TBool& /*aReference*/)
1.1283 + {
1.1284 + User::Leave(KErrNotSupported);
1.1285 + return NULL ;
1.1286 + }
1.1287 +
1.1288 +/**
1.1289 +Primes the source.
1.1290 +
1.1291 +When used as a source, the file prime opens the file as read only.
1.1292 +*/
1.1293 +void CMMFFile::SourcePrimeL()
1.1294 + {
1.1295 + // don't reopen file if already open
1.1296 + if (!iFile)
1.1297 + {
1.1298 + if (iFileHandle)
1.1299 + {
1.1300 + iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI);
1.1301 + }
1.1302 + else
1.1303 + {
1.1304 + // Open for read-only access
1.1305 + iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareReadersOnly, iCAFParameters->iEnableUI);
1.1306 + }
1.1307 + }
1.1308 + }
1.1309 +
1.1310 +/**
1.1311 +Primes the sink.
1.1312 +
1.1313 +When used as a sink, the file prime opens the file for read/write access.
1.1314 +*/
1.1315 +void CMMFFile::SinkPrimeL()
1.1316 + {
1.1317 + // don't reopen file if already open
1.1318 + if (!iFile)
1.1319 + {
1.1320 + if (iFileHandle)
1.1321 + iFile = CF32File::NewL(iHandle);
1.1322 + else
1.1323 + iFile = CF32File::NewL(iFsSession, iFullFileName, EFileRead | EFileWrite);
1.1324 + }
1.1325 + iSinkNotStopped = ETrue;
1.1326 + }
1.1327 +
1.1328 +/**
1.1329 +Stops the file source. When stopping close the file. If the source is a file handle, the position is reset, but the
1.1330 +file handle remains open.
1.1331 +*/
1.1332 +void CMMFFile::SourceStopL()
1.1333 + {
1.1334 + TInt pos = 0;
1.1335 +
1.1336 + CancelRequests();
1.1337 +
1.1338 + // It is possible the file could have disappeared at this point (MMC/SD Card)
1.1339 + //
1.1340 + if (!iFile)
1.1341 + {
1.1342 + iPosition=pos;
1.1343 + return;
1.1344 + }
1.1345 +
1.1346 + if (!iFileHandle && !iFile->IsProtected())
1.1347 + {
1.1348 + delete iFile;
1.1349 + iFile = NULL;
1.1350 + iFileSize = -1;
1.1351 + }
1.1352 + else
1.1353 + {
1.1354 + User::LeaveIfError(iFile->Seek(ESeekStart, pos));
1.1355 + }
1.1356 + iPosition=pos;
1.1357 + }
1.1358 +
1.1359 +/**
1.1360 +Stops the file sink.
1.1361 +
1.1362 +When stopping close the file. When the file sink is a file handle, the position is reset, but the file handle
1.1363 +remains open
1.1364 +*/
1.1365 +void CMMFFile::SinkStopL()
1.1366 + {
1.1367 + iFileSize = -1;
1.1368 + iPosition=0;
1.1369 +
1.1370 + CancelRequests();
1.1371 + iSinkNotStopped = EFalse;
1.1372 + if (!iFileHandle)
1.1373 + {
1.1374 + delete iFile;
1.1375 + iFile = NULL;
1.1376 + }
1.1377 + else
1.1378 + {
1.1379 + TInt pos = 0;
1.1380 + User::LeaveIfError(iFile->Seek(ESeekStart, pos));
1.1381 + }
1.1382 + }
1.1383 +
1.1384 +/**
1.1385 +Pauses the file source
1.1386 +*/
1.1387 +void CMMFFile::SourcePauseL()
1.1388 + {
1.1389 + CancelRequests();
1.1390 + }
1.1391 +
1.1392 +/**
1.1393 +Returns a boolean indicating if the sink has been stopped.
1.1394 +
1.1395 +@return A boolean indicating if the sink has stopped.
1.1396 + */
1.1397 +TBool CMMFFile::SinkStopped()
1.1398 + {
1.1399 + if(iSinkNotStopped == EFalse)
1.1400 + return ETrue;
1.1401 + else
1.1402 + return EFalse;
1.1403 + }
1.1404 +
1.1405 +/**
1.1406 +Evaluates a given intent against the rights associated with the file.
1.1407 +
1.1408 +The rights are not updated by this function call.
1.1409 +
1.1410 +@param aIntent
1.1411 + The intent to evaluate.
1.1412 +
1.1413 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
1.1414 + another of the system-wide error codes.
1.1415 +*/
1.1416 +TInt CMMFFile::EvaluateIntent(ContentAccess::TIntent aIntent) const
1.1417 + {
1.1418 + if (iFile==NULL)
1.1419 + {
1.1420 + return KErrNotReady;
1.1421 + }
1.1422 +
1.1423 + return iFile->EvaluateIntent(aIntent);
1.1424 + }
1.1425 +
1.1426 +/**
1.1427 +Evaluates and executes a given intent against the rights associated with the file.
1.1428 +
1.1429 +The rights object is updated after calling this function.
1.1430 +
1.1431 +@param aIntent
1.1432 + The intent to evaluate.
1.1433 +
1.1434 +@return An error code indicating if the function call was successful. KErrNone on success, otherwise
1.1435 + another of the system-wide error codes.
1.1436 +*/
1.1437 +TInt CMMFFile::ExecuteIntent(ContentAccess::TIntent aIntent)
1.1438 + {
1.1439 + if (iFile==NULL)
1.1440 + {
1.1441 + return KErrNotReady;
1.1442 + }
1.1443 +
1.1444 + return iFile->ExecuteIntent(aIntent);
1.1445 + }
1.1446 +
1.1447 +/**
1.1448 +Returns whether the file is protected.
1.1449 +
1.1450 +@return A boolean indicating if the file is protected. ETrue if the file is protected.
1.1451 +*/
1.1452 +TBool CMMFFile::IsProtectedL() const
1.1453 + {
1.1454 + if (iFile==NULL)
1.1455 + {
1.1456 + User::Leave(KErrNotReady);
1.1457 + }
1.1458 +
1.1459 + return iFile->IsProtected();
1.1460 + }
1.1461 +
1.1462 +TInt CMMFFile::SetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
1.1463 + {
1.1464 + if (iFile==NULL)
1.1465 + {
1.1466 + return KErrNotReady;
1.1467 + }
1.1468 +
1.1469 + return iFile->SetAgentProperty(aProperty, aValue);
1.1470 + }
1.1471 +
1.1472 +/*
1.1473 + * Returns ETrue if the request can safely be deleted.
1.1474 + */
1.1475 +TBool CReadWriteRequest::Completed()
1.1476 + {
1.1477 + return iCompleted ;
1.1478 + }
1.1479 +
1.1480 +/*
1.1481 + * Returns the data member of CMMFDataBuffer or CMMFTransferBuffer (as TPtr8)
1.1482 + *
1.1483 + */
1.1484 +TDes8& CReadWriteRequest::BufferDes()
1.1485 + {
1.1486 + if(iTransferBufferCopy)
1.1487 + return iTransferBufferCopy->Des();
1.1488 + else
1.1489 + {
1.1490 + //reset iBufferDes in case iBuffer has changed...
1.1491 + iBufferDes = &(STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data());
1.1492 + return *iBufferDes;
1.1493 + }
1.1494 + }
1.1495 +
1.1496 +const TDesC8& CReadWriteRequest::BufferDesC()
1.1497 + {
1.1498 + if(iTransferBufferCopy)
1.1499 + return iTransferBufferCopy->Des();
1.1500 + else
1.1501 + return BufferDes();
1.1502 + }
1.1503 +
1.1504 +
1.1505 +/*
1.1506 + * Destructor.
1.1507 + */
1.1508 +CReadWriteRequest::~CReadWriteRequest()
1.1509 + {
1.1510 + Cancel();
1.1511 + if(iTransferBufferCopy)
1.1512 + iTransferBufferCopy->SetInUse(EFalse);
1.1513 + }
1.1514 +
1.1515 +/*
1.1516 + * Allows owning class access to SetActive()
1.1517 + */
1.1518 +void CReadWriteRequest::SetActive()
1.1519 + {
1.1520 + CActive::SetActive() ;
1.1521 + }
1.1522 +
1.1523 +/*
1.1524 + * For the moment at least... Canceled requests may be deleted
1.1525 + */
1.1526 +void CReadWriteRequest::DoCancel()
1.1527 + {
1.1528 + iCompleted = ETrue ;
1.1529 + }
1.1530 +
1.1531 +/*
1.1532 + * Called when errors in RunL force Leave. For the moment just mark the request deletable
1.1533 + */
1.1534 +TInt CReadWriteRequest::RunError( TInt aError )
1.1535 + {
1.1536 + //RunL can leave.
1.1537 + iCompleted = ETrue ;
1.1538 + iError = aError; //keep this error internally for now
1.1539 + return KErrNone ;
1.1540 + }
1.1541 +
1.1542 +/*
1.1543 + * On completion of read request call back to the MDataSink
1.1544 + */
1.1545 +void CReadRequest::RunL()
1.1546 + {
1.1547 + if (iStatus != KErrNone)
1.1548 + {
1.1549 + TMMFEvent event(KMMFErrorCategoryControllerGeneralError, iStatus.Int());
1.1550 + iEventHandler->SendEventToClient(event);
1.1551 + }
1.1552 + else
1.1553 + {
1.1554 + //Copy the data from the normal buffer into the Transfer buffer
1.1555 + if(iTransferBufferCopy)
1.1556 + {
1.1557 + //must specify the size here as the dest may be smaller than the source.
1.1558 + TDes8& destDesc = STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data();
1.1559 + destDesc.Copy(iTransferBufferCopy->Des().Left(destDesc.MaxLength()));
1.1560 +
1.1561 + iTransferBufferCopy->SetInUse(EFalse);
1.1562 + }
1.1563 +
1.1564 + // removed checking EOF from here, it should be checked in CMMFFile
1.1565 +
1.1566 + REINTERPRET_CAST(MDataSink*, iSinkOrSource)->BufferFilledL(iBuffer) ; // callback to MDataSource/Sink
1.1567 + }
1.1568 +
1.1569 + iCompleted = ETrue ;
1.1570 + }
1.1571 +
1.1572 +/*
1.1573 + * On completion of write request call back to the MDataSource
1.1574 + */
1.1575 +void CWriteRequest::RunL()
1.1576 + {
1.1577 + if(iTransferBufferCopy)
1.1578 + iTransferBufferCopy->SetInUse(EFalse);
1.1579 +
1.1580 + if (iStatus != KErrNone)
1.1581 + {
1.1582 + TMMFEvent event(KMMFErrorCategoryControllerGeneralError, iStatus.Int());
1.1583 + iEventHandler->SendEventToClient(event);
1.1584 + }
1.1585 + else
1.1586 + REINTERPRET_CAST(MDataSource*, iSinkOrSource)->BufferEmptiedL(iBuffer) ; // callback to MDataSource/Sink
1.1587 +
1.1588 + iCompleted = ETrue ;
1.1589 + }
1.1590 +
1.1591 +CMMFFile::CMMFFileAsyncEventHandler::CMMFFileAsyncEventHandler(CMMFFile* aParent)
1.1592 + {
1.1593 + iParent = aParent;
1.1594 + }
1.1595 +
1.1596 +CMMFFile::CMMFFileAsyncEventHandler::~CMMFFileAsyncEventHandler()
1.1597 + {
1.1598 + }
1.1599 +
1.1600 +TInt CMMFFile::CMMFFileAsyncEventHandler::SendEventToClient(const TMMFEvent& aEvent)
1.1601 + {
1.1602 + if(aEvent.iErrorCode == KErrNotReady)//i.e. MMC removed while recording
1.1603 + {
1.1604 + TRAPD(err, iParent->SinkStopL() );
1.1605 + if (err != KErrNone)
1.1606 + {
1.1607 + return err;
1.1608 + }
1.1609 + }
1.1610 + return iParent->iEventHandler->SendEventToClient(aEvent);
1.1611 + }
1.1612 +
1.1613 +/**
1.1614 +Returns access to internal CData property
1.1615 +
1.1616 +@param aData
1.1617 + On return, set to the internal CData property used to access file for reading.
1.1618 +
1.1619 +Returns:
1.1620 + * KErrNotReady if the file is not open/data object has not been created.
1.1621 + * KErrNotSupported if not supported (e.g. on data sink)
1.1622 +
1.1623 +@return Standard error code
1.1624 +*/
1.1625 +TInt CMMFFile::Data(ContentAccess::CData*& aData)
1.1626 + {
1.1627 + if (!iFile)
1.1628 + {
1.1629 + return KErrNotReady;
1.1630 + }
1.1631 + else
1.1632 + {
1.1633 + return iFile->Data(aData);
1.1634 + }
1.1635 + }
1.1636 +