diff -r 8ce15fced3a6 -r cad71a31b7fc srsf/nssvasapi/nssvascore/src/nssvascspeechitemtrainer.cpp --- a/srsf/nssvasapi/nssvascore/src/nssvascspeechitemtrainer.cpp Thu Aug 19 09:56:14 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1965 +0,0 @@ -/* -* Copyright (c) 2004-2006 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - initial contribution. -* -* Contributors: -* -* Description: The CNssSpeechItemTrainer provides methods to train, save -* and delete CNssSpeechItem objects in large quantities. -* -*/ - - -/* Here is a state machine for training: -* -* Summary: -* -* Idle state -* | -* Waiting state <------------------- -* | | (loop back to waiting state) -* ################################### | -* # IF NEEDED: Create lexicon state # | -* # | # | -* # IF NEEDED: Create grammar state #--- -* # | # -* # Training state # -* ################################### -* | -* Idle state -* -* -* -* State: Idle state -* Event: A client calls TrainTextL, -* Action:This induces a call to CNssSpeechItemTrainer::TrainTextDealyed(). -* -* The basic idea of _delayed_training_ is that several training calls -* are piled up before taking action. When a large number of names is -* trained at a time, the economies of scale are considerable. -* -* So, TrainTextDelayed() adds the name to the to-be-trained list, -* and starts a _delay_timer_. When this delay timer has finished, the -* actual training starts. -* Transition: Idle state -> Waiting state -* -* -* State: Waiting state -* Event: A client calls TrainTextL. -* Action:The function adds the name to the to-be-trained list, and -* resets the timer -* (background: In contact synchronization via PC Suite, names are added -* every 1/2 seconds. We want to keep piling the names as long as -* new names keep coming. Since we can't wait 50 seconds -* before training, the only reasonable solution is to reset the timer -* every time a new name arrives) -* Transition: Waiting state -> Waiting state -* -* -* State: Waiting state -* Event: Timer finishes doing time. -* Action:Check the preparations for training: -* * Has the grammar for the context been created? -* * Has the lexicon for the context been created? -* CASE: Preconditions OK -* Action : Send async AddVoiceTags call -* Transition: Waiting state -> Training state -* -* State: Training state -* Event: Training finished -* Action: Save the newly created Rule IDs to the speech items. -* Commit the database. -* Make the callbacks (success or failure) to the client. -* -* Transition: Check if new names were piled during traning. -* YES: Training state -> Waiting state -* NO : Training state -> Idle state -* -*/ - -#include "srsfbldvariant.hrh" -#include "nssvascspeechitemtrainer.h" -#include "nssvasctrainingparameters.h" -#include "nssvascvasdatabase.h" -#include "nssvasmsavetagclient.h" -#include "nssvasmdeletetagclient.h" - -#include "rubydebug.h" - -#include - -#ifdef _DEBUG - // Used in UDEB only - _LIT( KSpeechItemTrainerPanic, "VasCSpeechItemTrainer" ); -#endif // _DEBUG - -#define DEBUGPANIC User::Panic( KSpeechItemTrainerPanic, __LINE__ ) -#define REACT( a, b ) if ( a != KErrNone ) { b; } -#define CHECK_NOT_NULL( a ) \ - if ( !(a) ) \ - { \ - return MNssSpeechItem::EVasTrainFailed; \ - } -#define ALLOWED_STATES( a, b, c ) \ - if ( iState != a && iState != b && iState != c ) \ - { \ - return MNssSpeechItem::EVasTrainFailed; \ - } - -// tags are buffered in the buffer that grows with this granularity -const TInt KTagBufferGranularity = 100; - -// rule ids are buffered in the buffer that grows with this granularity -const TInt KRuleIdBufferGranularity = 50; - -// tag ids are buffered in the buffer that grows with this granularity -const TInt KRemoveTagIdBufferGranularity = 50; - -// Granularity for the array of words per sinde phrase -const TInt KSindeWordArrayGranularity = 2; - - -// Local function declarations -TInt EnforceRuleIdCountInvariant( RArray& aArray, TInt aCount ); - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::CNssSpeechItemTrainer -// C++ default constructor can NOT contain any code, that -// might leave. -// --------------------------------------------------------- -// -CNssSpeechItemTrainer::CNssSpeechItemTrainer( CNssVASDatabase* aDatabase ) -: iDatabase( aDatabase ), - iSpeechItemBuffer ( NULL ), - iSpeechItemTrainingBuffer( NULL ), - iGrammarIdBuffer ( NULL ), - iGrammarIdDeletingBuffer( NULL ), - iTagBuffer(NULL) - { - // empty - } - - -// ----------------------------------------------------------------------------- -// CNssSpeechItemTrainer::ConstructL -// Symbian 2nd phase constructor can leave. -// This is overloaded function for SpeechItemTrainer from database -// ----------------------------------------------------------------------------- -// -void CNssSpeechItemTrainer::ConstructL() - { - RUBY_DEBUG_BLOCK("CNssSpeechItemTrainer::ConstructL"); - iActionTracker = CNssTrainingActionTracker::NewL( *this ); - - // Create buffer for grouping phrases in training - iSpeechItemBuffer = new(ELeave)RPointerArray; - iSpeechItemTrainingBuffer = 0; // No name being currently trained. - } - - -// ----------------------------------------------------------------------------- -// CNssSpeechItemTrainer::NewL -// Two-phased constructor. -// This is for new SpeechItemTrainer -// ----------------------------------------------------------------------------- -// -CNssSpeechItemTrainer* CNssSpeechItemTrainer::NewL( CNssVASDatabase* aDatabase ) - { - RUBY_DEBUG_BLOCK( "CNssSpeechItemTrainer::NewL" ); - - CNssSpeechItemTrainer* self = NewLC( aDatabase ); - CleanupStack::Pop( self ); - return self; - } - - -// ----------------------------------------------------------------------------- -// CNssSpeechItemTrainer::NewLC -// Two-phased constructor. -// This is overloaded function for SpeechItemTrainer from database -// ----------------------------------------------------------------------------- -// -CNssSpeechItemTrainer* CNssSpeechItemTrainer::NewLC( CNssVASDatabase* aDatabase ) - { - CNssSpeechItemTrainer* self - = new (ELeave) CNssSpeechItemTrainer( aDatabase ); - - CleanupStack::PushL( self ); - self->ConstructL(); - return self; - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::~CNssSpeechItemTrainer -// Delete the SpeechItemTrainer object and set the Portal's -// state to Terminate. -// The Trainer does not delete the Portal, the Portal -// deletes itself. -// --------------------------------------------------------- -// -CNssSpeechItemTrainer::~CNssSpeechItemTrainer() - { - RUBY_DEBUG0( "CNssSpeechItemTrainer::~CNssSpeechItemTrainer" ); - - delete iActionTracker; - - - // Buffer for grouping the MNssSpeechItems for efficient training. - if ( iSpeechItemBuffer ) - { - iSpeechItemBuffer->Reset(); - delete iSpeechItemBuffer; - } - - // Names, which are being trained by CSISpeechRecognitionUtility. - if ( iSpeechItemTrainingBuffer ) - { - iSpeechItemTrainingBuffer->Reset(); - delete iSpeechItemTrainingBuffer; - } - - // This buffer is sent to SRS Utility. Contains: The recognition phrase split into subwords. - iPhraseArray.ResetAndDestroy(); - - // Training parameters - delete iTrainingParams; - - // Context - delete iContext; - - // Rule ID array. Return values from AddVoiceTags() are placed here. - if ( iRuleIDArray ) - { - iRuleIDArray->Close(); - delete iRuleIDArray; - } - - if ( iDeleteRuleIDArray ) - { - RUBY_DEBUG0( "CNssSpeechItemTrainer::~CNssSpeechItemTrainer Deleting iDeleteRuleIDArray" ); - iDeleteRuleIDArray->Close(); - delete iDeleteRuleIDArray; - } - - // Handle to speech services - if ( iSrsApi ) - { - iSrsApi->CancelUtility(); - delete iSrsApi; - iSrsApi = NULL; - } - - // The tags to be saved: Owned by client - // RPointerArray *iTagBuffer; - if ( iTagBuffer ) - { - iTagBuffer->Reset(); - delete iTagBuffer; - iTagBuffer = 0; - } - - if ( iGrammarIdBuffer ) - { - iGrammarIdBuffer->Reset(); - delete iGrammarIdBuffer; - iGrammarIdBuffer = 0; - } - - if ( iGrammarIdDeletingBuffer ) - { - iGrammarIdDeletingBuffer->Reset(); - delete iGrammarIdDeletingBuffer; - iGrammarIdDeletingBuffer = 0; - } - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::RetrainTextDelayed -// Does delayed retraining. -// --------------------------------------------------------- -// -MNssSpeechItem::TNssSpeechItemResult CNssSpeechItemTrainer::RetrainTextDelayed( - MNssTrainTextEventHandler* aEventHandler, - CNssTrainingParameters* aTrainingParams, - CNssSpeechItem& aSpeechItem, - CNssContext& aContext) - { - RUBY_DEBUG0( "CNssSpeechItemTrainer::RetrainTextDelayed" ); - - // Check parameters: - // callback - CHECK_NOT_NULL( aEventHandler ); - - // phrase to be trained - CHECK_NOT_NULL( aSpeechItem.Text().Length() ); - - // Check state - ALLOWED_STATES( EStateIdle, ERetrainStateWaiting, ERetrainStateRetraining ); - - // Check event handler - if ( !iTrainEventHandler ) - { - iTrainEventHandler = aEventHandler; - } - else if ( iTrainEventHandler != aEventHandler ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - - // The training parameters and the context - // must be the same for all in the buffer. - TRAPD( error, - if ( !CheckTrainingParametersL( aTrainingParams ) || - !CheckContext( aContext ) ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - ); - if ( error != KErrNone ) - { - return MNssSpeechItem::EVasTrainFailed; - } - - // Buffer the training request - - // Allocate buffer, if not done earlier - if ( !SpeechItemBufferNeeded() ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - - // If this is the first tag, save Lexicon ID and Grammar ID. - if ( iSpeechItemBuffer->Count() == 0 ) - { - iLexiconId = aContext.LexiconId(); - iGrammarId = aContext.GrammarId(); - } - else - { - // The tags after the first one must have the same Gramamr ID & Lexicon ID. - if ( iLexiconId != aContext.LexiconId() || - iGrammarId != aContext.GrammarId() ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - } - - // Add request to buffer - TInt ret = iSpeechItemBuffer->Append( &aSpeechItem ); - - if ( ret != KErrNone ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - - // Restart timer. When the timer has waited for a defined period, the names - // get retrained. Timer is reseted every time RetrainTextDelayed is called. - // - // Retraining in groups is more efficient. The delay ensures this grouping. - switch( iState ) - { - case ERetrainStateRetraining: - // Wait for the retraining to finish before acting. - break; - - case EStateIdle: - SetState( ERetrainStateWaiting ); - RestartTimer(); - break; - - case ERetrainStateWaiting: - RestartTimer(); - break; - - default: - return( MNssSpeechItem::EVasTrainFailed ); - } - - return( MNssSpeechItem::EVasErrorNone ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::SaveTagDelayed -// Does delayed saving. -// --------------------------------------------------------- -// -TInt CNssSpeechItemTrainer::SaveTagDelayed( - MNssSaveTagClient* aSaveTagClient, - CNssTag& aTag ) - { - RUBY_DEBUG0( "CNssSpeechItemTrainer::SaveTagDelayed" ); - - // Check internal state: Must not be training - if ( this->iState != EStateIdle && - this->iState != ESaveStateWaiting && - this->iState != ESaveStateSaving ) - { - return( KErrNotReady ); - } - - // Check arguments - if ( aSaveTagClient == 0 ) - { - return KErrArgument; - } - - if ( !((CNssSpeechItem*)aTag.SpeechItem())->Trained() ) - { - return KErrNotReady; - } - - // The event handler must be the same for all group-saved tags - if ( !iSaveEventHandler ) - { - iSaveEventHandler = aSaveTagClient; - } - else if ( aSaveTagClient != iSaveEventHandler ) - { - return KErrArgument; - } - - // Buffer the saving request - - // Allocate buffer, if not done earlier - if ( !iTagBuffer ) - { - iTagBuffer = new RPointerArray( KTagBufferGranularity ); - - if ( !iTagBuffer ) - { - return KErrNoMemory; - } - } - - // Add request to buffer - TInt ret = iTagBuffer->Append( &aTag ); - - if ( ret != KErrNone ) - { - return( ret ); - } - - // Restart timer. When the timer has waited for a defined period, the names - // get saved. Timer is reseted every time SaveTagDelayed is called. - // - // Saving in groups is more efficient. The delay ensures this grouping. - switch( iState ) - { - case ESaveStateSaving: - // Wait for the training to finish before acting. - break; - - case EStateIdle: - SetState( ESaveStateWaiting ); - RestartTimer(); - break; - - case ESaveStateWaiting: - RestartTimer(); - break; - - default: - return( KErrCorrupt ); - } - - return( KErrNone ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::DeleteTagDelayed -// Does delayed deleting. -// (other items were commented in a header) -// --------------------------------------------------------- -// -TInt CNssSpeechItemTrainer::DeleteTagDelayed( - MNssDeleteTagClient* aDeleteTagClient, - CNssTag& aTag ) - { - RUBY_DEBUG0( "CNssSpeechItemTrainer::DeleteTagDelayed" ); - - // Check internal state: Must not be doing something else - ALLOWED_STATES( EStateIdle, EDeleteStateWaiting, EDeleteStateDeleting ); - - // Check arguments - CHECK_NOT_NULL( aDeleteTagClient ); - - // The event handler must be the same for all group-deleted tags - if ( !iDeleteEventHandler ) - { - iDeleteEventHandler = aDeleteTagClient; - } - else if ( aDeleteTagClient != iDeleteEventHandler ) - { - return KErrArgument; - } - - // Buffer the deleting request - - // Allocate buffer, if not done earlier - if ( !SpeechItemBufferNeeded() || - !GrammarIdBufferNeeded() ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - - // If this is the first tag, save the grammar id. - if ( iSpeechItemBuffer->Count() == 0 ) - { - iGrammarId = ((CNssContext*)aTag.Context())->GrammarId(); - if ( !iDeleteRuleIDArray ) - { - iDeleteRuleIDArray = new RArray; - if( !iDeleteRuleIDArray ) - { - return KErrNoMemory; - } - // no deletion. iDeleteRuleIDArray might still be used - } -// delete iDeleteRuleIDArray; // if any -// iDeleteRuleIDArray = new RArray; - } - else - { - // subsequent tags must have the same grammar id. - if ( iGrammarId != ((CNssContext*)aTag.Context())->GrammarId() ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - } - - // Add request to buffer - // iSpeechItemBuffer will be copied into iSpeechItemTrainingBuffer later and - // iSpeechItemTrainingBuffer will be used to delete tags from the VAS DB - TInt ret = iSpeechItemBuffer->Append( (CNssSpeechItem*)aTag.SpeechItem() ); - if ( ret != KErrNone ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - - RUBY_DEBUG1( "CNssSpeechItemTrainer::DeleteTagDelayed Adding [%d] to iDeleteRuleIDArray", - ( ( CNssSpeechItem* )aTag.SpeechItem() )->RuleID() ); - - ret = iDeleteRuleIDArray->Append( ( ( CNssSpeechItem* )aTag.SpeechItem() )->RuleID() ); - - if ( ret != KErrNone ) - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::DeleteTagDelayed Adding to iDeleteRuleIDArray failed with error [%d]", ret ); - return( MNssSpeechItem::EVasTrainFailed ); - } - - // Restart timer. When the timer has waited for a defined period, the names - // get deleted. Timer is reseted every time DeleteDagDelayed is called. - // - // Deleting in groups is more efficient. The delay ensures this grouping. - switch( iState ) - { - case EDeleteStateDeleting: - // Wait for the training to finish before acting. - break; - - case EStateIdle: - SetState( EDeleteStateWaiting ); - RestartTimer(); - break; - - case EDeleteStateWaiting: - RestartTimer(); - break; - - default: - return( KErrCorrupt ); - } - - return( KErrNone ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::TrainTextDelayed -// Does delayed training. -// --------------------------------------------------------- -// -MNssSpeechItem::TNssSpeechItemResult CNssSpeechItemTrainer::TrainTextDelayed( - MNssTrainTextEventHandler* aEventHandler, - CNssTrainingParameters* aTrainingParams, - CNssSpeechItem& aSpeechItem, - CNssContext& aContext) - { - RUBY_DEBUG0( "CNssSpeechItemTrainer::TrainTextDelayed" ); - - // Check parameters: - // callback - CHECK_NOT_NULL( aEventHandler ); - - // Text is not null - CHECK_NOT_NULL( aSpeechItem.Text().Length() ); - - // Check state - ALLOWED_STATES( EStateIdle, ETrainStateWaiting, ETrainStateTraining ); - - // Check event handler - if ( !iTrainEventHandler ) - { - iTrainEventHandler = aEventHandler; - } - else if ( iTrainEventHandler != aEventHandler ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - - // The training parameters and the context - // must be the same for all in the buffer. - TRAPD( error, - if ( !CheckTrainingParametersL( aTrainingParams ) || - !CheckContext( aContext ) ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - ); - if ( error != KErrNone ) - { - return MNssSpeechItem::EVasTrainFailed; - } - - // Buffer the training request - if ( !SpeechItemBufferNeeded() ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - - TInt ret = iSpeechItemBuffer->Append( &aSpeechItem ); - - if ( ret == KErrNoMemory ) - { - return( MNssSpeechItem::EVasTrainFailed ); - } - - // Restart timer. When the timer has waited for a defined period, the names - // get trained. Timer is reseted every time TrainTextDelayed is called. - // - // Training in groups is more efficient. The delay ensures this grouping. - switch( iState ) - { - case ETrainStateTraining: - // Wait for the training to finish before acting. - break; - - case EStateIdle: - SetState( ETrainStateWaiting ); - RestartTimer(); - break; - - case ETrainStateWaiting: - RestartTimer(); - break; - - default: - return( MNssSpeechItem::EVasTrainFailed ); - } - - return( MNssSpeechItem::EVasErrorNone ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::HandleTrainError -// Called if AddVoiceTags() call failed. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::HandleTrainError( RPointerArray*& anItemArray ) - { - RUBY_DEBUG0( "CNssSpeechItemTrainer::HandleTrainError" ); - - TInt count = anItemArray->Count(); - - CleanUpTraining(); - - // Announce the error to the client - for( TInt k=0; kHandleTrainComplete( KErrGeneral ); - - } - iTrainEventHandler = NULL; - // All the errors reported, everything was rolled back - // Back tothe idle state - SetState( EStateIdle ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::CleanUpTrianing -// Cleans memory allocated by training. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::CleanUpTraining(void) - { - // Delete buffered names - if ( iSpeechItemTrainingBuffer ) - { - iSpeechItemTrainingBuffer->Close(); - } - delete iSpeechItemTrainingBuffer; - iSpeechItemTrainingBuffer = 0; - - // Delete parameters common to all names - delete iTrainingParams; - iTrainingParams = 0; - - delete iContext; - iContext = 0; - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::DoTrainTextDelayed -// Starts training tags. Sends the AddVoiceTags() call. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::DoTrainTextDelayed() - { - SetState( ETrainStateTraining ); - - // Move from speech item buffers from filling state to processing state. - - // names to be trained + names to be retrained - iSpeechItemTrainingBuffer = iSpeechItemBuffer; - iSpeechItemBuffer = 0; - - // Initialize iSrsApi (speech recognition utility) - TInt error = CreateSrsApi(); - if ( error != KErrNone ) - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::DoTrainTextDelayed Creating SrsApi failed. Error [%d]", error ); - HandleTrainError( iSpeechItemTrainingBuffer ); - } - else - { - - __ASSERT_DEBUG( iContext->LexiconId() != KInvalidLexiconID, - User::Panic( KSpeechItemTrainerPanic, KErrCorrupt ) ); - __ASSERT_DEBUG( iContext->GrammarId() != KInvalidGrammarID, - User::Panic( KSpeechItemTrainerPanic, KErrCorrupt ) ); - - // Extract texts from speech items to phrase array. - - // iPhraseArray is an array of arrays: - // - // |-- firstname1 - // tag1 -|-- lastname1 - // - // tag2 -|-- firstname2 - // |-- lastname2 - iPhraseArray.ResetAndDestroy(); - - // Convert speech item array to the format understood by the Utility. - TInt ret = SpeechItems2Phrases( *iSpeechItemTrainingBuffer, iPhraseArray ); - if ( ret != KErrNone ) - { - SendTrainingCallbacks( ret ); - /** @todo reengineer into signle return path - @todo check that everything is cleaned up before the return */ - return; - } - - // Initialize Rule ID array. The Utility puts the IDs - // of newly created rules here. - // Not using (ELeave) since this is non-leaving function (trapping of (ELeave) is not allowed). - iRuleIDArray = new RArray; - - if ( iRuleIDArray == 0 ) - { - RUBY_DEBUG0( "CNssSpeechItemTrainer::DoTrainTextDelayed iRuleIDArray == 0" ); - - HandleTrainError( iSpeechItemTrainingBuffer ); - } - else - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::Calling AddVoiceTags (%d names)", - iPhraseArray.Count() ); - // allocation succeeded - - TRAPD( errSinde, const RArray& languages = - iTrainingParams->SindeLanguagesL() ); - - if ( errSinde == KErrNone ) - { -#ifdef __SINDE_TRAINING - TRAP_IGNORE( - const RArray& languages = - iTrainingParams->SindeLanguagesL(); - ret = iSrsApi->AddVoiceTags( iPhraseArray, - languages, - (TSILexiconID)iContext->LexiconId(), - (TSIGrammarID)iContext->GrammarId(), - *iRuleIDArray ); - ); // TRAP_IGNORE -#endif // __SINDE_TRAINING - } - else - { - // Use the old style of training if SINDE languages are not available - ret = iSrsApi->AddVoiceTags( iPhraseArray, - iTrainingParams->Languages(), - (TSILexiconID)iContext->LexiconId(), - (TSIGrammarID)iContext->GrammarId(), - *iRuleIDArray ); - } - - // error -> cleanup - if ( ret != KErrNone ) - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::AddVoiceTags failed(%d)", ret ); - - HandleTrainComplete( ret ); - } // if ret is not KErrNone - } // if iRuleIDArray allocation succeeded - } // if SRS API was created successfully - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::DoRetrainTextDelayed -// Starts the 1st phase of retraining, -// which is removing old rules. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::DoRetrainTextDelayed() - { - __ASSERT_DEBUG( iSpeechItemBuffer != 0, DEBUGPANIC ); - - SetState( ERetrainStateRetraining ); - - // Move speech item buffer from filling state to processing state. - iSpeechItemTrainingBuffer = iSpeechItemBuffer; - iSpeechItemBuffer = 0; - - // Initialize iSrsApi (speech recognition utility) - TInt error = CreateSrsApi(); - if ( error != KErrNone ) - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::DoRetrainTextDelayed Creating SrsApi failed. Error [%d]", error ); - HandleTrainError( iSpeechItemTrainingBuffer ); - return; - } - - // Start deleting tags - iTagDeleteCounter = 0; - DeleteNextTag(); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::DoRetrainAddVoiceTags -// Phase 2 of retraining: Add voice tags -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::DoRetrainAddVoiceTags() - { - SetState( ERetrainStateRetraining ); - - // Move from speech item buffers from filling state to processing state. - - __ASSERT_DEBUG( iContext->LexiconId() != KInvalidLexiconID, - User::Panic( KSpeechItemTrainerPanic, KErrCorrupt ) ); - __ASSERT_DEBUG( iContext->GrammarId() != KInvalidGrammarID, - User::Panic( KSpeechItemTrainerPanic, KErrCorrupt ) ); - - // Extract texts from speech items to phrase array. - - iPhraseArray.ResetAndDestroy(); - - // Convert speech item array to the format understood by the Utility. - TInt ret = SpeechItems2Phrases( *iSpeechItemTrainingBuffer, iPhraseArray ); - if ( ret != KErrNone ) - { - SendTrainingCallbacks( ret ); - return; - } - - // Allocate Rule ID array. The Utility fills this array. - // When the utility trans a name, it attaches a Rule ID to the name. - iRuleIDArray = new RArray; - if ( iRuleIDArray == 0 ) - { - SendTrainingCallbacks( KErrNoMemory ); - return; - } - - RUBY_DEBUG1( "CNssSpeechItemTrainer::Retrain Calling AddVoiceTags (%d names)", - iPhraseArray.Count() ); - - TRAPD( errSinde, const RArray& languages = - iTrainingParams->SindeLanguagesL() ); - - if ( errSinde == KErrNone ) - { -#ifdef __SINDE_TRAINING - TRAP_IGNORE( - const RArray& languages = - iTrainingParams->SindeLanguagesL(); - ret = iSrsApi->AddVoiceTags( iPhraseArray, - languages, - (TSILexiconID)iContext->LexiconId(), - (TSIGrammarID)iContext->GrammarId(), - *iRuleIDArray ); - ); // TRAP_IGNORE -#endif // __SINDE_TRAINING - } - else - { - // Use the old style of training if SINDE languages are not available - ret = iSrsApi->AddVoiceTags( iPhraseArray, - iTrainingParams->Languages(), - (TSILexiconID)iLexiconId, - (TSIGrammarID)iGrammarId, - *iRuleIDArray ); - } - - // error -> cleanup - if ( ret != KErrNone ) - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::Retrain ERROR: AddVoiceTags(%d)", ret ); - - SendTrainingCallbacks( ret ); - } - - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::DoRetrainAddVoiceTags -// After the new tags have been trained: -// Announce the new rule IDs for speech items, -// and update the rule IDs to the VAS database. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::HandleRetrainComplete( TInt aResult ) - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::HandleTrainComplete(%d)", aResult ); - - // iRuleIdArray contains the rule IDs of the newly trained tags. - // The following call makes sure that - // iRuleIdArray.Count() == iSpeechItemTrainingBuffer.Count(). - if ( EnforceRuleIdCountInvariant( *iRuleIDArray, - iSpeechItemTrainingBuffer->Count() ) != KErrNone ) - { - SendTrainingCallbacks( KErrNoMemory ); - } - else - { - TInt count = iSpeechItemTrainingBuffer->Count(); - RArray ruleIdUpdateArray( KRuleIdBufferGranularity ); - - for( TInt itemIdx = 0; itemIdx < count; itemIdx++ ) - { - CNssSpeechItem* item = (*iSpeechItemTrainingBuffer)[itemIdx]; - TUint32 ruleID = (*iRuleIDArray)[itemIdx]; - if ( ruleID != KInvalidRuleID ) - { - // tag was trained successfully - - item->DelayedTrainingComplete( ruleID ); - - TNssSpeechItem flatItem; - - flatItem.iRuleId = item->RuleID(); - flatItem.iTagId = item->TagId(); - - TInt ret = ruleIdUpdateArray.Append( flatItem ); - - if ( ret != KErrNone ) - { - ruleIdUpdateArray.Close(); - SendTrainingCallbacks( KErrNoMemory ); - return; - } - } - else - { - // training failed -> remove tag - iDatabase->DeleteTag( item->TagId() ); - } - } - - aResult = iDatabase->UpdateTagRuleIDs( ruleIdUpdateArray ); - ruleIdUpdateArray.Close(); - SendTrainingCallbacks( aResult ); - } - - - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::DoSaveTags -// Saves tags. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::DoSaveTags() - { - - __ASSERT_DEBUG( iState == ESaveStateWaiting, DEBUGPANIC ); - - // Save the tags en masse - TInt ret = iDatabase->SaveTags( iTagBuffer ); - - // Next, we're going to make callbacks to the client. - // Before that, we have to return the object to idle state, - // This way, the last callback can trigger new train/save action. - - // Destroy buffered tags - TInt count = iTagBuffer->Count(); - iTagBuffer->Close(); - delete iTagBuffer; - iTagBuffer = 0; - - // Detach save tag client - MNssSaveTagClient* client = iSaveEventHandler; - iSaveEventHandler = 0; - - // Make SpeechItemTrainer ready for new challenges - SetState( EStateIdle ); - - // Make callbacks - for ( TInt k = 0; k < count; k++ ) - { - if ( ret == KErrNone ) - { -#ifdef _DEBUG - TRAPD( err, client->SaveTagCompleted( KErrNone ) ); - __ASSERT_DEBUG( err == KErrNone, DEBUGPANIC ); -#else - client->SaveTagCompleted( KErrNone ); -#endif // _DEBUG - } - else - { -#ifdef _DEBUG - TRAPD( err, client->SaveTagCompleted( KErrGeneral ) ); - __ASSERT_DEBUG( err == KErrNone, DEBUGPANIC ); -#else - client->SaveTagCompleted( KErrGeneral ); -#endif // _DEBUG - } - } - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::DoDeleteTags -// Starts tag removal. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::DoDeleteTags() - { - // NOTE: This method is never called from anywhere! - - SetState( EDeleteStateDeleting ); - - TInt err = CreateSrsApi(); - if ( err != KErrNone ) - { - RemoveTagsFinished( err ); - return; - } - - // Move Tag Buffer from filling state to processing state. - iSpeechItemTrainingBuffer = iSpeechItemBuffer; - iSpeechItemBuffer = 0; - iSpeechItemBuffer = new RPointerArray; // New filling buffer - if( !iSpeechItemBuffer ) - { - SendTrainingCallbacks( KErrNoMemory ); - return; - } - - iTagDeleteCounter = 0; - DeleteNextTag(); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::DoDeleteGroupedTags -// Starts grouped tag removal. -// Used when deleting tags without retraining. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::DoDeleteGroupedTags() - { - RUBY_DEBUG1("CNssSpeechItemTrainer::DoDeleteGroupedTags iDeleteRuleIDArray->Count() = [%d]", iDeleteRuleIDArray->Count() ); - SetState( EDeleteStateDeleting ); - - // Move Tag Buffer from filling state to processing state. - // We want to have this buffer != NULL so that we are able to do callbacks (with appropriate error code ) - // in RemoveTagsFinished method even if e.g. CreateSrsApi fails. - iSpeechItemTrainingBuffer = iSpeechItemBuffer; - iSpeechItemBuffer = 0; - - TInt err = CreateSrsApi(); - if ( err != KErrNone ) - { - RemoveTagsFinished( err ); - return; - } - - iSpeechItemBuffer = new RPointerArray; // New filling buffer - - if( !iSpeechItemBuffer ) - { - // As this method is not used when retraining, no need - // to send other callbacks than those related to deleting tags. - RemoveTagsFinished( KErrNoMemory ); - return; - } - - TInt ret = iSrsApi->RemoveRules( ( TSIGrammarID )iGrammarId, - *iDeleteRuleIDArray ); - - if ( ret != KErrNone && ret != KErrNotFound ) - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::DoDeleteGroupedTags RemoveRules failed. \ - Error [%d]", ret ); - RemoveTagsFinished( ret ); - return; - } - - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::DeleteNextTag -// Sends a RemoveRule() call for the next rule in the removal queue. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::DeleteNextTag() - { - RUBY_DEBUG2( "CNssSpeechItemTrainer::DeleteNextTag iTagDeleteCounter [%d], iSpeechItemTrainingBuffer->Count() [%d]", iTagDeleteCounter, iSpeechItemTrainingBuffer->Count() ); - - __ASSERT_DEBUG( iTagDeleteCounter <= iSpeechItemTrainingBuffer->Count(), - User::Panic( KSpeechItemTrainerPanic, __LINE__ ) ); - - CNssSpeechItem* speechItem = (*iSpeechItemTrainingBuffer)[iTagDeleteCounter]; - - TInt ret = iSrsApi->RemoveRule( - (TSIGrammarID)speechItem->GrammarId(), - (TSIRuleID)speechItem->RuleID() - ); - - if ( ret != KErrNone && ret != KErrNotFound ) - { - RemoveTagsFinished( ret ); - return; - } - } - - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::HandleRemoveTagComplete -// Called after SRS has successfully removed a tag. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::HandleRemoveTagComplete() - { - iTagDeleteCounter++; - - if ( iTagDeleteCounter < iSpeechItemTrainingBuffer->Count() ) - { - DeleteNextTag(); - } - else - { - RemoveTagsFinished( KErrNone ); - return; - } - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::HandleRemoveTagsComplete -// Called after SRS has successfully removed a group of tags. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::HandleRemoveTagsComplete() - { - RemoveTagsFinished( KErrNone ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::HandleRemoveTagFailed -// Called if SRS fails to remove a tag. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::HandleRemoveTagFailed( TInt aError ) - { - RemoveTagsFinished( aError ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::RemoveTagsFinished -// All required tags have been removed. -// Go to next phase. -// functions a bit defferently depending on whether we were retraining or -// deleting tags -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::RemoveTagsFinished( TInt aSuccess ) - { - // The continuation depends on what we are doing: - - // If we are deleting tags - if ( iState == EDeleteStateDeleting ) - { - if ( aSuccess == KErrNone ) - { - RemoveTagsFromVAS(); - } - else{ - FinishDeleteTags( aSuccess ); - } - } - - // If we are retraining - // (removing the old rules before adding the new ones) - else if ( iState == ERetrainStateRetraining ) - { - if ( aSuccess == KErrNone ) - { - DoRetrainAddVoiceTags(); - } - else{ - SendTrainingCallbacks( aSuccess ); - } - } - else - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::RemoveTagsFinished - ERROR: Wrong state(%d)", iState ); - } - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::RemoveTagsFromVAS -// Deletes tags from VAS. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::RemoveTagsFromVAS() - { - RArray tagIdArray( KRemoveTagIdBufferGranularity ); - TInt ret = KErrNone; - - ////////////// Remove tags from VAS DB /////////////////// - - // Take the Tag IDs to an array. - for ( TInt k( 0 ); k < iSpeechItemTrainingBuffer->Count(); k++ ) - { - ret |= tagIdArray.Append( (*iSpeechItemTrainingBuffer)[k]->TagId() ); - } - - // Delete tags from VAS DB - if ( ret == KErrNone ) - { - ret = iDatabase->DeleteTags( tagIdArray ); - } - - // Close tag ID array. - tagIdArray.Close(); - - ////////////// Remove tags from VAS DB done ////////////// - - FinishDeleteTags( KErrNone ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::FinishDeleteTags -// Cleans up and sends calbacks after -// deleting has finished or completed. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::FinishDeleteTags( TInt aSuccess ) - { - RUBY_DEBUG1("CNssSpeechItemTrainer::FinishDeleteTags aSuccess [%d]", aSuccess); - // Commit or uncommit according to success - if ( iSrsApi ) - { - if ( aSuccess == KErrNone ) - { - CommitSIUpdate(); - } - else{ - UncommitSIUpdate(); - } - } - - // Free memory - TInt count( 0 ); - if ( iSpeechItemTrainingBuffer ) - { - count = iSpeechItemTrainingBuffer->Count(); - RUBY_DEBUG1("CNssSpeechItemTrainer::FinishDeleteTags aSuccess Freeing [%d] items from the training buffer", count); - iSpeechItemTrainingBuffer->Close(); - } - delete iSpeechItemTrainingBuffer; - iSpeechItemTrainingBuffer = 0; - - // Send callbacks - MNssDeleteTagClient* client = iDeleteEventHandler; - iDeleteEventHandler = 0; - iTagDeleteCounter = 0; - - - for ( TInt k( 0 ); k < count; k++ ) - { - RUBY_DEBUG1("CNssSpeechItemTrainer::FinishDeleteTags sending callback for item [%d]", k); - // Failed or succeedeed, one rule is processed - iDeleteRuleIDArray->Remove(0); - - client->DeleteTagCompleted( aSuccess ); - } - RUBY_DEBUG2("CNssSpeechItemTrainer::FinishDeleteTags Reported [%d] deletions. [%d] remaining. Setting idle state", count, iDeleteRuleIDArray->Count()); - SetState( EStateIdle ); - - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::RunBufferedActionsL -// Called when it is time to execute the buffered actions -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::RunBufferedActionsL() - { - RUBY_DEBUG_BLOCK( "CNssSpeechItemTrainer::RunL" ); - - if ( iState == ETrainStateWaiting ) - { - DoTrainTextDelayed(); - } - else if ( iState == ESaveStateWaiting ) - { - DoSaveTags(); - } - else if ( iState == EDeleteStateWaiting ) - { - DoDeleteGroupedTags(); - } - else if ( iState == ERetrainStateWaiting ) - { - DoRetrainTextDelayed(); - } - else - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::RunL - ERROR: Wrong state (%d)", iState ); - } - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::RestartTimer -// Restarts the timer. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::RestartTimer() - { - TRAP_IGNORE( iActionTracker->ActionRequestedL() ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::CheckTrainingParametersL -// All tags in the queue should have the same training parameters. This -// function check that a new context has similar training parameters -// as the previous ones. -// --------------------------------------------------------- -// -TBool CNssSpeechItemTrainer::CheckTrainingParametersL( const CNssTrainingParameters* aParams ) - { - if ( aParams ) - { - if ( !iTrainingParams ) - { - // Make a local copy of training parameters - iTrainingParams = CNssTrainingParameters::NewL(); - - const RArray& paramLangArray = aParams->Languages(); - - RArray* langArray = new ( ELeave ) RArray; - CleanupStack::PushL( langArray ); - - for ( TInt k = 0; k < paramLangArray.Count(); k++ ) - { - TInt ret = langArray->Append( paramLangArray[ k ] ); - if ( ret != KErrNone ) - { - langArray->Close(); - delete langArray; - return EFalse; - } - } - - // Copy training languages - iTrainingParams->SetLanguages( langArray ); - CleanupStack::Pop( langArray ); - - // Copy SINDE languages - TRAP_IGNORE( iTrainingParams->SetSindeLanguages( aParams->SindeLanguagesL() ) ); - - // Copy separator - iTrainingParams->SetSeparator( aParams->Separator() ); - } - else - { - // Compare with previous training parameters - - // Separator - if ( aParams->Separator() != iTrainingParams->Separator() ) - { - return EFalse; - } - - // Training languages - for ( TInt k = 0; k < aParams->Languages().Count(); k++ ) - { - if ( aParams->Languages()[ k ] != iTrainingParams->Languages()[ k ] ) - { - return EFalse; - } - } - - // @todo SINDE languages should be checked also! - } - } - - return ETrue; - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::CheckContext -// All tags in the queue should have the same contexts. This -// function check that a new context is similar to that of previous tags. -// --------------------------------------------------------- -// -TBool CNssSpeechItemTrainer::CheckContext(CNssContext& aContext) - { - if ( &aContext == 0 ) // Default settings - anything goes. - { - return( EFalse ); - } - - if ( aContext.RecognitionMode() != ENSSSdSiMode && - aContext.RecognitionMode() != ENSSSiMode ) - { - return( EFalse ); - } - - if ( iContext ) - { - // Check that identifiers (name & ID) are identical. - if ( aContext.ContextId() != iContext->ContextId() ) - { - return( EFalse ); - } - - if ( aContext.ContextName().Compare( iContext->ContextName() ) != 0 ) - { - return( EFalse ); - } - } - else - { - if ( aContext.RecognitionMode() == ENSSSdSiMode ) - { - aContext.SetRecognitionMode( ENSSSiMode ); - } - - TRAPD( error, iContext = aContext.CopyL() ); - if ( error != KErrNone ) - { - return EFalse; - } - } - - return( ETrue ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::HandleTrainComplete -// Called after speech recognition utility has trained all tags. -// Announces the newly assigned Rule IDs for the speech items. -// Signals the VAS client that training has been finished. -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::HandleTrainComplete( TInt aResult ) - { - RUBY_DEBUG1( "CNssSpeechItemTrainer::HandleTrainComplete(%d)", aResult ); - - // iRuleIdArray contains the rule IDs of the newly trained tags. - // The following call makes sure that - // iRuleIdArray.Count() == iSpeechItemTrainingBuffer.Count(). - if ( EnforceRuleIdCountInvariant( *iRuleIDArray, - iSpeechItemTrainingBuffer->Count() ) != KErrNone ) - { - SendTrainingCallbacks( KErrNoMemory ); - } - - // Save rule IDs. Some rule IDs may have "KInvalidRuleID". This is a sign - // that training failed. It's good to save also that info to speech items. - for( TInt itemIdx = 0; itemIdx < iSpeechItemTrainingBuffer->Count(); itemIdx++ ) - { - CNssSpeechItem* item = (*iSpeechItemTrainingBuffer)[ itemIdx ]; - TUint32 ruleID = (*iRuleIDArray)[ itemIdx ]; - - item->DelayedTrainingComplete( ruleID ); - } - - SendTrainingCallbacks( aResult ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::SendTrainingCallbacks -// -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::SendTrainingCallbacks( TInt aResult ) - { - // If the changes were successful, commit them. - // If they werent, roll back the changes. - if ( aResult == KErrNone ) - { - CommitSIUpdate(); - } - else{ - UncommitSIUpdate(); - } - - // Save count (callback count)... - TInt count = iSpeechItemTrainingBuffer->Count(); - MNssTrainTextEventHandler* callback = iTrainEventHandler; - RArray* ruleIdArray = iRuleIDArray; - iRuleIDArray = 0; - - // Delete buffered names that were just trained - if ( iSpeechItemTrainingBuffer ) - { - iSpeechItemTrainingBuffer->Close(); - } - delete iSpeechItemTrainingBuffer; - iSpeechItemTrainingBuffer = 0; - - - // If there are names on the training queue, - // restart the waiting of delayed training. - if ( iSpeechItemBuffer && iSpeechItemBuffer->Count() > 0 ) - { - // don't delete context etc as training will be continued - SetState( ETrainStateWaiting ); - RestartTimer(); - } - else - { - SetState( EStateIdle ); - - // Cleanup - delete iTrainingParams; - iTrainingParams = 0; - - delete iContext; - iContext = 0; - - iTrainEventHandler = 0; - } - - // Make the callbacks to the client according to the recognition result. - for( TInt k( 0 ); k < count; k++ ) - { - if ( ruleIdArray->Count() <= k ) - { - RUBY_DEBUG2( "CNssSpeechItemTrainer::SendTrainingCallbacks ruleIdArray->Count() [%d] <= k [%d]", ruleIdArray->Count(), k ); - callback->HandleTrainComplete( KErrNoMemory ); - } - if ( (*ruleIdArray)[ k ] == KInvalidRuleID ) - { - RUBY_DEBUG0( "CNssSpeechItemTrainer::SendTrainingCallbacks (*ruleIdArray)[ k ] == KInvalidRuleID" ); - if ( aResult == KErrNone ) - { - callback->HandleTrainComplete( KErrGeneral ); - } - else - { - callback->HandleTrainComplete( aResult ); - } - - } - else - { - callback->HandleTrainComplete( KErrNone ); - } - } - - ruleIdArray->Close(); - delete ruleIdArray; - ruleIdArray = 0; - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::MsruoEvent -// SRS Utility callback function -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::MsruoEvent( TUid aEvent, TInt aResult ) - { - switch( aEvent.iUid ) - { - case KUidAsrEventAddVoiceTagsVal: - RUBY_DEBUG0( "CNssSpeechItemTrainer::MsruoEvent - state is KUidAsrEventAddVoiceTagsVal" ); - - if ( iState == ETrainStateTraining ) - { - HandleTrainComplete( aResult ); - } - else if ( iState == ERetrainStateRetraining ) - { - HandleRetrainComplete( aResult ); - } - break; - - case KUidAsrEventRemoveRuleVal: - RUBY_DEBUG0( "CNssSpeechItemTrainer::MsruoEvent - state is KUidAsrEventRemoveRuleVal" ); - - if ( aResult == KErrNone || aResult == KErrNotFound ) - { - HandleRemoveTagComplete(); - } - else{ - HandleRemoveTagFailed( aResult ); - } - break; - - case KUidAsrEventRemoveRulesVal: - RUBY_DEBUG0( "CNssSpeechItemTrainer::MsruoEvent - state is KUidAsrEventRemoveRulesVal" ); - - if( aResult == KErrNone || aResult == KErrNotFound ) - { - HandleRemoveTagsComplete(); - } - else - { - HandleRemoveTagFailed( aResult ); - } - break; - - default: - RUBY_DEBUG2( "CNssSpeechItemTrainer::MsruoEvent - ERROR: Uknown state (%d,%d)", aEvent.iUid, aResult ); - break; - } - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::SplitPhraseSindeL -// Splits a phrase to parts. Returns the parts in array. -// --------------------------------------------------------- -// -CDesC16ArrayFlat* CNssSpeechItemTrainer::SplitPhraseSindeL( const TDesC& aPhrase, - TChar aSeparator ) - { - CDesC16ArrayFlat* wordArray = new ( ELeave ) CDesC16ArrayFlat( KSindeWordArrayGranularity ); - CleanupStack::PushL( wordArray ); - - // Separate the words in the phrase. - TPtrC text = aPhrase; // Cursor to the phrase - - do - { - TInt index = text.Locate( aSeparator ); - - if ( index != 0 ) - { - // no more separators -> this is the last word -> end of word == end of string - if ( index == KErrNotFound ) - { - index = text.Length(); - } - - // Add word to array - wordArray->AppendL( text.Left( index ) ); - } - - // Discard the processed word - TInt charactersLeft = text.Length() - index; - // Forget the separator - if ( charactersLeft > 0 ) - { - charactersLeft--; - } - - // Update text cursor - text.Set( text.Right( charactersLeft ) ); - - } - while( text.Length() > 0 ); - - CleanupStack::Pop( wordArray ); - return wordArray; - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::SplitPhrase -// Splits a phrase to parts. Returns the parts in array. -// --------------------------------------------------------- -// -CDesC16ArrayFlat* CNssSpeechItemTrainer::SplitPhraseL( const TDesC& aPhrase, TChar aSeparator ) - { - CDesC16ArrayFlat *wordArray = new (ELeave) CDesC16ArrayFlat( KSindeWordArrayGranularity ); - - // Separate the words in the phrase. Especially firstname / lastname. - TPtrC text = aPhrase; // Cursor to the phrase - - do - { - TInt index = text.Locate( aSeparator ); - - // no more separators -> this is the last word -> end of word == end of string - if ( index == -1 ) - { - index = text.Length(); - } - - // Add word to array - wordArray->AppendL( text.Left( index ) ); - - // Discard the processed word - TInt charactersLeft = text.Length() - index; - // Forget the separator - // (the last word doesn't have one) - if ( charactersLeft > 0 ) - { - charactersLeft--; - } - - // Update text cursor - text.Set( text.Right( charactersLeft ) ); - - } - while( text.Length() > 0 ); - - return wordArray; - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::CommitSIUpdate -// Commits changes to SRS and destroys SRS utility. -// --------------------------------------------------------- -// -TInt CNssSpeechItemTrainer::CommitSIUpdate() - { - if ( !iSrsApi ) - { - return( KErrNotReady ); - } - - iSrsApi->CommitChanges(); - - delete iSrsApi; - iSrsApi = NULL; - - return( KErrNone ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::UncommitSIUpdate -// Destroys SRS utility without committing. -// --------------------------------------------------------- -// -TInt CNssSpeechItemTrainer::UncommitSIUpdate() - { - if ( !iSrsApi ) - { - return( KErrNotReady ); - } - - delete iSrsApi; - iSrsApi = NULL; - - return( KErrNone ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::SpeechItemBufferNeeded -// Trys to allocate a speech item buffer -// --------------------------------------------------------- -// -TBool CNssSpeechItemTrainer::SpeechItemBufferNeeded() - { - if ( !iSpeechItemBuffer ) - { - iSpeechItemBuffer = new RPointerArray; - if ( !iSpeechItemBuffer ) - { - return( EFalse ); - } - } - - return( ETrue ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::SpeechItemBufferNeeded -// Trys to allocate a grammar id buffer -// --------------------------------------------------------- -// -TBool CNssSpeechItemTrainer::GrammarIdBufferNeeded() - { - if ( !iGrammarIdBuffer ) - { - iGrammarIdBuffer = new RArray; - if ( !iGrammarIdBuffer ) - { - return( EFalse ); - } - } - - return( ETrue ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::SpeechItemBufferNeeded -// Trys to create SRS api. Returns success status. -// --------------------------------------------------------- -// -TInt CNssSpeechItemTrainer::CreateSrsApi() - { - if ( !iSrsApi ) - { - TRAPD( err, iSrsApi = CNssSiUtilityWrapper::NewL( *this, KNssVASApiUid ) ); - REACT( err, return( err ) ); - - iSrsApi->SetEventHandler( this ); - } - - return KErrNone; - } - - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::SpeechItems2Phrases -// Converts an array of speech items -// into Utility's AddVoiceTags array format. -// --------------------------------------------------------- -// -TInt CNssSpeechItemTrainer::SpeechItems2Phrases( - RPointerArray& aSpeechItems, - RPointerArray& aPhrases ) - { - // iPhraseArray is an array of arrays: - // - // |-- firstname1 - // tag1 -|-- lastname1 - // - // tag2 -|-- firstname2 - // |-- lastname2 - - // Create training parameters, if none were given - if ( iTrainingParams == 0 ) - { - RArray* languages = new RArray(); - - if ( !languages ) - { - return( KErrNoMemory ); - } - - // Use UI language + 1 other as default if languages are not given - // in training parameters - TInt err = languages->Append( User::Language() ); - - if ( err == KErrNone ) - { - err = languages->Append( ELangOther ); - } - - if ( err != KErrNone ) - { - languages->Close(); - delete languages; - return( err ); - } - - TRAP( err, iTrainingParams = CNssTrainingParameters::NewL() ); - if ( err != KErrNone ) - { - languages->Close(); - delete languages; - return( err ); - } - - iTrainingParams->SetLanguages( languages ); - } - - // Split the phrases to subwords (names -> first name + last name) - for ( TInt k( 0 ); k < aSpeechItems.Count(); k++ ) - { - // Split names into the first name and the last name - CDesC16ArrayFlat *wordArray = 0; - - // Check if SINDE type of training should be used - TRAPD( errSinde, const RArray& temp = - iTrainingParams->SindeLanguagesL() ); - if ( errSinde == KErrNone ) - { - TRAP_IGNORE( wordArray = SplitPhraseSindeL( aSpeechItems[ k ]->RawText(), - iTrainingParams->Separator() ) ); - } - else - { - TRAP_IGNORE( wordArray = SplitPhraseL( aSpeechItems[ k ]->Text(), - iTrainingParams->Separator() ) ); - } - - if ( wordArray == 0 ) - { - return KErrNoMemory; - } - - TInt ret = aPhrases.Append( wordArray ); - - if ( ret != KErrNone ) - { - return ret; - } - } - - return( KErrNone ); - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::SetState -// Changes state of the trainer -// --------------------------------------------------------- -// -void CNssSpeechItemTrainer::SetState(TTrainState aState) - { - RUBY_DEBUG2("CNssSpeechItemTrainer::SetState Switching state from [%d] to [%d]", iState, aState); -#ifdef _DEBUG - if( iState == EDeleteStateWaiting ) - { - RUBY_DEBUG0("CNssSpeechItemTrainer::SetState From EDeleteStateWaiting"); - } - if( aState == EDeleteStateWaiting ) - { - RUBY_DEBUG0("CNssSpeechItemTrainer::SetState To EDeleteStateWaiting"); - } - -#endif - iState = aState; - } - -// --------------------------------------------------------- -// CNssSpeechItemTrainer::EnforceRuleIdCountInvariant -// Adds KInvalidRuleId to the Rule ID Array, until -// the number of rules is equal to count. -// --------------------------------------------------------- -// -TInt EnforceRuleIdCountInvariant( RArray& aArray, TInt aCount ) - { - while( aArray.Count() < aCount ) - { - TInt err = aArray.Append( KInvalidRuleID ); - if ( err != KErrNone ) - { - return( err ); - } - } - - return KErrNone; - }