srsf/vcommandhandler/src/tagnameset.cpp
branchRCL_3
changeset 19 e36f3802f733
--- /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 <nssvasmspeechitem.h>
+#include <nssvasmtag.h>
+#include <nssvasmtagmgr.h>
+
+_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<MNssTag&>(aTag).SpeechItem();
+    speechItem->SetTextL( aSpokenText );
+    MNssSpeechItem::TNssSpeechItemResult nssErr = 
+		speechItem->TrainTextL( this, const_cast<CNssTrainingParameters*>( &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<MNssTag*>( &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