diff -r cad71a31b7fc -r e36f3802f733 srsf/ttsutility/src/ttsutilitybody.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srsf/ttsutility/src/ttsutilitybody.cpp Wed Sep 01 12:29:17 2010 +0100 @@ -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 +#include +#include +#include +#include +#include +#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 temp; + ListPluginsL( temp ); + temp.Close(); + + // Default audio priority + StorePriority( KAudioPriorityVoiceDial, + static_cast( 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& aUids ) + { + // Empty the list + aUids.Reset(); + + RMMFControllerImplInfoArray controllers; + CleanupResetAndDestroyPushL( controllers ); + + CMMFControllerPluginSelectionParameters* selectionParams = CMMFControllerPluginSelectionParameters::NewLC(); + + // Select the media IDs to allow + RArray 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& aLanguages ) + { + User::LeaveIfError( iTtsCustomCommands.GetSupportedLanguages( aLanguages ) ); + } + +// ----------------------------------------------------------------------------- +// CTtsUtilityBody::GetSupportedVoicesL +// Returns list of supported voices +// ----------------------------------------------------------------------------- +// +void CTtsUtilityBody::GetSupportedVoicesL( TLanguage aLanguage, + RArray& 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 languages; + iTtsCustomCommands.GetSupportedLanguages( languages ); + + if ( languages.Find( aLanguage ) != KErrNotFound ) + { + if ( aVoice == KNullDesC ) + { + // Language found and undefined voice + answer = ETrue; + } + else + { + RArray 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