diff -r cad71a31b7fc -r e36f3802f733 srsf/vcommandmanager/src/vcommandmanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srsf/vcommandmanager/src/vcommandmanager.cpp Wed Sep 01 12:29:17 2010 +0100 @@ -0,0 +1,413 @@ +/* +* Copyright (c) 2005-2006 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: VCommandManager application which is started during boot. +* +*/ + + +// INCLUDE FILES +#include "rubydebug.h" + +#include + +#include "srsfprivatecrkeys.h" +#include +#include +#include "vcommandmanager.h" +#include "vcxmlparser.h" +#include "vcommandmerger.h" + +// CONSTANTS +_LIT( KPrivateSubDirectory, "import\\" ); +_LIT( KFileFilter, "*.xml" ); + +//static const TInt KUndefinedLanguage = -1; + + +// ----------------------------------------------------------------------------- +// CVCommandManager::CVCommandManager +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CVCommandManager::CVCommandManager( TBool aForceRetrain ) + : iCommands(), iMatchingIndices(), iLanguageChanged( aForceRetrain ) + { + // Nothing + } + +// ----------------------------------------------------------------------------- +// CVCommandManager::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CVCommandManager::ConstructL() + { + User::LeaveIfError( iRFs.Connect() ); + + iParser = CVcXmlParser::NewL( iRFs, *this ); + + // Create service object + CVCommandHandler* service = CVCommandHandler::NewL(); + CleanupStack::PushL( service ); + + ParseAllFilesL(); + + // Get all existing commands from VCommandHandler + iCommandArray = service->ListCommandsL(); + + CVCommandMerger* merger = CVCommandMerger::NewLC(); + CVCommandArray* deduction = merger->ProduceDeductionByRunnablesLC( *iCommandArray, iCommands ); + CVCommandArray* addition = merger->ProduceAdditionByRunnablesLC( *iCommandArray, iCommands ); + + service->RemoveCommandsL( deduction->PointerArray(), ETrue ); + service->AddCommandsL( addition->PointerArray(), ETrue ); + + CleanupStack::PopAndDestroy( addition ); + CleanupStack::PopAndDestroy( deduction ); + CleanupStack::PopAndDestroy( merger ); + CleanupStack::PopAndDestroy( service ); + } + +// ----------------------------------------------------------------------------- +// CVCommandManager::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CVCommandManager* CVCommandManager::NewL( TBool aForceRetrain ) + { + CVCommandManager* self = new ( ELeave ) CVCommandManager( aForceRetrain ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CVCommandManager::ParseAllFilesL +// Goes through directories and parses all xml files. +// ----------------------------------------------------------------------------- +// +void CVCommandManager::ParseAllFilesL() + { + RUBY_DEBUG_BLOCK( "CVCommandManager::ParseAllFilesL" ); + + TDriveList drivelist; + User::LeaveIfError( iRFs.DriveList( drivelist ) ); + + for ( TInt drive( EDriveA ); drive <= EDriveZ; drive++ ) + { + if ( drivelist[drive] ) + { + TChar driveLetter; + User::LeaveIfError( iRFs.DriveToChar( drive, driveLetter ) ); + + TFileName directory; + iRFs.PrivatePath( directory ); + directory.Insert( 0, _L(" :")); + directory[0] = driveLetter; // replace " " with a drive letter + + // parse files from private directory + ParseAllFilesFromDirectoryL( directory ); + + // parse filer from import directory + directory.Append( KPrivateSubDirectory ); + ParseAllFilesFromDirectoryL( directory ); + + } + } + } + + + +// ----------------------------------------------------------------------------- +// CVCommandManager::ParseAllFilesFromDirectoryL +// Goes through directory and parses all xml files. +// ----------------------------------------------------------------------------- +// +void CVCommandManager::ParseAllFilesFromDirectoryL( const TDesC& aDirectory ) + { + RUBY_DEBUG_BLOCK( "CVCommandManager::ParseAllFilesFromDirectoryL" ); + + CDir* dirContents = NULL; + + TFileName searchPath( aDirectory ); + searchPath.Append( KFileFilter ); + + RUBY_DEBUG1( "CVCommandManager::ParseAllFilesFromDirectoryL - Search path: [%S]", &searchPath ); + + TInt error = iRFs.GetDir( searchPath, KEntryAttMatchMask, ESortNone, dirContents ); + if ( error == KErrNone ) + { + CleanupStack::PushL( dirContents ); + + RUBY_DEBUG1( "CVCommandManager::ParseAllFilesFromDirectoryL - Found %d xml-file(s)", dirContents->Count() ); + + // Go through all found xml files + for ( TInt iCounter = 0; iCounter < dirContents->Count(); iCounter++ ) + { + TEntry entry = (*dirContents)[iCounter]; + if ( !entry.IsDir() ) + { + TFileName filename( aDirectory ); + filename.Append( entry.iName ); + + TRAPD( error, iParser->ParseFileL( filename ) ); + if ( error ) + { + // Reset parser if an error occurs + delete iParser; + iParser = NULL; + + iParser = CVcXmlParser::NewL( iRFs, *this ); + } + } + } + + CleanupStack::PopAndDestroy( dirContents ); + } + else + { + RUBY_DEBUG1( "CVCommandManager::ParseAllFilesFromDirectoryL - GetDir returns [%d]", error ); + } + } + +// ----------------------------------------------------------------------------- +// CVCommandManager::CompareCommands +// Compares if two commands are equal +// ----------------------------------------------------------------------------- +// +TBool CVCommandManager::CompareCommands( const CVCommand* aFirst, const CVCommand* aSecond ) + { + TBool result = EFalse; + + if ( aFirst && aSecond ) + { + result = aFirst->Runnable() == aSecond->Runnable(); + } + + return result; + } + +// ----------------------------------------------------------------------------- +// CVCommandManager::~CVCommandManager +// Destructor. +// ----------------------------------------------------------------------------- +// +CVCommandManager::~CVCommandManager() + { + delete iParser; +// delete iClient; + delete iCommandArray; + + iCommands.ResetAndDestroy(); + iMatchingIndices.Close(); + + iRFs.Close(); + } + +// ----------------------------------------------------------------------------- +// CVCommandManager::VCMThreadFunction +// Static main function for Voice Command Manager thread +// ----------------------------------------------------------------------------- +// +TInt CVCommandManager::VCMThreadFunction( TAny* /*aParams*/ ) + { + __UHEAP_MARK; + + // CleanupStack creation + CTrapCleanup* cleanupStack = CTrapCleanup::New(); + + CActiveScheduler* scheduler = NULL; + + TInt error = KErrNone; + + TRAP( error, + + // ActiveScheduler creation + scheduler = new ( ELeave ) CActiveScheduler(); + + CleanupStack::PushL( scheduler ); + + CActiveScheduler::Install( scheduler ); + + TSecureId sid = RThread().SecureId(); + RUBY_DEBUG1( "VCommandManager secure id [%x]", sid.iId ); + + // Create VCommandManager + CVCommandManager* vcmanager = CVCommandManager::NewL( EFalse ); + delete vcmanager; + + CleanupStack::PopAndDestroy( scheduler ); + ); // TRAP + + delete cleanupStack; + + __UHEAP_MARKEND; + + RUBY_DEBUG0( "CVCommandManager::VCMThreadFunction finished ok" ); + + return error; + } + +// ----------------------------------------------------------------------------- +// CVCommandManager::ConstructCommandL +// Constructs new command with given data +// ----------------------------------------------------------------------------- +// +void CVCommandManager::ConstructCommandL( const TDesC& aWrittenText, + const TDesC& aSpokenText, + const TDesC& aTooltipText, + const TDesC& aFolder, + const TDesC& aFolderTitle, + const TDesC& aParameters, + TUid aIcon, + TUid aAppId, + const TDesC& aAppName, + TBool aStartImmediately, + TBool aUserCanModify, + const TDesC& aFolderIconFile, + TInt aFolderIconIndex + ) + { + const TInt KCenRepBufferSize = 255; + + RUBY_DEBUG_BLOCKL( "CVCommandManager::ConstructCommandL" ); + + RUBY_DEBUG1( "CVCommandManager::ConstructCommandL - Creating command: [%S]", &aWrittenText ); + + // First check that if the application is hidden so voice command is not created then + if ( aAppId != KNullUid ) + { + + TBuf buf; + CRepository* cenRepSession = CRepository::NewLC( KCRUidMenu ); + cenRepSession->Get( KMenuHideApplication, buf ); + CleanupStack::PopAndDestroy( cenRepSession ); + + buf.LowerCase(); + TBuf<8> textUidHex; + textUidHex.AppendNumFixedWidth( aAppId.iUid, EHex, 8 ); + if ( buf.Find( textUidHex ) != KErrNotFound ) + { + // hidden application: no voice tag needed + RUBY_DEBUG1( "%S hidden application", &aWrittenText ); + return; + } + } + + HBufC8* arguments = HBufC8::NewL( aParameters.Length() ); + CleanupStack::PushL( arguments ); + TPtr8 argumentsPtr = arguments->Des(); + argumentsPtr.Copy( aParameters ); + + + // Create runnable object + CVCRunnable* runnable = NULL; + if ( aAppId != KNullUid ) + { + runnable = CVCRunnable::NewL( aAppId, argumentsPtr ); + } + else + { + runnable = CVCRunnable::NewL( aAppName, argumentsPtr ); + } + CleanupStack::PushL( runnable ); + + CVCFolderInfo* folderInfo = CVCFolderInfo::NewL( aFolderTitle, aFolder, 0, + aFolderIconIndex, aFolderIconFile ); + CleanupStack::PushL( folderInfo ); + // Create commandUi object + CVCCommandUi* commandUi = CVCCommandUi::NewL( aWrittenText, + *folderInfo, + aUserCanModify, + aTooltipText, + aIcon, + KNullDesC, + !aStartImmediately ); + CleanupStack::PopAndDestroy( folderInfo ); + CleanupStack::PushL( commandUi ); + + // Create command object + CVCommand* command = CVCommand::NewL( aSpokenText, *runnable, *commandUi ); + + TBool found = EFalse; + + // Check that identical command has not already been found from some xml-file + for ( int i = 0; i < iCommands.Count(); ++i ) + { + if ( CompareCommands( iCommands[ i ], command ) ) + { + found = ETrue; + break; + } + } + + // Add command if not found already + if ( !found ) + { + iCommands.Append( command ); + iMatchingIndices.Append( KErrNotFound ); + } + else + { + delete command; + } + + CleanupStack::PopAndDestroy( commandUi ); + CleanupStack::PopAndDestroy( runnable ); + CleanupStack::PopAndDestroy( arguments ); + } + +// ----------------------------------------------------------------------------- +// CVCommandManager::MvcxpoVoiceCommandFound +// Callback from VC XML parser +// ----------------------------------------------------------------------------- +// +void CVCommandManager::MvcxpoVoiceCommandFound( const TDesC& aWrittenText, + const TDesC& aSpokenText, + const TDesC& aTooltipText, + const TDesC& aFolder, + const TDesC& aFolderTitle, + const TDesC& aParameters, + TUid aIcon, + TUid aAppId, + const TDesC& aAppName, + TBool aStartImmediately, + TBool aUserCanModify, + const TDesC& aFolderIconFile, + TInt aFolderIconIndex + ) + { + RUBY_DEBUG0( "CVCommandManager::MvcxpoVoiceCommandFound START" ); + + TRAP_IGNORE( ConstructCommandL( aWrittenText, + aSpokenText, + aTooltipText, + aFolder, + aFolderTitle, + aParameters, + aIcon, + aAppId, + aAppName, + aStartImmediately, + aUserCanModify, + aFolderIconFile, + aFolderIconIndex ) ); + + RUBY_DEBUG0( "CVCommandManager::MvcxpoVoiceCommandFound EXIT" ); + } + +// End of File +