--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/ttsutility/src/ttsutilitybody.cpp Thu Dec 17 08:46:30 2009 +0200
@@ -0,0 +1,1181 @@
+/*
+* Copyright (c) 2004-2007 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: Implementations for methods in CTtsUtilityBody
+*
+*/
+
+
+// INCLUDE FILES
+#include "ttsutilitybody.h"
+#include <mmf/server/mmffile.h>
+#include <mmf/server/mmfdes.h>
+#include <mmf/common/mmfcontrollerpluginresolver.h>
+#include <ecom/ecom.h>
+#include <AudioPreference.h>
+#include <utf.h>
+#include "rubydebug.h"
+
+// CONSTANTS
+
+// TTS media type equals to audio media type
+const TUid KUidMediaTypeTTS = { 0x101F5D07 };
+
+// Implementation UID of Tts Plugin
+const TUid KUidTtsPlugin = { 0x101FF934 };
+
+// Implementation UID of HQ-TTS Plugin
+const TUid KUidHqTtsPlugin = { 0x10201AF5 };
+
+// Header for TTS input
+_LIT8( KTtsDataHeader, "(tts)" );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::CTtsUtilityBody
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CTtsUtilityBody::CTtsUtilityBody( MTtsClientUtilityObserver& aObserver ) :
+ iAudioPlayDeviceCommands( iController ),
+ iAudioPlayControllerCommands( iController ),
+ iTtsCustomCommands( iController ),
+ iObserver( aObserver ),
+ iTime( 0 ),
+ iCurrentStyleID( 0 ),
+ iTrailingSilence( 0 ),
+ iOpenPlugin( KNullUid ),
+ iUidOfDataSink( KUidMmfAudioOutput )
+ {
+ // Nothing
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::ConstructL()
+ {
+ // Dummy priority settings
+ iPrioritySettings.iPriority = 0;
+ iPrioritySettings.iPref = ( TMdaPriorityPreference ) 0;
+ iPrioritySettings.iState = EMMFStateIdle; // idle
+
+ // List plugins to make sure that at least one is found
+ RArray<TUid> temp;
+ ListPluginsL( temp );
+ temp.Close();
+
+ // Default audio priority
+ StorePriority( KAudioPriorityVoiceDial,
+ static_cast<TMdaPriorityPreference>( KAudioPrefVocosPlayback ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CTtsUtilityBody* CTtsUtilityBody::NewL( MTtsClientUtilityObserver& aObserver )
+ {
+ CTtsUtilityBody* self = new( ELeave ) CTtsUtilityBody( aObserver );
+
+ CleanupStack::PushL( self );
+
+ self->ConstructL();
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::~CTtsUtilityBody
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CTtsUtilityBody::~CTtsUtilityBody()
+ {
+ // Cancel any pending requests
+ if ( iControllerEventMonitor != NULL )
+ {
+ iControllerEventMonitor->Cancel();
+ }
+
+ delete iControllerEventMonitor;
+ iController.Close();
+
+ iStyles.Close();
+ iInternalStyleIDs.Close();
+ iControllerStyleIDs.Close();
+
+ delete iParsedText;
+
+ REComSession::FinalClose();
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::HandleEvent
+// Handles events from plugin via MMF.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::HandleEvent( const TMMFEvent& aEvent )
+ {
+ TInt result = (TInt)aEvent.iErrorCode;
+
+#ifdef _DEBUG
+ TInt event = (TInt)aEvent.iEventType.iUid;
+ RUBY_DEBUG2( "CTtsUtilityBody::HandleEvent() - Event Type = %d, Event Result = %d",
+ event, result );
+#endif
+
+ if ( aEvent.iEventType == KMMFEventCategoryPlaybackComplete )
+ {
+ if ( result == KErrNone )
+ {
+ iRepeats--;
+
+ if ( iRepeats > 0 )
+ {
+ // @todo Not too good way to handle waiting, we're blocking
+ // the client thread here... Should be done in plugin side..
+ User::After( iTrailingSilence );
+ Play();
+ // Don't make the callback at this point
+ return;
+ }
+ }
+ else
+ {
+ iRepeats = 0;
+ }
+
+ iUidOfDataSink = KUidMmfAudioOutput;
+
+ // Remove data sink - otherwise file handle stays open.
+ // Return value ignored because there is nothing we can do.
+ iController.RemoveDataSink( iSinkHandle );
+
+ iObserver.MapcPlayComplete( result );
+
+ }
+ else if ( aEvent.iEventType == KMMFEventCategoryAudioLoadingComplete )
+ {
+ if ( result != KErrNone )
+ {
+ iUidOfDataSink = KUidMmfAudioOutput;
+ iController.RemoveDataSink( iSinkHandle );
+ }
+
+ iTime = Duration();
+ iObserver.MapcInitComplete( result, iTime );
+ if ( iPlayImmediately )
+ {
+ iPlayImmediately = EFalse;
+ if ( result == KErrNone )
+ {
+ Play();
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::AddStyleL
+// Adds style to collection, calls TTS custom commands.
+// -----------------------------------------------------------------------------
+//
+TTtsStyleID CTtsUtilityBody::AddStyleL( const TTtsStyle& aStyle )
+ {
+ TTtsStyleID controllerID( 0 );
+
+ if ( IsPluginOpen() )
+ {
+ User::LeaveIfError( iTtsCustomCommands.AddStyle( aStyle, controllerID ) );
+ }
+
+ // Add style also to our own array
+ iStyles.Append( aStyle );
+ TTtsStyleID internalID( iCurrentStyleID );
+ iInternalStyleIDs.Append( internalID );
+
+ // This is zero if no open controller connection, will be updated later
+ iControllerStyleIDs.Append( controllerID );
+ iCurrentStyleID++;
+
+ return internalID;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::DeleteStyle
+// Deletes style from collection, calls TTS custom commands.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::DeleteStyle( TTtsStyleID aID )
+ {
+ TTtsStyleID controllerStyleId( 0 );
+
+ // Delete from local storage
+ for ( TInt i = 0; i < iInternalStyleIDs.Count(); i++ )
+ {
+ if ( iInternalStyleIDs[i] == aID )
+ {
+ iInternalStyleIDs.Remove( i );
+ iStyles.Remove( i );
+ // Take note of the controller side style id before removing it
+ controllerStyleId = iControllerStyleIDs[i];
+ iControllerStyleIDs.Remove( i );
+ break;
+ }
+ }
+
+ // Reset style id counter if no styles registered anymore
+ if ( iInternalStyleIDs.Count() == 0 )
+ {
+ iCurrentStyleID = 0;
+ }
+
+ if ( IsPluginOpen() )
+ {
+ // Delete style from controller plugin
+ TInt error = iTtsCustomCommands.DeleteStyle( controllerStyleId );
+ if ( error != KErrNone )
+ {
+ return error;
+ }
+ }
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::NumberOfStyles
+// Returns number of registered styles.
+// -----------------------------------------------------------------------------
+//
+TUint16 CTtsUtilityBody::NumberOfStyles()
+ {
+ return ( TUint16 ) iStyles.Count();
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::StyleL
+// Returns reference to registered style based on style ID.
+// -----------------------------------------------------------------------------
+//
+TTtsStyle& CTtsUtilityBody::StyleL( TTtsStyleID aStyleID )
+ {
+ TInt i( 0 );
+ TInt count( iInternalStyleIDs.Count() );
+
+ while ( i < count && iInternalStyleIDs[i] != aStyleID )
+ {
+ i++;
+ }
+
+ if ( i == count )
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ return iStyles[i];
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::StyleL
+// Returns reference to registered style based on style index.
+// -----------------------------------------------------------------------------
+//
+TTtsStyle& CTtsUtilityBody::StyleL( TUint16 aIndex )
+ {
+ if ( aIndex >= iStyles.Count() )
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ return iStyles[aIndex];
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::Play
+// Starts playback.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::Play()
+ {
+ iController.Play();
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::Stop
+// Stops playback.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::Stop()
+ {
+ iRepeats = 0;
+ iController.Stop();
+ iUidOfDataSink = KUidMmfAudioOutput;
+ iController.RemoveDataSink( iSinkHandle );
+ iPlayImmediately = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SetVolume
+// Sets playback volume.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::SetVolume( TInt aVolume )
+ {
+ iAudioPlayDeviceCommands.SetVolume( aVolume );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SetRepeats
+// Sets number of repeats.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::SetRepeats( TInt aRepeatNumberOfTimes,
+ const TTimeIntervalMicroSeconds& aTrailingSilence )
+ {
+ iTrailingSilence = TTimeIntervalMicroSeconds32( I64LOW( aTrailingSilence.Int64() ) );
+ iRepeats = aRepeatNumberOfTimes;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::Duration
+// Returns duration of TTS 'clip'.
+// -----------------------------------------------------------------------------
+//
+const TTimeIntervalMicroSeconds& CTtsUtilityBody::Duration()
+ {
+ iDuration = 0;
+ iController.GetDuration( iDuration ); // Ignoring return value
+
+ return iDuration;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::MaxVolume
+// Returns maximum volume.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::MaxVolume()
+ {
+ TInt volume = 0;
+ if ( iAudioPlayDeviceCommands.GetMaxVolume( volume ) != KErrNone )
+ {
+ return 0;
+ }
+ return volume;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::OpenAndPlayDesL
+// Opens descriptor source and plays it immediately.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenAndPlayDesL( const TDesC8& aDescriptor )
+ {
+ iPlayImmediately = ETrue;
+
+ TRAPD( error, OpenDesL( aDescriptor ) );
+ if ( error != KErrNone )
+ {
+ iPlayImmediately = EFalse;
+ User::Leave( error );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::OpenAndPlayFileL
+// Opens file source and plays it immediately.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenAndPlayFileL( const TDesC& aFileName )
+ {
+ iPlayImmediately = ETrue;
+
+ TRAPD( error, OpenFileL( aFileName ) );
+ if ( error != KErrNone )
+ {
+ iPlayImmediately = EFalse;
+ User::Leave( error );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::OpenAndPlayParsedTextL
+// Opens parsed text source and plays it immediately.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenAndPlayParsedTextL( CTtsParsedText& aText )
+ {
+ iPlayImmediately = ETrue;
+
+ TRAPD( error, OpenParsedTextL( aText ) );
+ if ( error != KErrNone )
+ {
+ iPlayImmediately = EFalse;
+ User::Leave( error );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::OpenDesL
+// Opens descriptor source
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenDesL( const TDesC8& aDescriptor )
+ {
+ if ( !iPluginOpenedExplicitly )
+ {
+ CheckAndLoadCorrectPluginL( iDefaultStyle.iQuality,
+ iDefaultStyle.iLanguage,
+ iDefaultStyle.iVoice );
+ }
+
+ // Add data descriptor source
+ TMMFDescriptorConfig sourceCfg;
+ sourceCfg().iDes = (TAny*)&aDescriptor;
+ sourceCfg().iDesThreadId = RThread().Id();
+ User::LeaveIfError( iController.AddDataSource( KUidMmfDescriptorSource,
+ sourceCfg, iSourceHandle ) );
+
+ // Add data sink to file or audio output
+ AddDataSinkL();
+
+ // Prime controller
+ User::LeaveIfError( iController.Prime() );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::OpenFileL
+// Opens file source
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenFileL( const TDesC& aFileName )
+ {
+ if ( !iPluginOpenedExplicitly )
+ {
+ CheckAndLoadCorrectPluginL( iDefaultStyle.iQuality,
+ iDefaultStyle.iLanguage,
+ iDefaultStyle.iVoice );
+ }
+
+ // Add data file source
+ TMMFFileConfig sourceCfg;
+ sourceCfg().iPath = aFileName;
+ User::LeaveIfError( iController.AddDataSource( KUidMmfFileSource, sourceCfg,
+ iSourceHandle ) );
+ // Add data sink to file or audio output
+ AddDataSinkL();
+
+ // Prime controller
+ User::LeaveIfError( iController.Prime() );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::OpenParsedTextL
+// Opens parsed text source with the help of TTS custom commands.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenParsedTextL( CTtsParsedText& aText )
+ {
+ if ( !iPluginOpenedExplicitly )
+ {
+ if ( aText.NumberOfSegments() > 0 )
+ {
+ // Take the first segment
+ const TTtsSegment& segment = aText.SegmentL( 0 );
+
+ TTtsStyleID styleID = segment.StyleID();
+
+ // Style should have been registered already
+ TTtsStyle& style = StyleL( styleID );
+
+ CheckAndLoadCorrectPluginL( style.iQuality, style.iLanguage,
+ style.iVoice );
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+
+ // Data source is now parsed text
+ CopyParsedTextL( aText );
+ User::LeaveIfError( iTtsCustomCommands.OpenParsedText( *iParsedText ) );
+
+ // Add data sink to file or audio output
+ AddDataSinkL();
+
+ User::LeaveIfError( iController.Prime() );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::Pause
+// Pauses playback.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::Pause()
+ {
+ return iController.Pause();
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::OpenPluginL
+// Opens connection to plugin
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenPluginL( TUid aUid )
+ {
+ OpenControllerConnectionL( aUid );
+
+ iPluginOpenedExplicitly = ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::ListPluginsL
+// Lists available plugins
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::ListPluginsL( RArray<TUid>& aUids )
+ {
+ // Empty the list
+ aUids.Reset();
+
+ RMMFControllerImplInfoArray controllers;
+ CleanupResetAndDestroyPushL( controllers );
+
+ CMMFControllerPluginSelectionParameters* selectionParams = CMMFControllerPluginSelectionParameters::NewLC();
+
+ // Select the media IDs to allow
+ RArray<TUid> mediaIds;
+ CleanupClosePushL( mediaIds );
+ User::LeaveIfError( mediaIds.Append( KUidMediaTypeTTS ) );
+
+ selectionParams->SetMediaIdsL( mediaIds, CMMFPluginSelectionParameters::EAllowOnlySuppliedMediaIds );
+ CleanupStack::PopAndDestroy( &mediaIds );
+
+ // Check also the allowed data headers
+ // Should be "(tts)"
+ CMMFFormatSelectionParameters* formatSelectParams = CMMFFormatSelectionParameters::NewLC();
+ formatSelectParams->SetMatchToHeaderDataL( KTtsDataHeader );
+
+ selectionParams->SetRequiredPlayFormatSupportL( *formatSelectParams );
+
+ CleanupStack::PopAndDestroy( formatSelectParams );
+
+ // Do the list of implementation
+ selectionParams->ListImplementationsL( controllers );
+
+ // Make sure at least one controller has been found
+ if( controllers.Count() == 0 )
+ {
+ RUBY_DEBUG1( "No controllers found using media type %x", KUidMediaTypeTTS );
+ User::Leave( KErrNotFound );
+ }
+
+ for ( TInt c = 0; c < controllers.Count(); c++ )
+ {
+ RUBY_DEBUG1( "UID = %x", controllers[c]->Uid() );
+ aUids.Append( controllers[c]->Uid() );
+ }
+
+ CleanupStack::PopAndDestroy( selectionParams );
+ CleanupStack::PopAndDestroy( &controllers );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SetDefaultStyleL
+// Sets deafault style
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::SetDefaultStyleL( const TTtsStyle& aStyle )
+ {
+ User::LeaveIfError( iTtsCustomCommands.SetDefaultStyle( aStyle ) );
+ iDefaultStyle = aStyle;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::DefaultStyleL
+// Returns default style
+// -----------------------------------------------------------------------------
+//
+TTtsStyle& CTtsUtilityBody::DefaultStyleL()
+ {
+ User::LeaveIfError( iTtsCustomCommands.GetDefaultStyle( iDefaultStyle ) );
+ return iDefaultStyle;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SetSpeakingRateL
+// Sets speaking rate
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::SetSpeakingRateL( TInt aRate )
+ {
+ User::LeaveIfError( iTtsCustomCommands.SetSpeakingRate( aRate ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SpeakingRateL
+// Returns speaking rate
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::SpeakingRateL()
+ {
+ TInt rate( KErrGeneral );
+ User::LeaveIfError( iTtsCustomCommands.GetSpeakingRate( rate ) );
+ return rate;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::GetSupportedLanguagesL
+// Returns list of supported languages
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::GetSupportedLanguagesL( RArray<TLanguage>& aLanguages )
+ {
+ User::LeaveIfError( iTtsCustomCommands.GetSupportedLanguages( aLanguages ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::GetSupportedVoicesL
+// Returns list of supported voices
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::GetSupportedVoicesL( TLanguage aLanguage,
+ RArray<TTtsStyle>& aVoices )
+ {
+ User::LeaveIfError( iTtsCustomCommands.GetSupportedVoices( aLanguage, aVoices ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::OpenDesL
+// Opens unicode descriptor
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenDesL( const TDesC& aDescriptor )
+ {
+ HBufC8* utf8string = ConvertToUtf8LC( aDescriptor );
+ OpenDesL( utf8string->Des() );
+ CleanupStack::PopAndDestroy( utf8string );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::GetSupportedVoicesL
+// Opens and plays unicode descriptor
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenAndPlayDesL( const TDesC& aDescriptor )
+ {
+ HBufC8* utf8string = ConvertToUtf8LC( aDescriptor );
+ OpenAndPlayDesL( utf8string->Des() );
+ CleanupStack::PopAndDestroy( utf8string );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SetOutputFileL
+// Sets output to be written to the file handle
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::SetOutputFileL( const RFile& aFile )
+ {
+ iUidOfDataSink = KUidMmfFileSink;
+
+ // iFile has to contain valid file handle when data sink
+ // is marked to be file sink.
+ iFile = aFile;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::Close
+// Closes current TTS synthesis source.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::Close()
+ {
+ iRepeats = 0;
+ if ( iControllerEventMonitor != NULL )
+ {
+ iControllerEventMonitor->Cancel();
+ }
+ delete iControllerEventMonitor;
+ iControllerEventMonitor = NULL;
+ iController.Close();
+ iPluginOpenedExplicitly = EFalse;
+ iOpenPlugin = KNullUid;
+ iUidOfDataSink = KUidMmfAudioOutput;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::GetPosition
+// Returns position of synthesis in microseconds.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::GetPosition( TTimeIntervalMicroSeconds& aPosition )
+ {
+ return iController.GetPosition( aPosition );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::GetPosition
+// Returns position of synthesis in words.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::GetPosition( TInt& aWordIndex )
+ {
+ return iTtsCustomCommands.GetPosition( aWordIndex );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SetPosition
+// Sets synthesis position in microseconds.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::SetPosition( const TTimeIntervalMicroSeconds& aPosition )
+ {
+ iController.SetPosition( aPosition );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SetPosition
+// Sets synthesis position in words.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::SetPosition( TInt aWordIndex )
+ {
+ iTtsCustomCommands.SetPosition( aWordIndex );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SetPriority
+// Sets playback priority.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::SetPriority( TInt aPriority, TMdaPriorityPreference aPref )
+ {
+ StorePriority( aPriority, aPref );
+
+ if ( IsPluginOpen() )
+ {
+ return iController.SetPrioritySettings( iPrioritySettings );
+ }
+ else
+ {
+ return KErrNone;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::GetVolume
+// Returns volume value.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::GetVolume( TInt& aVolume )
+ {
+ return iAudioPlayDeviceCommands.GetVolume( aVolume );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::SetBalance
+// Sets balance.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::SetBalance( TInt aBalance )
+ {
+ return iAudioPlayDeviceCommands.SetBalance( aBalance );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::GetBalance
+// Returns current balance setting.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::GetBalance( TInt& aBalance )
+ {
+ return iAudioPlayDeviceCommands.GetBalance( aBalance );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::CustomCommandSync
+// Sends synchronous custom command via MMF.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::CustomCommandSync( const TMMFMessageDestinationPckg& aDestination,
+ TInt aFunction,
+ const TDesC8& aDataTo1,
+ const TDesC8& aDataTo2,
+ TDes8& aDataFrom )
+ {
+ return iController.CustomCommandSync( aDestination, aFunction, aDataTo1, aDataTo2, aDataFrom );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::CustomCommandSync
+// Sends synchronous custom command via MMF.
+// -----------------------------------------------------------------------------
+//
+TInt CTtsUtilityBody::CustomCommandSync( const TMMFMessageDestinationPckg& aDestination,
+ TInt aFunction,
+ const TDesC8& aDataTo1,
+ const TDesC8& aDataTo2 )
+ {
+ return iController.CustomCommandSync( aDestination, aFunction, aDataTo1, aDataTo2 );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::CustomCommandAsync
+// Sends asynchronous custom command via MMF.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::CustomCommandAsync( const TMMFMessageDestinationPckg& aDestination,
+ TInt aFunction,
+ const TDesC8& aDataTo1,
+ const TDesC8& aDataTo2,
+ TDes8& aDataFrom,
+ TRequestStatus& aStatus )
+ {
+ iController.CustomCommandAsync( aDestination, aFunction, aDataTo1, aDataTo2, aDataFrom, aStatus );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::CustomCommandAsync
+// Sends asynchronous custom command via MMF.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::CustomCommandAsync( const TMMFMessageDestinationPckg& aDestination,
+ TInt aFunction,
+ const TDesC8& aDataTo1,
+ const TDesC8& aDataTo2,
+ TRequestStatus& aStatus )
+ {
+ iController.CustomCommandAsync( aDestination, aFunction, aDataTo1, aDataTo2, aStatus );
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::IsPluginOpen
+// Returns ETrue if connection is established with controller plugin
+// -----------------------------------------------------------------------------
+//
+TBool CTtsUtilityBody::IsPluginOpen()
+ {
+ if ( iOpenPlugin == KNullUid )
+ {
+ return EFalse;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::OpenControllerConnectionL
+// Opens controller connection if it has been closed
+// Changes plugin if the one requested is not loaded currently
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::OpenControllerConnectionL( TUid aPluginUid )
+ {
+ RUBY_DEBUG_BLOCK( "CTtsUtilityBody::OpenControllerConnectionL(aPluginUid)" );
+
+ if ( iOpenPlugin != aPluginUid )
+ {
+ // Clear previously loaded plugin if needed
+ if ( IsPluginOpen() )
+ {
+ Close();
+ }
+
+ TInt error = iController.Open( aPluginUid, iPrioritySettings );
+ if ( error )
+ {
+ RUBY_DEBUG2( "Unable to load controller plugin, error = %d, UID = %x",
+ error, aPluginUid );
+ User::Leave( error );
+ }
+ else
+ {
+ if ( iControllerEventMonitor == NULL )
+ {
+ // Start the event monitor
+ iControllerEventMonitor = CMMFControllerEventMonitor::NewL( *this, iController );
+ iControllerEventMonitor->Start();
+ }
+ }
+
+ iOpenPlugin = aPluginUid;
+
+ // Add already registered styles to controller plugin too
+ for ( TInt i( 0 ); i < iStyles.Count(); i++ )
+ {
+ TTtsStyleID controllerStyleId( 0 );
+ User::LeaveIfError( iTtsCustomCommands.AddStyle( iStyles[i], controllerStyleId ) );
+ iControllerStyleIDs[i] = controllerStyleId;
+ }
+
+ // Set priority settings
+ User::LeaveIfError( SetPriority( iPrioritySettings.iPriority,
+ (TMdaPriorityPreference) iPrioritySettings.iPref ) );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::CopyParsedTextL
+// Copies parsed text structure and substitutes style ids to corresponding plugin
+// ids.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::CopyParsedTextL( CTtsParsedText& aText )
+ {
+ RUBY_DEBUG_BLOCK( "CTtsUtilityBody::CopyParsedTextL" );
+
+ // Delete previous object if exists
+ delete iParsedText;
+ iParsedText = NULL;
+
+ // New instance
+ iParsedText = CTtsParsedText::NewL( aText.Text(), aText.PhonemeSequence(),
+ aText.PhonemeNotation() );
+
+ // Segments
+
+ // Indexes for starting points for segment's text and phoneme part in
+ // CTtsParsedText object's text and phoneme sequence
+ TInt textIndex( 0 );
+ TInt phonemeIndex( 0 );
+
+ for ( TInt i = 0; i < aText.NumberOfSegments(); i++ )
+ {
+ TTtsSegment segment = aText.SegmentL( i );
+
+ TInt styleIndex = iInternalStyleIDs.Find( aText.SegmentL( i ).StyleID() );
+ User::LeaveIfError( styleIndex );
+ segment.SetStyleID( iControllerStyleIDs[styleIndex] );
+
+ TInt segTextLength = aText.SegmentL( i ).TextPtr().Length();
+ TInt segPhonemeSeqLength = aText.SegmentL( i )
+ .PhonemeSequencePtr().Length();
+
+ // Text
+ if ( textIndex + segTextLength
+ <= iParsedText->Text().Length() )
+ {
+ segment.SetTextPtr( iParsedText->Text()
+ .Mid( textIndex, segTextLength ) );
+
+ textIndex += segTextLength;
+ }
+ // Segments are somehow constructed illegally. Copy the whole text.
+ else
+ {
+ segment.SetTextPtr( iParsedText->Text() );
+ }
+
+ // Phoneme sequence
+ if ( phonemeIndex + segPhonemeSeqLength
+ <= iParsedText->PhonemeSequence().Length() )
+ {
+ segment.SetPhonemeSequencePtr(
+ iParsedText->PhonemeSequence().Mid( phonemeIndex, segPhonemeSeqLength ) );
+
+ phonemeIndex += segPhonemeSeqLength;
+ }
+ else
+ {
+ segment.SetPhonemeSequencePtr(
+ iParsedText->PhonemeSequence() );
+ }
+
+ // Add segment to the new instance of CTtsParsedText
+ iParsedText->AddSegmentL( segment );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::StorePriority
+// Stores priority values locally to be sent to the plugin when connection is
+// opened.
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::StorePriority( TInt aPriority, TMdaPriorityPreference aPref )
+ {
+ iPrioritySettings.iPriority = aPriority;
+ iPrioritySettings.iPref = aPref;
+ iPrioritySettings.iState = EMMFStateIdle;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::ConvertToUtf8LC
+// Converts unicode descriptor to utf-8
+// -----------------------------------------------------------------------------
+//
+HBufC8* CTtsUtilityBody::ConvertToUtf8LC( const TDesC& aDes )
+ {
+ HBufC8* utf8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aDes );
+ CleanupStack::PushL( utf8 );
+ return utf8;
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::AddDataSinkL
+// Adds data sink (file and audio supported)
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::AddDataSinkL()
+ {
+ RUBY_DEBUG_BLOCKL( "CTtsUtilityBody::AddDataSinkL" );
+
+ if ( iUidOfDataSink == KUidMmfAudioOutput )
+ {
+ User::LeaveIfError( iController.AddDataSink( KUidMmfAudioOutput,
+ KNullDesC8, iSinkHandle ) );
+ }
+ else if ( iUidOfDataSink == KUidMmfFileSink )
+ {
+ TMMFFileHandleConfig destCfg( &iFile );
+
+ TInt error = iController.AddDataSink( KUidMmfFileSink,destCfg, iSinkHandle );
+ if ( error )
+ {
+ iUidOfDataSink = KUidMmfAudioOutput;
+ User::Leave( error );
+ }
+ }
+ else
+ {
+ User::Leave( KErrNotSupported );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::CheckAndLoadCorrectPluginL
+//
+// -----------------------------------------------------------------------------
+//
+void CTtsUtilityBody::CheckAndLoadCorrectPluginL( TTtsQuality aQuality,
+ TLanguage aLanguage,
+ const TTtsVoice& aVoice )
+ {
+ RUBY_DEBUG_BLOCKL( "CTtsUtilityBody::CheckAndLoadCorrectPluginL" );
+
+ TInt error( KErrNone );
+
+ switch ( aQuality )
+ {
+ case ETtsQualityHighOnly:
+
+ OpenControllerConnectionL( KUidHqTtsPlugin );
+
+ break;
+
+ case ETtsQualityLowOnly:
+ case ETtsQualityUndefined:
+
+ OpenControllerConnectionL( KUidTtsPlugin );
+
+ break;
+
+ case ETtsQualityHighPreferred:
+
+ TRAP( error, OpenControllerConnectionL( KUidHqTtsPlugin ) );
+ if ( error || !IsSupportedSpeaker( aLanguage, aVoice ) )
+ {
+ // Try to use Klatt if Hqtts not found or specific language/speaker
+ // not available
+ OpenControllerConnectionL( KUidTtsPlugin );
+ }
+
+ break;
+
+ case ETtsQualityLowPreferred:
+
+ TRAP( error, OpenControllerConnectionL( KUidTtsPlugin ) );
+ if ( error || !IsSupportedSpeaker( aLanguage, aVoice ) )
+ {
+ // Try to use Hqtts if Klatt not found or specific language/speaker
+ // not available
+ OpenControllerConnectionL( KUidHqTtsPlugin );
+ }
+
+ break;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CTtsUtilityBody::IsSupportedSpeaker
+//
+// -----------------------------------------------------------------------------
+//
+TBool CTtsUtilityBody::IsSupportedSpeaker( TLanguage aLanguage,
+ const TTtsVoice& aVoice )
+ {
+ TBool answer( EFalse );
+
+ if ( aLanguage == KTtsUndefinedLanguage )
+ {
+ // Undefined language -> plugin can use default language and voice.
+ answer = ETrue;
+ }
+ else
+ {
+ RArray<TLanguage> languages;
+ iTtsCustomCommands.GetSupportedLanguages( languages );
+
+ if ( languages.Find( aLanguage ) != KErrNotFound )
+ {
+ if ( aVoice == KNullDesC )
+ {
+ // Language found and undefined voice
+ answer = ETrue;
+ }
+ else
+ {
+ RArray<TTtsStyle> voices;
+ iTtsCustomCommands.GetSupportedVoices( aLanguage, voices );
+
+ TInt counter( 0 );
+
+ while ( answer == EFalse && counter < voices.Count() )
+ {
+ if ( voices[counter].iVoice == aVoice )
+ {
+ // Both language and voice are supported
+ // by currently loaded plugin.
+ answer = ETrue;
+ }
+
+ counter++;
+ }
+
+ voices.Close();
+ }
+ }
+
+ languages.Close();
+ }
+
+ return answer;
+ }
+
+// End of File