Update contrib.
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
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"
26 void Panic(TMMFFilePanicCode aPanicCode)
28 _LIT(KMMFFilePanicCategory, "MMFFile");
29 User::Panic(KMMFFilePanicCategory, aPanicCode);
33 * Constructs a CTransferBufferCopy
35 * @return CTransferBufferCopy*
37 CTransferBufferCopy* CTransferBufferCopy::NewL(TInt aMaxLength)
39 CTransferBufferCopy* self = new (ELeave) CTransferBufferCopy(aMaxLength);
40 CleanupStack::PushL(self);
42 CleanupStack::Pop(self);
47 * Second phase constructor for CTransferBufferCopy
51 void CTransferBufferCopy::ConstructL()
53 iBuffer = static_cast<TUint8*>(User::AllocL(iMaxLength));
54 iBufferDes.Set(iBuffer,0,iMaxLength);
71 delete iMmfFileEventHandler;
72 delete iCAFParameters;
74 // Get rid of everything in RArray's & close them.
75 iRequests.ResetAndDestroy();
76 iTransferBufferCopies.ResetAndDestroy();
80 Protected constructor.
82 The default implementation is empty.
84 CMMFFile::CMMFFile() : CMMFClip( KUidMmfFileSource, KUidMmfFileSink ), iFileSize(-1)
86 iSinkNotStopped = EFalse;
90 Constructs an CMMFFile MDataSource.
92 @return A pointer to the new CMMFFile data source.
94 MDataSource* CMMFFile::NewSourceL()
96 CMMFFile* self = new (ELeave) CMMFFile ;
97 return STATIC_CAST( MDataSource*, self ) ;
101 Constructs a CMMFFile MDataSink
103 @return A pointer to the new CMMFFile data sink.
105 MDataSink* CMMFFile::NewSinkL()
107 CMMFFile* self = new (ELeave) CMMFFile ;
108 return STATIC_CAST( MDataSink*, self ) ;
112 Perform source construction dependant on the source construction
113 initialisation data aInitData.
116 The TPckg<TMMFFileParams> descriptor package containing the file name and full path.
118 void CMMFFile::ConstructSourceL(const TDesC8& aInitData )
120 ConstructL(aInitData, ESourceMode);
124 Performs sink construction dependant on the sink construction
125 initialisation data aInitData.
128 The TPckg<TMMFFileParams> descriptor package containing the file name and full path.
130 void CMMFFile::ConstructSinkL(const TDesC8& aInitData)
132 ConstructL(aInitData, ESinkMode);
136 Protected constructor.
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.
143 If aInitData contains a TMMFFileHandleParams instead of TMMFFileParams, the source/sink is constructed from
144 the file handle provided by the caller
147 Initialisation data packaged in a TMMFFileParams or in a TMMFFileHandleParams (File Handle)
149 void CMMFFile::ConstructL(const TDesC8& aInitData,TMMFileMode aFileMode)
151 User::LeaveIfError(iFsSession.Connect());
152 #ifdef __IPC_V2_PRESENT__
153 // on IPCv2 we auto attach
154 User::LeaveIfError(iFsSession.ShareAuto());
156 // on IPCv1 we use explicit - more efficient
157 User::LeaveIfError(iFsSession.Share(RSessionBase::EExplicitAttach));
160 User::LeaveIfError(iFsSession.ShareProtected());
162 HBufC* filename = NULL;
164 iCAFParameters = new (ELeave) CCAFParameters;
165 TBool drmContent = EFalse;
166 RDesReadStream stream(aInitData);
167 CleanupClosePushL(stream);
169 TUid initUid = TUid::Uid(stream.ReadInt32L());
171 if (initUid == KMMFileHandleSourceUid)
173 TPckgBuf<RFile*> fileptr;
174 stream.ReadL(fileptr);
176 iHandle.Duplicate(*fileptr());
178 TInt length = stream.ReadInt32L();
181 iCAFParameters->iUniqueId = HBufC::NewL(length);
182 TPtr16 ptr = iCAFParameters->iUniqueId->Des();
183 stream.ReadL(ptr, length);
187 filename = HBufC::NewMaxLC(KMaxFileName);
188 TPtr ptr = filename->Des();
189 User::LeaveIfError(iHandle.FullName(ptr));
192 iCAFParameters->iEnableUI = stream.ReadInt32L();
195 else if (initUid == KMMFileSourceUid)
197 TInt length = stream.ReadInt32L();
198 filename = HBufC::NewMaxLC(length);
199 TPtr ptr = filename->Des();
200 stream.ReadL(ptr, length);
202 length = stream.ReadInt32L();
205 iCAFParameters->iUniqueId = HBufC::NewMaxL(length);
206 ptr.Set(iCAFParameters->iUniqueId->Des());
207 stream.ReadL(ptr, length);
210 iCAFParameters->iEnableUI = stream.ReadInt32L();
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);
219 if ((filename == NULL) && aInitData.Length() == sizeof(TMMFFileHandleParams))
221 TMMFFileHandleParams params;
222 TPckgC<TMMFFileHandleParams> config(params);
223 config.Set(aInitData);
227 if (params.iUid == KFileHandleUid)
229 User::LeaveIfError(iHandle.Duplicate(*params.iFile));
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));
234 ASSERT(filename == NULL);
235 filename = HBufC::NewMaxLC(KMaxFileName);
236 TPtr ptr = filename->Des();
237 User::LeaveIfError(iHandle.FullName(ptr));
241 if (filename == NULL) // do old case as last resort
243 TMMFFileParams params;
244 TPckgC<TMMFFileParams> config(params);
245 config.Set(aInitData);
248 filename = params.iPath.AllocLC();
251 ASSERT(filename != NULL);
254 User::LeaveIfError(parser.Set(*filename, NULL, NULL));
255 CleanupStack::PopAndDestroy(2, &stream); //filename, stream
256 if ( !( parser.NamePresent() ) && !( parser.ExtPresent() ) )
258 User::Leave( KErrBadName ) ;
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() ;
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)
275 iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI);
280 // Open for read-only access
282 iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareReadersOnly, iCAFParameters->iEnableUI);
290 @deprecated - Replaced by CMMFFile::Data()
292 Returns an RFile handle to the current file.
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
299 The file is not open.
301 @return A handle to the current file.
302 @see CMMFFile::Data()
304 RFile& CMMFFile::FileL()
307 User::Leave(KErrNotReady);
311 return iFile->FileL();
315 Returns the file name of the current file.
317 Note: This will give the wrong answer if the file is renamed!
319 @return The FileName (without extension).
321 const TDesC& CMMFFile::FileName() const
327 Returns the extension of the current file.
329 Note: This will give the wrong answer if the file is renamed!
331 @return The File Extension.
333 const TDesC& CMMFFile::Extension() const
339 Returns the path of the current file.
341 Note: This will give the wrong answer if the file is renamed!
343 @return The FilePath (without filename and extension)
345 const TDesC& CMMFFile::FilePath() const
351 Returns the drive on which the current file is located.
353 Note: This will give the wrong answer if the file is renamed!
355 @return The FileDrive (drive letter only, without path, filename and extension).
357 const TDesC& CMMFFile::FileDrive() const
363 Returns the full name of the current file.
365 Note: This will give the wrong answer if the file is renamed!
367 @return The file name (full filename including drive letter, without path, filename and extension).
369 const TFileName CMMFFile::FullName() const
371 return iFullFileName;
375 Returns the uniqueID associated with this content. If no uniqueID has been provided, a null
376 descriptor will be provided
380 const TDesC& CMMFFile::UniqueId() const
382 if (iCAFParameters->iUniqueId)
383 return *(iCAFParameters->iUniqueId);
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.
395 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
396 another of the system-wide error codes.
398 TInt CMMFFile::Delete()
400 TInt result = KErrNone;
408 result = iFsSession.Delete(iFullFileName);
417 result = iFile->SetSize(0);
428 The size of the file.
430 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
431 another of the system-wide error codes.
433 TInt CMMFFile::SetSize(TInt aSize)
437 TInt err = iFile->SetSize(aSize);
447 Obtains a CTransferBufferCopy from iTransferBufferCopies that is
448 at least as big as that required.
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.
456 @return A pointer to a valid CTransferBufferCopy.
458 CTransferBufferCopy* CMMFFile::ObtainCopyOfTransferBufferL(TInt aMaxLength)
460 //find a free transfer buffer copy of the right size
462 CTransferBufferCopy* transBufCopyToUse = NULL;
464 for(TInt cnt=0; cnt < iTransferBufferCopies.Count(); cnt++)
466 if(!iTransferBufferCopies[cnt]->InUse())
468 //record the first free entry, we may remove this
469 //if entries in iTransferBufferCopies > KAcceptableTransferBufferCopiesSize
473 if(iTransferBufferCopies[cnt]->MaxLength() >= aMaxLength)
475 transBufCopyToUse = iTransferBufferCopies[cnt];
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);
485 //If we failed to find a suitable entry, we need to create a new one
486 if(!transBufCopyToUse)
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) &&
494 (iTransferBufferCopies.Count() > KAcceptableTransferBufferCopiesSize))
496 delete iTransferBufferCopies[firstFree];
497 iTransferBufferCopies.Remove(firstFree);
499 transBufCopyToUse = CTransferBufferCopy::NewL(aMaxLength);
500 CleanupStack::PushL(transBufCopyToUse);
501 User::LeaveIfError(iTransferBufferCopies.Insert(transBufCopyToUse,firstFree));
508 if(iTransferBufferCopies.Count() > KMaximumTransferBufferCopiesSize)
510 User::Panic(_L("iTransferBufferCopies grew too large in CMMFFile"),KErrTooBig);
514 transBufCopyToUse = CTransferBufferCopy::NewL(aMaxLength);
515 CleanupStack::PushL(transBufCopyToUse);
516 User::LeaveIfError(iTransferBufferCopies.Append(transBufCopyToUse));
522 return transBufCopyToUse;
528 Loads aBuffer from iFile.
530 The file must already be open for reading. File read is asynchronous. CReadRequest is created to
531 respond to completion.
534 The buffer to be filled from the file.
536 The data sink consumer of the buffer.
538 void CMMFFile::FillBufferL( CMMFBuffer* aBuffer, MDataSink* aConsumer, TMediaId /*aMediaId*/ )
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);
545 if (!iFile || (iMmfFileEventHandler == NULL))
546 User::Leave(KErrNotReady);
548 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
550 CTransferBufferCopy* transBufCopy = NULL;
551 CReadRequest* request = NULL;
553 TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
556 if(aBuffer->RequestSize())
557 requestSize = aBuffer->RequestSize();
559 requestSize = aBufferDes.MaxLength();
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()))
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);
572 request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, iPosition, Size(), iMmfFileEventHandler);
575 CleanupStack::PushL( request );
577 StoreRequestL(request); // transfers ownership
578 CleanupStack::Pop() ; // request
580 iFile->Read(request->BufferDes(), requestSize, request->iStatus);
581 iPosition += requestSize;
583 if (iPosition >= iFileSize)
585 aBuffer->SetLastBuffer(ETrue);
588 request->SetActive();
590 else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
591 User::Leave( KErrNotSupported ) ;
595 Empties aBuffer into iFile. The file must be already open for writing.
598 The buffer to be written to the file.
600 The data source supplier of the buffer.
602 void CMMFFile::EmptyBufferL( CMMFBuffer* aBuffer, MDataSource* aSupplier, TMediaId /*aMediaId*/ )
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);
609 if (!iFile || (iMmfFileEventHandler == NULL))
610 User::Leave(KErrNotReady);
612 CTransferBufferCopy* transBufCopy = NULL;
614 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
616 CWriteRequest* request = NULL;
617 TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
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()))
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());
628 //Copy the data into the buffer we will send to the file server
629 transBufCopy->Des().Copy(aBufferDes);
631 request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, transBufCopy, iMmfFileEventHandler);
635 request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, iMmfFileEventHandler);
638 CleanupStack::PushL( request );
640 StoreRequestL(request); // transfers ownership
641 CleanupStack::Pop(); // request
643 iFile->Write(request->BufferDes(), request->BufferDes().Length(), request->iStatus);
644 request->SetActive();
646 else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
648 User::Leave( KErrNotSupported ) ;
653 Loads aLength number of bytes into aBuffer from specified point in iFile.
656 The number of bytes to be read into buffer.
658 The buffer to be filled from the file.
660 The offset into the file at which to start reading.
662 The data sink consumer of the buffer.
664 void CMMFFile::ReadBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer)
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);
671 if (!iFile || (iMmfFileEventHandler == NULL))
672 User::Leave(KErrNotReady);
674 CTransferBufferCopy* transBufCopy = NULL;
676 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
678 CReadRequest* request = NULL;
679 TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
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()))
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());
690 request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, transBufCopy, aPosition, Size(), iMmfFileEventHandler);
694 request = new(ELeave) CReadRequest(STATIC_CAST(TAny*, aConsumer), aBuffer, aPosition, Size(), iMmfFileEventHandler);
697 CleanupStack::PushL( request );
699 StoreRequestL(request) ; //transfers ownership
700 CleanupStack::Pop() ; //request
702 TInt err = iFile->Read(aPosition, request->BufferDes(), aLength, request->iStatus);
703 if (err == KErrCANotSupported)
706 if (aPosition != iPosition)
708 err = iFile->Seek(ESeekStart, aPosition);
712 iFile->Read(request->BufferDes(), aLength, request->iStatus);
718 TRequestStatus* status = &request->iStatus;
719 User::RequestComplete(status, err);
722 iPosition = aPosition + aLength;
724 if (iPosition >= iFileSize)
726 aBuffer->SetLastBuffer(ETrue);
729 request->SetActive();
731 else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
732 User::Leave( KErrNotSupported ) ;
737 Loads aBuffer from specified point in iFile.
739 The file must already be open for reading.
742 The buffer to be filled from the file.
744 The offset into file at which to start reading.
746 The data sink consumer of the buffer.
748 void CMMFFile::ReadBufferL(CMMFBuffer* aBuffer, TInt aPosition, MDataSink* aConsumer)
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);
755 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
758 if(aBuffer->RequestSize())
759 requestSize = aBuffer->RequestSize();
761 requestSize = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data().MaxLength();
763 ReadBufferL(requestSize, aBuffer, aPosition, aConsumer);
765 else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
766 User::Leave(KErrNotSupported);
771 Loads aBuffer from specified point in iFile. Note that this is a synchronous read.
774 The buffer to be filled from the file.
776 The offset into file at which to start reading.
778 void CMMFFile::ReadBufferL( CMMFBuffer* aBuffer, TInt aPosition)
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);
786 User::Leave(KErrNotReady);
788 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
790 TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
793 if(aBuffer->RequestSize())
794 requestSize = aBuffer->RequestSize();
796 requestSize = aBufferDes.MaxLength();
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()))
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());
806 User::LeaveIfError(iFile->Seek(ESeekStart, aPosition));
807 User::LeaveIfError(iFile->Read(transBufCopy->Des(), requestSize));
808 aBufferDes.Copy(transBufCopy->Des().Left(aBufferDes.MaxLength()));
812 User::LeaveIfError(iFile->Seek(ESeekStart, aPosition));
813 User::LeaveIfError(iFile->Read(aBufferDes, requestSize));
816 iPosition = aPosition + aBufferDes.Length();
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())
823 aBuffer->SetLastBuffer(ETrue);
826 else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
827 User::Leave(KErrNotSupported);
831 Empties aLength bytes from aBuffer into iFile at specified location.
834 The number of bytes to be emptied from buffer.
836 The data buffer containing bytes to be written.
838 The offset into file at which to start writing.
840 The data source to be notified when the write has been completed.
843 SinkPrimeL() and SinkThreadLogon() have not been called.
845 aLength<0 or aPosition<0 or aSupplier is NULL.
846 @leave KErrNotSupported
847 aBuffer is not a supported CMMFDataBuffer
849 void CMMFFile::WriteBufferL(TInt aLength, CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier)
851 if ((aLength<0) || (aPosition<0) || (aSupplier == NULL) || (aBuffer == NULL))
852 User::Leave(KErrArgument);
854 if (!iFile || (iMmfFileEventHandler == NULL))
855 User::Leave(KErrNotReady);
857 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
859 CWriteRequest* request = NULL;
860 TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
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()))
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());
870 transBufCopy->Des().Copy(aBufferDes);
872 request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, transBufCopy, iMmfFileEventHandler);
876 request = new(ELeave) CWriteRequest(STATIC_CAST(TAny*, aSupplier), aBuffer, iMmfFileEventHandler);
879 CleanupStack::PushL( request );
881 StoreRequestL(request); // transfers ownership
882 CleanupStack::Pop(); // request
884 User::LeaveIfError(iFile->Seek(ESeekStart, aPosition));
885 iFile->Write(request->BufferDes(), aLength, request->iStatus);
886 iFileSize = -1; //reset cached size
888 request->SetActive();
890 else // if (!CMMFBuffer::IsFileServerSafe(aBuffer->Type()))
892 //write bitmap to file
893 User::Leave(KErrNotSupported);
898 Empties aBuffer into iFile at the specified location.
901 The data buffer containing bytes to be written.
903 The offset into file at which to start writing.
905 The data source to be notified when the write has been completed.
908 SinkPrimeL() and SinkThreadLogon() have not been called.
911 @leave KErrNotSupported
912 The aBuffer is not of type KMMFDataBuffer.
914 void CMMFFile::WriteBufferL( CMMFBuffer* aBuffer, TInt aPosition, MDataSource* aSupplier)
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);
921 if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
923 TUint requestSize = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data().Length();
925 WriteBufferL(requestSize, aBuffer, aPosition, aSupplier);
927 else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
929 //write bitmap to file
930 User::Leave( KErrNotSupported ) ;
935 Empties aBuffer into iFile at specified location. Note that this is a synchronous write.
938 The data buffer containing bytes to be written.
940 The offset into file at which to start writing.
942 @return The error code from RFile.
944 void CMMFFile::WriteBufferL( CMMFBuffer* aBuffer, TInt aPosition )
946 if ((aPosition<0) || (aBuffer == NULL))
947 User::Leave(KErrArgument);
950 User::Leave(KErrNotReady);
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())))
959 TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
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());
965 transBufCopy->Des().Copy(aBufferDes);
966 err = iFile->Seek(ESeekStart, aPosition);
968 err = iFile->Write(transBufCopy->Des(),transBufCopy->Des().Length());
969 iFileSize = -1; //reset cached size
971 else if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
973 TDes8& aBufferDes = STATIC_CAST( CMMFDataBuffer*, aBuffer )->Data();
975 err = iFile->Seek(ESeekStart, aPosition);
977 err = iFile->Write(aBufferDes, aBufferDes.Length());
978 iFileSize = -1; //reset cached size
980 else // if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type()))
982 User::Leave(KErrNotSupported);
985 User::LeaveIfError(err);
989 Gets the number of free bytes in the device's file system.
991 @return The number of free bytes.
993 TInt64 CMMFFile::BytesFree()
995 TInt driveNumber = KDefaultDrive;
997 if (FileDrive().Length() > 0)
999 TChar driveLetter = FileDrive()[0];
1000 RFs::CharToDrive(driveLetter, driveNumber);
1003 TVolumeInfo volInfo;
1004 if (iFsSession.Volume(volInfo, driveNumber) == KErrNone)
1006 return volInfo.iFree;
1012 Returns the size of the file in bytes.
1014 Note: This is not the maximum length.
1016 @return The size of the file in bytes.
1018 TInt CMMFFile::Size()
1021 TInt err = KErrNone;
1022 TBool fileOpened = EFalse;
1029 // Open the file. We only need read access, so SourcePrimeL will open the file with read flag
1030 TRAP(err, SourcePrimeL());
1034 if (err == KErrNone)
1036 __ASSERT_DEBUG(iFile != NULL,Panic(EMMFFileHandleNULL));
1037 err = iFile->Size(size);
1042 iFileSize = -1; //reset cached size
1045 iFileSize = size; //cache the filesize
1049 __ASSERT_DEBUG(iFile != NULL,Panic(EMMFFileHandleNULL));
1059 Source thread logon.
1061 Shares fsSession between threads
1063 @param aEventHandler
1064 This is an MAsyncEventHandler to handle asynchronous events that occur during the
1065 transfer of multimedia data.
1067 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
1068 another of the system-wide error codes.
1070 TInt CMMFFile::SourceThreadLogon(MAsyncEventHandler& aEventHandler)
1072 iEventHandler = &aEventHandler;
1073 if(!iMmfFileEventHandler)
1075 iMmfFileEventHandler = new CMMFFileAsyncEventHandler(this);
1076 if(!iMmfFileEventHandler)
1077 return KErrNoMemory;
1079 #ifdef __IPC_V2_PRESENT__
1080 return KErrNone; // nothing to do
1082 return iFsSession.Attach();
1083 #endif // __HIDE_IPC_V1__
1087 Logs off source thread.
1089 void CMMFFile::SourceThreadLogoff()
1091 delete iMmfFileEventHandler;
1092 iMmfFileEventHandler = NULL;
1093 iEventHandler = NULL;
1100 Shares fsSession between threads.
1102 @param aEventHandler
1103 This is an MAsyncEventHandler to handle asynchronous events that occur during the
1104 transfer of multimedia data.
1106 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
1107 another of the system-wide error codes.
1109 TInt CMMFFile::SinkThreadLogon(MAsyncEventHandler& aEventHandler)
1111 iEventHandler = &aEventHandler;
1112 if(!iMmfFileEventHandler)
1114 iMmfFileEventHandler = new CMMFFileAsyncEventHandler(this);
1115 if(!iMmfFileEventHandler)
1116 return KErrNoMemory;
1118 #ifdef __IPC_V2_PRESENT__
1121 return iFsSession.Attach();
1122 #endif // __HIDE_IPC_V1__
1126 Sink thread log off.
1128 void CMMFFile::SinkThreadLogoff()
1130 delete iMmfFileEventHandler;
1131 iMmfFileEventHandler = NULL;
1132 iEventHandler = NULL;
1136 Stores a request in an array.
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.
1143 The request to store.
1145 void CMMFFile::StoreRequestL( CReadWriteRequest* aRequest )
1147 // add aRequest to iRequests
1148 User::LeaveIfError( iRequests.Append( aRequest ) ) ;
1150 // Clear out any completed requests
1151 for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ )
1153 if (iRequests[ii]->Completed())
1155 CReadWriteRequest* request = iRequests[ii];
1158 iRequests.Remove(ii);
1166 Cancels outstanding requests.
1168 CReadWriteRequests are stored in the array iRequests.
1169 This function cancels any outstanding requests and removes them
1172 void CMMFFile::CancelRequests()
1174 // Clear out any completed requests
1175 for ( TInt ii = 0 ; ii < iRequests.Count() ; ii++ )
1177 CReadWriteRequest* request = iRequests[ii];
1179 iRequests.Remove(ii);
1187 Returns the data type as a fourCC code of CMMFFile as a data source.
1189 @return The data type fourCC code.
1191 TFourCC CMMFFile::SourceDataTypeCode(TMediaId /*aMediaId*/)
1193 return iSourceFourCC ;
1197 Returns the data type as a fourCC code of CMMFFile as a data sink.
1199 @return The data type fourCC code
1201 TFourCC CMMFFile::SinkDataTypeCode(TMediaId /*aMediaId*/)
1203 return iSinkFourCC ;
1208 CMMFFile as a source is always passive so this function is not supported.
1213 void CMMFFile::BufferEmptiedL(CMMFBuffer* /* aBuffer */)
1215 Panic(EMMFFilePanicBufferEmptiedLNotSupported);
1219 Tests whether a source buffer can be created.
1221 @return A boolean indicating if if CMMFFile can create its own buffer. EFalse if CMMFFile cannot
1222 create it's own buffer.
1224 TBool CMMFFile::CanCreateSourceBuffer()
1230 Creates a source buffer.
1235 A boolean indicating if MDataSource owns the buffer. ETrue if it does, EFalse if the caller
1238 @return NULL as a CMMFFile cannot create it's own buffer
1240 CMMFBuffer* CMMFFile::CreateSourceBufferL( TMediaId /*aMediaId*/ , TBool& /*aReference*/)
1242 User::Leave(KErrNotSupported);
1247 CMMFFile as a sink is always passive so this function is not supported.
1252 void CMMFFile::BufferFilledL(CMMFBuffer* /* aBuffer */)
1254 Panic(EMMFFilePanicBufferFilledLNotSupported);
1258 Tests whether a sink buffer can be created.
1260 @return A boolean indicating if the sink buffer can be created. EFalse if CMMFFile cannot create
1263 TBool CMMFFile::CanCreateSinkBuffer()
1269 Creates a sink buffer.
1274 A boolean indicating if MDataSource owns the buffer. ETrue if MDataSource owns the buffer,
1275 EFalse if the caller owns the buffer.
1277 @return NULL as a CMMFFile cannot create it's own buffer
1279 CMMFBuffer* CMMFFile::CreateSinkBufferL(TMediaId /*aMediaId*/ , TBool& /*aReference*/)
1281 User::Leave(KErrNotSupported);
1288 When used as a source, the file prime opens the file as read only.
1290 void CMMFFile::SourcePrimeL()
1292 // don't reopen file if already open
1297 iFile = CContentFile::NewL(iHandle, UniqueId(), iCAFParameters->iEnableUI);
1301 // Open for read-only access
1302 iFile = CContentFile::NewL(iFsSession, iFullFileName, UniqueId(), EFileShareReadersOnly, iCAFParameters->iEnableUI);
1310 When used as a sink, the file prime opens the file for read/write access.
1312 void CMMFFile::SinkPrimeL()
1314 // don't reopen file if already open
1318 iFile = CF32File::NewL(iHandle);
1320 iFile = CF32File::NewL(iFsSession, iFullFileName, EFileRead | EFileWrite);
1322 iSinkNotStopped = ETrue;
1326 Stops the file source. When stopping close the file. If the source is a file handle, the position is reset, but the
1327 file handle remains open.
1329 void CMMFFile::SourceStopL()
1335 // It is possible the file could have disappeared at this point (MMC/SD Card)
1343 if (!iFileHandle && !iFile->IsProtected())
1351 User::LeaveIfError(iFile->Seek(ESeekStart, pos));
1357 Stops the file sink.
1359 When stopping close the file. When the file sink is a file handle, the position is reset, but the file handle
1362 void CMMFFile::SinkStopL()
1368 iSinkNotStopped = EFalse;
1377 User::LeaveIfError(iFile->Seek(ESeekStart, pos));
1382 Pauses the file source
1384 void CMMFFile::SourcePauseL()
1390 Returns a boolean indicating if the sink has been stopped.
1392 @return A boolean indicating if the sink has stopped.
1394 TBool CMMFFile::SinkStopped()
1396 if(iSinkNotStopped == EFalse)
1403 Evaluates a given intent against the rights associated with the file.
1405 The rights are not updated by this function call.
1408 The intent to evaluate.
1410 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
1411 another of the system-wide error codes.
1413 TInt CMMFFile::EvaluateIntent(ContentAccess::TIntent aIntent) const
1417 return KErrNotReady;
1420 return iFile->EvaluateIntent(aIntent);
1424 Evaluates and executes a given intent against the rights associated with the file.
1426 The rights object is updated after calling this function.
1429 The intent to evaluate.
1431 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
1432 another of the system-wide error codes.
1434 TInt CMMFFile::ExecuteIntent(ContentAccess::TIntent aIntent)
1438 return KErrNotReady;
1441 return iFile->ExecuteIntent(aIntent);
1445 Returns whether the file is protected.
1447 @return A boolean indicating if the file is protected. ETrue if the file is protected.
1449 TBool CMMFFile::IsProtectedL() const
1453 User::Leave(KErrNotReady);
1456 return iFile->IsProtected();
1459 TInt CMMFFile::SetAgentProperty(ContentAccess::TAgentProperty aProperty, TInt aValue)
1463 return KErrNotReady;
1466 return iFile->SetAgentProperty(aProperty, aValue);
1470 * Returns ETrue if the request can safely be deleted.
1472 TBool CReadWriteRequest::Completed()
1478 * Returns the data member of CMMFDataBuffer or CMMFTransferBuffer (as TPtr8)
1481 TDes8& CReadWriteRequest::BufferDes()
1483 if(iTransferBufferCopy)
1484 return iTransferBufferCopy->Des();
1487 //reset iBufferDes in case iBuffer has changed...
1488 iBufferDes = &(STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data());
1493 const TDesC8& CReadWriteRequest::BufferDesC()
1495 if(iTransferBufferCopy)
1496 return iTransferBufferCopy->Des();
1505 CReadWriteRequest::~CReadWriteRequest()
1508 if(iTransferBufferCopy)
1509 iTransferBufferCopy->SetInUse(EFalse);
1513 * Allows owning class access to SetActive()
1515 void CReadWriteRequest::SetActive()
1517 CActive::SetActive() ;
1521 * For the moment at least... Canceled requests may be deleted
1523 void CReadWriteRequest::DoCancel()
1525 iCompleted = ETrue ;
1529 * Called when errors in RunL force Leave. For the moment just mark the request deletable
1531 TInt CReadWriteRequest::RunError( TInt aError )
1534 iCompleted = ETrue ;
1535 iError = aError; //keep this error internally for now
1540 * On completion of read request call back to the MDataSink
1542 void CReadRequest::RunL()
1544 if (iStatus != KErrNone)
1546 TMMFEvent event(KMMFErrorCategoryControllerGeneralError, iStatus.Int());
1547 iEventHandler->SendEventToClient(event);
1551 //Copy the data from the normal buffer into the Transfer buffer
1552 if(iTransferBufferCopy)
1554 //must specify the size here as the dest may be smaller than the source.
1555 TDes8& destDesc = STATIC_CAST(CMMFDataBuffer*, iBuffer)->Data();
1556 destDesc.Copy(iTransferBufferCopy->Des().Left(destDesc.MaxLength()));
1558 iTransferBufferCopy->SetInUse(EFalse);
1561 // removed checking EOF from here, it should be checked in CMMFFile
1563 REINTERPRET_CAST(MDataSink*, iSinkOrSource)->BufferFilledL(iBuffer) ; // callback to MDataSource/Sink
1566 iCompleted = ETrue ;
1570 * On completion of write request call back to the MDataSource
1572 void CWriteRequest::RunL()
1574 if(iTransferBufferCopy)
1575 iTransferBufferCopy->SetInUse(EFalse);
1577 if (iStatus != KErrNone)
1579 TMMFEvent event(KMMFErrorCategoryControllerGeneralError, iStatus.Int());
1580 iEventHandler->SendEventToClient(event);
1583 REINTERPRET_CAST(MDataSource*, iSinkOrSource)->BufferEmptiedL(iBuffer) ; // callback to MDataSource/Sink
1585 iCompleted = ETrue ;
1588 CMMFFile::CMMFFileAsyncEventHandler::CMMFFileAsyncEventHandler(CMMFFile* aParent)
1593 CMMFFile::CMMFFileAsyncEventHandler::~CMMFFileAsyncEventHandler()
1597 TInt CMMFFile::CMMFFileAsyncEventHandler::SendEventToClient(const TMMFEvent& aEvent)
1599 if(aEvent.iErrorCode == KErrNotReady)//i.e. MMC removed while recording
1601 TRAPD(err, iParent->SinkStopL() );
1602 if (err != KErrNone)
1607 return iParent->iEventHandler->SendEventToClient(aEvent);
1611 Returns access to internal CData property
1614 On return, set to the internal CData property used to access file for reading.
1617 * KErrNotReady if the file is not open/data object has not been created.
1618 * KErrNotSupported if not supported (e.g. on data sink)
1620 @return Standard error code
1622 TInt CMMFFile::Data(ContentAccess::CData*& aData)
1626 return KErrNotReady;
1630 return iFile->Data(aData);