srsf/nssvasapi/nssvasrecognition/src/nssvascrecognitionhandler.cpp
branchRCL_3
changeset 19 e36f3802f733
parent 0 bf1d17376201
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/nssvasapi/nssvasrecognition/src/nssvascrecognitionhandler.cpp	Wed Sep 01 12:29:17 2010 +0100
@@ -0,0 +1,1859 @@
+/*
+* Copyright (c) 2003-2007 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:  The CNssRecognitionHandler class performs the recognition function.
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <e32property.h>
+#include "nssvascoreconstant.h"
+
+#include "nssvascrecognitionhandler.h"
+#include "nssvasctagmgr.h"
+#include "nssvascadaptationitem.h"
+#include <nsssispeechrecognitionutilityobserver.h>
+
+#ifndef __WINS__
+	// for hardware
+    #include <AudioPreference.h>
+#else
+  // use default values for WINS
+  const TUint KAudioPriorityVoiceDial = 73;
+
+  const TUint KAudioPrefVocosPlayback = 0x00030001;
+  const TUint KAudioPrefVocosTrain = 0x00020001;
+  const TUint KAudioPrefVocosRecog = 0x00010001;
+#endif
+#include "nssvascdbtagselectnotifier.h"
+#include "nssvascoreconstant.h"
+#include "nssvasmrecognizeinitcompletehandler.h"
+#include "nssvascvasdbbuilder.h"
+#include "rubydebug.h"
+
+// maximal number of results that can be handled
+const TInt KMaxResults = 100;
+
+#ifdef _DEBUG
+// Used under UDEB only
+_LIT( KRecognitionHandlerPanic, "VasCNssRecognitionHandler.cpp" );
+#endif  // _DEBUG
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CNssRecognitionHandler* CNssRecognitionHandler::NewL()
+    {
+    RUBY_DEBUG_BLOCK( "CNssRecognitionHandler::NewL" );
+
+    // version of NewLC which leaves nothing on the cleanup stack
+    CNssRecognitionHandler* self=NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CNssRecognitionHandler* CNssRecognitionHandler::NewLC()
+    {
+    CNssRecognitionHandler* self = new (ELeave)  CNssRecognitionHandler();
+    CleanupStack::PushL(self);
+    // push onto cleanup stack 
+    // (in case self->ConstructL leaves)
+    self->ConstructL();      // use two-stage construct
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::~CNssRecognitionHandler
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CNssRecognitionHandler::~CNssRecognitionHandler()
+    {
+    RUBY_DEBUG0( "CNssRecognitionHandler::~CNssRecognitionHandler" );
+    
+    Cleanup();
+    
+    for ( TInt k( 0 ); k < iAdaptItemArray.Count(); k++ )
+        {
+        iAdaptItemArray[k]->Disable();
+        }
+    iAdaptItemArray.Close();
+    
+    CNssVASDBBuilder::RemoveInstance();  // remove iVasDBBuilder instance
+    
+    TInt state( ERecognitionFail );
+    RProperty::Get( KSINDUID, ERecognitionState, state );
+    
+    if ( state == ERecognitionStarted || state == ERecognitionSpeechEnd )
+        {
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail );
+        }
+    // Delete P&S property
+    RProperty::Delete( KSINDUID, ERecognitionState ); 
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::RecognizeInitL
+// Method to perform initialization for the recognize funtion.
+// -----------------------------------------------------------------------------
+//
+MNssRecognitionHandler::TNssRecognitionResult CNssRecognitionHandler::RecognizeInitL(
+    MNssRecognizeInitCompleteHandler* aInitCompleteHandler,
+    const CArrayPtrFlat<MNssContext>& aRecognitionVocabulary,
+	TInt aMaxResults)
+    {
+    RUBY_DEBUG_BLOCK( "CNssRecognitionHandler::RecognizeInitL" );
+
+    MNssRecognitionHandler::TNssRecognitionResult res = EVasErrorNone;
+
+    // Vocabulary independent initialization:
+    // CSISpeechRecognitionUtility and CSIClientResultSet.
+    res = CommonRecognizeInitL( aInitCompleteHandler, aMaxResults );
+
+    if ( res != EVasErrorNone )
+        {
+        return( res );
+        }
+
+    // Agenda for vocab dependent init:
+    // 1. Get the list of global contexts from VAS DB.
+    //    The information we need is:
+    //     * Model Bank ID, which is the same for all contexts
+    //     * Grammar ID for each context
+    // 2. Load a model bank from SRS DB.
+    // 3. Load the grammars from SRS DB. Each context has one grammar.
+	if ( !iContextList )
+	    {
+		iContextList = new (ELeave) TMNssContextList(1);
+        }
+    else
+        {
+        iContextList->Reset();
+        }
+
+
+    for ( TInt k( 0 ); k < aRecognitionVocabulary.Count(); k++ )
+        {
+        CNssContext* context = ((CNssContext*)aRecognitionVocabulary[k])->CopyL();
+        CleanupStack::PushL( context );
+
+        iContextList->AppendL( context );
+
+        CleanupStack::Pop( context );
+        }
+    iContextCount = iContextList->Count();
+
+    // Check if there are tags in the contexts.
+    // If there are, load a model bank. After that, further initializations
+    // follow: Loading lexicons and grammars.
+	// Check for Tags in contexts and continue recognition
+	TRAPD( err, HandleTagCheckL() );
+
+	if ( err != KErrNone )
+	    {
+        RUBY_DEBUG0( "CNssRecognitionHandler: TRAPD HandleTagCheckL() failed" );
+		// Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+		Cleanup();
+        return EVasRecognitionInitFailed;
+	    }
+
+    return( EVasErrorNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::RecognizeInitL
+// Method to perform initialization for the recognize funtion.
+// -----------------------------------------------------------------------------
+//
+MNssRecognitionHandler::TNssRecognitionResult CNssRecognitionHandler::RecognizeInitL(
+		                   MNssRecognizeInitCompleteHandler* aInitCompleteHandler,
+						   TInt aMaxResults)
+    {
+    RUBY_DEBUG_BLOCK( "CNssRecognitionHandler::RecognizeInitL" );
+
+    MNssRecognitionHandler::TNssRecognitionResult res = EVasErrorNone;
+
+    // Vocabulary independent initialization:
+    // CSISpeechRecognitionUtility and CSIClientResultSet.
+    res = CommonRecognizeInitL( aInitCompleteHandler, aMaxResults );
+
+    if ( res != EVasErrorNone )
+        {
+        return( res );
+        }
+
+    // Agenda for vocab dependent init:
+    // 1. Get the list of global contexts from VAS DB.
+    //    The information we need is:
+    //     * Model Bank ID, which is the same for all contexts
+    //     * Grammar ID for each context
+    // 2. Load a model bank from SRS DB.
+    // 3. Load the grammars from SRS DB. Each context has one grammar.
+
+    if ( iContextList )
+        {
+        iContextList->Reset();
+        delete iContextList;
+        }
+
+	// Get Global Context List from Vas Db
+    iContextList = iContextMgr->GetGlobalContexts();
+    
+    if ( !iContextList )
+        {
+        return EVasRecognitionInitFailed;
+        }
+
+    iContextCount = iContextList->Count();
+
+
+	// Check for Tags in contexts and continue recognition
+	TRAPD( err, HandleTagCheckL() );
+
+	if ( err != KErrNone )
+	    {
+        RUBY_DEBUG0( "CNssRecognitionHandler: TRAPD HandleTagCheckL() failed" );
+
+		// Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+		Cleanup();
+        return EVasRecognitionInitFailed;
+	    }
+
+	return EVasErrorNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::Recognize
+// Method to perform the recognize function.
+// -----------------------------------------------------------------------------
+//
+MNssRecognitionHandler::TNssRecognitionResult CNssRecognitionHandler::Recognize(
+                                        MNssRecognizeEventHandler* aEventHandler )
+    {
+    RUBY_DEBUG0( "CNssRecognitionHandler::Recognize" );
+    
+    if ( iRState != EVasWaitingForRecognize )
+        {
+        RUBY_DEBUG0( "CNssRecognitionHandler::Recognize - Unexpected Request" );
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        Cleanup();
+        return EVasUnexpectedRequest;
+        }
+    
+    iEventHandler = aEventHandler;
+	   
+    iRState = EVasWaitingForRecordStarted;
+    
+    RUBY_DEBUG0( "CNssRecognitionHandler: SRSF Record()" );
+    
+    // Asynchronous call: next expected event: ERecordStarted
+    
+    TInt errorCode = iSrsApi->Record( KNssVASRecordTime );
+    
+    if ( errorCode != KErrNone )
+        {
+        RUBY_DEBUG1( "CNssRecognitionHandler: Record Err = %d", errorCode );
+
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        Cleanup();
+        return EVasRecognitionFailed;
+        }
+    
+    return EVasErrorNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::PreStartSampling
+// Method to start pre-sampling before the actual recognition start.
+// -----------------------------------------------------------------------------
+//
+MNssRecognitionHandler::TNssRecognitionResult 
+CNssRecognitionHandler::PreStartSampling( MNssRecognizeInitCompleteHandler* aInitCompleteHandler )
+    {
+    RUBY_DEBUG0( "" ); 
+    
+    // State check
+    if ( iRState != EVasIdle )
+        {
+        RUBY_DEBUG0( "Unexpected Request" );
+        return EVasUnexpectedRequest;
+        }
+    
+    // Check callback
+    if ( !aInitCompleteHandler )
+        {
+        return EVasInvalidParameter;
+        }    
+    
+    iInitCompleteHandler = aInitCompleteHandler;
+    
+    if ( !iSrsApi )
+        {		
+        TRAPD( err, CreateSrfL() );
+        if ( err != KErrNone )
+            {
+            RUBY_DEBUG0( "SRS creation fails" );
+            iSrsApi = NULL;
+            Cleanup();
+            return EVasRecognitionInitFailed;
+            }    
+        }
+      
+    iSrsApi->SetAudioPriority( KAudioPriorityVoiceDial, 
+                               KAudioPrefVocosTrain, 
+                               KAudioPrefVocosPlayback, 
+                               KAudioPrefVocosRecog );               
+    
+    TInt errorCode = iSrsApi->PreStartSampling();
+    
+    if ( errorCode != KErrNone )
+        {
+        RUBY_DEBUG1( "PreStartSampling Err = %d", errorCode );
+        Cleanup();
+        return EVasRecognitionInitFailed;
+        }    
+    
+    return EVasErrorNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::SelectTagL
+// Method to initiate the Select Tag event.
+// -----------------------------------------------------------------------------
+//
+MNssRecognitionHandler::TNssRecognitionResult CNssRecognitionHandler::SelectTagL(
+															   MNssTag *aClientTag)
+    {
+    return SelectTagL( aClientTag, ETrue );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::SelectTagL
+// Method to initiate the Select Tag event.
+// -----------------------------------------------------------------------------
+//
+MNssRecognitionHandler::TNssRecognitionResult CNssRecognitionHandler::SelectTagL( 
+                                                            MNssTag* aClientTag, 
+                                                            TBool aNotifyHandlers )
+    {
+    RUBY_DEBUG_BLOCK( "CNssRecognitionHandler::SelectTagL" );
+    
+    if ( iRState != EVasWaitingForSelectTag )
+        {
+        RUBY_DEBUG0( "CNssRecognitionHandler::SelectTagL - Unexpected Request" );
+
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        
+        Cleanup();
+        return EVasUnexpectedRequest;
+        }
+    
+    if ( !aClientTag )
+        {
+        RUBY_DEBUG0( "CNssRecognitionHandler: Invalid Parameter" );
+
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        
+        Cleanup();
+        return EVasInvalidParameter;
+        }
+    
+    // Check if we want to notify GlobalContext handlers
+    if ( !aNotifyHandlers )
+        {
+        // No; just cleanup
+        Cleanup();
+        }
+    else
+        { // Yes
+        // make a copy of the client tag, aClientTag, so the client can delete it
+        CNssTag* internalTag = ((CNssTag*)aClientTag)->CopyL();
+        
+        Cleanup();
+        
+        CNssDBTagSelectNotifier *selectNotifier = iVasDBBuilder->GetTagSelectNotifier();
+        
+        selectNotifier->HandleSelection(internalTag);
+        
+        delete internalTag;
+        }
+    
+    return EVasErrorNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::RejectTagL
+// Method to perform Reject Tag, i.e. blacklisting.
+// -----------------------------------------------------------------------------
+//
+MNssRecognitionHandler::TNssRecognitionResult CNssRecognitionHandler::RejectTagL(
+						   MNssRejectTagCompleteHandler* aRejectTagCompleteHandler,
+		                   CArrayPtrFlat<MNssTag>* aClientTagList)
+    {
+    RUBY_DEBUG_BLOCK( "CNssRecognitionHandler::RejectTagL" );
+    
+    if ( iRState != EVasWaitingForSelectTag )
+        {
+        RUBY_DEBUG0( "CNssRecognitionHandler::RejectTagL - Unexpected Request" );
+
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 	
+        Cleanup();
+        return EVasUnexpectedRequest;
+        }
+    
+    // Begin a Loop to unload rules. A rule is contained in a tag.
+    // The unload rule requests are Asynchronous. The 
+    // loop is continued and completed in the event handler logic, 
+    // MsruoEvent(aEvent=UnloadRuleComplete).
+    // Loop through the input client tag list to build a Rule List, one rule 	
+    // for each tag. Unload the rule corresponding to each tag.
+    // iRejectTagCurrentLoopCount and iRejectTagCount control the loop.
+    
+    iRejectTagCompleteHandler = aRejectTagCompleteHandler;
+    
+    if (aClientTagList == 0)
+        {
+        // client tag list is NULL error
+        RUBY_DEBUG0( "CNssRecognitionHandler: Invalid Parm: Tag List Null" );
+
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        Cleanup();
+        return EVasInvalidParameter;
+        }
+    iRejectTagCount = aClientTagList->Count(); 
+    
+    if (iRejectTagCount == 0)
+        {
+        // tag list is empty error
+        RUBY_DEBUG0( "NssRecognitionHandler: Invalid Parm: Tag List Empty" );
+
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        Cleanup();
+        return EVasInvalidParameter;
+        }
+    
+    iRejectTagCurrentLoopCount = 0; 
+    
+    if (!iRuleList)
+        {
+        iRuleList = new (ELeave) CArrayFixFlat<TRuleEntry>(iRejectTagCount);
+        }
+    
+    TRuleEntry ruleEntry;
+    
+    for ( TInt index=0; index < iRejectTagCount; index++ )
+        {
+        CNssTag* tempTag = (CNssTag*)aClientTagList->At(index);
+        CNssSpeechItem* speechItem = (CNssSpeechItem*)tempTag->SpeechItem();
+        TUint32 ruleID = speechItem->RuleID();
+        
+        CNssContext* context = (CNssContext*)tempTag->Context();
+        TUint32 grammarID = context->GrammarId();
+        
+        ruleEntry.ruleId = ruleID; 
+        ruleEntry.grammarId = grammarID;
+        
+        iRuleList->AppendL(ruleEntry);
+        }
+    
+    // get the first iRuleList entry = 0. The rest of the entries are
+    // processed in the event handler, MsruoEvent(aEvent=UnloadRuleComplete)
+    ruleEntry = iRuleList->At(iRejectTagCurrentLoopCount);
+    TUint32 ruleID = ruleEntry.ruleId;
+    TUint32 grammarID = ruleEntry.grammarId;
+    
+    iRState = EVasWaitingForUnloadRuleComplete;
+    
+    RUBY_DEBUG0( "CNssRecognitionHandler: SRSF UnloadRule()" );
+    
+    TInt errorCode = iSrsApi->UnloadRule( (TSIGrammarID)grammarID, ruleID );
+    if ( errorCode )
+        {
+        RUBY_DEBUG1( "CNssRecognitionHandler: UnloadRule Err = %d", errorCode );
+
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        Cleanup();
+        return EVasRejectTagFailed;
+        }
+    
+    return EVasErrorNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::Cancel
+// Method to cancel the last recognition function.
+// -----------------------------------------------------------------------------
+//
+MNssRecognitionHandler::TNssRecognitionResult CNssRecognitionHandler::Cancel()
+    {
+    RUBY_DEBUG1( "CNssRecognitionHandler::Cancel() iRState = %d", iRState );
+
+	// a Cancel request for the Idle state requires no action.	
+    if ( iRState == EVasIdle )
+        {
+		return EVasErrorNone;    
+        }
+ 
+    // Notify P&S
+    RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+
+	// for all states except Idle call Cleanup which calls SRF cancel and 
+	// transitions to Idle state.
+    Cleanup();
+    return EVasErrorNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::GetAdaptationItemL
+// Method to get the adaptation data.
+// -----------------------------------------------------------------------------
+//
+MNssAdaptationItem* CNssRecognitionHandler::GetAdaptationItemL(void)
+    {
+    RUBY_DEBUG_BLOCK( "CNssRecognitionHandler::GetAdaptationItemL" );
+	
+    // Check state
+	if ( iRState != EVasWaitingForSelectTag )
+    	{
+        User::Leave( KErrNotReady );
+    	}
+
+    // Client Result Set should be there since the state is what it is.
+    if ( !iSIClientResultSet )
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+    // Construct adaptation item
+    CNssAdaptationItem* adaptationItem = CNssAdaptationItem::NewL( this, iSIClientResultSet );
+    // Adaptation item now owns the previous Client Result Set.
+    iSIClientResultSet = 0; 
+
+    // Add the item to our catalog of adaptation items.
+    CleanupStack::PushL( adaptationItem );
+    User::LeaveIfError( iAdaptItemArray.Append( adaptationItem ) );
+    CleanupStack::Pop( adaptationItem );
+
+    return( adaptationItem );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::GetAdaptationItemL
+// Method to get the adaptation data.
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::RemoveAdaptationItem(CNssAdaptationItem* anItem)
+    {
+    for ( TInt k( 0 ); k < iAdaptItemArray.Count(); k++ )
+        {
+        if ( iAdaptItemArray[k] == anItem )
+            {
+            iAdaptItemArray.Remove( k );
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::MsruoEvent
+// Method to process the events from SRS utility object
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::MsruoEvent( TUid aEvent, TInt aResult )
+    {
+    RUBY_DEBUG2( "CNssRecognitionHandler::MsruoEvent Event = 0x%x, Result = %d", aEvent.iUid, aResult );
+
+    switch ( aEvent.iUid )
+        {
+        case KUidAsrEventLoadModelsVal:
+            {
+            if (aResult == KErrNone)
+                {
+                DoLoadModelsComplete();
+                }
+            else
+                {
+                DoLoadModelsFailed();
+                }
+            break;
+            }
+            
+        case KUidAsrEventLoadGrammarVal:
+            {
+            if (aResult == KErrNone)
+                {
+                DoLoadGrammarComplete();
+                }
+            else
+                {
+                DoLoadGrammarFailed();
+                }
+            break;
+            }	
+        case KUidAsrEventRecognitionReadyVal:
+            {
+            if (aResult == KErrNone)
+                {
+                DoRecognitionReady();                
+                }
+            else
+                {
+                DoRecognitionFailed();
+                }
+            break;
+            }	
+        case KUidAsrEventRecognitionVal:
+            {
+            
+            if (aResult == KErrNone)
+                {
+                DoRecognitionComplete();
+                }
+            else if ((aResult == KErrAsrNoSpeech) ||
+                (aResult == KErrAsrSpeechTooEarly) ||
+                (aResult == KErrAsrSpeechTooLong) ||
+                (aResult == KErrAsrSpeechTooShort))
+                {
+                DoRecognitionFailedNoSpeech(aResult);
+                }
+            else if (aResult == KErrAsrNoMatch)
+                {
+                DoRecognitionFailedNoMatch();
+                }
+            // Handle Cancelled the same as Failed
+            else
+                {
+                DoRecognitionFailed();
+                }
+            break;
+            }	
+        case KUidAsrEventRecordStartedVal:
+            {
+            DoRecordStarted();
+            break;
+            }
+        case KUidAsrEventRecordVal:
+            {
+            if (aResult != KErrNone)
+                {
+                DoRecordFailed(aResult);
+                }
+            // ignore Record KErrNone
+            break;
+            }
+        case KUidAsrEventEouDetectedVal:
+            {
+            DoEouDetected();
+            break;
+            }
+            
+        case KUidAsrEventUnloadRuleVal:
+            {
+            if (aResult == KErrNone)
+                {
+                DoUnloadRuleComplete();
+                }
+            else
+                {
+                DoUnloadRuleFailed();
+                }
+            break;
+            }	
+            
+        case KUidAsrEventAdaptVal:
+            {
+            if ( iRState != EVasDirectAdaptation && iRState != EVasIdleAdaptation )
+                {
+#ifdef _DEBUG
+                User::Panic( KRecognitionHandlerPanic, __LINE__ );
+#endif
+                return;
+                }
+            
+            if ( iRState == EVasIdleAdaptation )
+                {
+                Cleanup();
+                }
+            
+            if ( aResult == KErrNone )
+                {
+                iAdaptationHandler->HandleAdaptComplete( KErrNone );
+                }
+            else{
+                iAdaptationHandler->HandleAdaptComplete( KErrGeneral );
+                }
+            iRState = EVasWaitingForSelectTag;
+            break;
+            }
+            
+        case KUidAsrEventRemoveRuleVal:
+            {
+            if ( iRState == EVasCorrectingPluginDatabase )
+                {
+                if ( iWait.IsStarted() )
+                    {
+                    iWait.AsyncStop();
+                    }
+                }
+            else
+                {
+                Cleanup();
+                }
+            break;
+            }
+            
+        case KUidAsrEventPreStartSamplingVal:
+            {
+            DoPreStartSamplingComplete( aResult );
+            break;
+            }     
+               
+        default:
+            {
+            UnexpectedEvent();
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::CNssRecognitionHandler
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CNssRecognitionHandler::CNssRecognitionHandler()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::ConstructL()
+    {
+    RUBY_DEBUG_BLOCK( "CNssRecognitionHandler::ConstructL" );
+    iVasDBBuilder = CNssVASDBBuilder::InstanceL();
+    iVasDBBuilder->InitializeL();
+    
+    iContextMgr = iVasDBBuilder->GetContextMgr();
+    
+    iTagMgr = iVasDBBuilder->GetTagMgr();
+    
+    iRState = EVasIdle;
+    
+    // Define P&S property
+    TInt err = RProperty::Define( KSINDUID, ERecognitionState, RProperty::EInt); 
+    if ( err != KErrNotFound && err != KErrAlreadyExists )
+        {
+        User::LeaveIfError( err );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::CleanupRecognizeInitFailed
+// Perform required cleanup to get back to the Idle state and issue the
+// HandleRecognizeInitError event with RecognizeInitFailed error code
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::CleanupRecognizeInitFailed()
+    {
+    RUBY_DEBUG0( "CNssRecognitionHandler::CleanupRecognizeInitFailed" );
+    
+    // Notify P&S
+    RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+    
+    Cleanup();
+    iInitCompleteHandler->HandleRecognizeInitComplete(
+        MNssRecognizeInitCompleteHandler::EVasRecognizeInitFailed );
+    }	
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::CleanupRecognizeFailed
+// Perform required cleanup to get back to the Idle state and issue the
+// HandleRecognizeError event with RecognizeFailed error code
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::CleanupRecognizeFailed()
+    {
+    RUBY_DEBUG0( "CNssRecognitionHandler::CleanupRecognizeFailed" );
+    
+    // Notify P&S
+    RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+    
+    Cleanup();
+    iEventHandler->HandleRecognizeComplete( NULL,
+        MNssRecognizeEventHandler::EVasRecognizeFailed);
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::CleanupRejectTagFailed
+// Perform required cleanup to get back to the Idle state and issue the
+// HandleRejectTagError event with RejectTagFailed error code
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::CleanupRejectTagFailed()
+    {
+    RUBY_DEBUG0( "CNssRecognitionHandler::CleanupRejectTagFailed" );
+    
+    // Notify P&S
+    RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 	
+    
+    Cleanup();
+    iRejectTagCompleteHandler->HandleRejectTagComplete(
+        MNssRejectTagCompleteHandler::EVasRejectTagFailed);
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::Cleanup
+// Perform required cleanup to get back to the Idle state
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::Cleanup()
+    {
+    RUBY_DEBUG0( "CNssRecognitionHandler::Cleanup" );
+    
+    if ( iTagMgr )
+        {
+        iTagMgr->CancelGetTag();
+        }
+    if ( iContextMgr )
+        {
+        iContextMgr->CancelGetContext();
+        }
+    DeleteSrf();
+    ClearContextList();
+    ClearTagList();
+    ClearRuleList();
+    ClearContextStatus();
+    
+    iRState = EVasIdle;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler:: DeleteSrf
+// Gracefully terminate and delete the SRF object, iSrsApi.
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DeleteSrf()
+    {
+    if ( iSrsApi )
+        {
+        RUBY_DEBUG0( "CNssRecognitionHandler::DeleteSrf" );
+        
+        iSrsApi->CancelUtility();
+        
+        iSrsApi->EndRecSession();  // no need to check return code
+        
+        iSrsApi->SetEventHandler(NULL);
+        
+        delete iSrsApi;
+        
+        iSrsApi=NULL;
+        }
+
+    if ( iSIClientResultSet )
+        {
+        delete iSIClientResultSet;
+        iSIClientResultSet = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::ClearContextList
+// Delete the context objects from iContextList
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::ClearContextList()
+    {
+    if (iContextList)
+        {
+        iContextList->ResetAndDestroy();
+        delete iContextList;
+        iContextList = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::ClearTagList
+// Delete the tag objects and tag list, iTagList
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::ClearTagList()
+    {
+    // The client deletes iTagList, its pointers,  and its tags
+    // There is a window in RecognitionComplete while looping
+    // through the ClientResultData and getting corresponding tags from
+    // VasDb (GetTag). If a VasDb error occurs during this loop, 
+    // Recognition still owns the iTagList tags and must delete them.
+    // Otherwise at the end of the GetTag loop the list is given to the
+    // client, and the client deletes the tags.
+    
+    // if iTagList is not NULL, delete iTagList and its tags.
+    
+    if ( iTagList )
+        {
+        iTagList->ResetAndDestroy();
+        delete iTagList;
+        iTagList = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::ClearRuleList
+// Delete the TRuleEntry objects from iRuleList
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::ClearRuleList()
+    {
+    if ( iRuleList )
+        {
+        iRuleList->Reset();
+        delete iRuleList;
+        iRuleList = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::ClearContextStatus
+// Delete the entries from iContextStatus
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::ClearContextStatus()
+    {
+    if ( iContextStatus )
+        {
+        iContextStatus->Reset();
+        delete iContextStatus;
+        iContextStatus = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::UnexpectedEvent
+// Unexpected event occurred. . 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::UnexpectedEvent()
+    {
+    RUBY_DEBUG1( "CNssRecognitionHandler - UnexpectedEvent() iRState = %d", iRState );
+    
+    switch ( iRState )
+        {
+        case EVasIdle:
+            {
+            RUBY_DEBUG0( "CNssRecognitionHandler - Idle, Unexpected Srs Event" );
+            break;
+            }
+            
+            // RecognitionInit
+        case EVasWaitingForLoadModelsComplete:
+        case EVasWaitingForLoadLexiconComplete:
+        case EVasWaitingForLoadGrammarComplete:
+        case EVasWaitingForRecognitionReadyRecognitionInit:
+            {
+            CleanupRecognizeInitFailed();
+            break;
+            }
+            
+            // Recognition
+        case EVasWaitingForRecordStarted:
+        case EVasWaitingForEouDetected:
+        case EVasWaitingForRecognitionComplete:
+            {
+            CleanupRecognizeFailed();
+            break;
+            }
+            
+            // RejectTag
+        case EVasWaitingForUnloadRuleComplete:
+        case EVasWaitingForRecognitionReadyRejectTag:
+            {
+            CleanupRejectTagFailed();
+            break;
+            }
+        case EVasWaitingForRecognize:
+        case EVasWaitingForSelectTag:
+            {
+            // There is no event handler to return to.
+            // Notify P&S
+            RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 			
+            Cleanup();
+            RUBY_DEBUG1( "CNssRecognitionHandler - Invalid State = %d", iRState );
+            break;
+            }
+        default:
+            {
+            // unknown state - do not know event handler to return to
+            // Notify P&S
+            RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+            Cleanup();
+            RUBY_DEBUG1( "CNssRecognitionHandler - Unknown State = %d", iRState );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoPreStartSamplingComplete
+// Handle PreStartSampling SRSF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoPreStartSamplingComplete( TInt aError )
+    {
+    iInitCompleteHandler->HandlePreSamplingStarted( aError );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoLoadModelsComplete
+// Handle LoadModelsComplete SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoLoadModelsComplete()
+    {
+    if ( iRState != EVasWaitingForLoadModelsComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    /*	iRState = EVasWaitingForLoadLexiconComplete;
+    TUint32 lexiconId = iContextList->
+    At(iContextCurrentLoopCount)->LexiconId();
+      
+    TInt errorCode = iSrsApi->LoadLexicon( (TSILexiconID)lexiconId );
+    if (errorCode)
+        {
+        CleanupRecognizeInitFailed();	
+        }
+    */
+    iRState = EVasWaitingForLoadGrammarComplete;
+    
+    // iContextCurrentLoopCount is 0
+    // set loop count to -1 so Load Grammar Complete converts it back to 0
+    iContextCurrentLoopCount = -1;
+    DoLoadGrammarComplete();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoLoadModelsFailed
+// Handle LoadModelsFailed SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoLoadModelsFailed()
+    {
+    if ( iRState != EVasWaitingForLoadModelsComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    CleanupRecognizeInitFailed();	
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoLoadLexiconComplete
+// Handle LoadLexiconComplete SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoLoadLexiconComplete()
+    {
+    if ( iRState != EVasWaitingForLoadLexiconComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    iRState = EVasWaitingForLoadGrammarComplete;
+    
+    // iContextCurrentLoopCount is 0
+    // set loop count to -1 so Load Grammar Complete converts it back to 0
+    iContextCurrentLoopCount--;
+    DoLoadGrammarComplete();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoLoadLexiconFailed
+// Handle LoadLexiconFailed SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoLoadLexiconFailed()
+    {
+    if ( iRState != EVasWaitingForLoadLexiconComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    CleanupRecognizeInitFailed();			
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoLoadGrammarComplete
+// Handle LoadGrammarComplete SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoLoadGrammarComplete()
+    {
+    if ( iRState != EVasWaitingForLoadGrammarComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    // if there are more contexts, 
+    // continue loading Grammars, into the SRS
+    iContextCurrentLoopCount++;
+    
+    while ( iContextCurrentLoopCount < iContextCount )
+        {
+        TBool status = iContextStatus->At( iContextCurrentLoopCount );
+        // if True, there are tags in the context load the grammar
+        if ( status )
+            {
+            TUint32 grammarId = iContextList->
+                At( iContextCurrentLoopCount )->GrammarId();
+            TInt errorCode = iSrsApi->LoadGrammar( (TSIGrammarID) grammarId ); 
+            if ( errorCode )
+                {
+                RUBY_DEBUG1( "CNssRecognitionHandler: LoadGrammar Err = %d", errorCode );
+                CleanupRecognizeInitFailed();			
+                }
+            return;
+            }
+        
+        // else False, skip the context and go to the next
+        else
+            {
+            iContextCurrentLoopCount++;	
+            }
+        }
+    
+    // are done loading contexts;				
+    iRState = EVasWaitingForRecognitionReadyRecognitionInit;
+    
+    RUBY_DEBUG0( "CNssRecognitionHandler: SRF Recognize" );
+    
+    // Asynchronous call: next expected event:  ERecognitionReady 
+    // dereference iClientResult ptr to make it a reference 
+    TInt errorCode = iSrsApi->Recognize( *iSIClientResultSet );
+    
+    if ( errorCode ) // Check if errorCode is zero (KErrNone) or non-zero.
+        {
+        RUBY_DEBUG1( "CNssRecognitionHandler: Recognize Err = %d", errorCode );
+        CleanupRecognizeInitFailed();
+        }							
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoLoadGrammarFailed
+// Handle LoadGrammarFailed SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoLoadGrammarFailed()
+    {
+    if ( iRState != EVasWaitingForLoadGrammarComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    CleanupRecognizeInitFailed();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoRecognitionReady
+// Handle RecognitionReady SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoRecognitionReady()
+    {
+    if ( iRState == EVasWaitingForRecognitionReadyRecognitionInit )
+        {
+        ClearContextStatus();
+        iRState = EVasWaitingForRecognize;
+        
+        RUBY_DEBUG0( "CNssRecognitionHandler: HandleRecognizeInitComplete" );
+       
+        iInitCompleteHandler->HandleRecognizeInitComplete( 
+            MNssRecognizeInitCompleteHandler::EVasErrorNone );
+        }
+    else if ( iRState == EVasWaitingForRecognitionReadyRejectTag )
+        {
+        iRState = EVasWaitingForRecognize;
+        
+        RUBY_DEBUG0( "CNssRecognitionHandler: HandleRejectTagComplete" );
+        
+        iRejectTagCompleteHandler->HandleRejectTagComplete(
+            MNssRejectTagCompleteHandler::EVasErrorNone );
+        }
+    else
+        {
+        UnexpectedEvent();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoRecognitionComplete
+// Handle RecognitionComplete SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoRecognitionComplete()
+    {
+    if ( iRState != EVasWaitingForRecognitionComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    
+    TInt resultSetCount = iSIClientResultSet->ResultCount();
+    
+    // allocate the Tag List - the client is responsible for deleting this
+    if (!iTagList)
+        {
+        iTagList = new CArrayPtrFlat<CNssTag>( 1 );
+        if ( !iTagList )
+            {
+            RUBY_DEBUG0( "CNssRecognitionHandler: TRAPD new CTAG Array failed" );
+            CleanupRecognizeFailed();
+            return;
+            }		
+        }
+    
+    // Loop to convert result set data to tags and put the tags 
+    // into a Tag List
+    // Since getTag is asynchronous the loop continues at
+    // member function GetTagCompleted(). Use loop control variables:
+    // iTagCurrentLoopCount and iTagCount
+    
+    iTagCurrentLoopCount = 0;
+    iTagCount = resultSetCount;
+    /*
+    const CSDClientResult& clientResult = iClientResultSet->At(0);
+    */
+    TInt count( iSIClientResultSet->ResultCount() );
+    TInt k( 0 );
+    TInt err( KErrNone );
+    
+    for ( k = 0; k < count; k++ )
+        {
+        const CSIClientResult* clientResult( NULL );
+        TRAP( err, clientResult = &iSIClientResultSet->AtL( k ) );
+        if ( err != KErrNone )
+            {
+            break;
+            }
+        
+        // Get the tag from DB
+        CNssTag* tag = iTagMgr->GetTag( 
+            clientResult->GrammarID(),
+            clientResult->RuleID() );
+        
+        if ( !tag )
+            {
+            RUBY_DEBUG0( "CNssRecognitionHandler::DoRecognitionComplete found a tag which is NOT in VAS database" );
+            TNssRState oldState = iRState;
+            iRState = EVasCorrectingPluginDatabase;
+
+            TInt error = iSrsApi->RemoveRule( clientResult->GrammarID(), clientResult->RuleID() );
+            if ( error == KErrNone && !iWait.IsStarted() )
+                {
+                iWait.Start();
+                }
+            iRState = oldState;
+            }
+        else
+            {
+            // Append it to the "our" tag list (which will be copied
+            // to produce client tag list)
+            TRAP( err, iTagList->AppendL( tag ) );
+        
+            if ( err != KErrNone )
+                {
+                break;
+                }
+            }
+        }
+    
+    // If no tags could be found
+    if ( iTagList->Count() == 0 )
+        {
+        RUBY_DEBUG0( "CNssRecognitionHandler::DoRecognitionComplete no tags found at all" );
+        // Cleans and makes the "RecognizeFailed" callback.
+        CleanupRecognizeFailed();
+        return;
+        }
+    
+    // Copy the tag list. The copy is sent to the client.
+    CArrayPtrFlat<MNssTag>* clientTagList = NULL;
+    
+    clientTagList = new CArrayPtrFlat<MNssTag>(1);
+    
+    if ( clientTagList == 0 )
+        {
+        // Cleans and makes the "RecognizeFailed" callback.
+        CleanupRecognizeFailed();
+        return;
+        }
+    
+    for ( k = 0; k < iTagList->Count(); k++ )
+        {
+        MNssTag* tag = STATIC_CAST( MNssTag*, (*iTagList)[k] );
+        
+        TRAP( err, clientTagList->AppendL( tag ) );
+        
+        if ( err != KErrNone )
+            {
+            RUBY_DEBUG0( "CRecognitionHandler: TRAPD DestList AppendL failed" );
+            
+            // Don't do the "ResetAndDestroy()" : iTagList still owns the tags.
+            clientTagList->Reset();
+            delete clientTagList;
+            
+            // Cleans and makes the "RecognizeFailed" callback.
+            CleanupRecognizeFailed();
+            return;
+            }			
+        }
+    
+    iRState = EVasWaitingForSelectTag;
+    
+    // After this, clientTagList owns the tags:
+    iTagList->Reset();
+    delete iTagList;
+    iTagList = 0;
+    
+    RUBY_DEBUG0( "CRecognitionHandler: HandleRecognizeComplete" );
+    
+    // Notify P&S
+    RProperty::Set( KSINDUID, ERecognitionState, ERecognitionSuccess ); 
+    
+    iEventHandler->HandleRecognizeComplete(
+        clientTagList, MNssRecognizeEventHandler::EVasErrorNone );
+    
+    //    const CSIClientResult& clientResult = iSIClientResultSet->AtL(0);
+    
+    /******************** Debug recognized tags *********************/
+    /*
+    RFs session;
+    RFile file;
+    _LIT( aFileName, "c:\\documents\\recotag.txt" );
+    
+      session.Connect();
+      if ( file.Open( session, aFileName, EFileWrite ) != KErrNone )
+      {
+      if ( file.Create( session, aFileName, EFileWrite ) != KErrNone )
+      {
+      User::Panic( _L("SDContrlDebug"), __LINE__ );
+      }
+      }
+      
+        for ( TInt k( 0 ); k < iSIClientResultSet->ResultCount(); k++ )
+        {
+        const CSIClientResult& clientResult = iSIClientResultSet->AtL(k);
+        
+          TBuf8<100> debugBuf;
+          debugBuf.AppendFormat( _L8("Recognized tag with RID:%d, GID:%d\n"), clientResult.RuleID(), clientResult.GrammarID() );
+          file.Write( debugBuf );
+          }
+          
+            
+              file.Close();
+              session.Close();
+    */
+    /****************************************************************/
+    
+    // get next tag
+    /*	TUint32 grammarId = clientResult.GrammarID();
+    TUint32 ruleId = clientResult.RuleID();
+    
+      TInt dbErrorCode;
+      dbErrorCode = iTagMgr->GetTag( this, 
+      grammarId, 
+      ruleId);
+      if (dbErrorCode!=KErrNone)
+      {
+        CleanupRecognizeFailed();
+        }
+    */
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoRecognitionFailedNoSpeech
+// Handle RecognitionFailedNoSpeech, RecognitionFailedTooEarly, 
+// RecognitionFailedTooLong, and RecognitionFailedTooShort SRF events 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoRecognitionFailedNoSpeech( TInt aResult )
+    {
+    if ( iRState != EVasWaitingForRecognitionComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    
+    MNssRecognizeEventHandler::TNssRecognizeError errCode;
+    errCode = MNssRecognizeEventHandler::EVasRecognizeFailed;
+    if ( aResult == KErrAsrNoSpeech )
+        {
+        errCode = MNssRecognizeEventHandler::EVasRecognitionFailedNoSpeech;
+        }
+    else if ( aResult == KErrAsrSpeechTooEarly )
+        {
+        errCode = MNssRecognizeEventHandler::EVasRecognitionFailedTooEarly;
+        }
+    else if ( aResult == KErrAsrSpeechTooLong )
+        {
+        errCode = MNssRecognizeEventHandler::EVasRecognitionFailedTooLong;
+        }
+    else if ( aResult == KErrAsrSpeechTooShort )
+        {
+        errCode = MNssRecognizeEventHandler::EVasRecognitionFailedTooShort;
+        }
+    
+    // Notify P&S
+    RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+    
+    Cleanup();
+    iEventHandler->HandleRecognizeComplete( NULL, errCode );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoRecognitionFailedNoMatch
+// Handle RecognitionFailedNoMatch SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoRecognitionFailedNoMatch()
+    {
+    if ( iRState == EVasWaitingForRecognitionReadyRecognitionInit )
+        {
+        CleanupRecognizeInitFailed();
+        }
+    else if ( iRState == EVasWaitingForRecognitionComplete )
+        {
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        Cleanup();
+        iEventHandler->HandleRecognizeComplete( NULL,
+            MNssRecognizeEventHandler::EVasRecognitionFailedNoMatch );	
+        }
+    else if ( iRState == EVasWaitingForRecognitionReadyRejectTag )
+        {
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        Cleanup();
+        iRejectTagCompleteHandler->HandleRejectTagComplete(
+            MNssRejectTagCompleteHandler::EVasNoTagInContexts);
+        }
+    else
+        {
+        UnexpectedEvent();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoRecognitionFailed
+// Handle RecognitionFailed SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoRecognitionFailed()
+    {
+    switch ( iRState )
+        {
+        case EVasWaitingForRecognitionReadyRecognitionInit:
+            {
+            CleanupRecognizeInitFailed();
+            break;
+            }
+        case EVasWaitingForRecordStarted:
+        case EVasWaitingForEouDetected:
+        case EVasWaitingForRecognitionComplete:
+            {
+            CleanupRecognizeFailed();
+            break;
+            }
+        case EVasWaitingForRecognitionReadyRejectTag:
+            {
+            CleanupRejectTagFailed();
+            break;
+            }
+        default:
+            {
+            UnexpectedEvent();
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoRecordStarted
+// Handle RecordStarted SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoRecordStarted()
+    {
+    if ( iRState != EVasWaitingForRecordStarted )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    iRState = EVasWaitingForEouDetected;
+    
+    // Notify P&S
+    RProperty::Set( KSINDUID, ERecognitionState, ERecognitionStarted ); 
+    
+    iEventHandler->HandleRecordStarted(); 
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoRecordFailed
+// Handle RecordFailed SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoRecordFailed( TInt aResult )
+    {
+    if ( iRState != EVasWaitingForEouDetected )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    if ( ( aResult == KErrDied ) ||
+        ( aResult == KErrAccessDenied ) )
+        {
+        
+        Cleanup();
+        iEventHandler->HandleRecognizeComplete( NULL,
+            MNssRecognizeEventHandler::EVasRecognizeAccessDeny );
+        }
+    else
+        {
+        CleanupRecognizeFailed();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoEouDetected
+// Handle EouDetected SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoEouDetected()
+    {
+    if ( iRState != EVasWaitingForEouDetected )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    iRState = EVasWaitingForRecognitionComplete;
+    // Notify P&S
+    RProperty::Set( KSINDUID, ERecognitionState, ERecognitionSpeechEnd ); 
+    
+    iEventHandler->HandleEouDetected();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoUnloadRuleComplete
+// Handle UnloadRuleComplete SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoUnloadRuleComplete()
+    {
+    if ( iRState != EVasWaitingForUnloadRuleComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    // if there are more tags
+    // continue unloading rules, from the SRS
+    iRejectTagCurrentLoopCount++;
+    if ( iRejectTagCurrentLoopCount < iRejectTagCount )
+        {
+        TRuleEntry ruleEntry = iRuleList->At( iRejectTagCurrentLoopCount );
+        TUint32 ruleID = ruleEntry.ruleId;
+        TUint32 grammarID = ruleEntry.grammarId;
+        
+        RUBY_DEBUG0( "CNssRecognitionHandler: SRF UnloadRule" );
+        
+        TInt errorCode = iSrsApi->UnloadRule( (TSIGrammarID)grammarID, ruleID );
+        if ( errorCode )
+            {
+            RUBY_DEBUG1( "CNssRecognitionHandler: UnloadRule Err = %d", errorCode );
+
+            CleanupRejectTagFailed();
+            }
+        }
+    else
+        {
+        ClearRuleList();
+        iRState = EVasWaitingForRecognitionReadyRejectTag;
+        
+        RUBY_DEBUG0( "CNssRecognitionHandler: SRF Recognize" );
+        
+        // dereference iClientResult ptr to make it a reference 
+        //TInt errorCode = iSrsApi->Recognize(*iClientResultSet);
+        TInt errorCode = iSrsApi->Recognize( *iSIClientResultSet );
+        if ( errorCode )
+            {
+            RUBY_DEBUG1( "CNssRecognitionHandler: Recognize Err = %d", errorCode );
+           
+            CleanupRejectTagFailed();
+            }	
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::DoUnloadRuleFailed
+// Handle UnloadRuleFailed SRF event 
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::DoUnloadRuleFailed()
+    {
+    ClearRuleList();
+    if ( iRState != EVasWaitingForUnloadRuleComplete )
+        {
+        UnexpectedEvent();
+        return;
+        }
+    CleanupRejectTagFailed();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::HandleTagCheckL
+// Loop through the contexts to build the ContextStatus array.
+// If there are any tags in any context,
+// Then proceed on with recognition and load models,
+// Else return with EVasNoTagInContexts.
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::HandleTagCheckL()
+    {
+    TBool anyTag = EFalse;
+    CNssContext* context;
+    
+    if ( !iContextStatus )
+        {
+        iContextStatus = new (ELeave) CArrayFixFlat<TBool>( iContextCount );
+        }
+    
+    __ASSERT_DEBUG( iContextCount == iContextList->Count(), User::Panic( KRecognitionHandlerPanic, __LINE__ ) );
+    
+    for ( TInt index=0; index < iContextCount; index++ )
+        {
+        context = iContextList->At( index );
+        // if a tag exists in the requested context, status is set to true
+        // if there are no tags in the requested context, status is set to false
+        TBool status = iContextMgr->TagExist( context );
+        
+        iContextStatus->AppendL( status );
+        if ( status )
+            {
+            // if a tag is found, set to True
+            anyTag = ETrue;
+            }
+        }
+    
+    if ( anyTag )
+        {
+        // True: there are tags, continue recognition
+        iRState = EVasWaitingForLoadModelsComplete;
+        
+        TUint32 modelBankID = iContextList->At( 0 )->ModelBankId();
+        TInt errorCode = iSrsApi->LoadModels( (TSIModelBankID)modelBankID ); 
+        if ( errorCode )
+            {
+            RUBY_DEBUG1( "CNssRecognitionHandler: LoadModels Err = %d", errorCode );
+            
+            CleanupRecognizeInitFailed();
+            }
+        }
+    else
+        {
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        // False: There are no tags in any context.
+        Cleanup();
+        iInitCompleteHandler->HandleRecognizeInitComplete(
+            MNssRecognizeInitCompleteHandler::EVasNoTagInContexts );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::CreateSrfL
+// Create the SRF object, iSrsApi.
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::CreateSrfL()
+    {
+    RUBY_DEBUG_BLOCK( "CNssRecognitionHandler::CreateSrfL" );
+    // passing the CNssRecognitionHandler object as an active event handler
+    // and passing the VAS Api's UID
+    iSrsApi	= CNssSiUtilityWrapper::NewL(*this, KNssVASApiUid);
+    }
+
+// -----------------------------------------------------------------------------
+// CNssRecognitionHandler::AdaptL
+// Starts adaptation. Called by MNssAdaptationItem.
+// -----------------------------------------------------------------------------
+//
+void CNssRecognitionHandler::AdaptL( MNssAdaptationEventHandler* aHandler,
+                                     CSIClientResultSet* aResult,
+                                     TInt aCorrect )
+    {
+    RUBY_DEBUG_BLOCK( "CNssRecognitionHandler::AdaptL" );
+    
+    if ( !aHandler || !aResult )
+        {
+        User::Leave( KErrArgument );
+        }
+    
+    // We can do an adaptation either
+    //  * directly after a recognition (direct adaptation), or
+    //  * when the state is idle (idle adaptation).
+    // In IDLE   Adaptation: We need to create and destroy SRS Utility object.
+    // In DIRECT Adaptation: We need to return to the same state where we left.
+    
+    if ( iRState == EVasIdle )
+        {
+        iRState = EVasIdleAdaptation;
+        
+        CreateSrfL();
+        
+        User::LeaveIfError( iSrsApi->Adapt( *aResult, aCorrect ) );
+        }
+    else if ( iRState == EVasWaitingForSelectTag )
+        {
+        iRState = EVasDirectAdaptation;
+        
+        if ( !iSrsApi )
+            {
+            User::Leave( KErrNotReady );
+            }
+        
+        User::LeaveIfError( iSrsApi->Adapt( *aResult, aCorrect ) );
+        }
+    else
+        {
+        User::Leave( KErrNotReady );
+        }
+    
+    iAdaptationHandler = aHandler;
+    }
+
+// -----------------------------------------------------------------------
+// CNssRecognitionHandler::CommonRecognizeInitL
+//
+// Called by RecognizeInitL -variants
+// to perform those initializations,
+// which do not depend on vocabulary.
+// -----------------------------------------------------------------------
+//
+MNssRecognitionHandler::TNssRecognitionResult
+CNssRecognitionHandler::CommonRecognizeInitL( 
+                    MNssRecognizeInitCompleteHandler* aInitCompleteHandler,
+                    TInt aMaxResults )
+    {
+    // Agenda:
+    // 1. Create CSISpeechRecognitoinUtility object
+    //
+    // 2. Call SetPrioritySettings & StartRecSession
+    //    - nothing interesting happens there
+    //
+    // 4. Initialize CSIClientResultSet for storing recongition results
+    //
+    if ( iRState != EVasIdle )
+        {
+        RUBY_DEBUG0( "CNssRecognitionHandler::RecognizeInitL - Unexpected Request" );
+
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        Cleanup();
+        return EVasUnexpectedRequest;
+        }
+    
+    // Check callback
+    if ( !aInitCompleteHandler )
+        {
+        return EVasInvalidParameter;
+        }
+    iInitCompleteHandler = aInitCompleteHandler;
+    
+    // Check that aMaxResults is reasonable (100 is an arbitrary limit)
+    if ( aMaxResults < 0 || aMaxResults > KMaxResults )
+        {
+        return EVasInvalidParameter; 
+        }
+    iMaxResults = aMaxResults;
+    
+    if ( !iSrsApi )
+        {		
+        // Put a trap in case instantiation of SRF leaves
+        TRAPD( err, CreateSrfL() );
+        if ( err != KErrNone )
+            {
+            RUBY_DEBUG0( "CNssRecognitionHandler::RecognizeInitL - create SRS fail" );
+            
+            iSrsApi = NULL;     // For clean up purpose
+            
+            // Notify P&S
+            RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+            
+            Cleanup();
+            return EVasRecognitionInitFailed;
+            }
+        }
+    
+    // Set audio priority. If some other application wants to play/record
+    // while we are recognizing, these priorities determine who gets the access.
+    iSrsApi->SetAudioPriority( KAudioPriorityVoiceDial, 
+                               KAudioPrefVocosTrain, 
+                               KAudioPrefVocosPlayback, 
+                               KAudioPrefVocosRecog );
+    
+    // speaker independent mode recognition session
+    TInt errorCode = iSrsApi->StartRecSession( ENSSSiMode );
+    
+    if ( errorCode != KErrNone )
+        {
+        RUBY_DEBUG1( "CNssRecognitionHandler: StartRecSession Err = %d", errorCode );
+
+        // Notify P&S
+        RProperty::Set( KSINDUID, ERecognitionState, ERecognitionFail ); 
+        
+        Cleanup();
+        return EVasRecognitionInitFailed;
+        }
+    
+    // Create the structure for recognition results
+    if ( !iSIClientResultSet )
+        {
+        iSIClientResultSet = CSIClientResultSet::NewL();
+        }
+    iSIClientResultSet->SetMaxResultsL( iMaxResults );
+    
+    return EVasErrorNone;
+    }
+
+// End of file