diff -r cad71a31b7fc -r e36f3802f733 voiceui/voiceuivoicerecognition/src/vuicresultsstate.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/voiceui/voiceuivoicerecognition/src/vuicresultsstate.cpp Wed Sep 01 12:29:17 2010 +0100 @@ -0,0 +1,778 @@ +/* +* Copyright (c) 2006-2008 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 FILES +#include +#include +#include + +#include + +#include + +#include "vuivoicerecognition.hrh" + +#include "vuicstate.h" +#include "vuicresultsstate.h" +#include "vuicplaystate.h" +#include "vuiccontactresultsstate.h" +#include "vuicabortstate.h" +#include "vuicerrorstate.h" +#include "vuicexitstate.h" + +#include "vuicdatastorage.h" + +#include "vuicvoicerecogdialogimpl.h" +#include "vuicnbestlistdialog.h" +#include "vuicttsplayer.h" +#include "vuivoiceicondefs.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "rubydebug.h" + +_LIT( KTab, "\t" ); + +// ----------------------------------------------------------------------------- +// CResultsState::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CResultsState* CResultsState::NewL( CDataStorage& aDataStorage, CUiModel& aUiModel ) + { + CResultsState* self = new (ELeave) CResultsState( aDataStorage, aUiModel ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// Destructor +CResultsState::~CResultsState() + { + RUBY_DEBUG0( "CResultsState::~CResultsState START" ); + + DataStorage().TtsPlayer()->Stop(); + + delete iNBestListDialog; + + delete iTagList; // Only copies of pointers, do not reset and destroy + + if ( iConnection ) + { + iConnection->Close(); + } + + RUBY_DEBUG0( "CResultsState::~CResultsState EXIT" ); + } + +// --------------------------------------------------------- +// CResultsState::HandleEventL +// --------------------------------------------------------- +// +void CResultsState::HandleEventL( TInt aEvent ) + { + RUBY_DEBUG_BLOCK( "CResultsState::HandleEventL" ); + + CState* nextState = NULL; + + switch( aEvent ) + { + case KErrNone: + + if ( iInternalState == EStarted ) + { + iInternalState = EInitialized; + } + else if ( iInternalState == EInitialized ) + { + iInternalState = ECompleted; + nextState = this; + } + break; + + case EVoiceTagSoftKeySelect: + + if ( DataStorage().Tag()->Context()->ContextName() == KVoiceDialContext ) + { + nextState = CContactResultsState::NewL( DataStorage(), UiModel() ); + } + else + { + nextState = CPlayState::NewL( DataStorage(), UiModel() ); + } + break; + + case EVoiceTagSoftKeyDirectSelect: + + nextState = CPlayState::NewL( DataStorage(), UiModel() ); + break; + + case EAknSoftkeyQuit: + case EAknSoftkeyNo: + case EVoiceTagSoftKeyQuit: + case EEndCallKeypress: + case ELongKeypress: + + nextState = CAbortState::NewL( DataStorage(), UiModel() ); + break; + + case EShortKeypress: + case EUpKeypress: + case EDownKeypress: + case ESelectKeypress: + case EDirectSelectKeypress: + case EOptionsKeypress: + case EOpenKeypress: + case EDragKeypress: + case EScrollKeypress: + + iKeypress = aEvent; + nextState = this; + break; + + case EAknSoftkeyOpen: + + nextState = CExitState::NewL( DataStorage(), UiModel() ); + break; + + default: + + nextState = CErrorState::NewL( DataStorage(), UiModel(), aEvent ); + break; + } + + DataStorage().VoiceRecognitionImpl()->ChangeState( nextState ); + } + +// --------------------------------------------------------- +// CResultsState::ExecuteL +// --------------------------------------------------------- +// +void CResultsState::ExecuteL() + { + RUBY_DEBUG_BLOCK( "CResultsState::ExecuteL" ); + + if ( HandleKeypressL() ) + { + iKeypress = ENoKeypress; + } + else if ( iInternalState == ECompleted ) + { + DataStorage().TtsPlayer()->Stop(); + } + else + { + TInt returnValue = KErrNoResults; + + if ( DataStorage().CompleteTagList()->Count() != KErrNone ) + { + iInternalState = EStarted; + + CreateContactArrayL(); + + if ( iTagList->Count() != KErrNone ) + { + iNBestListDialog = CNBestListDialog::NewL(); + + CDesC16ArrayFlat* items = NULL; + TRAPD( error, items = CreateItemsArrayL() ); + + if ( !error ) + { + iNBestListDialog->CreateNBestListPopupLC( items ); + iNBestListDialog->SetSoftkeysL( R_SOFTKEYS_OPTIONS_QUIT__SELECT ); + + CheckOptionsCommands(); + PlaySelectedNameL(); + BringToForeground(); + + // If automatic confirmation or device lock is on then start the timer + if ( DataStorage().VerificationMode() == EAutomatic || + DataStorage().DeviceLockMode() ) + { + StartTimerL( *this, KTimeoutMicroseconds, KTimeoutMicroseconds ); + } + + iNBestListDialog->RegisterForKeyCallback( DataStorage().VoiceRecognitionImpl() ); + returnValue = iNBestListDialog->ShowNBestListPopupL(); // Pops things pushed in CreateNBestListPopupLC + RUBY_DEBUG1( "CResultsState::ExecuteL - N-Best list returns [%d]", returnValue ); + } + else if ( error != KErrNotFound ) + { + User::Leave( error ); + } + } + } + + if ( returnValue != KErrNone ) + { + iInternalState = ECompleted; + + SelectTag(); + + HandleEventL( returnValue ); + } + } + } + +// --------------------------------------------------------- +// CResultsState::CResultsState +// --------------------------------------------------------- +// +void CResultsState::CCASimpleNotifyL( TNotifyType /*aType*/, TInt /*aReason*/ ) + { + RUBY_DEBUG_BLOCK( "CResultsState::CCASimpleNotifyL" ); + + HandleEventL( EAknSoftkeyOpen ); + } + +// --------------------------------------------------------- +// CResultsState::CResultsState +// --------------------------------------------------------- +// +CResultsState::CResultsState( CDataStorage& aDataStorage, CUiModel& aUiModel ) + : CState( aDataStorage, aUiModel ), iKeypress( ENoKeypress ), + iInternalState( ENotStarted ) + { + } + +// --------------------------------------------------------- +// CResultsState::ConstructL +// --------------------------------------------------------- +// +void CResultsState::ConstructL() + { + RUBY_DEBUG_BLOCK( "CResultsState::ConstructL" ); + + CState::ConstructL(); + + DataStorage().SetAdaptationEnabled( ETrue ); + } + +// --------------------------------------------------------- +// CResultsState::DoTimedEventL +// --------------------------------------------------------- +// +void CResultsState::DoTimedEventL() + { + RUBY_DEBUG_BLOCK( "CResultsState::DoTimedEventL" ); + + SelectTag(); + + HandleEventL( EVoiceTagSoftKeySelect ); + } + +// --------------------------------------------------------- +// CResultsState::HandleKeypressL +// --------------------------------------------------------- +// +TBool CResultsState::HandleKeypressL() + { + RUBY_DEBUG_BLOCK( "CResultsState::HandleKeypressL" ); + + TBool handled = ETrue; + + if ( iKeypress == EShortKeypress ) + { + CDesC16ArrayFlat* items = NULL; + + if ( UpdateContactArray() ) + { + items = CreateItemsArrayL(); + } + + if ( iNBestListDialog->HandleShortKeypressL( items ) ) + { + iInternalState = EStarted; + + CheckOptionsCommands(); + PlaySelectedNameL(); + + // If automatic confirmation or device lock is on then start the timer + if ( DataStorage().VerificationMode() == EAutomatic || + DataStorage().DeviceLockMode() ) + { + StartTimerL( *this, KTimeoutMicroseconds, KTimeoutMicroseconds ); + } + } + else + { + HandleEventL( KErrNoResults ); + } + } + else if ( iKeypress == EUpKeypress || iKeypress == EDownKeypress || + iKeypress == EDragKeypress ) + { + iInternalState = EStarted; + + CheckOptionsCommands(); + PlaySelectedNameL(); + + // If automatic confirmation or device lock is on then start the timer + if ( DataStorage().VerificationMode() == EAutomatic || + DataStorage().DeviceLockMode() ) + { + StartTimerL( *this, KTimeoutMicroseconds, KTimeoutMicroseconds ); + } + } + else if ( iKeypress == EScrollKeypress ) + { + StopTimer(); + } + else if ( iKeypress == ESelectKeypress ) + { + if ( !DataStorage().Tag() ) + { + SelectTag(); + + HandleEventL( EVoiceTagSoftKeySelect ); + } + } + else if ( iKeypress == EDirectSelectKeypress ) + { + if ( !DataStorage().Tag() ) + { + SelectTag(); + + HandleEventL( EVoiceTagSoftKeyDirectSelect ); + } + } + else if ( iKeypress == EOptionsKeypress ) + { + StopTimer(); + DataStorage().SetVerificationMode( EManual ); + } + else if ( iKeypress == EOpenKeypress ) + { + OpenPhonebookContactL(); + } + else + { + handled = EFalse; + } + + return handled; + } + +// --------------------------------------------------------------------------- +// CResultsState::PlaySelectedNameL +// --------------------------------------------------------------------------- +// +void CResultsState::PlaySelectedNameL() + { + RUBY_DEBUG_BLOCK( "CResultsState::PlaySelectedNameL" ); + + // if TTS is used + if ( ( DataStorage().SynthesizerMode() != KErrNone || + DataStorage().DeviceLockMode() ) && + iTagList->Count() > 0 ) + { + TInt index = iNBestListDialog->SelectedIndex(); + HBufC* text = NULL; + + if ( iTagList->At( index )->Context()->ContextName() == KVoiceDialContext ) + { + text = iTagList->At( index )->SpeechItem()->PartialTextL( KNameTrainingIndex ); + } + else + { + text = HBufC::NewL( 0 ); + } + + CleanupStack::PushL( text ); + + DataStorage().TtsPlayer()->PlayL( iTagList->At( index )->SpeechItem()->Text(), 0, + iTagList->At( index )->SpeechItem()->Text().Length(), + *text ); + + CleanupStack::PopAndDestroy( text ); + } + } + +// --------------------------------------------------------------------------- +// CResultsState::CheckOptionsCommands +// --------------------------------------------------------------------------- +// +void CResultsState::CheckOptionsCommands() + { + RUBY_DEBUG0( "CResultsState::CheckOptionsCommands START" ); + + if ( iTagList->Count() > 0 ) + { + TBool hidden = ETrue; + + TInt index = iNBestListDialog->SelectedIndex(); + if ( iTagList->At( index )->Context()->ContextName() == KVoiceDialContext ) + { + hidden = EFalse; + } + iNBestListDialog->SetCommandsHidden( hidden ); + } + RUBY_DEBUG0( "CResultsState::CheckOptionsCommands EXIT" ); + } + +// --------------------------------------------------------------------------- +// CResultsState::CreateContactArrayL +// --------------------------------------------------------------------------- +// +void CResultsState::CreateContactArrayL() + { + RUBY_DEBUG_BLOCK( "CResultsState::CreateContactArrayL" ); + + CArrayPtrFlat* completeTagList = DataStorage().CompleteTagList(); + + iTagList = new ( ELeave ) CArrayPtrFlat( KSindMaxResults ); + + // Add commands to taglist + for ( TInt i = 0; i < completeTagList->Count() && iTagList->Count() < KSindMaxResults; ++i ) + { + MNssTag* tag = completeTagList->At( i ); + + if ( tag->Context()->ContextName() == KVoiceDialContext && + ( !DataStorage().DeviceLockMode() || tag->RRD()->IntArray()->At( KVasExtensionRrdLocation ) == EDial ) ) + { + if ( !CheckIfAlreadyAdded( tag ) ) + { + iTagList->AppendL( tag ); + } + } + else if ( !DataStorage().DeviceLockMode() ) + { + iTagList->AppendL( tag ); + } + } + } + +// --------------------------------------------------------------------------- +// CResultsState::UpdateContactArray +// --------------------------------------------------------------------------- +// +TBool CResultsState::UpdateContactArray() + { + RUBY_DEBUG0( "CResultsState::UpdateContactArray START" ); + + MNssTag* tag = iTagList->At( iNBestListDialog->SelectedIndex() ); + + TBool currentTagFound = EFalse; + TBool updated = EFalse; + + if ( tag->Context()->ContextName() == KVoiceDialContext ) + { + for ( TInt i = 0; i < DataStorage().CompleteTagList()->Count(); ++i ) + { + MNssTag* newTag = DataStorage().CompleteTagList()->At( i ); + + if ( newTag->Context()->ContextName() == KVoiceDialContext && + ( !DataStorage().DeviceLockMode() || newTag->RRD()->IntArray()->At( KVasExtensionRrdLocation ) == EDial ) && + tag->RRD()->IntArray()->At( KVasContactIdRrdLocation ) == + newTag->RRD()->IntArray()->At( KVasContactIdRrdLocation ) ) + { + if ( currentTagFound ) + { + iTagList->At( iNBestListDialog->SelectedIndex() ) = newTag; + updated = ETrue; + break; + } + else if ( tag->SpeechItem()->RawText() == newTag->SpeechItem()->RawText() ) + { + currentTagFound = ETrue; + } + } + } + } + + RUBY_DEBUG0( "CResultsState::UpdateContactArray EXIT" ); + + return updated; + } + +// --------------------------------------------------------- +// CResultsState::CheckIfAlreadyAdded +// --------------------------------------------------------- +// +TBool CResultsState::CheckIfAlreadyAdded( MNssTag* aTag ) + { + RUBY_DEBUG0( "CResultsState::CheckIfAlreadyAdded START" ); + + TBool returnValue = EFalse; + + for ( TInt i = 0; i < iTagList->Count(); ++i ) + { + if ( aTag->RRD()->IntArray()->At( KVasContactIdRrdLocation ) == + iTagList->At( i )->RRD()->IntArray()->At( KVasContactIdRrdLocation ) ) + { + returnValue = ETrue; + + break; + } + } + + RUBY_DEBUG0( "CResultsState::CheckIfAlreadyAdded EXIT" ); + + return returnValue; + } + +// --------------------------------------------------------------------------- +// CResultsState::CreateItemsArrayLC +// --------------------------------------------------------------------------- +// +CDesC16ArrayFlat* CResultsState::CreateItemsArrayL() + { + RUBY_DEBUG_BLOCK( "CResultsState::CreateItemsArrayL" ); + + TInt count = iTagList->Count(); + + CDesC16ArrayFlat* items = new ( ELeave ) CDesC16ArrayFlat( KSindMaxResults ); + CleanupStack::PushL( items ); + + TName buffer; + + for ( TInt i = 0; i < count; ++i ) + { + MNssTag* tag = iTagList->At( i ); + + if ( tag->Context()->ContextName() == KVoiceDialContext ) + { + FillDialContextBufferL( tag, buffer ); + + items->AppendL( buffer ); + } + else + { + FillCommandContextBuffer( tag, buffer ); + + items->AppendL( buffer ); + } + } + + CleanupStack::Pop( items ); + + return items; + } + +// --------------------------------------------------------- +// CResultsState::FillDialContextBufferL +// --------------------------------------------------------- +// +void CResultsState::FillDialContextBufferL( MNssTag* aTag, TDes& aBuffer ) + { + RUBY_DEBUG_BLOCK( "CResultsState::FillDialContextBufferL" ); + + TPtrC type = KNullDesC(); + + DataStorage().PbkHandler()->FindContactFieldL( aTag ); + + type.Set( GetContactIconType( DataStorage().PbkHandler()->FieldTypeL() ) ); + + // Get the actual name only + HBufC* name = aTag->SpeechItem()->PartialTextL( KNameTrainingIndex ); + CleanupStack::PushL( name ); + + aBuffer.Zero(); + aBuffer.Append( type ); + aBuffer.Append( KTab ); + aBuffer.Append( *name ); + aBuffer.Append( KTab ); + + HBufC* label = NULL; + + TRAPD( error, label = aTag->SpeechItem()->PartialTextL( KExtensionTrainingIndex ) ); + if ( error == KErrNone || error == KErrNotFound ) + { + // If there is no extension then the phonebook label is shown + if ( label ) + { + CleanupStack::PushL( label ); + + aBuffer.Append( *label ); + + CleanupStack::PopAndDestroy( label ); + } + else + { + aBuffer.Append( DataStorage().PbkHandler()->LabelL() ); + } + } + else + { + User::Leave( error ); + } + + CleanupStack::PopAndDestroy( name ); + } + +// --------------------------------------------------------- +// CResultsState::FillCommandContextBuffer +// --------------------------------------------------------- +// +void CResultsState::FillCommandContextBuffer( MNssTag* aTag, TDes& aBuffer ) + { + RUBY_DEBUG0( "CResultsState::FillCommandContextBuffer START" ); + + aBuffer.Zero(); + + if ( aTag->RRD()->IntArray()->At( KVasContactIdRrdLocation ) >= KProfileValue ) + { + aBuffer.Append( KIconProfile ); + } + else + { + aBuffer.Append( KIconApplication ); + } + + aBuffer.Append( KTab ); + aBuffer.Append( aTag->SpeechItem()->Text() ); + + RUBY_DEBUG0( "CResultsState::FillCommandContextBuffer EXIT" ); + } + +// --------------------------------------------------------- +// CResultsState::GetContactIconType +// --------------------------------------------------------- +// +TPtrC CResultsState::GetContactIconType( TFieldType aFieldType ) + { + RUBY_DEBUG0( "CResultsState::GetContactIconType START" ); + + TPtrC type; + // select a phone type + if ( aFieldType == KUidContactFieldVCardMapVOICE ) + { + type.Set( KIconPhone ); + } + else if ( aFieldType == KUidContactFieldVCardMapCELL ) + { + type.Set( KIconMobile ); + } + else if ( aFieldType == KUidContactFieldVCardMapFAX ) + { + type.Set( KIconFax ); + } + else if ( aFieldType == KUidContactFieldVCardMapEMAILINTERNET ) + { + type.Set( KIconEmail ); + } + else if ( aFieldType == KUidContactFieldVCardMapVIDEO ) + { + type.Set( KIconVideo ); + } + else if ( aFieldType == KUidContactFieldVCardMapVOIP ) + { + type.Set( KIconVoip ); + } + else + { + type.Set( KIconBlank ); + } + + RUBY_DEBUG0( "CResultsState::GetContactIconType EXIT" ); + + return type; + } + +// --------------------------------------------------------- +// CResultsState::SelectTag +// --------------------------------------------------------- +// +void CResultsState::SelectTag() + { + RUBY_DEBUG0( "CResultsState::SelectTag START" ); + + if ( iTagList && iTagList->Count() > 0 ) + { + DataStorage().SetTag( iTagList->At( iNBestListDialog->SelectedIndex() ), ETrue ); + + // Remove selected item from the complete taglist + for ( TInt i = 0; i < DataStorage().CompleteTagList()->Count(); ++i ) + { + if ( DataStorage().CompleteTagList()->At( i ) == + DataStorage().Tag() ) + { + DataStorage().CompleteTagList()->Delete( i ); + break; + } + } + } + + RUBY_DEBUG0( "CResultsState::SelectTag EXIT" ); + } + +// --------------------------------------------------------- +// CResultsState::OpenPhonebookContactL +// --------------------------------------------------------- +// +void CResultsState::OpenPhonebookContactL() + { + RUBY_DEBUG_BLOCK( "CResultsState::OpenPhonebookContactL" ); + + SelectTag(); + + if ( iConnection ) + { + iConnection->Close(); + } + iConnection = TCCAFactory::NewConnectionL(); + + MCCAParameter* parameter = TCCAFactory::NewParameterL(); + CleanupClosePushL( *parameter ); + + parameter->SetConnectionFlag( MCCAParameter::ENormal ); + parameter->SetContactDataFlag( MCCAParameter::EContactLink ); + + // Create a Contact Manager and bind it with the default contact database + CVPbkContactStoreUriArray* uriArray = CVPbkContactStoreUriArray::NewL(); + CleanupStack::PushL( uriArray ); + + TVPbkContactStoreUriPtr uri( VPbkContactStoreUris::DefaultCntDbUri() ); + uriArray->AppendL( uri ); + + CVPbkContactManager* contactManager = CVPbkContactManager::NewL(*uriArray); + CleanupStack::PushL( contactManager ); + + // Find Contacts Model store URI from the contact manager (copied from Phonebook app) + MVPbkContactStore* defaultStore = contactManager->ContactStoresL().Find( uri ); + User::LeaveIfNull( defaultStore ); + + // Create a ContactIdConverter object for the ContactId-to-ContactLink conversion + CVPbkContactIdConverter* idConverter = CVPbkContactIdConverter::NewL( *defaultStore ); + CleanupStack::PushL( idConverter ); + + MVPbkContactLink* link = idConverter->IdentifierToLinkLC( + DataStorage().Tag()->RRD()->IntArray()->At( KVasContactIdRrdLocation )); + + HBufC8* link8 = link->PackLC(); + HBufC16* link16 = HBufC16::NewLC( link8->Length() ); + link16->Des().Copy( *link8 ); + + parameter->SetContactDataL( link16->Des() ); + + iConnection->LaunchAppL( *parameter, this ); + + CleanupStack::PopAndDestroy(6,uriArray); + CleanupStack::Pop();//parameter + } + +// End of File +