First public contribution.
1 // Copyright (c) 2006-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.
19 #include "constants.h"
23 _LIT(KRUFPanic, "MMRUF");
24 static const TInt KReasonNoFunction = 1;
28 // A table of recognised file formats.
29 // It should be sorted in order of format popularity.
31 static const TSignature KSigs[] =
33 CUSTOM_SIG(KMimeAAC, TAACParser::DoRecognise),
34 CUSTOM_SIG(KMimeMP3, TMP3Parser::DoRecognise),
35 CUSTOM_SIG(KMimeMP4_V, TMPEG4Parser::DoRecognise),
36 CUSTOM_SIG(KMimeWMV, TASFParser::DoRecognise),
37 CUSTOM_SIG(KMimeMPEG2_V, TMPEG2Parser::DoRecognise),
38 CUSTOM_SIG(KMimeRM_V, TRMParser::DoRecognise),
39 CUSTOM_SIG(KMimeRAM, TRAMParser::DoRecognise),
40 CUSTOM_SIG(KMimeSDP, TSDPParser::DoRecognise),
41 CUSTOM_SIG(KMimeXPS, TXPSParser::DoRecognise),
42 HEADER_SIG(KMimeRA, KExtRA, KSigRA),
43 HEADER_SIG(KMimeAIFF, KExtAIFF_1, KSigAIFF),
44 HEADER_SIG(KMimeAIFF, KExtAIFF_2, KSigAIFF),
45 HEADER_SIG(KMimeAIFF, KExtAIFF_3, KSigAIFF),
46 HEADER_SIG(KMimeAMR, KExtAMR, KSigAMR_1),
47 HEADER_SIG(KMimeAMR, KExtAMR, KSigAMR_2),
48 HEADER_SIG(KMimeAMRWB, KExtAMRWB, KSigAMRWB_1),
49 HEADER_SIG(KMimeAMRWB, KExtAMRWB, KSigAMRWB_2),
50 HEADER_SIG(KMimeAU, KExtAU, KSigAU),
51 HEADER_SIG(KMimeAVI, KExtAVI, KSigAVI),
52 HEADER_SIG(KMimeDIVX, KExtDIVX, KSigDIVX_1),
53 HEADER_SIG(KMimeDIVX, KExtDIVX, KSigDIVX_2),
54 HEADER_SIG(KMimeDLS, KExtDLS, KSigDLS),
55 HEADER_SIG(KMimeFLAC, KExtFLAC_1, KSigFLAC),
56 HEADER_SIG(KMimeFLAC, KExtFLAC_2, KSigFLAC),
57 HEADER_SIG(KMimeGSM, KExtGSM, KSigGSM),
58 HEADER_SIG(KMimeM3U, KExtM3U, KSigM3U),
59 HEADER_SIG(KMimeMID, KExtMID, KSigMID),
60 HEADER_SIG(KMimeMLD, KExtMLD, KSigMLD),
61 HEADER_SIG(KMimeMMF, KExtMMF, KSigMMF),
62 HEADER_SIG(KMimeMXMF, KExtMXMF, KSigMXMF),
63 HEADER_SIG(KMimeOGG, KExtOGG, KSigOGG),
64 HEADER_SIG(KMimeBeatnikRMF, KExtBeatnikRMF, KSigBeatnikRMF),
65 HEADER_SIG(KMimeSMF, KExtSMF, KSigSMF),
66 HEADER_SIG(KMimeSND, KExtSND, KSigSND),
67 HEADER_SIG(KMimeWAV, KExtWAV, KSigWAV_1),
68 HEADER_SIG(KMimeWAV, KExtWAV, KSigWAV_2),
69 HEADER_SIG(KMimeXMF, KExtXMF, KSigXMF),
70 CUSTOM_SIG(KMimeMAT_V, TMatroskaParser::DoRecognise),
73 static const TInt KDataTypesCount = sizeof(KSigs) / sizeof(TSignature);
76 // Map all combinations of [ext_match][header_match] to confidence levels.
78 static const TInt KResultToConfidence[] =
89 const TImplementationProxy ImplementationTable[] =
91 // UID taken from Multimedia's UID allocation table.
92 IMPLEMENTATION_PROXY_ENTRY(KRecogniserUID, CMMRUF::NewL)
99 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
101 aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
102 return ImplementationTable;
110 : CApaDataRecognizerType(KMMRUFDLLUid, KRecogniserPriority)
112 iCountDataTypes = KDataTypesCount;
119 CMMRUF* CMMRUF::NewL()
121 return new(ELeave)CMMRUF();
136 TUint CMMRUF::PreferredBufSize()
138 return KPreferredBufSize;
143 // Required for CApaDataRecognizerType parent class.
144 // It creates a mime-type string for the signature at aIndex.
146 TDataType CMMRUF::SupportedDataTypeL(TInt aIndex) const
148 if ((aIndex < 0) || (aIndex >= KDataTypesCount))
150 User::Leave(KErrArgument);
153 return SupportedDataTypeL(KSigs[aIndex].iMime);
160 TDataType CMMRUF::SupportedDataTypeL(const TText8* aMime) const
164 User::Leave(KErrArgument);
167 return TDataType(TPtrC8(aMime));
172 // Records the matched data type and the confidence.
174 void CMMRUF::SetDataTypeL(TInt aConfidence, const TText8* aMime)
176 iDataType = SupportedDataTypeL(aMime);
177 iConfidence = aConfidence;
182 // Utility function for matching file extensions.
183 // Returns 1 if the extensions match, 0 otherwise.
185 TUint8 CMMRUF::MatchExtension(const TDesC& aFileExt, const TText* aKnownExt) const
187 if (aFileExt.Length() > 0)
189 return ((aFileExt.MatchF(TPtrC(aKnownExt)) != KErrNotFound) ? 1 : 0);
197 // Utility function for matching known header data.
198 // Returns 1 if the buffer contents match the header, 0 otherwise.
200 TUint8 CMMRUF::MatchHeader(const TDesC8& aBuffer, const TDesC8& aHeader) const
202 if (aBuffer.Length() > 0)
204 if (aHeader.Length() <= aBuffer.Length())
206 return ((aBuffer.Match(aHeader) != KErrNotFound) ? 1 : 0);
215 // This function is called by AppArc when something needs recognising.
217 void CMMRUF::DoRecognizeL(const TDesC& aFileName, const TDesC8& aBuffer)
220 RArray<TMatch> matches;
221 CleanupClosePushL(matches);
223 // If a handle to the file is available, AppArc prepends "::" to the
224 // aFileName parameter for some reason. This causes TParse to fail
225 // to get the file extension, so we have to fix it.
226 TPtrC fName(aFileName);
227 if (aFileName.Match(_L("::*")) == 0)
229 fName.Set(aFileName.Mid(2));
233 User::LeaveIfError(parse.Set(fName, NULL, NULL));
234 const TPtrC& ext = parse.Ext();
236 RFile* pFile = FilePassedByHandleL();
237 CReader* pReader = (pFile ? CFileReader::NewLC(pFile) : CBufferReader::NewLC(aBuffer));
239 // The main recognition loop.
240 TBool certainMatch = EFalse;
241 for (TInt i = 0; (i < KDataTypesCount) && !certainMatch; i++)
243 // Reset the results for each iteration.
247 if (KSigs[i].iHeaderLen == 0)
249 // Call the custom recognition function.
250 // match contains the results.
251 __ASSERT_DEBUG(KSigs[i].iHeaderOrProc, User::Panic(KRUFPanic, KReasonNoFunction));
252 TCustomProc proc = (TCustomProc)(KSigs[i].iHeaderOrProc);
253 proc(ext, *pReader, match);
257 // This format has a known signature.
258 TPtrC8 header(_S8(KSigs[i].iHeaderOrProc), KSigs[i].iHeaderLen);
260 TUint8 sameHeader = MatchHeader(aBuffer, header);
261 TUint8 sameExt = MatchExtension(ext, KSigs[i].iExt);
262 TUint8 confIndex = MAKE_BYTE2(sameExt, sameHeader);
264 match.iConfidence = KResultToConfidence[confIndex];
265 match.iMime = KSigs[i].iMime;
268 // Evaluate the result.
269 switch (match.iConfidence)
271 case KConfNotRecognised:
275 certainMatch = ETrue;
276 // Deliberate fall through to add match to array of matches.
279 // Add it to the start of the array.
280 User::LeaveIfError(matches.Insert(TMatch(match), 0));
284 // Add it to the end of the array.
285 if (matches.Count() == 0)
287 User::LeaveIfError(matches.Append(TMatch(match)));
292 // Should never get here.
293 User::Leave(KErrArgument);
295 } // for (TInt i = 0; i < KDataTypesCount; i++)
297 // We've done looping.
298 if (matches.Count() > 0)
301 SetDataTypeL(match.iConfidence, match.iMime);
304 CleanupStack::PopAndDestroy(pReader);
305 CleanupStack::PopAndDestroy(&matches);