|
1 /* |
|
2 * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: VCommandManager application which is started during boot. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include "rubydebug.h" |
|
21 |
|
22 #include <centralrepository.h> |
|
23 |
|
24 #include "srsfprivatecrkeys.h" |
|
25 #include <menu2internalcrkeys.h> |
|
26 #include <f32file.h> |
|
27 #include "vcommandmanager.h" |
|
28 #include "vcxmlparser.h" |
|
29 #include "vcommandmerger.h" |
|
30 |
|
31 // CONSTANTS |
|
32 _LIT( KPrivateSubDirectory, "import\\" ); |
|
33 _LIT( KFileFilter, "*.xml" ); |
|
34 |
|
35 //static const TInt KUndefinedLanguage = -1; |
|
36 |
|
37 |
|
38 // ----------------------------------------------------------------------------- |
|
39 // CVCommandManager::CVCommandManager |
|
40 // C++ default constructor can NOT contain any code, that |
|
41 // might leave. |
|
42 // ----------------------------------------------------------------------------- |
|
43 // |
|
44 CVCommandManager::CVCommandManager( TBool aForceRetrain ) |
|
45 : iCommands(), iMatchingIndices(), iLanguageChanged( aForceRetrain ) |
|
46 { |
|
47 // Nothing |
|
48 } |
|
49 |
|
50 // ----------------------------------------------------------------------------- |
|
51 // CVCommandManager::ConstructL |
|
52 // Symbian 2nd phase constructor can leave. |
|
53 // ----------------------------------------------------------------------------- |
|
54 // |
|
55 void CVCommandManager::ConstructL() |
|
56 { |
|
57 User::LeaveIfError( iRFs.Connect() ); |
|
58 |
|
59 iParser = CVcXmlParser::NewL( iRFs, *this ); |
|
60 |
|
61 // Create service object |
|
62 CVCommandHandler* service = CVCommandHandler::NewL(); |
|
63 CleanupStack::PushL( service ); |
|
64 |
|
65 ParseAllFilesL(); |
|
66 |
|
67 // Get all existing commands from VCommandHandler |
|
68 iCommandArray = service->ListCommandsL(); |
|
69 |
|
70 CVCommandMerger* merger = CVCommandMerger::NewLC(); |
|
71 CVCommandArray* deduction = merger->ProduceDeductionByRunnablesLC( *iCommandArray, iCommands ); |
|
72 CVCommandArray* addition = merger->ProduceAdditionByRunnablesLC( *iCommandArray, iCommands ); |
|
73 |
|
74 service->RemoveCommandsL( deduction->PointerArray(), ETrue ); |
|
75 service->AddCommandsL( addition->PointerArray(), ETrue ); |
|
76 |
|
77 CleanupStack::PopAndDestroy( addition ); |
|
78 CleanupStack::PopAndDestroy( deduction ); |
|
79 CleanupStack::PopAndDestroy( merger ); |
|
80 CleanupStack::PopAndDestroy( service ); |
|
81 } |
|
82 |
|
83 // ----------------------------------------------------------------------------- |
|
84 // CVCommandManager::NewL |
|
85 // Two-phased constructor. |
|
86 // ----------------------------------------------------------------------------- |
|
87 // |
|
88 CVCommandManager* CVCommandManager::NewL( TBool aForceRetrain ) |
|
89 { |
|
90 CVCommandManager* self = new ( ELeave ) CVCommandManager( aForceRetrain ); |
|
91 CleanupStack::PushL( self ); |
|
92 self->ConstructL(); |
|
93 CleanupStack::Pop( self ); |
|
94 return self; |
|
95 } |
|
96 |
|
97 // ----------------------------------------------------------------------------- |
|
98 // CVCommandManager::ParseAllFilesL |
|
99 // Goes through directories and parses all xml files. |
|
100 // ----------------------------------------------------------------------------- |
|
101 // |
|
102 void CVCommandManager::ParseAllFilesL() |
|
103 { |
|
104 RUBY_DEBUG_BLOCK( "CVCommandManager::ParseAllFilesL" ); |
|
105 |
|
106 TDriveList drivelist; |
|
107 User::LeaveIfError( iRFs.DriveList( drivelist ) ); |
|
108 |
|
109 for ( TInt drive( EDriveA ); drive <= EDriveZ; drive++ ) |
|
110 { |
|
111 if ( drivelist[drive] ) |
|
112 { |
|
113 TChar driveLetter; |
|
114 User::LeaveIfError( iRFs.DriveToChar( drive, driveLetter ) ); |
|
115 |
|
116 TFileName directory; |
|
117 iRFs.PrivatePath( directory ); |
|
118 directory.Insert( 0, _L(" :")); |
|
119 directory[0] = driveLetter; // replace " " with a drive letter |
|
120 |
|
121 // parse files from private directory |
|
122 ParseAllFilesFromDirectoryL( directory ); |
|
123 |
|
124 // parse filer from import directory |
|
125 directory.Append( KPrivateSubDirectory ); |
|
126 ParseAllFilesFromDirectoryL( directory ); |
|
127 |
|
128 } |
|
129 } |
|
130 } |
|
131 |
|
132 |
|
133 |
|
134 // ----------------------------------------------------------------------------- |
|
135 // CVCommandManager::ParseAllFilesFromDirectoryL |
|
136 // Goes through directory and parses all xml files. |
|
137 // ----------------------------------------------------------------------------- |
|
138 // |
|
139 void CVCommandManager::ParseAllFilesFromDirectoryL( const TDesC& aDirectory ) |
|
140 { |
|
141 RUBY_DEBUG_BLOCK( "CVCommandManager::ParseAllFilesFromDirectoryL" ); |
|
142 |
|
143 CDir* dirContents = NULL; |
|
144 |
|
145 TFileName searchPath( aDirectory ); |
|
146 searchPath.Append( KFileFilter ); |
|
147 |
|
148 RUBY_DEBUG1( "CVCommandManager::ParseAllFilesFromDirectoryL - Search path: [%S]", &searchPath ); |
|
149 |
|
150 TInt error = iRFs.GetDir( searchPath, KEntryAttMatchMask, ESortNone, dirContents ); |
|
151 if ( error == KErrNone ) |
|
152 { |
|
153 CleanupStack::PushL( dirContents ); |
|
154 |
|
155 RUBY_DEBUG1( "CVCommandManager::ParseAllFilesFromDirectoryL - Found %d xml-file(s)", dirContents->Count() ); |
|
156 |
|
157 // Go through all found xml files |
|
158 for ( TInt iCounter = 0; iCounter < dirContents->Count(); iCounter++ ) |
|
159 { |
|
160 TEntry entry = (*dirContents)[iCounter]; |
|
161 if ( !entry.IsDir() ) |
|
162 { |
|
163 TFileName filename( aDirectory ); |
|
164 filename.Append( entry.iName ); |
|
165 |
|
166 TRAPD( error, iParser->ParseFileL( filename ) ); |
|
167 if ( error ) |
|
168 { |
|
169 // Reset parser if an error occurs |
|
170 delete iParser; |
|
171 iParser = NULL; |
|
172 |
|
173 iParser = CVcXmlParser::NewL( iRFs, *this ); |
|
174 } |
|
175 } |
|
176 } |
|
177 |
|
178 CleanupStack::PopAndDestroy( dirContents ); |
|
179 } |
|
180 else |
|
181 { |
|
182 RUBY_ERROR1( "CVCommandManager::ParseAllFilesFromDirectoryL - GetDir returns [%d]", error ); |
|
183 } |
|
184 } |
|
185 |
|
186 // ----------------------------------------------------------------------------- |
|
187 // CVCommandManager::CompareCommands |
|
188 // Compares if two commands are equal |
|
189 // ----------------------------------------------------------------------------- |
|
190 // |
|
191 TBool CVCommandManager::CompareCommands( const CVCommand* aFirst, const CVCommand* aSecond ) |
|
192 { |
|
193 TBool result = EFalse; |
|
194 |
|
195 if ( aFirst && aSecond ) |
|
196 { |
|
197 result = aFirst->Runnable() == aSecond->Runnable(); |
|
198 } |
|
199 |
|
200 return result; |
|
201 } |
|
202 |
|
203 // ----------------------------------------------------------------------------- |
|
204 // CVCommandManager::~CVCommandManager |
|
205 // Destructor. |
|
206 // ----------------------------------------------------------------------------- |
|
207 // |
|
208 CVCommandManager::~CVCommandManager() |
|
209 { |
|
210 delete iParser; |
|
211 // delete iClient; |
|
212 delete iCommandArray; |
|
213 |
|
214 iCommands.ResetAndDestroy(); |
|
215 iMatchingIndices.Close(); |
|
216 |
|
217 iRFs.Close(); |
|
218 } |
|
219 |
|
220 // ----------------------------------------------------------------------------- |
|
221 // CVCommandManager::VCMThreadFunction |
|
222 // Static main function for Voice Command Manager thread |
|
223 // ----------------------------------------------------------------------------- |
|
224 // |
|
225 TInt CVCommandManager::VCMThreadFunction( TAny* /*aParams*/ ) |
|
226 { |
|
227 __UHEAP_MARK; |
|
228 |
|
229 // CleanupStack creation |
|
230 CTrapCleanup* cleanupStack = CTrapCleanup::New(); |
|
231 |
|
232 CActiveScheduler* scheduler = NULL; |
|
233 |
|
234 TInt error = KErrNone; |
|
235 |
|
236 TRAP( error, |
|
237 |
|
238 // ActiveScheduler creation |
|
239 scheduler = new ( ELeave ) CActiveScheduler(); |
|
240 |
|
241 CleanupStack::PushL( scheduler ); |
|
242 |
|
243 CActiveScheduler::Install( scheduler ); |
|
244 |
|
245 TSecureId sid = RThread().SecureId(); |
|
246 RUBY_DEBUG1( "VCommandManager secure id [%x]", sid.iId ); |
|
247 |
|
248 // Create VCommandManager |
|
249 CVCommandManager* vcmanager = CVCommandManager::NewL( EFalse ); |
|
250 delete vcmanager; |
|
251 |
|
252 CleanupStack::PopAndDestroy( scheduler ); |
|
253 ); // TRAP |
|
254 |
|
255 delete cleanupStack; |
|
256 |
|
257 __UHEAP_MARKEND; |
|
258 |
|
259 RUBY_DEBUG0( "CVCommandManager::VCMThreadFunction finished ok" ); |
|
260 |
|
261 return error; |
|
262 } |
|
263 |
|
264 // ----------------------------------------------------------------------------- |
|
265 // CVCommandManager::ConstructCommandL |
|
266 // Constructs new command with given data |
|
267 // ----------------------------------------------------------------------------- |
|
268 // |
|
269 void CVCommandManager::ConstructCommandL( const TDesC& aWrittenText, |
|
270 const TDesC& aSpokenText, |
|
271 const TDesC& aTooltipText, |
|
272 const TDesC& aFolder, |
|
273 const TDesC& aFolderTitle, |
|
274 const TDesC& aParameters, |
|
275 TUid aIcon, |
|
276 TUid aAppId, |
|
277 const TDesC& aAppName, |
|
278 TBool aStartImmediately, |
|
279 TBool aUserCanModify, |
|
280 const TDesC& aFolderIconFile, |
|
281 TInt aFolderIconIndex |
|
282 ) |
|
283 { |
|
284 const TInt KCenRepBufferSize = 255; |
|
285 |
|
286 RUBY_DEBUG_BLOCKL( "CVCommandManager::ConstructCommandL" ); |
|
287 |
|
288 RUBY_DEBUG1( "CVCommandManager::ConstructCommandL - Creating command: [%S]", &aWrittenText ); |
|
289 |
|
290 // First check that if the application is hidden so voice command is not created then |
|
291 if ( aAppId != KNullUid ) |
|
292 { |
|
293 |
|
294 TBuf<KCenRepBufferSize> buf; |
|
295 CRepository* cenRepSession = CRepository::NewLC( KCRUidMenu ); |
|
296 cenRepSession->Get( KMenuHideApplication, buf ); |
|
297 CleanupStack::PopAndDestroy( cenRepSession ); |
|
298 |
|
299 buf.LowerCase(); |
|
300 TBuf<8> textUidHex; |
|
301 textUidHex.AppendNumFixedWidth( aAppId.iUid, EHex, 8 ); |
|
302 if ( buf.Find( textUidHex ) != KErrNotFound ) |
|
303 { |
|
304 // hidden application: no voice tag needed |
|
305 RUBY_DEBUG1( "%S hidden application", &aWrittenText ); |
|
306 return; |
|
307 } |
|
308 } |
|
309 |
|
310 HBufC8* arguments = HBufC8::NewL( aParameters.Length() ); |
|
311 CleanupStack::PushL( arguments ); |
|
312 TPtr8 argumentsPtr = arguments->Des(); |
|
313 argumentsPtr.Copy( aParameters ); |
|
314 |
|
315 |
|
316 // Create runnable object |
|
317 CVCRunnable* runnable = NULL; |
|
318 if ( aAppId != KNullUid ) |
|
319 { |
|
320 runnable = CVCRunnable::NewL( aAppId, argumentsPtr ); |
|
321 } |
|
322 else |
|
323 { |
|
324 runnable = CVCRunnable::NewL( aAppName, argumentsPtr ); |
|
325 } |
|
326 CleanupStack::PushL( runnable ); |
|
327 |
|
328 CVCFolderInfo* folderInfo = CVCFolderInfo::NewL( aFolderTitle, aFolder, 0, |
|
329 aFolderIconIndex, aFolderIconFile ); |
|
330 CleanupStack::PushL( folderInfo ); |
|
331 // Create commandUi object |
|
332 CVCCommandUi* commandUi = CVCCommandUi::NewL( aWrittenText, |
|
333 *folderInfo, |
|
334 aUserCanModify, |
|
335 aTooltipText, |
|
336 aIcon, |
|
337 KNullDesC, |
|
338 !aStartImmediately ); |
|
339 CleanupStack::PopAndDestroy( folderInfo ); |
|
340 CleanupStack::PushL( commandUi ); |
|
341 |
|
342 // Create command object |
|
343 CVCommand* command = CVCommand::NewL( aSpokenText, *runnable, *commandUi ); |
|
344 |
|
345 TBool found = EFalse; |
|
346 |
|
347 // Check that identical command has not already been found from some xml-file |
|
348 for ( int i = 0; i < iCommands.Count(); ++i ) |
|
349 { |
|
350 if ( CompareCommands( iCommands[ i ], command ) ) |
|
351 { |
|
352 found = ETrue; |
|
353 break; |
|
354 } |
|
355 } |
|
356 |
|
357 // Add command if not found already |
|
358 if ( !found ) |
|
359 { |
|
360 iCommands.Append( command ); |
|
361 iMatchingIndices.Append( KErrNotFound ); |
|
362 } |
|
363 else |
|
364 { |
|
365 delete command; |
|
366 } |
|
367 |
|
368 CleanupStack::PopAndDestroy( commandUi ); |
|
369 CleanupStack::PopAndDestroy( runnable ); |
|
370 CleanupStack::PopAndDestroy( arguments ); |
|
371 } |
|
372 |
|
373 // ----------------------------------------------------------------------------- |
|
374 // CVCommandManager::MvcxpoVoiceCommandFound |
|
375 // Callback from VC XML parser |
|
376 // ----------------------------------------------------------------------------- |
|
377 // |
|
378 void CVCommandManager::MvcxpoVoiceCommandFound( const TDesC& aWrittenText, |
|
379 const TDesC& aSpokenText, |
|
380 const TDesC& aTooltipText, |
|
381 const TDesC& aFolder, |
|
382 const TDesC& aFolderTitle, |
|
383 const TDesC& aParameters, |
|
384 TUid aIcon, |
|
385 TUid aAppId, |
|
386 const TDesC& aAppName, |
|
387 TBool aStartImmediately, |
|
388 TBool aUserCanModify, |
|
389 const TDesC& aFolderIconFile, |
|
390 TInt aFolderIconIndex |
|
391 ) |
|
392 { |
|
393 RUBY_DEBUG0( "CVCommandManager::MvcxpoVoiceCommandFound START" ); |
|
394 |
|
395 TRAP_IGNORE( ConstructCommandL( aWrittenText, |
|
396 aSpokenText, |
|
397 aTooltipText, |
|
398 aFolder, |
|
399 aFolderTitle, |
|
400 aParameters, |
|
401 aIcon, |
|
402 aAppId, |
|
403 aAppName, |
|
404 aStartImmediately, |
|
405 aUserCanModify, |
|
406 aFolderIconFile, |
|
407 aFolderIconIndex ) ); |
|
408 |
|
409 RUBY_DEBUG0( "CVCommandManager::MvcxpoVoiceCommandFound EXIT" ); |
|
410 } |
|
411 |
|
412 // End of File |
|
413 |