--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmlibs/mmfw/Recogniser/src/mmruf.cpp Thu Oct 07 22:34:12 2010 +0100
@@ -0,0 +1,310 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "mmruf.h"
+#include <e32uid.h>
+
+#include "constants.h"
+#include "parsers.h"
+
+#ifdef _DEBUG
+_LIT(KRUFPanic, "MMRUF");
+static const TInt KReasonNoFunction = 1;
+#endif
+
+//
+// A table of recognised file formats.
+// It should be sorted in order of format popularity.
+//
+static const TSignature KSigs[] =
+ {
+ CUSTOM_SIG(KMimeAAC, TAACParser::DoRecognise),
+ CUSTOM_SIG(KMimeMP3, TMP3Parser::DoRecognise),
+ CUSTOM_SIG(KMimeMP4_V, TMPEG4Parser::DoRecognise),
+ CUSTOM_SIG(KMimeWMV, TASFParser::DoRecognise),
+ CUSTOM_SIG(KMimeMPEG2_V, TMPEG2Parser::DoRecognise),
+ CUSTOM_SIG(KMimeRM_V, TRMParser::DoRecognise),
+ CUSTOM_SIG(KMimeRAM, TRAMParser::DoRecognise),
+ CUSTOM_SIG(KMimeSDP, TSDPParser::DoRecognise),
+ CUSTOM_SIG(KMimeXPS, TXPSParser::DoRecognise),
+ HEADER_SIG(KMimeRA, KExtRA, KSigRA),
+ HEADER_SIG(KMimeAIFF, KExtAIFF_1, KSigAIFF),
+ HEADER_SIG(KMimeAIFF, KExtAIFF_2, KSigAIFF),
+ HEADER_SIG(KMimeAIFF, KExtAIFF_3, KSigAIFF),
+ HEADER_SIG(KMimeAMR, KExtAMR, KSigAMR_1),
+ HEADER_SIG(KMimeAMR, KExtAMR, KSigAMR_2),
+ HEADER_SIG(KMimeAMRWB, KExtAMRWB, KSigAMRWB_1),
+ HEADER_SIG(KMimeAMRWB, KExtAMRWB, KSigAMRWB_2),
+ HEADER_SIG(KMimeAU, KExtAU, KSigAU),
+ HEADER_SIG(KMimeAVI, KExtAVI, KSigAVI),
+ HEADER_SIG(KMimeDIVX, KExtDIVX, KSigDIVX_1),
+ HEADER_SIG(KMimeDIVX, KExtDIVX, KSigDIVX_2),
+ HEADER_SIG(KMimeDLS, KExtDLS, KSigDLS),
+ HEADER_SIG(KMimeFLAC, KExtFLAC_1, KSigFLAC),
+ HEADER_SIG(KMimeFLAC, KExtFLAC_2, KSigFLAC),
+ HEADER_SIG(KMimeGSM, KExtGSM, KSigGSM),
+ HEADER_SIG(KMimeM3U, KExtM3U, KSigM3U),
+ HEADER_SIG(KMimeMID, KExtMID, KSigMID),
+ HEADER_SIG(KMimeMLD, KExtMLD, KSigMLD),
+ HEADER_SIG(KMimeMMF, KExtMMF, KSigMMF),
+ HEADER_SIG(KMimeMXMF, KExtMXMF, KSigMXMF),
+ HEADER_SIG(KMimeOGG, KExtOGG, KSigOGG),
+ HEADER_SIG(KMimeBeatnikRMF, KExtBeatnikRMF, KSigBeatnikRMF),
+ HEADER_SIG(KMimeSMF, KExtSMF, KSigSMF),
+ HEADER_SIG(KMimeSND, KExtSND, KSigSND),
+ HEADER_SIG(KMimeWAV, KExtWAV, KSigWAV_1),
+ HEADER_SIG(KMimeWAV, KExtWAV, KSigWAV_2),
+ HEADER_SIG(KMimeXMF, KExtXMF, KSigXMF),
+ CUSTOM_SIG(KMimeMAT_V, TMatroskaParser::DoRecognise),
+ };
+
+static const TInt KDataTypesCount = sizeof(KSigs) / sizeof(TSignature);
+
+//
+// Map all combinations of [ext_match][header_match] to confidence levels.
+//
+static const TInt KResultToConfidence[] =
+ {
+ KConfNotRecognised,
+ KConfProbable,
+ KConfPossible,
+ KConfCertain
+ };
+
+//
+//
+//
+const TImplementationProxy ImplementationTable[] =
+ {
+ // UID taken from Multimedia's UID allocation table.
+ IMPLEMENTATION_PROXY_ENTRY(KRecogniserUID, CMMRUF::NewL)
+ };
+
+
+//
+//
+//
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
+ {
+ aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+ return ImplementationTable;
+ }
+
+
+//
+//
+//
+CMMRUF::CMMRUF()
+ : CApaDataRecognizerType(KMMRUFDLLUid, KRecogniserPriority)
+ {
+ iCountDataTypes = KDataTypesCount;
+ }
+
+
+//
+//
+//
+CMMRUF* CMMRUF::NewL()
+ {
+ return new(ELeave)CMMRUF();
+ }
+
+
+//
+//
+//
+CMMRUF::~CMMRUF()
+ {
+ }
+
+
+//
+//
+//
+TUint CMMRUF::PreferredBufSize()
+ {
+ return KPreferredBufSize;
+ }
+
+
+//
+// Required for CApaDataRecognizerType parent class.
+// It creates a mime-type string for the signature at aIndex.
+//
+TDataType CMMRUF::SupportedDataTypeL(TInt aIndex) const
+ {
+ if ((aIndex < 0) || (aIndex >= KDataTypesCount))
+ {
+ User::Leave(KErrArgument);
+ }
+
+ return SupportedDataTypeL(KSigs[aIndex].iMime);
+ }
+
+
+//
+//
+//
+TDataType CMMRUF::SupportedDataTypeL(const TText8* aMime) const
+ {
+ if (aMime == NULL)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ return TDataType(TPtrC8(aMime));
+ }
+
+
+//
+// Records the matched data type and the confidence.
+//
+void CMMRUF::SetDataTypeL(TInt aConfidence, const TText8* aMime)
+ {
+ iDataType = SupportedDataTypeL(aMime);
+ iConfidence = aConfidence;
+ }
+
+
+//
+// Utility function for matching file extensions.
+// Returns 1 if the extensions match, 0 otherwise.
+//
+TUint8 CMMRUF::MatchExtension(const TDesC& aFileExt, const TText* aKnownExt) const
+ {
+ if (aFileExt.Length() > 0)
+ {
+ return ((aFileExt.MatchF(TPtrC(aKnownExt)) != KErrNotFound) ? 1 : 0);
+ }
+
+ return 0;
+ }
+
+
+//
+// Utility function for matching known header data.
+// Returns 1 if the buffer contents match the header, 0 otherwise.
+//
+TUint8 CMMRUF::MatchHeader(const TDesC8& aBuffer, const TDesC8& aHeader) const
+ {
+ if (aBuffer.Length() > 0)
+ {
+ if (aHeader.Length() <= aBuffer.Length())
+ {
+ return ((aBuffer.Match(aHeader) != KErrNotFound) ? 1 : 0);
+ }
+ }
+
+ return 0;
+ }
+
+
+//
+// This function is called by AppArc when something needs recognising.
+//
+void CMMRUF::DoRecognizeL(const TDesC& aFileName, const TDesC8& aBuffer)
+ {
+ TMatch match;
+ RArray<TMatch> matches;
+ CleanupClosePushL(matches);
+
+ // If a handle to the file is available, AppArc prepends "::" to the
+ // aFileName parameter for some reason. This causes TParse to fail
+ // to get the file extension, so we have to fix it.
+ TPtrC fName(aFileName);
+ if (aFileName.Match(_L("::*")) == 0)
+ {
+ fName.Set(aFileName.Mid(2));
+ }
+
+ TParse parse;
+ User::LeaveIfError(parse.Set(fName, NULL, NULL));
+ const TPtrC& ext = parse.Ext();
+
+ RFile* pFile = FilePassedByHandleL();
+ CReader* pReader = (pFile ? CFileReader::NewLC(pFile) : CBufferReader::NewLC(aBuffer));
+
+ // The main recognition loop.
+ TBool certainMatch = EFalse;
+ for (TInt i = 0; (i < KDataTypesCount) && !certainMatch; i++)
+ {
+ // Reset the results for each iteration.
+ pReader->Reset();
+ match.Reset();
+
+ if (KSigs[i].iHeaderLen == 0)
+ {
+ // Call the custom recognition function.
+ // match contains the results.
+ __ASSERT_DEBUG(KSigs[i].iHeaderOrProc, User::Panic(KRUFPanic, KReasonNoFunction));
+ TCustomProc proc = (TCustomProc)(KSigs[i].iHeaderOrProc);
+ proc(ext, *pReader, match);
+ }
+ else
+ {
+ // This format has a known signature.
+ TPtrC8 header(_S8(KSigs[i].iHeaderOrProc), KSigs[i].iHeaderLen);
+
+ TUint8 sameHeader = MatchHeader(aBuffer, header);
+ TUint8 sameExt = MatchExtension(ext, KSigs[i].iExt);
+ TUint8 confIndex = MAKE_BYTE2(sameExt, sameHeader);
+
+ match.iConfidence = KResultToConfidence[confIndex];
+ match.iMime = KSigs[i].iMime;
+ }
+
+ // Evaluate the result.
+ switch (match.iConfidence)
+ {
+ case KConfNotRecognised:
+ continue;
+
+ case KConfCertain:
+ certainMatch = ETrue;
+ // Deliberate fall through to add match to array of matches.
+
+ case KConfProbable:
+ // Add it to the start of the array.
+ User::LeaveIfError(matches.Insert(TMatch(match), 0));
+ break;
+
+ case KConfPossible:
+ // Add it to the end of the array.
+ if (matches.Count() == 0)
+ {
+ User::LeaveIfError(matches.Append(TMatch(match)));
+ }
+ break;
+
+ default:
+ // Should never get here.
+ User::Leave(KErrArgument);
+ }
+ } // for (TInt i = 0; i < KDataTypesCount; i++)
+
+ // We've done looping.
+ if (matches.Count() > 0)
+ {
+ match = matches[0];
+ SetDataTypeL(match.iConfidence, match.iMime);
+ }
+
+ CleanupStack::PopAndDestroy(pReader);
+ CleanupStack::PopAndDestroy(&matches);
+ }
+
+
+
+