diff -r cad71a31b7fc -r e36f3802f733 srsf/vcommandhandler/src/tagnameset.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srsf/vcommandhandler/src/tagnameset.cpp Wed Sep 01 12:29:17 2010 +0100 @@ -0,0 +1,353 @@ +/* +* 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: Array of tags and corresponding spoken texts +* +*/ + + +#include "rubydebug.h" +#include "tagnameset.h" +#include +#include +#include + +_LIT( KTagNameSetPanic, "TNS" ); + +CTagNameSet* CTagNameSet::NewLC() + { + CTagNameSet* self = new (ELeave) CTagNameSet; + CleanupStack::PushL( self ); + return self; + } + +CTagNameSet::~CTagNameSet() + { + iTags.ResetAndDestroy(); + iTexts.ResetAndDestroy(); + } + + +/** +* Adds a tag-text pair to be trained +* @param aTag tag to be trained and saved. This objects takes ownership +* on the aTag +* @param aTrainingText text to be recognized. This object doesn't +* take ownership on aTrainingText, but makes an own copy +*/ +void CTagNameSet::AppendL( const MNssTag* aTag, const TDesC& aTrainingText ) + { + HBufC* text = aTrainingText.AllocL(); + iTexts.Append( text ); + iTags.Append( aTag ); + } + +/** +* Train and save to VAS all the stored tags. It is not specified what happens +* to VAS if this method leaves +* @param aParams +* @param aTagMgr +* @param aIgnoreErrors If ETrue, doesn't fail the whole operation if some +* individual trainings/savings failed. Trains and saves as much as +* possible +*/ +void CTagNameSet::TrainAndSaveL( const CNssTrainingParameters& aParams, + MNssTagMgr& aTagMgr, TBool aIgnoreErrors ) + { + RUBY_DEBUG_BLOCK( "CTrainingPack::TrainAndSaveL" ); + iIgnoreErrors = aIgnoreErrors; + RUBY_DEBUG1( "CTrainingPack::TrainAndSaveL Processing [%d] pairs", iTags.Count() ); + + TrainTagsL( aParams ); + SaveTagsL( aTagMgr ); + } + +/** +* Remove all the stored tags from VAS. It is not specified what happens +* to VAS if this method leaves +* @param aTagMgr +* @param aIgnoreErrors If ETrue, doesn't fail the whole operation if some +* individual removals failed. Removes as many tags as +* possible +*/ +void CTagNameSet::UntrainL( MNssTagMgr& aTagMgr, TBool aIgnoreErrors ) + { + RUBY_DEBUG_BLOCK(""); + iIgnoreErrors = aIgnoreErrors; + RUBY_DEBUG1( "Removing [%d] tags from VAS", iTags.Count() ); + SetCallbacksExpected( iTags.Count() ); + + if( iCallbacksExpected > 0 ) + { + for( TInt i = 0; i < iTags.Count(); i++ ) + { + DeleteTagL( aTagMgr, *iTags[i] ); + } // for + WaitUntilOperationsAreCompletedL(); + } + } + +/** +* @return Number of tag-name pairs stored +*/ +TInt CTagNameSet::Count() const + { + return iTags.Count(); + } + +/** +* @param aIndex must be >= 0 and < Count() +* @return Voice tag at the given position +* @panic KErrArgument if aIndex is out of bounds +*/ +const MNssTag& CTagNameSet::TagAt( TInt aIndex ) const + { + __ASSERT_ALWAYS( aIndex >= 0 && aIndex < iTags.Count(), + User::Panic( KTagNameSetPanic, KErrArgument )); + return *iTags[aIndex]; + } + +/** +* @param aIndex must be >= 0 and < Count() +* @return Recognition text at the given position +* @panic KErrArgument if aIndex is out of bounds +*/ +const TDesC& CTagNameSet::TextAt( TInt aIndex ) const + { + __ASSERT_ALWAYS( aIndex >= 0 && aIndex < iTexts.Count(), + User::Panic( KTagNameSetPanic, KErrArgument )); + return *iTexts[aIndex]; + } + +/** +* Train all the stored tag-name pairs. Synchronous +*/ +void CTagNameSet::TrainTagsL( const CNssTrainingParameters& aParams ) + { + __ASSERT_ALWAYS( iCallbacksExpected == 0, User::Leave( KErrInUse) ); + SetCallbacksExpected( Count() ); + if( iCallbacksExpected > 0 ) + { + for( TInt i = 0; i < Count(); i++ ) + { + TrainTagL( TagAt( i ), aParams, TextAt( i ) ); + } // for + WaitUntilOperationsAreCompletedL(); + } // if + } + + +/** +* Trains the voice tag. Asynchronous +* @leave VAS error code +* @todo Is it ok to mix system-wide codes with the TNssSpeechItemResult codes +*/ +void CTagNameSet::TrainTagL( const MNssTag& aTag, + const CNssTrainingParameters& aParams, const TDesC& aSpokenText ) + { + RUBY_DEBUG_BLOCKL( "CTagNameSet::TrainTagL" ); + RUBY_DEBUG1( "Training for spoken text [%S]", &aSpokenText ) + + MNssSpeechItem* speechItem = const_cast(aTag).SpeechItem(); + speechItem->SetTextL( aSpokenText ); + MNssSpeechItem::TNssSpeechItemResult nssErr = + speechItem->TrainTextL( this, const_cast( &aParams ) ); + + if ( nssErr != MNssSpeechItem::EVasErrorNone ) + { + RUBY_ERROR1( "CTagNameSet::TrainTagL training start failed with the nss code [%d]", + nssErr ); + if( iIgnoreErrors ) + { + RUBY_DEBUG0( "CTagNameSet::TrainTagL ignoring error" ); + DecreaseCallbacksExpected(); + } + else + { + // Wait for started operations before leaving + DecreaseCallbacksExpected(); + WaitUntilOperationsAreCompletedL(); + + switch( nssErr ) + { + case MNssSpeechItem::EVasInvalidParameter: + User::Leave( KErrArgument ); + case MNssSpeechItem::EVasTrainFailed: + User::Leave( KErrGeneral ); + default: + User::Leave( nssErr ); + } + } + } + RUBY_DEBUG0( "CTagNameSet::TrainTagL Tag training has been initiated" ); + } + + +/** +* Train Complete Event - Voice tag training completed +* @param aErrorCode KErrNone if training was successfull +*/ +void CTagNameSet::HandleTrainComplete( TInt aErrorCode ) + { + //RUBY_DEBUG0( "Start" ); + ProcessCallback( aErrorCode ); + //RUBY_DEBUG0( "End" ); + } + +/** +* Saves the trained voice tag to VAS. Synchronous +*/ +void CTagNameSet::SaveTagsL( MNssTagMgr& aTagManager ) + { + RUBY_DEBUG_BLOCK( "CTagSaver::SaveTagsL" ); + __ASSERT_ALWAYS( iCallbacksExpected == 0, User::Leave( KErrInUse) ); + SetCallbacksExpected( Count() ); + if( iCallbacksExpected > 0 ) + { + for( TInt i = 0; i < Count(); i++ ) + { + SaveTagL( aTagManager, TagAt( i ) ); + } // for + + WaitUntilOperationsAreCompletedL(); + } // if + } + + +/** +* Saves the trained voice tag to VAS. +*/ +void CTagNameSet::SaveTagL( MNssTagMgr& aTagManager, const MNssTag& aTag ) + { + RUBY_DEBUG_BLOCKL( "CTagNameSet::SaveTagL" ); + TInt nssErr = + aTagManager.SaveTag( this, const_cast( &aTag ) ); + if( nssErr != KErrNone ) + { + RUBY_ERROR1( "CTagNameSet::SaveTagL Savetag start failed with the nss code [%d]", nssErr ); + if( iIgnoreErrors ) + { + RUBY_DEBUG0( "CTagNameSet::SaveTagL ignoring error" ); + DecreaseCallbacksExpected(); + } + else + { + // Wait for started operations before leaving + DecreaseCallbacksExpected(); + WaitUntilOperationsAreCompletedL(); + + User::Leave( KErrGeneral ); + } + } + RUBY_DEBUG0( "CTagNameSet::SaveTagL Savetag sequence started" ); + + } + +/** +* Callback to indicate that SaveTag sequence has been completed +* @param aErrorCode KErrNone if saving of tag was successfull +*/ +void CTagNameSet::SaveTagCompleted( TInt aErrorCode ) + { + RUBY_DEBUG0( "Start" ); + ProcessCallback( aErrorCode ); + RUBY_DEBUG0( "End" ); + } + +/** +* Deletes the voice tag from VAS. Asynchronous +* @leave VAS error codes +*/ +void CTagNameSet::DeleteTagL( MNssTagMgr& aTagManager, MNssTag& aTag ) + { + User::LeaveIfError( aTagManager.DeleteTag( this, &aTag ) ); + } + +/** +* Callback to indicate a tag was deleted successfully. +* @param aErrorCode KErrNone if deletion of tag was successfull +*/ +void CTagNameSet::DeleteTagCompleted( TInt aErrorCode ) + { + RUBY_DEBUG0( "Start" ); + ProcessCallback( aErrorCode ); + RUBY_DEBUG0( "End" ); + } + +/** +* Handles the common part of the callback processing +* Decrements the number of still expected callbacks and +* handles the errors according to aIgnoreErrors from the +* public methods +*/ +void CTagNameSet::ProcessCallback( TInt aErrorCode ) + { + //RUBY_DEBUG0( "Start" ); + if( iIgnoreErrors || aErrorCode == KErrNone ) + { + if( DecreaseCallbacksExpected() == 0 ) + { + StopAsyncWaitingOrPanic( KErrNone ); + } + } + else + { + RUBY_ERROR1( "Callback reported error [%d] ", aErrorCode ); + if( DecreaseCallbacksExpected() == 0 ) + { + StopAsyncWaitingOrPanic( aErrorCode ); + } + } + //RUBY_DEBUG0( "End" ); + } + +/** +* Sets the number of callbacks to expect +*/ +void CTagNameSet::SetCallbacksExpected (TUint aCallbacksExpected ) + { + RUBY_DEBUG2( "Changing from [%d] to [%d]", iCallbacksExpected, aCallbacksExpected ); + iCallbacksExpected = aCallbacksExpected; + } + +/** +* Decreases the number of callbacks to expect by one +* @return Number of callbacks expected after decreasing +*/ +TUint CTagNameSet::DecreaseCallbacksExpected() + { + __ASSERT_ALWAYS( iCallbacksExpected > 0, User::Panic( KTagNameSetPanic, KErrNotReady ) ); + RUBY_DEBUG2( "Changing from [%d] to [%d]", iCallbacksExpected, iCallbacksExpected - 1 ); + return --iCallbacksExpected; + } + +/** +* Waits until all the expected callbacks are received +* If no callbacks are expected returns immediately +* @leave @see CAsyncWorker::WaitForAsyncCallbackL +*/ +void CTagNameSet::WaitUntilOperationsAreCompletedL() + { + RUBY_DEBUG_BLOCK( "" ); + if( iCallbacksExpected > 0 ) + { + RUBY_DEBUG1( "[%d] callbacks expected. Waiting for them", iCallbacksExpected ); + WaitForAsyncCallbackL(); + } + else + { + RUBY_DEBUG0( "no callbacks expected. Returning immediately" ); + } + } + +//End of file