srsf/nssvasapi/nssvascore/src/nssvascspeechitem.cpp
branchRCL_3
changeset 19 e36f3802f733
parent 0 bf1d17376201
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/nssvasapi/nssvascore/src/nssvascspeechitem.cpp	Wed Sep 01 12:29:17 2010 +0100
@@ -0,0 +1,1310 @@
+/*
+* 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 CNssSpeechItem provides speech mechanism to request services 
+*               from SRS.
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32std.h>
+
+#include "srsfbldvariant.hrh"
+#include <nssvascoreconstant.h>
+#include "nssvascspeechitem.h"
+#include "nssvascspeechitemtrainer.h"
+#include "nssvasctag.h"
+#include "nssvasctrainingparameters.h"
+#include "nssvasdbkonsts.h"
+#include "rubydebug.h"
+
+// CONSTANTS
+// This value is used for maximum retry times
+const TInt KVASSpeechItemMaxRetry = 2;   
+// This value is used to reset the retry number 
+const TInt KVASSpeechItemResetRetry = 0;
+
+// Character which is used instead of separator marker
+_LIT( KEmptySpace, " " );
+
+// Panic category
+_LIT( KSpeechItemPanic, "CNssSpeechItem" );
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::CNssSpeechItem
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CNssSpeechItem::CNssSpeechItem( CNssContext& aContext, 
+                                CNssSpeechItemSrsPortal& aPortal, 
+                                CNssSpeechItemTrainer& aTrainer )
+                              : iRuleID( KInvalidRuleID ),
+                                iTrainedType( TNssVasCoreConstant::EVasNotTrained ),
+                                iState( TNssSpeechItemConstant::EIdle ),
+                                iContext( aContext ),
+                                iPortal( aPortal ),
+                                iTrainer( aTrainer ),
+                                iTagId( KNssVASDbDefaultValue ),
+                                iTrained( EFalse ),
+                                iRecover( EFalse )
+    {
+    //Register to Portal
+    iPortal.Register();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::~CNssSpeechItem
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CNssSpeechItem::~CNssSpeechItem()
+    {
+    delete iText;
+    delete iTrimmedText;
+    
+    if ( iTtsData )
+        {
+        CleanPlayback();
+        }
+    
+    iPortal.Deregister(); // Deregister to Portal
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::NewL
+// Two-phased constructor.
+// This is for new SpeechItem
+// -----------------------------------------------------------------------------
+//
+CNssSpeechItem* CNssSpeechItem::NewL( CNssContext& aContext, 
+                                      CNssSpeechItemSrsPortal& aPortal, 
+                                      CNssSpeechItemTrainer& aTrainer )
+    {
+    CNssSpeechItem* self = new (ELeave) CNssSpeechItem( aContext, aPortal, aTrainer );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::ConstructL
+// Symbian 2nd phase constructor can leave.
+// This is overloaded function for SpeechItem from database
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::ConstructL( TUint32 aRuleID, const TDesC& aText )
+    {
+    SetTextL( aText );
+    iRuleID = aRuleID;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::NewLC
+// Two-phased constructor.
+// This is overloaded function for SpeechItem from database
+// -----------------------------------------------------------------------------
+//
+CNssSpeechItem* CNssSpeechItem::NewLC( CNssContext& aContext,
+                                       CNssSpeechItemSrsPortal& aPortal,
+                                       CNssSpeechItemTrainer& aTrainer,
+                                       TUint32 aRuleID, const TDesC& aText )
+    {
+    CNssSpeechItem* self = new (ELeave) CNssSpeechItem( aContext, aPortal, aTrainer );
+    CleanupStack::PushL( self );
+    self->ConstructL( aRuleID, aText );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::NewL
+// Two-phased constructor.
+// This is overloaded function for SpeechItem from database
+// -----------------------------------------------------------------------------
+//
+CNssSpeechItem* CNssSpeechItem::NewL( CNssContext& aContext,
+                                      CNssSpeechItemSrsPortal& aPortal,
+                                      CNssSpeechItemTrainer& aTrainer,
+                                      TUint32 aRuleID, 
+                                      const TDesC& aText )
+    {
+    CNssSpeechItem* self = NewLC( aContext, aPortal, aTrainer, aRuleID, 
+                                  aText );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::PlayL
+// Method to do play operation. In SI, this means synthesizing the name.
+// -----------------------------------------------------------------------------
+//
+MNssSpeechItem::TNssSpeechItemResult
+CNssSpeechItem::PlayL( MNssPlayEventHandler* aPlayEventHandler, TLanguage aLanguage )
+    {
+    if ( !iTtsData )
+        {
+        iTtsData = new (ELeave) TTtsData;
+        }
+    
+    iTtsData->iStyle.iLanguage = aLanguage;
+    
+    RUBY_DEBUG1( "CNssSpeechItem::PlayL lang id: %d", iTtsData->iStyle.iLanguage );
+    
+    // Verify for valid state
+    if (!(iState == TNssSpeechItemConstant::EIdle ||
+        iState == TNssSpeechItemConstant::ETrainComplete))
+        {
+        RUBY_DEBUG0( "CNssSpeechItem::PlayL - wrong state" );
+
+        return MNssSpeechItem::EVasUnexpectedRequest;
+        }
+    
+    // Verify for valid event handler
+    if ( aPlayEventHandler )
+        {
+        iPlayEventHandler = aPlayEventHandler;
+        }
+    else
+        {
+        return MNssSpeechItem::EVasInvalidParameter;
+        }
+    
+    TRAPD( err, DoPlayL() );
+    if ( err != KErrNone )
+        {
+        CleanPlayback();
+        return MNssSpeechItem::EVasPlayFailed;
+        }
+    
+    return MNssSpeechItem::EVasErrorNone;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::PlayL
+// Method to do play operation. In SI, this means synthesizing the name.
+// -----------------------------------------------------------------------------
+//
+MNssSpeechItem::TNssSpeechItemResult 
+CNssSpeechItem::PlayL( MNssPlayEventHandler* aPlayEventHandler )
+    {
+    // Use UI language by default
+    // If synthesis engine does not support UI language for some reason,
+    // then language identification will be used instead
+    return PlayL( aPlayEventHandler, User::Language() );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::DoPlayL
+// Starts playing. Assumes that all checks have been done earlier.
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::DoPlayL()
+    {
+    TTtsData* d = iTtsData;
+
+    d->iTts = CNssTtsUtilityWrapper::NewL( *this );
+    d->iStyleID = d->iTts->AddStyleL( d->iStyle );
+
+    d->iParsedText = CTtsParsedText::NewL();
+    d->iParsedText->SetTextL( Text() );
+
+    d->iSegment.SetTextPtr( d->iParsedText->Text() );
+    d->iSegment.SetStyleID( d->iStyleID );
+
+    d->iParsedText->AddSegmentL( d->iSegment );
+
+    d->iTts->OpenAndPlayParsedTextL( *d->iParsedText );
+
+    iOldState = iState;
+    iState = TNssSpeechItemConstant::EPlayStart;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::CleanPlayback
+// Cleans playback and releases all memory.
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::CleanPlayback()
+    {
+    TTtsData* d = iTtsData;
+
+    if ( d->iTts )
+        {
+        d->iTts->Stop();
+        d->iTts->Close();
+        }
+
+    delete d->iParsedText;
+    d->iParsedText = NULL;
+
+    delete d->iTts;
+    d->iTts = NULL;
+
+    delete iTtsData;
+    iTtsData = NULL;
+
+    iState = iOldState;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::MakePlayCallback
+// Makes callback to VAS client. Uses error status from TTS Utility to decide
+// callback and parameters.
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::MakePlayCallback( TInt aResult )
+    {
+    MNssPlayEventHandler::TNssPlayResult res;
+
+    if ( aResult == KErrNone )
+        {
+        iPlayEventHandler->HandlePlayComplete( MNssPlayEventHandler::EVasErrorNone );
+        }
+    else{
+        switch( aResult )
+            {
+            case KErrNoMemory:
+                res = MNssPlayEventHandler::EVasPlayNoMemory;
+                break;
+
+            case KErrAccessDenied:
+                res = MNssPlayEventHandler::EVasPlayAccessDeny;
+                break;
+
+            default:
+                res = MNssPlayEventHandler::EVasPlayFailed;
+                break;
+            }
+        iPlayEventHandler->HandlePlayComplete( res );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::MapcCustomCommandEvent
+// TTS may call this method if we had used custom interfaces,
+// But we don't use custom interfaces.
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::MapcCustomCommandEvent( TInt /*aEvent*/, TInt /*aError*/ )
+    {
+    // We don't expect to arrive here
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::MapcInitComplete
+// TTS calls this method to announce that it has initialized playing.
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::MapcInitComplete( TInt aError, const TTimeIntervalMicroSeconds& aDuration )
+    {
+    if ( aError != KErrNone )
+        {
+        CleanPlayback();
+        MakePlayCallback( aError );
+        }
+    else
+        {
+        if ((iState == TNssSpeechItemConstant::EPlayStart) || 
+            (iState == TNssSpeechItemConstant::EPlayMemoryStart)
+            )
+            {
+            iPlayDuration = I64LOW( aDuration.Int64() );
+            iPlayEventHandler->HandlePlayStarted(iPlayDuration);
+            }
+        else
+            {
+            NotifyHandlerForUnexpectedEvent();
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::MapcPlayComplete
+// TTS calls this method to announce that playing has finished.
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::MapcPlayComplete( TInt aError )
+    {
+    CleanPlayback();
+    MakePlayCallback( aError );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::RecordL
+// Method to do record operation
+// -----------------------------------------------------------------------------
+//
+MNssSpeechItem::TNssSpeechItemResult 
+CNssSpeechItem::RecordL( MNssTrainVoiceEventHandler* aTrainVoiceEventHandler )
+    {
+    RUBY_DEBUG1( "CNssSpeechItem::RecordL tagid [%d]", iTagId );
+    
+    // Verify for valid state
+    if (iState == TNssSpeechItemConstant::EIdle)
+        {
+        RUBY_DEBUG0( "CNssSpeechItem::RecordL - wrong state" );
+
+        return MNssSpeechItem::EVasUnexpectedRequest;
+        }
+    
+    // Verify for valid event handler
+    if (aTrainVoiceEventHandler)
+        {
+        iTrainVoiceEventHandler = aTrainVoiceEventHandler;
+        }
+    else
+        {
+        return MNssSpeechItem::EVasInvalidParameter;
+        }
+    
+    return MNssSpeechItem::EVasErrorNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::TrainVoiceL
+// Method to do train operation
+// For retraining, the previous utterance data need to be preserved for the 
+// delete operation later.
+// -----------------------------------------------------------------------------
+//
+MNssSpeechItem::TNssSpeechItemResult 
+CNssSpeechItem::TrainVoiceL(MNssTrainVoiceEventHandler* /*aTrainVoiceEventHandler*/)
+    {
+    // This is SI, don't even try to train by voice.
+    return MNssSpeechItem::EVasUnexpectedRequest;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::CancelL
+// Method to do cancel operation by calling the SpeechRecognitionUtility Cancel
+// method, and cleanup the SRS from the current transaction.
+// -----------------------------------------------------------------------------
+//
+MNssSpeechItem::TNssSpeechItemResult CNssSpeechItem::CancelL()
+    {
+    RUBY_DEBUG1( "CNssSpeechItem::CancelL tagid [%d]", iTagId );
+
+    //Verify a transaction is in progress
+    if (iState == TNssSpeechItemConstant::EIdle)
+        {   
+        return MNssSpeechItem::EVasUnexpectedRequest;
+        }
+    
+    // Do the Clean up
+    CleanUp();
+    
+    return MNssSpeechItem::EVasErrorNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::TrainingCapabilities
+// Method to get the Training capabilities
+// -----------------------------------------------------------------------------
+//
+CArrayFixFlat<TNssVasCoreConstant::TNssTrainingCapability>* 
+CNssSpeechItem::TrainingCapabilities()
+    { 
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::RuleID
+// Method to get the rule ID
+// -----------------------------------------------------------------------------
+//
+TUint32 CNssSpeechItem::RuleID()
+    {
+    return iRuleID;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::SetRuleID
+// Method to set the rule ID
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::SetRuleID(TUint32 aRuleID)
+    {
+    iRuleID = aRuleID;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::TrainedType
+// Method to get the Trained Type
+// -----------------------------------------------------------------------------
+//
+TNssVasCoreConstant::TNssTrainedType CNssSpeechItem::TrainedType()
+    {
+    return iTrainedType;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::SetTrainedType
+// Method to set the Trained Type
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::SetTrainedType( TNssVasCoreConstant::TNssTrainedType aTrainType )
+    {
+    iTrainedType = aTrainType;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::Text
+// Method to get the Text
+// -----------------------------------------------------------------------------
+//
+TDesC& CNssSpeechItem::Text()
+    {
+    if ( iTrimmedText )
+        {
+        return *iTrimmedText;
+        }
+
+    if ( iText )
+        {
+        return *iText;
+        }
+    else
+        {
+        return (TDesC&)KNullDesC;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::RawText
+// Method to get the raw text
+// -----------------------------------------------------------------------------
+//
+TDesC& CNssSpeechItem::RawText()
+    {
+    if ( !iText )
+        {
+        return (TDesC&)KNullDesC;
+        }
+    
+    return *iText;
+    }
+    
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::PartialTextL
+// Returns the part of the text which is indentified with the given ID
+// -----------------------------------------------------------------------------
+//
+HBufC* CNssSpeechItem::PartialTextL( const TDesC& aIdentifier )
+    {
+    if ( !iText )
+        {
+        User::Leave( KErrNotFound  );
+        }
+        
+    // Copy text for manipulation
+    HBufC* partialText = HBufC::NewL( iText->Length() );
+    CleanupStack::PushL( partialText );
+    *partialText = *iText;
+    TPtr partialTextPtr = partialText->Des();
+
+    // Find all separator characters from text
+    TInt markerIndex = partialTextPtr.Find( KNameSeparator );
+    TBool found( EFalse );
+    
+    while ( markerIndex != KErrNotFound )
+        {
+        // Separator marker should never be the last character of string
+        __ASSERT_ALWAYS( markerIndex <= partialTextPtr.Length(), User::Leave( KErrCorrupt ) );
+        
+        TBool removeThisPart( ETrue );
+        
+        if ( partialTextPtr.Mid( markerIndex + 1, 1 ) == aIdentifier )
+            {
+            found = ETrue;
+            removeThisPart = EFalse;
+            }
+        
+        if ( markerIndex == 0 )
+            {
+            // Remove separator marker & the next char (which is the identifier)
+            partialTextPtr.Delete( markerIndex, KTrainingIndexSize );
+            }
+        else
+            {
+            // Replace separator marker & the next char
+            partialTextPtr.Replace( markerIndex, KTrainingIndexSize, KEmptySpace );
+            }         
+        
+        if ( removeThisPart )
+            {
+            // Find next separator
+            TInt tempIndex = partialTextPtr.Find( KNameSeparator );
+            if ( tempIndex != KErrNotFound )
+                {
+                partialTextPtr.Delete( markerIndex, tempIndex - markerIndex );
+                }
+            else
+                {
+                partialTextPtr.Delete( markerIndex, partialTextPtr.Length() );
+                }
+            }
+        
+        // Find the next marker
+        markerIndex = partialTextPtr.Find( KNameSeparator );
+        }
+    
+    if ( found )
+        {
+        CleanupStack::Pop( partialText );
+        }
+    else
+        {
+        CleanupStack::PopAndDestroy( partialText );
+        User::Leave( KErrNotFound );
+        }
+    
+    // Ownership transferred to client 
+    return partialText;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::SetTextL
+// Method to set the Text
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::SetTextL( const TDesC& aText )
+    {
+    if ( iText )
+        {
+        delete iText;
+        iText = NULL;
+        }
+    iText = aText.Left( KNssVasDbTagName ).AllocL();
+    
+    if ( iTrimmedText )
+        {
+        delete iTrimmedText;
+        iTrimmedText = NULL;
+        }
+    iTrimmedText = iText->AllocL();
+    
+    // Remove escape characters
+    for ( TInt iCounter = 0; iCounter < iTrimmedText->Length(); iCounter ++ )
+        {
+        if ( (*iTrimmedText)[iCounter] == KNameSeparator()[0] )
+            {
+            TPtr ptr( iTrimmedText->Des() );
+            if ( iCounter == iTrimmedText->Length() - 1 )
+                {
+                // Special handling for last char
+                ptr.Delete( iCounter, 1 );
+                }
+            else
+                {
+                ptr.Replace( iCounter, KTrainingIndexSize, KEmptySpace );
+                }
+            }
+        
+        }
+    TPtr ptr( iTrimmedText->Des() );
+    ptr.Trim();
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::IsPlayingSupported
+// Method to query playing support
+// -----------------------------------------------------------------------------
+//
+TBool CNssSpeechItem::IsPlayingSupported()
+    {
+    if ( Text().Length() == 0 )
+        {
+        return EFalse;
+        }
+
+    return( ETrue );
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::TrainTextL
+// Method to train a speech model from text
+// -----------------------------------------------------------------------------
+//
+CNssSpeechItem::TNssSpeechItemResult CNssSpeechItem::TrainTextL(
+                           MNssTrainTextEventHandler *aEventHandler,
+                           CNssTrainingParameters    *aTrainingParams )
+    {
+    
+    if ( /*aEventHandler == 0 ||*/ Text().Length() == 0 )
+        {
+        return CNssSpeechItem::EVasInvalidParameter;
+        }
+    
+    RUBY_DEBUG1( "CNssSpeechItem::TrainTextL tagig [%d]", iTagId );
+    
+    // Verify for the valid state
+    if (iState != TNssSpeechItemConstant::EIdle && 
+        iState != TNssSpeechItemConstant::ETrainComplete )
+        {
+        RUBY_DEBUG0( "CNssSpeechItem::TrainTextL - wrong state" );
+       
+        return MNssSpeechItem::EVasUnexpectedRequest;
+        }
+    
+    // Verify for the valid event handler
+    if ( !aEventHandler )
+        {
+        return MNssSpeechItem::EVasInvalidParameter;
+        }
+    
+    
+    iState = TNssSpeechItemConstant::ETrainStart;
+    
+    // To diffrentiate from voice trained tags
+    iTrainedType = TNssVasCoreConstant::EVasTrainText;
+    
+    // Training assigns rule ID from KInvalidRuleID to some correct value.
+    if ( iRuleID == KInvalidRuleID )
+        {
+        return( iTrainer.TrainTextDelayed( aEventHandler, aTrainingParams, *this, iContext ));
+        }
+    else
+        {
+        return( iTrainer.RetrainTextDelayed( aEventHandler, aTrainingParams, *this, iContext ));
+        }
+    
+    // Use delayed training to train the new phrase.
+    //return EVasErrorNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::NSSBeginSaveToSrsL
+// Method to begin the transaction for saving the utterance data to SRS 
+// -----------------------------------------------------------------------------
+//
+MNssCoreSrsDBEventHandler::TNssSrsDBResult 
+CNssSpeechItem::NSSBeginSaveToSrs( MNssSaveTagClient* aSaveTagClient, CNssTag* aTag )
+    {
+    RUBY_DEBUG1( "CNssSpeechItem::BeginSaveToSrsL tagid: [%d]", aTag->TagId() );
+    
+    // The state should be in the Training Complete
+    if (iState != TNssSpeechItemConstant::ETrainComplete)
+        {
+        RUBY_DEBUG0( "CNssSpeechItem::BeginSaveToSrsL - wrong state" );
+
+        return MNssCoreSrsDBEventHandler::EVasUnexpectedRequest;
+        }
+    
+    TInt ret = iTrainer.SaveTagDelayed( aSaveTagClient, *aTag );
+    
+    if ( ret != KErrNone )
+        {
+        return MNssCoreSrsDBEventHandler::EVasUnexpectedRequest;
+        }
+    
+    return MNssCoreSrsDBEventHandler::EVasSuccess;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::NSSBeginDeleteFromSrsL
+// Method to begin the transaction for saving the utterance data to SRS 
+// -----------------------------------------------------------------------------
+//
+MNssCoreSrsDBEventHandler::TNssSrsDBResult 
+CNssSpeechItem::NSSBeginDeleteFromSrs( MNssDeleteTagClient* aDeleteTagClient, CNssTag* aTag )
+    {
+    RUBY_DEBUG1( "CNssSpeechItem::BeginDeleteFromSrsL tagid: [%d]", aTag->TagId() );
+    
+    // The state should be in the Training Complete
+    if (iState != TNssSpeechItemConstant::ETrainComplete &&
+        iState != TNssSpeechItemConstant::EIdle )
+        {
+        RUBY_DEBUG0( "CNssSpeechItem::BeginSaveToSrsL - wrong state" );
+        
+        return MNssCoreSrsDBEventHandler::EVasUnexpectedRequest;
+        }
+    
+    TInt ret = iTrainer.DeleteTagDelayed( aDeleteTagClient, *aTag );
+    
+    if ( ret != KErrNone )
+        {
+        return MNssCoreSrsDBEventHandler::EVasUnexpectedRequest;
+        }
+    
+    return MNssCoreSrsDBEventHandler::EVasSuccess;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::CommitSrsChanges
+// Method to to commit the transaction to the SRS.
+// This is a SYNCHRONOUS method
+// -----------------------------------------------------------------------------
+//
+MNssCoreSrsDBEventHandler::TNssSrsDBResult CNssSpeechItem::CommitSrsChanges()
+    {
+    // Not used
+    User::Panic( KSpeechItemPanic, __LINE__ );
+    return MNssCoreSrsDBEventHandler::EVasSuccess;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::CommitSrsChanges
+// Method to to roll back the transaction to the SRS.
+// This is a SYNCHRONOUS method
+// -----------------------------------------------------------------------------
+//
+MNssCoreSrsDBEventHandler::TNssSrsDBResult CNssSpeechItem::RollbackSrsChanges()
+    {
+    // Not used
+    User::Panic( KSpeechItemPanic, __LINE__ );
+    return MNssCoreSrsDBEventHandler::EVasSuccess;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::CopyUtteranceData
+// Method to copy utterance data from current data to transient data
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::CopyUtteranceData()
+    {
+    iTransientRuleID = iRuleID;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::MsruoEvent
+// Method to process the events from SRS utility object
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::MsruoEvent( TUid aEvent, TInt aResult )
+    {
+    RUBY_DEBUG2( "CNssSpeechItem::MsruoEvent, Event=0x%x, Result=%d", aEvent.iUid, aResult  );
+    
+    switch (aEvent.iUid)
+        {
+        
+        
+        //----------------------------------------------------------------------
+        //  Pre-Train Events 
+        //----------------------------------------------------------------------
+        
+        
+        case KUidAsrEventGetModelCountVal:
+            RUBY_ERROR0( "CNssSpeechItem::MsruoEvent KUidAsrEventAddRuleVal not expected" );
+            break;
+                        
+        case KUidAsrEventGetAvailableStorageVal:
+            if (aResult == KErrNone)
+                {
+                DoGetAvailableStorageCompleteEvent();
+                }
+            else
+                {
+                DoTrainFailEvent(aResult);
+                }
+            break;
+            
+            
+            //----------------------------------------------------------------------
+            //  Train Events 
+            //----------------------------------------------------------------------
+            
+        case KUidAsrEventTrainReadyVal:
+            RUBY_DEBUG0( "CNssSpeechItem::MsruoEvent - TrainReadyEvent" );
+            
+            // Always success, no need to verify aResult
+            if (iState == TNssSpeechItemConstant::ETrainStart)
+                {
+                iTrainVoiceEventHandler->HandleReadyToRecord();
+                }
+            else
+                {
+                NotifyHandlerForUnexpectedEvent();
+                }
+            break;
+            
+        case KUidAsrEventRecordStartedVal:
+            RUBY_DEBUG0( "CNssSpeechItem::MsruoEvent - RecordStartedEvent" );
+            
+            // Always success, no need to verify aResult
+            if (iState == TNssSpeechItemConstant::ETrainStart)
+                {
+                iTrainVoiceEventHandler->HandleRecordStarted();
+                }
+            else
+                {
+                NotifyHandlerForUnexpectedEvent();
+                }
+            break;
+        case KUidAsrEventEouDetectedVal:
+            RUBY_DEBUG0( "CNssSpeechItem::MsruoEvent - EouDetectedEvent" );
+            
+            // Always success, no need to verify aResult
+            if (iState == TNssSpeechItemConstant::ETrainStart)
+                {
+                iTrainVoiceEventHandler->HandleEouDetected();
+                }
+            else
+                {
+                NotifyHandlerForUnexpectedEvent();
+                }
+            break;
+            
+        case KUidAsrEventTrainVal:
+            if (aResult == KErrNone)
+                {
+                DoTrainCompleteEvent();
+                }
+            else
+                {
+                DoTrainFailEvent(aResult);
+                }
+            break;
+            
+            // currently this is only for fail cases
+        case KUidAsrEventRecordVal: 
+            RUBY_DEBUG0( "CNssSpeechItem::MsruoEvent - ERecordFailed" );
+
+            // If the result is success, do nothing
+            if (aResult != KErrNone)
+                {
+                DoTrainFailEvent(aResult);
+                }
+            break;
+            
+            
+            // End of Train Events 
+            
+            
+            //----------------------------------------------------------------------
+            //  Save Events 
+            //----------------------------------------------------------------------
+            
+        case KUidAsrEventAddRuleVal:
+            RUBY_ERROR0( "CNssSpeechItem::MsruoEvent KUidAsrEventAddRuleVal not expected" );
+            break;
+            
+            // End of Save to Srs Events  
+            
+            
+            //----------------------------------------------------------------------
+            //  Delete Events 
+            //----------------------------------------------------------------------
+            
+            
+        case KUidAsrEventRemoveRuleVal:
+            RUBY_ERROR0( "CNssSpeechItem::MsruoEvent KUidAsrEventRemoveRuleVal not expected" );
+            break;
+            
+            // End of Deleting from Srs Events  
+            
+            
+        default:
+            RUBY_DEBUG0( "CNssSpeechItem::MsruoEvent ERROR:default in switch" );
+            
+            NotifyHandlerForUnexpectedEvent();
+            break;
+    }
+}
+
+
+
+//  -------------------------       Play       -----------------------------  //
+
+//  -------------------------       Train       ----------------------------  //
+
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::DoGetAvailableStorageCompleteEvent
+// Method to handle the "GetAvailableStorage" Event.
+// Verify the size of available storage, if it is not zero, continue with
+// the next operation to train.
+// If the size is zero, send the error message.
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::DoGetAvailableStorageCompleteEvent()
+    {
+    // Obsolete
+    User::Panic( KSpeechItemPanic, __LINE__ );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::DoTrainCompleteEvent
+// Method to process the Train event.
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::DoTrainCompleteEvent()
+    {
+    RUBY_DEBUG0( "CNssSpeechItem::DoTrainCompleteEvent" );
+
+    if (iState == TNssSpeechItemConstant::ETrainStart)
+        {
+        iState = TNssSpeechItemConstant::ETrainComplete;
+        //iTrainVoiceEventHandler->HandleTrainComplete();
+        iTrainVoiceEventHandler->HandleTrainComplete( KErrNone );
+        }
+    else
+        {
+        NotifyHandlerForUnexpectedEvent();
+        }
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::DoTrainFailEvent
+// Method to process the train failed events
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::DoTrainFailEvent( TInt aResult )
+    {
+    RUBY_DEBUG1( "CNssSpeechItem::DoTrainFailEvent [%d]", aResult );
+    
+    if (iState != TNssSpeechItemConstant::ETrainStart)
+        {
+        NotifyHandlerForUnexpectedEvent();
+        return;
+        }
+    
+    CleanUp();
+    MNssTrainVoiceEventHandler::TNssTrainResult errorCode = DoTrainResult( aResult );
+    
+    iTrainVoiceEventHandler->HandleTrainComplete( errorCode );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::DoTrainResult
+// Method to process the Train result.
+// -----------------------------------------------------------------------------
+//
+MNssTrainVoiceEventHandler::TNssTrainResult 
+CNssSpeechItem::DoTrainResult( TInt aResult )
+    {
+    
+    MNssTrainVoiceEventHandler::TNssTrainResult errorCode;
+    
+    switch (aResult)
+        {
+        case KErrAsrNoSpeech:
+            RUBY_DEBUG0( "CNssSpeechItem::DoTrainResult - EVasTrainFailedNoSpeech" );
+           
+            errorCode = MNssTrainVoiceEventHandler::EVasTrainFailedNoSpeech;
+            break;
+        case KErrAsrSpeechTooEarly:
+            RUBY_DEBUG0( "CNssSpeechItem::DoTrainResult - EVasTrainFailedTooEarly" );
+
+            errorCode = MNssTrainVoiceEventHandler::EVasTrainFailedTooEarly;
+            break;
+        case KErrAsrSpeechTooLong:
+            RUBY_DEBUG0( "CNssSpeechItem::DoTrainResult - EVasTrainFailedTooLong" );
+            
+            errorCode = MNssTrainVoiceEventHandler::EVasTrainFailedTooLong;
+            break;
+        case KErrAsrSpeechTooShort:
+            RUBY_DEBUG0( "CNssSpeechItem::DoTrainResult - KErrAsrSpeechTooShort" );
+
+            errorCode = MNssTrainVoiceEventHandler::EVasTrainFailedTooShort;
+            break;
+        case KErrAccessDenied:      // this is temporary .....
+        case KErrDied:
+            RUBY_DEBUG0( "CNssSpeechItem::DoTrainResult - EVasTrainAccessDeny" );
+
+            errorCode = MNssTrainVoiceEventHandler::EVasTrainAccessDeny;
+            break;
+        case KErrNoMemory:
+            RUBY_DEBUG0( "CNssSpeechItem::DoTrainResult - EVasTrainNoMemory" );
+
+            errorCode = MNssTrainVoiceEventHandler::EVasTrainNoMemory;
+            break;
+        default:
+            RUBY_DEBUG0( "CNssSpeechItem::DoTrainResult - default" );
+
+            errorCode = MNssTrainVoiceEventHandler::EVasTrainFailed;
+            break;
+        }
+    
+    return errorCode;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::DoSrsDBResult
+// Method to process the SRS DB result.
+// -----------------------------------------------------------------------------
+//
+MNssCoreSrsDBEventHandler::TNssSrsDBResult 
+CNssSpeechItem::DoSrsDBResult( TInt aResult )
+    {
+    
+    MNssCoreSrsDBEventHandler::TNssSrsDBResult errorCode;
+    
+    switch (aResult)
+        {
+        case KErrDiskFull:
+            RUBY_DEBUG0( "CNssSpeechItem::DoSrsDBResult - KErrDiskFull" );
+            
+            errorCode = MNssCoreSrsDBEventHandler::EVasDiskFull;
+            break;
+        case KErrNoMemory:
+            RUBY_DEBUG0( "CNssSpeechItem::DoSrsDBResult - EVasNoMemory" );
+            
+            errorCode = MNssCoreSrsDBEventHandler::EVasNoMemory;
+            break;
+        default:
+            {
+            RUBY_DEBUG0( "CNssSpeechItem::DoSrsDBResult - default" );
+
+            switch ( iState )
+                {
+                case TNssSpeechItemConstant::ESaveToSrsStart:
+                    errorCode = MNssCoreSrsDBEventHandler::EVasAddPronunciationFailed;
+                    break;
+                case TNssSpeechItemConstant::EAddPronounciationComplete:
+                    errorCode = MNssCoreSrsDBEventHandler::EVasAddRuleFailed;
+                    break;
+                case TNssSpeechItemConstant::EDeleteToSrsStart:
+                    errorCode = MNssCoreSrsDBEventHandler::EVasRemoveRuleFailed;
+                    break;
+                case TNssSpeechItemConstant::ERemoveRuleComplete:
+                    errorCode = MNssCoreSrsDBEventHandler::EVasRemovePronunciationFailed;
+                    break;
+                case TNssSpeechItemConstant::ERemovePronounciationComplete:
+                    errorCode = MNssCoreSrsDBEventHandler::EVasRemoveModelFailed;
+                    break;
+                default:
+                    errorCode = MNssCoreSrsDBEventHandler::EVasDBOperationError;
+                    break;
+                }
+            }
+        }
+    
+    return errorCode;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::NotifyHandlerForUnexpectedEvent
+// Method to notify the event handler for receiving the Unexpected Event
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::NotifyHandlerForUnexpectedEvent()
+    {
+    RUBY_DEBUG1( "CNssSpeechItem::NotifyHandlerForUnexpectedEvent tagid: %d", iTagId );
+    
+    switch( iState )
+        {
+        case TNssSpeechItemConstant::EAddPronounciationComplete:
+        case TNssSpeechItemConstant::EAddRuleComplete:
+        case TNssSpeechItemConstant::ERemoveRuleComplete:
+        case TNssSpeechItemConstant::ERemovePronounciationComplete:
+        case TNssSpeechItemConstant::ERemoveModelCompelete:
+        case TNssSpeechItemConstant::EWaitForCommitChanges:
+            // Shouldn't happen, since all calls to SRS
+            // are done at CNssSpeechItemTrainer.
+            User::Panic( KSpeechItemPanic, __LINE__ );
+            
+            break;
+            
+        case TNssSpeechItemConstant::EPlayMemoryStart:
+        case TNssSpeechItemConstant::EPlayStart:
+            if (iPlayEventHandler)
+                {
+                CleanUp();
+                iPlayEventHandler->HandlePlayComplete(
+                    MNssPlayEventHandler::EVasPlayFailed);
+                }
+            break;
+            
+        case TNssSpeechItemConstant::ETrainStart:
+            if (iTrainVoiceEventHandler)
+                {
+                CleanUp();
+                iTrainVoiceEventHandler->HandleTrainComplete(
+                    MNssTrainVoiceEventHandler::EVasTrainFailed);
+                }
+            break;
+            
+        default:
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::SetTagId
+// Method to set the Tag ID
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::SetTagId( TInt aTagId )
+    {
+    iTagId = aTagId;
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::TagId
+// Method to return the Tag ID
+// -----------------------------------------------------------------------------
+//
+TInt CNssSpeechItem::TagId()
+    {
+    return iTagId;
+    }		
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::GrammarId
+// Method to return the Grammar ID
+// -----------------------------------------------------------------------------
+//
+TUint32 CNssSpeechItem::GrammarId()
+    {
+    return iContext.GrammarId();
+    }		
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::SetTrained
+// Method to set the Trained flag
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::SetTrained( TBool aTrained )
+    {
+    iTrained = aTrained;
+    }		
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::Trained
+// Method to return the Trained flag
+// -----------------------------------------------------------------------------
+//
+TBool CNssSpeechItem::Trained()
+    {
+    return iTrained;
+    }		
+
+// ---------------------------------------------------------
+// CNssSpeechItem::CopyL
+// creates a copy of this SpeechItem
+// ---------------------------------------------------------
+//
+CNssSpeechItem* CNssSpeechItem::CopyL( CNssContext* aContext )
+    {
+    RUBY_DEBUG1( "CNssSpeechItem::CopyL tagid: %d", iTagId );
+    
+    CNssSpeechItem* copy = new (ELeave) CNssSpeechItem(*aContext, iPortal, iTrainer);
+    
+    if ( iText )
+        {
+        copy->iText = iText->Alloc();
+        }
+    if ( iTrimmedText )
+        {
+        copy->iTrimmedText = iTrimmedText->Alloc();
+        }
+    copy->iRuleID = iRuleID;
+    copy->iTransientRuleID = iTransientRuleID;
+    
+    copy->iTrainedType = iTrainedType;
+    copy->iState = iState;
+    copy->iContext = iContext;
+    copy->iPortal = iPortal;
+    copy->iPlayEventHandler = iPlayEventHandler;
+    //copy->iSrsDBEventHandler = iSrsDBEventHandler;
+    copy->iTrainVoiceEventHandler = iTrainVoiceEventHandler;
+    
+    copy->iTagId = iTagId;
+    copy->iTrained = iTrained;
+    copy->iPlayDuration = iPlayDuration;
+    
+    
+    // set the iSrsApi to NULL
+    // set the iRetry to NULL
+    
+    // set the state to Idle
+    copy->iState = TNssSpeechItemConstant::EIdle;
+    // set iRecover to False
+    copy->iRecover = EFalse;
+    
+    return copy;
+    }
+
+// ---------------------------------------------------------
+// CNssSpeechItem::CleanUp
+// Method to do the clean up
+// ---------------------------------------------------------
+//
+void CNssSpeechItem::CleanUp()
+    {
+    RUBY_DEBUG1( "CNssSpeechItem::CleanUp tagid: %d", iTagId );
+
+    if ( iTtsData )
+        {
+        CleanPlayback();
+        }
+    }
+
+// ---------------------------------------------------------
+// CNssSpeechItem::DoRetry
+// Method to verify whether retry is already max out,
+// if not return ETrue, else return EFalse
+// ---------------------------------------------------------
+//
+TBool CNssSpeechItem::DoRetry()
+    {
+    if ( iRetry < KVASSpeechItemMaxRetry )
+        {
+        iRetry++;
+        return ETrue;
+        }
+    else
+        {
+        // Reset the retry count
+        iRetry = KVASSpeechItemResetRetry;
+        return EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CNssSpeechItem::DelayedTrainingComplete
+// Updates the speech item, after SI training has been carried out.
+// -----------------------------------------------------------------------------
+//
+void CNssSpeechItem::DelayedTrainingComplete( TUint32 aRuleID )
+    {
+    SetRuleID( aRuleID );
+    
+    if ( aRuleID != KInvalidRuleID )
+        {
+        this->iTrainedType = TNssVasCoreConstant::EVasTrainText;
+        }
+    else
+        {
+        // Training failed; mark all invalid
+        SetRuleID( KInvalidRuleID );
+        
+        this->iTrainedType = TNssVasCoreConstant::EVasNotTrained;
+        }
+    
+    this->iTrained = ETrue;
+    this->iState = TNssSpeechItemConstant::ETrainComplete;
+    }
+
+// -----------------------------------------------------------------------------
+// TTtsData::TTtsData
+// Initializes everything to zero.
+// -----------------------------------------------------------------------------
+//
+CNssSpeechItem::TTtsData::TTtsData() : iStyle(),
+                                       iStyleID( 0 ),
+                                       iSegment( 0 ),
+                                       iTts( NULL ),
+                                       iParsedText( NULL )
+    {
+    // Nothing
+    }
+
+// End of file