/*
* 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