diff -r cad71a31b7fc -r e36f3802f733 srsf/sisrscontrollerplugin/src/sindetraining.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srsf/sisrscontrollerplugin/src/sindetraining.cpp Wed Sep 01 12:29:17 2010 +0100 @@ -0,0 +1,505 @@ +/* +* Copyright (c) 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: Implementation for CSindeTrainer +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include "sindetraining.h" +#include "rubydebug.h" +#include "sidatabase.h" +#include "sigrammardb.h" +#include "silexicondb.h" + +// CONSTANTS + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CSindeTrainer::CSindeTrainer +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CSindeTrainer::CSindeTrainer( CDevASR& aDevAsr, + CSIControllerPluginInterface& aControllerIf, + CSIControllerPlugin& aPlugin, + CSIDatabase& aDatabase, + CSIGrammarDB& aGrammarDatabase, + CSILexiconDB& aLexiconDatabase ) : + CActive( EPriorityStandard ), + iState( ESindeTrainerIdle ), + iDevAsr( aDevAsr ), + iControllerIf( aControllerIf ), + iPlugin( aPlugin ), + iDatabase( aDatabase ), + iGrammarDatabase( aGrammarDatabase ), + iLexiconDatabase( aLexiconDatabase ) + { + // Nothing + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::ConstructL() + { + RUBY_DEBUG_BLOCK( "CSindeTrainer::ConstructL" ); + + // Add active object to active scheduler + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CSindeTrainer* CSindeTrainer::NewL( CDevASR& aDevAsr, + CSIControllerPluginInterface& aControllerIf, + CSIControllerPlugin& aPlugin, + CSIDatabase& aDatabase, + CSIGrammarDB& aGrammarDatabase, + CSILexiconDB& aLexiconDatabase ) + { + RUBY_DEBUG_BLOCK( "CSindeTrainer::NewL" ); + CSindeTrainer* self = new( ELeave ) CSindeTrainer( aDevAsr, aControllerIf, aPlugin, + aDatabase, aGrammarDatabase, + aLexiconDatabase ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::~CSindeTrainer +// Destructor +// ----------------------------------------------------------------------------- +// +CSindeTrainer::~CSindeTrainer() + { + RUBY_DEBUG0( "CSindeTrainer::~CSindeTrainer" ); + + Cancel(); + + delete iTtpWordList; + iMaxPronunsForWord.Close(); + + iTtpDataArray.ResetAndDestroy(); + iTtpDataArray.Close(); + + if ( iTrainArrays != NULL ) + { + iTrainArrays->ResetAndDestroy(); + iTrainArrays->Close(); + delete iTrainArrays; + } + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::SetReady +// Sets the object active and signals active scheduler to run it. +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::SetReady() + { + TRequestStatus* pRS = &iStatus; + User::RequestComplete( pRS, KErrNone ); + SetActive(); + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::RunL +// RunL of CActive +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::RunL() + { + RUBY_DEBUG0( "CSindeTrainer::RunL" ); + + switch ( iState ) + { + case ESindeTrainerTraining: + { + TRAPD( error, DoOneTrainingStepL() ); + if ( error != KErrNone ) + { + // Move to next state + iState = ESindeTrainerDbUpdate; + SetReady(); + } + break; + } + + case ESindeTrainerDbUpdate: + { + TRAPD( error, DoDatabaseUpdateL() ); + iError = error; + iState = ESindeGrammarCompilation; + SetReady(); + break; + } + + case ESindeGrammarCompilation: + { + TRAPD( error, DoGrammarCompilationL() ); + iError = error; + if ( error != KErrNone ) + { + // Move to next state + iState = ESindeTrainerFinished; + SetReady(); + } + break; + } + + case ESindeTrainerFinished: + { + RUBY_DEBUG1( "CSindeTrainer::RunL sending KUidAsrEventAddVoiceTags callback with error: %d", iError ); + // All done, do callback to client thread + iControllerIf.SendSrsEvent( KUidAsrEventAddVoiceTags, iError ); + iState = ESindeTrainerIdle; + break; + } + + default: + RUBY_ERROR0( "CSindeTrainer::RunL unexpected state" ); + break; + + } + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::DoCancel +// DoCancel of CActive +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::DoCancel() + { + RUBY_DEBUG0( "CSindeTrainer::DoCancel" ); + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::HandleEvent +// Handles event originated from DevASR +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::HandleEvent( TDevASREvent aEvent, TDevASRError aError ) + { + RUBY_DEBUG2( "CSindeTrainer::HandleEvent event: %d error: %d", aEvent, aError ); + + if ( aError == KErrNone ) + { + if ( aEvent == EDevASRTrainFromText ) + { + // Store the data + iTtpDataArray.Append( iTtpWordList ); + // Ownership transferred to array + iTtpWordList = NULL; + } + else if ( aEvent == EDevASRGrammarCompile ) + { + StoreCompiledGrammar(); + iState = ESindeTrainerFinished; + } + } + + // Do the next step in RunL + SetReady(); + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::AddSindeVoiceTagsL +// Starts training of SINDE voice tags +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::AddSindeVoiceTagsL( RPointerArray* aTrainArrays, + RArray& aLanguageArray, + TSILexiconID aLexiconId, + TSIGrammarID aGrammarId, + TSIModelBankID aModelBankId, + TUid aClientUid, + RArray& aRuleIds ) + { + RUBY_DEBUG_BLOCK( "CSindeTrainer::AddSindeVoiceTagsL" ); + + if ( IsActive() ) + { + User::Leave( KErrInUse ); + } + + // Start reading the input arrays from zero index + iLanguageIndex = 1; + iTextIndex = 0; + + // Destruct previous input if it still exists + if ( iTrainArrays != NULL ) + { + iTrainArrays->ResetAndDestroy(); + iTrainArrays->Close(); + delete iTrainArrays; + iTrainArrays = NULL; + } + + // Store parameters for asynchronous processing + iTrainArrays = aTrainArrays; + iLanguageArray = &aLanguageArray; + iLexiconId = aLexiconId; + iGrammarId = aGrammarId; + iClientUid = aClientUid; + iModelBankId = aModelBankId; + iRuleIds = &aRuleIds; + + iState = ESindeTrainerTraining; + SetReady(); + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::DoOneTrainingStep +// Starts one step of training using DevASR +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::DoOneTrainingStepL() + { + RUBY_DEBUG_BLOCK( "CSindeTrainer::DoOneTrainingStepL" ); + + // Delete the previous DevASR input data + delete iTtpWordList; + iTtpWordList = NULL; + iTtpWordList = CSITtpWordList::NewL(); + + for ( TInt i = 0; i < iTrainArrays->Count(); i++ ) + { + MDesCArray* originalText = (*iTrainArrays)[i]; + + CDesC16ArrayFlat* wordArray = new ( ELeave ) CDesC16ArrayFlat( 1 ); + CleanupStack::PushL( wordArray ); + + // Loop through all descriptors that are needed for this group and + // add them to new wordArray + for ( TInt j = 0; j < originalText->MdcaCount(); j++ ) + { + TInt textLength = originalText->MdcaPoint( j ).Length(); + if ( textLength > 0 ) + { + TPtrC firstChar( originalText->MdcaPoint( j ).Left( 1 ) ); + TInt length( 0 ); + TInt result( 0 ); + TDigitType type; + result = NumberConversion::ConvertFirstNumber( firstChar, length, type ); + + if ( result == iLanguageIndex ) + { + // Take off the first character + TPtrC text( originalText->MdcaPoint( j ).Right( textLength - 1 ) ); + wordArray->AppendL( text ); + } + } + } + + // Append empty descriptor if nothing else was found + if ( wordArray->Count() == 0 ) + { + wordArray->AppendL( KNullDesC ); + } + + iTtpWordList->AddL( wordArray ); + // Ownership transferred to iTtpWordList + CleanupStack::Pop( wordArray ); + } + + // Decrease 1 to get the current index, iLanguageIndex starts from 1 + TInt currentLanguageIndex( iLanguageIndex - 1 ); + + // Check that there is legal index for languageArray available + if ( ( currentLanguageIndex < 0 ) || ( currentLanguageIndex >= iLanguageArray->Count() ) ) + { + RUBY_ERROR0( "CSindeTrainer::DoOneTrainingStep language array index out of bounds" ); + User::Leave( KErrNotFound ); + } + + iMaxPronunsForWord.Reset(); + iMaxPronunsForWord.Append( (*iLanguageArray)[currentLanguageIndex].Count() ); + + // Do the training call to DevASR + iDevAsr.StartTrainingFromTextL( *iTtpWordList, (*iLanguageArray)[currentLanguageIndex], iMaxPronunsForWord ); + + // Move to next group + iLanguageIndex++; + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::DoDatabaseUpdateL +// Stores the training results into grammar and lexicon and updates the DB +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::DoDatabaseUpdateL() + { + RUBY_DEBUG_BLOCK( "CSindeTrainer::DoDatabaseUpdateL" ); + + iRuleIds->Reset(); + + iDatabase.BeginTransactionL(); + + // Get the grammar + iGrammarDatabase.VerifyOwnershipL( iClientUid, KGrammarIdTable, KGrammarIndex, iGrammarId ); + CSICompiledGrammar* grammar = ( CSICompiledGrammar* ) iGrammarDatabase.GrammarL( iGrammarId ); + CleanupStack::PushL( grammar ); + + // Get the lexicon + iLexiconDatabase.VerifyOwnershipL( iClientUid, KLexiconIdTable, KLexiconIndex, iLexiconId ); + CSILexicon* lexicon = iLexiconDatabase.LexiconL( iLexiconId ); + CleanupStack::PushL( lexicon ); + + iDatabase.CommitChangesL( EFalse ); + + // There should be at least one element in ttp data array + if ( iTtpDataArray.Count() > 0 ) + { + // Take the first word list + CSITtpWordList* ttpWordList = iTtpDataArray[0]; + + for ( TInt i = 0; i < ttpWordList->Count(); i++ ) + { + RPointerArray pronunciations; + RArray pronunciationIDs; + CleanupClosePushL( pronunciationIDs ); + CleanupClosePushL( pronunciations ); + // Take the pronunciations from ttp output + ttpWordList->GetPronunciationsL( i, pronunciations ); + + CSIRule* rule = iPlugin.CreateNewRuleL( grammar ); + CleanupStack::PushL( rule ); + + // if pronunciation generation failed, skip that word. + if ( pronunciations.Count() == 0 ) + { + User::LeaveIfError( iRuleIds->Append( KInvalidRuleID ) ); + CleanupStack::PopAndDestroy( rule ); + } + else + { + for ( TInt k = 0; k < pronunciations.Count(); k++ ) + { + pronunciationIDs.Reset(); + + for ( TInt n = 0; n < pronunciations[k]->Count(); n++ ) + { + // Add Pronunciation into lexicon + TDesC8& pronunciation = pronunciations[k]->PronunciationL( n ); + TSIPronunciationID pronunId = iPlugin.CreateNewPronunciationL( lexicon, pronunciation, iModelBankId ); + User::LeaveIfError( pronunciationIDs.Append( pronunId ) ); + } + + AppendPronunciationsL( i, *lexicon, pronunciationIDs ); + + // Add RuleVariant into grammar + iPlugin.AddNewRuleVariantL( *rule, iLexiconId, pronunciationIDs, *pronunciations[k] ); + } + + grammar->AddL( rule ); + CleanupStack::Pop( rule ); + + // Add rule to client side array + User::LeaveIfError( iRuleIds->Append( rule->RuleID() ) ); + } + + // Close the arrays + CleanupStack::PopAndDestroy( &pronunciations ); + CleanupStack::PopAndDestroy( &pronunciationIDs ); + + } // for ( TInt i = 0; i < ttpWordList->Count(); i++ ) + + // Do the updates into the database + iDatabase.BeginTransactionL(); + iGrammarDatabase.UpdateGrammarL( iClientUid, grammar ); + iLexiconDatabase.UpdateLexiconL( iClientUid, lexicon ); + // Commit changes to db with compact + iDatabase.CommitChangesL( ETrue ); + } // if ( iTtpDataArray.Count() > 0 ) + + CleanupStack::PopAndDestroy( lexicon ); + CleanupStack::PopAndDestroy( grammar ); + + // All data has been stored elsewhere + iTtpDataArray.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::DoGrammarCompilationL +// Does grammar compilation using DevASR +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::DoGrammarCompilationL() + { + iDatabase.BeginTransactionL(); + iCompiledGrammar = ( CSICompiledGrammar* )iGrammarDatabase.LoadGrammarL( iGrammarId ); + iDatabase.CommitChangesL( EFalse ); + + iDevAsr.CompileGrammarL( *iCompiledGrammar ); + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::StoreCompiledGrammar +// Stores compiled grammar to plugin database +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::StoreCompiledGrammar() + { + TRAP_IGNORE( + iDatabase.BeginTransactionL(); + // save the compiled grammar + iGrammarDatabase.UpdateGrammarL( iClientUid, iCompiledGrammar ); + iDatabase.CommitChangesL( ETrue ); + ); // TRAP_IGNORE + } + +// ----------------------------------------------------------------------------- +// CSindeTrainer::AppendPronunciationsL +// Appends pronunciations from other ttp word lists than the first one +// ----------------------------------------------------------------------------- +// +void CSindeTrainer::AppendPronunciationsL( TInt aIndex, CSILexicon& aLexicon, + RArray& aPronunIds ) + { + // Append pronunciations also from other word lists + for ( TInt counter = 1; counter < iTtpDataArray.Count(); counter++ ) + { + CSITtpWordList* ttpWordList = iTtpDataArray[counter]; + RPointerArray pronunciations; + CleanupClosePushL( pronunciations ); + // Take the same index as from first word list + ttpWordList->GetPronunciationsL( aIndex, pronunciations ); + + for ( TInt pronunArrayCounter = 0; pronunArrayCounter < pronunciations.Count(); pronunArrayCounter++ ) + { + for ( TInt pronunCounter = 0; pronunCounter < pronunciations[pronunArrayCounter]->Count(); pronunCounter++ ) + { + TDesC8& pronun = pronunciations[pronunArrayCounter]->PronunciationL( pronunCounter ); + TSIPronunciationID pronunId = iPlugin.CreateNewPronunciationL( &aLexicon, pronun, iModelBankId ); + User::LeaveIfError( aPronunIds.Append( pronunId ) ); + } + } + CleanupStack::PopAndDestroy( &pronunciations ); + } + } + +// End of File