srsf/ttsutility/src/ttsutilitybody.cpp
changeset 13 57b735022c18
parent 1 b13cd05eeb2f
equal deleted inserted replaced
1:b13cd05eeb2f 13:57b735022c18
     1 /*
       
     2 * Copyright (c) 2004-2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementations for methods in CTtsUtilityBody
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "ttsutilitybody.h"
       
    21 #include <mmf/server/mmffile.h>
       
    22 #include <mmf/server/mmfdes.h>
       
    23 #include <mmf/common/mmfcontrollerpluginresolver.h>
       
    24 #include <ecom/ecom.h>
       
    25 #include <AudioPreference.h>
       
    26 #include <utf.h>
       
    27 #include "rubydebug.h"
       
    28 
       
    29 // CONSTANTS
       
    30 
       
    31 // TTS media type equals to audio media type
       
    32 const TUid KUidMediaTypeTTS = { 0x101F5D07 };
       
    33 
       
    34 // Implementation UID of Tts Plugin
       
    35 const TUid KUidTtsPlugin = { 0x101FF934 };
       
    36 
       
    37 // Implementation UID of HQ-TTS Plugin
       
    38 const TUid KUidHqTtsPlugin = { 0x10201AF5 };
       
    39 
       
    40 // Header for TTS input
       
    41 _LIT8( KTtsDataHeader, "(tts)" );
       
    42 
       
    43 // ============================ MEMBER FUNCTIONS ===============================
       
    44 
       
    45 // -----------------------------------------------------------------------------
       
    46 // CTtsUtilityBody::CTtsUtilityBody
       
    47 // C++ default constructor can NOT contain any code, that
       
    48 // might leave.
       
    49 // -----------------------------------------------------------------------------
       
    50 //
       
    51 CTtsUtilityBody::CTtsUtilityBody( MTtsClientUtilityObserver& aObserver ) : 
       
    52                                   iAudioPlayDeviceCommands( iController ),
       
    53                                   iAudioPlayControllerCommands( iController ),
       
    54                                   iTtsCustomCommands( iController ),
       
    55                                   iObserver( aObserver ),
       
    56                                   iTime( 0 ),
       
    57                                   iCurrentStyleID( 0 ),
       
    58                                   iTrailingSilence( 0 ),
       
    59                                   iOpenPlugin( KNullUid ),
       
    60                                   iUidOfDataSink( KUidMmfAudioOutput )
       
    61     {
       
    62     // Nothing
       
    63     }
       
    64 
       
    65 // -----------------------------------------------------------------------------
       
    66 // CTtsUtilityBody::ConstructL
       
    67 // Symbian 2nd phase constructor can leave.
       
    68 // -----------------------------------------------------------------------------
       
    69 //
       
    70 void CTtsUtilityBody::ConstructL()
       
    71     {
       
    72     // Dummy priority settings
       
    73     iPrioritySettings.iPriority = 0;
       
    74     iPrioritySettings.iPref = ( TMdaPriorityPreference ) 0;
       
    75     iPrioritySettings.iState = EMMFStateIdle; // idle
       
    76     
       
    77     // List plugins to make sure that at least one is found
       
    78     RArray<TUid> temp;
       
    79     ListPluginsL( temp );
       
    80     temp.Close();
       
    81 
       
    82     // Default audio priority
       
    83     StorePriority( KAudioPriorityVoiceDial, 
       
    84                    static_cast<TMdaPriorityPreference>( KAudioPrefVocosPlayback ) );
       
    85     }
       
    86 
       
    87 // -----------------------------------------------------------------------------
       
    88 // CTtsUtilityBody::NewL
       
    89 // Two-phased constructor.
       
    90 // -----------------------------------------------------------------------------
       
    91 //
       
    92 CTtsUtilityBody* CTtsUtilityBody::NewL( MTtsClientUtilityObserver& aObserver )
       
    93     {
       
    94     CTtsUtilityBody* self = new( ELeave ) CTtsUtilityBody( aObserver );
       
    95     
       
    96     CleanupStack::PushL( self );
       
    97 
       
    98     self->ConstructL();
       
    99     CleanupStack::Pop();
       
   100     
       
   101     return self;
       
   102     }
       
   103 
       
   104 // -----------------------------------------------------------------------------
       
   105 // CTtsUtilityBody::~CTtsUtilityBody
       
   106 // Destructor.
       
   107 // -----------------------------------------------------------------------------
       
   108 //
       
   109 CTtsUtilityBody::~CTtsUtilityBody()
       
   110     {
       
   111     // Cancel any pending requests
       
   112     if ( iControllerEventMonitor != NULL )
       
   113         {
       
   114         iControllerEventMonitor->Cancel();
       
   115         }
       
   116 
       
   117     delete iControllerEventMonitor;
       
   118     iController.Close();
       
   119  
       
   120     iStyles.Close();
       
   121     iInternalStyleIDs.Close();
       
   122     iControllerStyleIDs.Close();
       
   123     
       
   124     delete iParsedText;
       
   125     
       
   126     REComSession::FinalClose();
       
   127     }
       
   128 
       
   129 // -----------------------------------------------------------------------------
       
   130 // CTtsUtilityBody::HandleEvent
       
   131 // Handles events from plugin via MMF.
       
   132 // -----------------------------------------------------------------------------
       
   133 //
       
   134 void CTtsUtilityBody::HandleEvent( const TMMFEvent& aEvent )
       
   135     {
       
   136     TInt result = (TInt)aEvent.iErrorCode;
       
   137 
       
   138 #ifdef _DEBUG
       
   139     TInt event = (TInt)aEvent.iEventType.iUid;
       
   140     RUBY_DEBUG2( "CTtsUtilityBody::HandleEvent() - Event Type = %d, Event Result = %d", 
       
   141                  event, result );
       
   142 #endif
       
   143     
       
   144     if ( aEvent.iEventType == KMMFEventCategoryPlaybackComplete )
       
   145         {
       
   146         if ( result == KErrNone )
       
   147             {
       
   148             iRepeats--;
       
   149             
       
   150             if ( iRepeats > 0 )
       
   151                 {
       
   152                 // @todo Not too good way to handle waiting, we're blocking
       
   153                 // the client thread here... Should be done in plugin side..
       
   154                 User::After( iTrailingSilence );
       
   155                 Play();
       
   156                 // Don't make the callback at this point
       
   157                 return;
       
   158                 }
       
   159             }
       
   160         else
       
   161             {
       
   162             iRepeats = 0;
       
   163             }
       
   164         
       
   165         iUidOfDataSink = KUidMmfAudioOutput;
       
   166 
       
   167         // Remove data sink - otherwise file handle stays open. 
       
   168         // Return value ignored because there is nothing we can do. 
       
   169         iController.RemoveDataSink( iSinkHandle );
       
   170 
       
   171         iObserver.MapcPlayComplete( result );
       
   172         
       
   173         }
       
   174     else if ( aEvent.iEventType == KMMFEventCategoryAudioLoadingComplete )
       
   175         {
       
   176         if ( result != KErrNone )
       
   177             {
       
   178             iUidOfDataSink = KUidMmfAudioOutput; 
       
   179             iController.RemoveDataSink( iSinkHandle );
       
   180             }
       
   181             
       
   182         iTime = Duration();
       
   183         iObserver.MapcInitComplete( result, iTime );
       
   184         if ( iPlayImmediately )
       
   185             {
       
   186             iPlayImmediately = EFalse;
       
   187             if ( result == KErrNone )
       
   188                 {
       
   189                 Play();
       
   190                 }
       
   191             }
       
   192         }
       
   193     }
       
   194 
       
   195 // -----------------------------------------------------------------------------
       
   196 // CTtsUtilityBody::AddStyleL
       
   197 // Adds style to collection, calls TTS custom commands.
       
   198 // -----------------------------------------------------------------------------
       
   199 //
       
   200 TTtsStyleID CTtsUtilityBody::AddStyleL( const TTtsStyle& aStyle )
       
   201     {
       
   202     TTtsStyleID controllerID( 0 );
       
   203     
       
   204     if ( IsPluginOpen() )
       
   205         {
       
   206         User::LeaveIfError( iTtsCustomCommands.AddStyle( aStyle, controllerID ) );
       
   207         }
       
   208 
       
   209     // Add style also to our own array
       
   210     iStyles.Append( aStyle );
       
   211     TTtsStyleID internalID( iCurrentStyleID ); 
       
   212     iInternalStyleIDs.Append( internalID );
       
   213 
       
   214     // This is zero if no open controller connection, will be updated later
       
   215     iControllerStyleIDs.Append( controllerID ); 
       
   216     iCurrentStyleID++;
       
   217 
       
   218     return internalID;
       
   219     }
       
   220 
       
   221 // -----------------------------------------------------------------------------
       
   222 // CTtsUtilityBody::DeleteStyle
       
   223 // Deletes style from collection, calls TTS custom commands.
       
   224 // -----------------------------------------------------------------------------
       
   225 //
       
   226 TInt CTtsUtilityBody::DeleteStyle( TTtsStyleID aID )
       
   227     {
       
   228     TTtsStyleID controllerStyleId( 0 );
       
   229 
       
   230     // Delete from local storage
       
   231     for ( TInt i = 0; i < iInternalStyleIDs.Count(); i++ )
       
   232         {
       
   233         if ( iInternalStyleIDs[i] == aID )
       
   234             {
       
   235             iInternalStyleIDs.Remove( i );
       
   236             iStyles.Remove( i );
       
   237             // Take note of the controller side style id before removing it
       
   238             controllerStyleId = iControllerStyleIDs[i];
       
   239             iControllerStyleIDs.Remove( i );
       
   240             break;
       
   241             }
       
   242         }
       
   243 
       
   244     // Reset style id counter if no styles registered anymore
       
   245     if ( iInternalStyleIDs.Count() == 0 )
       
   246         {
       
   247         iCurrentStyleID = 0;
       
   248         }
       
   249 
       
   250     if ( IsPluginOpen() )
       
   251         {
       
   252         // Delete style from controller plugin
       
   253         TInt error = iTtsCustomCommands.DeleteStyle( controllerStyleId );
       
   254         if ( error != KErrNone )
       
   255             {
       
   256             return error;
       
   257             }
       
   258         }
       
   259 
       
   260     return KErrNone;
       
   261     }
       
   262 
       
   263 // -----------------------------------------------------------------------------
       
   264 // CTtsUtilityBody::NumberOfStyles
       
   265 // Returns number of registered styles.
       
   266 // -----------------------------------------------------------------------------
       
   267 //
       
   268 TUint16 CTtsUtilityBody::NumberOfStyles()
       
   269     {
       
   270     return ( TUint16 ) iStyles.Count();
       
   271     }
       
   272 
       
   273 // -----------------------------------------------------------------------------
       
   274 // CTtsUtilityBody::StyleL
       
   275 // Returns reference to registered style based on style ID.
       
   276 // -----------------------------------------------------------------------------
       
   277 //
       
   278 TTtsStyle& CTtsUtilityBody::StyleL( TTtsStyleID aStyleID )
       
   279     {
       
   280     TInt i( 0 );
       
   281     TInt count( iInternalStyleIDs.Count() );
       
   282     
       
   283     while ( i < count && iInternalStyleIDs[i] != aStyleID )
       
   284         {
       
   285         i++;
       
   286         }
       
   287     
       
   288     if ( i == count )
       
   289         {
       
   290         User::Leave( KErrNotFound );
       
   291         }
       
   292 
       
   293     return iStyles[i];
       
   294     }
       
   295 
       
   296 // -----------------------------------------------------------------------------
       
   297 // CTtsUtilityBody::StyleL
       
   298 // Returns reference to registered style based on style index.
       
   299 // -----------------------------------------------------------------------------
       
   300 //
       
   301 TTtsStyle& CTtsUtilityBody::StyleL( TUint16 aIndex )
       
   302     {
       
   303     if ( aIndex >= iStyles.Count() )
       
   304         {
       
   305         User::Leave( KErrNotFound );
       
   306         }
       
   307 
       
   308     return iStyles[aIndex];
       
   309     }
       
   310 
       
   311 // -----------------------------------------------------------------------------
       
   312 // CTtsUtilityBody::Play
       
   313 // Starts playback.
       
   314 // -----------------------------------------------------------------------------
       
   315 //
       
   316 void CTtsUtilityBody::Play()
       
   317     {
       
   318     iController.Play();
       
   319     }
       
   320 
       
   321 // -----------------------------------------------------------------------------
       
   322 // CTtsUtilityBody::Stop
       
   323 // Stops playback.
       
   324 // -----------------------------------------------------------------------------
       
   325 //
       
   326 void CTtsUtilityBody::Stop()
       
   327     {
       
   328     iRepeats = 0;
       
   329     iController.Stop();
       
   330     iUidOfDataSink = KUidMmfAudioOutput;
       
   331     iController.RemoveDataSink( iSinkHandle );
       
   332     iPlayImmediately = EFalse;
       
   333     }
       
   334 
       
   335 // -----------------------------------------------------------------------------
       
   336 // CTtsUtilityBody::SetVolume
       
   337 // Sets playback volume.
       
   338 // -----------------------------------------------------------------------------
       
   339 //
       
   340 void CTtsUtilityBody::SetVolume( TInt aVolume )
       
   341     {
       
   342     iAudioPlayDeviceCommands.SetVolume( aVolume );
       
   343     }
       
   344 
       
   345 // -----------------------------------------------------------------------------
       
   346 // CTtsUtilityBody::SetRepeats
       
   347 // Sets number of repeats.
       
   348 // -----------------------------------------------------------------------------
       
   349 //
       
   350 void CTtsUtilityBody::SetRepeats( TInt aRepeatNumberOfTimes, 
       
   351                                   const TTimeIntervalMicroSeconds& aTrailingSilence )
       
   352     {
       
   353     iTrailingSilence = TTimeIntervalMicroSeconds32( I64LOW( aTrailingSilence.Int64() ) );
       
   354     iRepeats = aRepeatNumberOfTimes;
       
   355     }
       
   356         
       
   357 // -----------------------------------------------------------------------------
       
   358 // CTtsUtilityBody::Duration
       
   359 // Returns duration of TTS 'clip'.
       
   360 // -----------------------------------------------------------------------------
       
   361 //
       
   362 const TTimeIntervalMicroSeconds& CTtsUtilityBody::Duration()
       
   363     {
       
   364     iDuration = 0; 
       
   365     iController.GetDuration( iDuration ); // Ignoring return value 
       
   366     
       
   367     return iDuration; 
       
   368     } 
       
   369     
       
   370 // -----------------------------------------------------------------------------
       
   371 // CTtsUtilityBody::MaxVolume
       
   372 // Returns maximum volume.
       
   373 // -----------------------------------------------------------------------------
       
   374 //
       
   375 TInt CTtsUtilityBody::MaxVolume()
       
   376     {
       
   377     TInt volume = 0;
       
   378     if ( iAudioPlayDeviceCommands.GetMaxVolume( volume ) != KErrNone )
       
   379         {
       
   380         return 0;
       
   381         }
       
   382     return volume;
       
   383     } 
       
   384 
       
   385 // -----------------------------------------------------------------------------
       
   386 // CTtsUtilityBody::OpenAndPlayDesL
       
   387 // Opens descriptor source and plays it immediately.
       
   388 // -----------------------------------------------------------------------------
       
   389 //
       
   390 void CTtsUtilityBody::OpenAndPlayDesL( const TDesC8& aDescriptor )
       
   391     {
       
   392     iPlayImmediately = ETrue;
       
   393     
       
   394     TRAPD( error, OpenDesL( aDescriptor ) );
       
   395     if ( error != KErrNone )
       
   396         {
       
   397         iPlayImmediately = EFalse;
       
   398         User::Leave( error );
       
   399         }
       
   400     }
       
   401 
       
   402 // -----------------------------------------------------------------------------
       
   403 // CTtsUtilityBody::OpenAndPlayFileL
       
   404 // Opens file source and plays it immediately.
       
   405 // -----------------------------------------------------------------------------
       
   406 //
       
   407 void CTtsUtilityBody::OpenAndPlayFileL( const TDesC& aFileName )
       
   408     {
       
   409     iPlayImmediately = ETrue;
       
   410     
       
   411     TRAPD( error, OpenFileL( aFileName ) );
       
   412     if ( error != KErrNone )
       
   413         {
       
   414         iPlayImmediately = EFalse;
       
   415         User::Leave( error );
       
   416         }
       
   417     }
       
   418 
       
   419 // -----------------------------------------------------------------------------
       
   420 // CTtsUtilityBody::OpenAndPlayParsedTextL
       
   421 // Opens parsed text source and plays it immediately.
       
   422 // -----------------------------------------------------------------------------
       
   423 //
       
   424 void CTtsUtilityBody::OpenAndPlayParsedTextL( CTtsParsedText& aText )
       
   425     {
       
   426     iPlayImmediately = ETrue;
       
   427     
       
   428     TRAPD( error, OpenParsedTextL( aText ) );
       
   429     if ( error != KErrNone )
       
   430         {
       
   431         iPlayImmediately = EFalse;
       
   432         User::Leave( error );
       
   433         }
       
   434     }
       
   435 
       
   436 // -----------------------------------------------------------------------------
       
   437 // CTtsUtilityBody::OpenDesL
       
   438 // Opens descriptor source 
       
   439 // -----------------------------------------------------------------------------
       
   440 //
       
   441 void CTtsUtilityBody::OpenDesL( const TDesC8& aDescriptor )
       
   442     {
       
   443     if ( !iPluginOpenedExplicitly )
       
   444         {
       
   445         CheckAndLoadCorrectPluginL( iDefaultStyle.iQuality, 
       
   446                                     iDefaultStyle.iLanguage, 
       
   447                                     iDefaultStyle.iVoice );
       
   448         }
       
   449 
       
   450     // Add data descriptor source
       
   451     TMMFDescriptorConfig sourceCfg;
       
   452     sourceCfg().iDes = (TAny*)&aDescriptor;
       
   453     sourceCfg().iDesThreadId = RThread().Id();
       
   454     User::LeaveIfError( iController.AddDataSource( KUidMmfDescriptorSource, 
       
   455                                                    sourceCfg, iSourceHandle ) );
       
   456 
       
   457     // Add data sink to file or audio output
       
   458     AddDataSinkL();
       
   459 
       
   460     // Prime controller
       
   461     User::LeaveIfError( iController.Prime() );
       
   462     }
       
   463 
       
   464 // -----------------------------------------------------------------------------
       
   465 // CTtsUtilityBody::OpenFileL
       
   466 // Opens file source
       
   467 // -----------------------------------------------------------------------------
       
   468 //
       
   469 void CTtsUtilityBody::OpenFileL( const TDesC& aFileName )
       
   470     {
       
   471     if ( !iPluginOpenedExplicitly )
       
   472         {
       
   473         CheckAndLoadCorrectPluginL( iDefaultStyle.iQuality, 
       
   474                                     iDefaultStyle.iLanguage, 
       
   475                                     iDefaultStyle.iVoice );
       
   476         }
       
   477 
       
   478     // Add data file source
       
   479     TMMFFileConfig sourceCfg;
       
   480     sourceCfg().iPath = aFileName;
       
   481     User::LeaveIfError( iController.AddDataSource( KUidMmfFileSource, sourceCfg, 
       
   482                                                    iSourceHandle ) );
       
   483     // Add data sink to file or audio output
       
   484     AddDataSinkL();
       
   485         
       
   486     // Prime controller
       
   487     User::LeaveIfError( iController.Prime() );
       
   488     }
       
   489 
       
   490 // -----------------------------------------------------------------------------
       
   491 // CTtsUtilityBody::OpenParsedTextL
       
   492 // Opens parsed text source with the help of TTS custom commands.
       
   493 // -----------------------------------------------------------------------------
       
   494 //
       
   495 void CTtsUtilityBody::OpenParsedTextL( CTtsParsedText& aText )
       
   496     {
       
   497     if ( !iPluginOpenedExplicitly )
       
   498         {
       
   499         if ( aText.NumberOfSegments() > 0 )
       
   500             {
       
   501             // Take the first segment
       
   502             const TTtsSegment& segment = aText.SegmentL( 0 );
       
   503         
       
   504             TTtsStyleID styleID = segment.StyleID();
       
   505         
       
   506             // Style should have been registered already
       
   507             TTtsStyle& style = StyleL( styleID );
       
   508         
       
   509             CheckAndLoadCorrectPluginL( style.iQuality, style.iLanguage, 
       
   510                                         style.iVoice );
       
   511             }
       
   512          else
       
   513             {
       
   514             User::Leave( KErrArgument );
       
   515             }
       
   516         }
       
   517 
       
   518     // Data source is now parsed text
       
   519     CopyParsedTextL( aText );
       
   520     User::LeaveIfError( iTtsCustomCommands.OpenParsedText( *iParsedText ) );
       
   521 
       
   522     // Add data sink to file or audio output
       
   523     AddDataSinkL();
       
   524 
       
   525     User::LeaveIfError( iController.Prime() );
       
   526     }
       
   527 
       
   528 // -----------------------------------------------------------------------------
       
   529 // CTtsUtilityBody::Pause
       
   530 // Pauses playback.
       
   531 // -----------------------------------------------------------------------------
       
   532 //
       
   533 TInt CTtsUtilityBody::Pause()
       
   534     {
       
   535     return iController.Pause();
       
   536     }   
       
   537 
       
   538 // -----------------------------------------------------------------------------
       
   539 // CTtsUtilityBody::OpenPluginL
       
   540 // Opens connection to plugin
       
   541 // -----------------------------------------------------------------------------
       
   542 //
       
   543 void CTtsUtilityBody::OpenPluginL( TUid aUid )
       
   544     {
       
   545     OpenControllerConnectionL( aUid );
       
   546     
       
   547     iPluginOpenedExplicitly = ETrue;
       
   548     }
       
   549 
       
   550 // -----------------------------------------------------------------------------
       
   551 // CTtsUtilityBody::ListPluginsL
       
   552 // Lists available plugins
       
   553 // -----------------------------------------------------------------------------
       
   554 //
       
   555 void CTtsUtilityBody::ListPluginsL( RArray<TUid>& aUids )
       
   556     {
       
   557     // Empty the list
       
   558     aUids.Reset();
       
   559     
       
   560     RMMFControllerImplInfoArray controllers;
       
   561     CleanupResetAndDestroyPushL( controllers );
       
   562     
       
   563     CMMFControllerPluginSelectionParameters* selectionParams = CMMFControllerPluginSelectionParameters::NewLC();
       
   564     
       
   565     // Select the media IDs to allow
       
   566     RArray<TUid> mediaIds;
       
   567     CleanupClosePushL( mediaIds );
       
   568     User::LeaveIfError( mediaIds.Append( KUidMediaTypeTTS ) );
       
   569 
       
   570     selectionParams->SetMediaIdsL( mediaIds, CMMFPluginSelectionParameters::EAllowOnlySuppliedMediaIds );
       
   571     CleanupStack::PopAndDestroy( &mediaIds );
       
   572     
       
   573     // Check also the allowed data headers
       
   574     // Should be "(tts)"
       
   575     CMMFFormatSelectionParameters* formatSelectParams = CMMFFormatSelectionParameters::NewLC();
       
   576     formatSelectParams->SetMatchToHeaderDataL( KTtsDataHeader );
       
   577     
       
   578     selectionParams->SetRequiredPlayFormatSupportL( *formatSelectParams );
       
   579     
       
   580     CleanupStack::PopAndDestroy( formatSelectParams );
       
   581     
       
   582     // Do the list of implementation
       
   583     selectionParams->ListImplementationsL( controllers );    
       
   584     
       
   585     // Make sure at least one controller has been found
       
   586     if( controllers.Count() == 0 )
       
   587         {
       
   588         RUBY_DEBUG1( "No controllers found using media type %x", KUidMediaTypeTTS );
       
   589         User::Leave( KErrNotFound );
       
   590         }
       
   591 
       
   592     for ( TInt c = 0; c < controllers.Count(); c++ )
       
   593         {
       
   594         RUBY_DEBUG1( "UID = %x", controllers[c]->Uid() );
       
   595         aUids.Append( controllers[c]->Uid() );
       
   596         }
       
   597 
       
   598     CleanupStack::PopAndDestroy( selectionParams );
       
   599     CleanupStack::PopAndDestroy( &controllers ); 
       
   600     }
       
   601 
       
   602 // -----------------------------------------------------------------------------
       
   603 // CTtsUtilityBody::SetDefaultStyleL
       
   604 // Sets deafault style 
       
   605 // -----------------------------------------------------------------------------
       
   606 //
       
   607 void CTtsUtilityBody::SetDefaultStyleL( const TTtsStyle& aStyle )
       
   608     {
       
   609     User::LeaveIfError( iTtsCustomCommands.SetDefaultStyle( aStyle ) );
       
   610     iDefaultStyle = aStyle;
       
   611     }
       
   612         
       
   613 // -----------------------------------------------------------------------------
       
   614 // CTtsUtilityBody::DefaultStyleL
       
   615 // Returns default style
       
   616 // -----------------------------------------------------------------------------
       
   617 //
       
   618 TTtsStyle& CTtsUtilityBody::DefaultStyleL()
       
   619     {   
       
   620     User::LeaveIfError( iTtsCustomCommands.GetDefaultStyle( iDefaultStyle ) );
       
   621     return iDefaultStyle;
       
   622     }
       
   623         
       
   624 // -----------------------------------------------------------------------------
       
   625 // CTtsUtilityBody::SetSpeakingRateL
       
   626 // Sets speaking rate
       
   627 // -----------------------------------------------------------------------------
       
   628 //
       
   629 void CTtsUtilityBody::SetSpeakingRateL( TInt aRate )
       
   630     {
       
   631     User::LeaveIfError( iTtsCustomCommands.SetSpeakingRate( aRate ) );
       
   632     }
       
   633 
       
   634 // -----------------------------------------------------------------------------
       
   635 // CTtsUtilityBody::SpeakingRateL
       
   636 // Returns speaking rate
       
   637 // -----------------------------------------------------------------------------
       
   638 //
       
   639 TInt CTtsUtilityBody::SpeakingRateL()
       
   640     {
       
   641     TInt rate( KErrGeneral );
       
   642     User::LeaveIfError( iTtsCustomCommands.GetSpeakingRate( rate ) );
       
   643     return rate;
       
   644     }
       
   645     
       
   646 // -----------------------------------------------------------------------------
       
   647 // CTtsUtilityBody::GetSupportedLanguagesL
       
   648 // Returns list of supported languages
       
   649 // -----------------------------------------------------------------------------
       
   650 //
       
   651 void CTtsUtilityBody::GetSupportedLanguagesL( RArray<TLanguage>& aLanguages )
       
   652     {
       
   653     User::LeaveIfError( iTtsCustomCommands.GetSupportedLanguages( aLanguages ) );
       
   654     }
       
   655         
       
   656 // -----------------------------------------------------------------------------
       
   657 // CTtsUtilityBody::GetSupportedVoicesL
       
   658 // Returns list of supported voices
       
   659 // -----------------------------------------------------------------------------
       
   660 //
       
   661 void CTtsUtilityBody::GetSupportedVoicesL( TLanguage aLanguage, 
       
   662                                            RArray<TTtsStyle>& aVoices )
       
   663     {
       
   664     User::LeaveIfError( iTtsCustomCommands.GetSupportedVoices( aLanguage, aVoices ) );
       
   665     }
       
   666     
       
   667 // -----------------------------------------------------------------------------
       
   668 // CTtsUtilityBody::OpenDesL
       
   669 // Opens unicode descriptor
       
   670 // -----------------------------------------------------------------------------
       
   671 //
       
   672 void CTtsUtilityBody::OpenDesL( const TDesC& aDescriptor )
       
   673     {
       
   674     HBufC8* utf8string = ConvertToUtf8LC( aDescriptor );
       
   675     OpenDesL( utf8string->Des() );
       
   676     CleanupStack::PopAndDestroy( utf8string );
       
   677     }
       
   678 
       
   679 // -----------------------------------------------------------------------------
       
   680 // CTtsUtilityBody::GetSupportedVoicesL
       
   681 // Opens and plays unicode descriptor
       
   682 // -----------------------------------------------------------------------------
       
   683 //
       
   684 void CTtsUtilityBody::OpenAndPlayDesL( const TDesC& aDescriptor )
       
   685     {
       
   686     HBufC8* utf8string = ConvertToUtf8LC( aDescriptor );
       
   687     OpenAndPlayDesL( utf8string->Des() );
       
   688     CleanupStack::PopAndDestroy( utf8string );        
       
   689     }
       
   690 
       
   691 // -----------------------------------------------------------------------------
       
   692 // CTtsUtilityBody::SetOutputFileL
       
   693 // Sets output to be written to the file handle 
       
   694 // -----------------------------------------------------------------------------
       
   695 //
       
   696 void CTtsUtilityBody::SetOutputFileL( const RFile& aFile )
       
   697     {
       
   698     iUidOfDataSink = KUidMmfFileSink; 
       
   699 
       
   700     // iFile has to contain valid file handle when data sink 
       
   701     // is marked to be file sink. 
       
   702     iFile = aFile; 
       
   703     }
       
   704     
       
   705 // -----------------------------------------------------------------------------
       
   706 // CTtsUtilityBody::Close
       
   707 // Closes current TTS synthesis source.
       
   708 // -----------------------------------------------------------------------------
       
   709 //
       
   710 void CTtsUtilityBody::Close()
       
   711     {
       
   712     iRepeats = 0;
       
   713     if ( iControllerEventMonitor != NULL )
       
   714         {
       
   715         iControllerEventMonitor->Cancel();
       
   716         }
       
   717     delete iControllerEventMonitor;
       
   718     iControllerEventMonitor = NULL;
       
   719     iController.Close();
       
   720     iPluginOpenedExplicitly = EFalse;
       
   721     iOpenPlugin = KNullUid;
       
   722     iUidOfDataSink = KUidMmfAudioOutput;
       
   723     }        
       
   724 
       
   725 // -----------------------------------------------------------------------------
       
   726 // CTtsUtilityBody::GetPosition
       
   727 // Returns position of synthesis in microseconds.
       
   728 // -----------------------------------------------------------------------------
       
   729 //
       
   730 TInt CTtsUtilityBody::GetPosition( TTimeIntervalMicroSeconds& aPosition )
       
   731     {
       
   732     return iController.GetPosition( aPosition );
       
   733     }
       
   734        
       
   735  
       
   736 // -----------------------------------------------------------------------------
       
   737 // CTtsUtilityBody::GetPosition
       
   738 // Returns position of synthesis in words.
       
   739 // -----------------------------------------------------------------------------
       
   740 //
       
   741 TInt CTtsUtilityBody::GetPosition( TInt& aWordIndex )
       
   742     {
       
   743     return iTtsCustomCommands.GetPosition( aWordIndex );
       
   744     }
       
   745 
       
   746 
       
   747 // -----------------------------------------------------------------------------
       
   748 // CTtsUtilityBody::SetPosition
       
   749 // Sets synthesis position in microseconds.
       
   750 // -----------------------------------------------------------------------------
       
   751 //
       
   752 void CTtsUtilityBody::SetPosition( const TTimeIntervalMicroSeconds& aPosition )
       
   753     {
       
   754     iController.SetPosition( aPosition );
       
   755     }
       
   756 
       
   757 
       
   758 // -----------------------------------------------------------------------------
       
   759 // CTtsUtilityBody::SetPosition
       
   760 // Sets synthesis position in words.
       
   761 // -----------------------------------------------------------------------------
       
   762 //
       
   763 void CTtsUtilityBody::SetPosition( TInt aWordIndex )
       
   764     {
       
   765     iTtsCustomCommands.SetPosition( aWordIndex );
       
   766     }
       
   767 
       
   768 
       
   769 // -----------------------------------------------------------------------------
       
   770 // CTtsUtilityBody::SetPriority
       
   771 // Sets playback priority.
       
   772 // -----------------------------------------------------------------------------
       
   773 //
       
   774 TInt CTtsUtilityBody::SetPriority( TInt aPriority, TMdaPriorityPreference aPref )
       
   775     {
       
   776     StorePriority( aPriority, aPref );
       
   777 
       
   778     if ( IsPluginOpen() )
       
   779         {
       
   780         return iController.SetPrioritySettings( iPrioritySettings );
       
   781         }
       
   782     else
       
   783         {
       
   784         return KErrNone;
       
   785         }
       
   786     }
       
   787     
       
   788 // -----------------------------------------------------------------------------
       
   789 // CTtsUtilityBody::GetVolume
       
   790 // Returns volume value.
       
   791 // -----------------------------------------------------------------------------
       
   792 //
       
   793 TInt CTtsUtilityBody::GetVolume( TInt& aVolume )
       
   794     {
       
   795     return iAudioPlayDeviceCommands.GetVolume( aVolume );
       
   796     }
       
   797         
       
   798 // -----------------------------------------------------------------------------
       
   799 // CTtsUtilityBody::SetBalance
       
   800 // Sets balance.
       
   801 // -----------------------------------------------------------------------------
       
   802 //
       
   803 TInt CTtsUtilityBody::SetBalance( TInt aBalance )
       
   804     {
       
   805     return iAudioPlayDeviceCommands.SetBalance( aBalance );
       
   806     }
       
   807 
       
   808 // -----------------------------------------------------------------------------
       
   809 // CTtsUtilityBody::GetBalance
       
   810 // Returns current balance setting.
       
   811 // -----------------------------------------------------------------------------
       
   812 //
       
   813 TInt CTtsUtilityBody::GetBalance( TInt& aBalance )
       
   814     {
       
   815     return iAudioPlayDeviceCommands.GetBalance( aBalance );
       
   816     }
       
   817 
       
   818 // -----------------------------------------------------------------------------
       
   819 // CTtsUtilityBody::CustomCommandSync
       
   820 // Sends synchronous custom command via MMF.
       
   821 // -----------------------------------------------------------------------------
       
   822 //
       
   823 TInt CTtsUtilityBody::CustomCommandSync( const TMMFMessageDestinationPckg& aDestination, 
       
   824                                          TInt aFunction, 
       
   825                                          const TDesC8& aDataTo1, 
       
   826                                          const TDesC8& aDataTo2, 
       
   827                                          TDes8& aDataFrom )
       
   828     {
       
   829     return iController.CustomCommandSync( aDestination, aFunction, aDataTo1, aDataTo2, aDataFrom );
       
   830     }
       
   831 
       
   832 // -----------------------------------------------------------------------------
       
   833 // CTtsUtilityBody::CustomCommandSync
       
   834 // Sends synchronous custom command via MMF.
       
   835 // -----------------------------------------------------------------------------
       
   836 //
       
   837 TInt CTtsUtilityBody::CustomCommandSync( const TMMFMessageDestinationPckg& aDestination, 
       
   838                                          TInt aFunction, 
       
   839                                          const TDesC8& aDataTo1, 
       
   840                                          const TDesC8& aDataTo2 )
       
   841     {
       
   842     return iController.CustomCommandSync( aDestination, aFunction, aDataTo1, aDataTo2 );
       
   843     }
       
   844 
       
   845 
       
   846 // -----------------------------------------------------------------------------
       
   847 // CTtsUtilityBody::CustomCommandAsync
       
   848 // Sends asynchronous custom command via MMF.
       
   849 // -----------------------------------------------------------------------------
       
   850 //
       
   851 void CTtsUtilityBody::CustomCommandAsync( const TMMFMessageDestinationPckg& aDestination,  
       
   852                                           TInt aFunction, 
       
   853                                           const TDesC8& aDataTo1, 
       
   854                                           const TDesC8& aDataTo2, 
       
   855                                           TDes8& aDataFrom,
       
   856                                           TRequestStatus& aStatus )
       
   857     {
       
   858     iController.CustomCommandAsync( aDestination, aFunction, aDataTo1, aDataTo2, aDataFrom, aStatus );
       
   859     }
       
   860 
       
   861 // -----------------------------------------------------------------------------
       
   862 // CTtsUtilityBody::CustomCommandAsync
       
   863 // Sends asynchronous custom command via MMF.
       
   864 // -----------------------------------------------------------------------------
       
   865 //
       
   866 void CTtsUtilityBody::CustomCommandAsync( const TMMFMessageDestinationPckg& aDestination, 
       
   867                                           TInt aFunction, 
       
   868                                           const TDesC8& aDataTo1, 
       
   869                                           const TDesC8& aDataTo2, 
       
   870                                           TRequestStatus& aStatus )
       
   871     {
       
   872     iController.CustomCommandAsync( aDestination, aFunction, aDataTo1, aDataTo2, aStatus );
       
   873     }
       
   874 
       
   875 // -----------------------------------------------------------------------------
       
   876 // CTtsUtilityBody::IsPluginOpen
       
   877 // Returns ETrue if connection is established with controller plugin
       
   878 // -----------------------------------------------------------------------------
       
   879 //
       
   880 TBool CTtsUtilityBody::IsPluginOpen()
       
   881     {
       
   882     if ( iOpenPlugin == KNullUid )
       
   883         {
       
   884         return EFalse;
       
   885         }
       
   886     else
       
   887         {
       
   888         return ETrue;
       
   889         }
       
   890     }
       
   891 
       
   892 // -----------------------------------------------------------------------------
       
   893 // CTtsUtilityBody::OpenControllerConnectionL
       
   894 // Opens controller connection if it has been closed
       
   895 // Changes plugin if the one requested is not loaded currently
       
   896 // -----------------------------------------------------------------------------
       
   897 //
       
   898 void CTtsUtilityBody::OpenControllerConnectionL( TUid aPluginUid )
       
   899     {
       
   900     RUBY_DEBUG_BLOCK( "CTtsUtilityBody::OpenControllerConnectionL(aPluginUid)" );
       
   901     
       
   902     if ( iOpenPlugin != aPluginUid )
       
   903         {
       
   904         // Clear previously loaded plugin if needed
       
   905         if ( IsPluginOpen() )
       
   906             {
       
   907             Close();
       
   908             }
       
   909 
       
   910         TInt error = iController.Open( aPluginUid, iPrioritySettings );
       
   911         if ( error ) 
       
   912             {
       
   913             RUBY_DEBUG2( "Unable to load controller plugin, error = %d, UID = %x", 
       
   914                          error, aPluginUid );            
       
   915             User::Leave( error );
       
   916             }
       
   917         else
       
   918             {
       
   919             if ( iControllerEventMonitor == NULL )
       
   920                 {
       
   921                 // Start the event monitor
       
   922                 iControllerEventMonitor = CMMFControllerEventMonitor::NewL( *this, iController );
       
   923                 iControllerEventMonitor->Start();
       
   924                 }
       
   925             }
       
   926       
       
   927         iOpenPlugin = aPluginUid;
       
   928 
       
   929         // Add already registered styles to controller plugin too         
       
   930         for ( TInt i( 0 ); i < iStyles.Count(); i++ )
       
   931             {
       
   932             TTtsStyleID controllerStyleId( 0 );
       
   933             User::LeaveIfError( iTtsCustomCommands.AddStyle( iStyles[i], controllerStyleId ) );
       
   934             iControllerStyleIDs[i] = controllerStyleId;
       
   935             } 
       
   936         
       
   937         // Set priority settings
       
   938         User::LeaveIfError( SetPriority( iPrioritySettings.iPriority, 
       
   939                                          (TMdaPriorityPreference) iPrioritySettings.iPref ) );
       
   940         }
       
   941     }
       
   942 
       
   943 // -----------------------------------------------------------------------------
       
   944 // CTtsUtilityBody::CopyParsedTextL
       
   945 // Copies parsed text structure and substitutes style ids to corresponding plugin
       
   946 // ids.
       
   947 // -----------------------------------------------------------------------------
       
   948 //
       
   949 void CTtsUtilityBody::CopyParsedTextL( CTtsParsedText& aText )
       
   950     {
       
   951     RUBY_DEBUG_BLOCK( "CTtsUtilityBody::CopyParsedTextL" );
       
   952 
       
   953     // Delete previous object if exists
       
   954     delete iParsedText;
       
   955     iParsedText = NULL;
       
   956 
       
   957     // New instance
       
   958     iParsedText = CTtsParsedText::NewL( aText.Text(), aText.PhonemeSequence(),
       
   959                                         aText.PhonemeNotation() );
       
   960 
       
   961     // Segments
       
   962 
       
   963     // Indexes for starting points for segment's text and phoneme part in
       
   964     // CTtsParsedText object's text and phoneme sequence    
       
   965     TInt textIndex( 0 );
       
   966     TInt phonemeIndex( 0 );
       
   967 
       
   968     for ( TInt i = 0; i < aText.NumberOfSegments(); i++ )
       
   969         {
       
   970         TTtsSegment segment = aText.SegmentL( i );
       
   971         
       
   972         TInt styleIndex = iInternalStyleIDs.Find( aText.SegmentL( i ).StyleID() );
       
   973         User::LeaveIfError( styleIndex );
       
   974         segment.SetStyleID( iControllerStyleIDs[styleIndex] );
       
   975         
       
   976         TInt segTextLength = aText.SegmentL( i ).TextPtr().Length();
       
   977         TInt segPhonemeSeqLength = aText.SegmentL( i )
       
   978                                       .PhonemeSequencePtr().Length();
       
   979         
       
   980         // Text
       
   981         if ( textIndex + segTextLength
       
   982              <= iParsedText->Text().Length() )
       
   983             {
       
   984             segment.SetTextPtr( iParsedText->Text()
       
   985                                 .Mid( textIndex, segTextLength ) );
       
   986             
       
   987             textIndex += segTextLength;
       
   988             }
       
   989         // Segments are somehow constructed illegally. Copy the whole text.
       
   990         else
       
   991             {
       
   992             segment.SetTextPtr( iParsedText->Text() );
       
   993             }
       
   994         
       
   995         // Phoneme sequence
       
   996         if ( phonemeIndex + segPhonemeSeqLength
       
   997              <= iParsedText->PhonemeSequence().Length() )
       
   998             {
       
   999             segment.SetPhonemeSequencePtr(
       
  1000                 iParsedText->PhonemeSequence().Mid( phonemeIndex, segPhonemeSeqLength ) );
       
  1001             
       
  1002             phonemeIndex += segPhonemeSeqLength;
       
  1003             }
       
  1004         else
       
  1005             {
       
  1006             segment.SetPhonemeSequencePtr(
       
  1007                 iParsedText->PhonemeSequence() );
       
  1008             }
       
  1009 
       
  1010         // Add segment to the new instance of CTtsParsedText
       
  1011         iParsedText->AddSegmentL( segment );
       
  1012         }
       
  1013     }
       
  1014 
       
  1015 // -----------------------------------------------------------------------------
       
  1016 // CTtsUtilityBody::StorePriority
       
  1017 // Stores priority values locally to be sent to the plugin when connection is
       
  1018 // opened.
       
  1019 // -----------------------------------------------------------------------------
       
  1020 //
       
  1021 void CTtsUtilityBody::StorePriority( TInt aPriority, TMdaPriorityPreference aPref )
       
  1022     {
       
  1023     iPrioritySettings.iPriority = aPriority;
       
  1024     iPrioritySettings.iPref = aPref;
       
  1025     iPrioritySettings.iState = EMMFStateIdle;
       
  1026     }    
       
  1027 
       
  1028 // -----------------------------------------------------------------------------
       
  1029 // CTtsUtilityBody::ConvertToUtf8LC
       
  1030 // Converts unicode descriptor to utf-8
       
  1031 // -----------------------------------------------------------------------------
       
  1032 //
       
  1033 HBufC8* CTtsUtilityBody::ConvertToUtf8LC( const TDesC& aDes )
       
  1034     {
       
  1035     HBufC8* utf8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aDes );
       
  1036     CleanupStack::PushL( utf8 );
       
  1037     return utf8;
       
  1038     }
       
  1039 
       
  1040 // -----------------------------------------------------------------------------
       
  1041 // CTtsUtilityBody::AddDataSinkL
       
  1042 // Adds data sink (file and audio supported)
       
  1043 // -----------------------------------------------------------------------------
       
  1044 //
       
  1045 void CTtsUtilityBody::AddDataSinkL()
       
  1046     {
       
  1047     RUBY_DEBUG_BLOCKL( "CTtsUtilityBody::AddDataSinkL" );
       
  1048     
       
  1049     if ( iUidOfDataSink == KUidMmfAudioOutput )
       
  1050         {
       
  1051         User::LeaveIfError( iController.AddDataSink( KUidMmfAudioOutput, 
       
  1052                                                      KNullDesC8, iSinkHandle ) ); 
       
  1053         }
       
  1054     else if ( iUidOfDataSink == KUidMmfFileSink )
       
  1055         {
       
  1056         TMMFFileHandleConfig destCfg( &iFile );
       
  1057 
       
  1058         TInt error = iController.AddDataSink( KUidMmfFileSink,destCfg, iSinkHandle ); 
       
  1059         if ( error )
       
  1060             {
       
  1061             iUidOfDataSink = KUidMmfAudioOutput; 
       
  1062             User::Leave( error ); 
       
  1063             }
       
  1064         }
       
  1065     else
       
  1066         {
       
  1067         User::Leave( KErrNotSupported );
       
  1068         }
       
  1069     }
       
  1070 
       
  1071 // -----------------------------------------------------------------------------
       
  1072 // CTtsUtilityBody::CheckAndLoadCorrectPluginL
       
  1073 // 
       
  1074 // -----------------------------------------------------------------------------
       
  1075 //
       
  1076 void CTtsUtilityBody::CheckAndLoadCorrectPluginL( TTtsQuality aQuality, 
       
  1077                                                   TLanguage aLanguage, 
       
  1078                                                   const TTtsVoice& aVoice )
       
  1079     {
       
  1080     RUBY_DEBUG_BLOCKL( "CTtsUtilityBody::CheckAndLoadCorrectPluginL" );
       
  1081     
       
  1082     TInt error( KErrNone );
       
  1083     
       
  1084     switch ( aQuality )
       
  1085         {
       
  1086         case ETtsQualityHighOnly:
       
  1087 
       
  1088             OpenControllerConnectionL( KUidHqTtsPlugin );
       
  1089             
       
  1090             break;
       
  1091             
       
  1092         case ETtsQualityLowOnly:
       
  1093         case ETtsQualityUndefined:
       
  1094         
       
  1095             OpenControllerConnectionL( KUidTtsPlugin );
       
  1096                 
       
  1097             break;
       
  1098             
       
  1099         case ETtsQualityHighPreferred:
       
  1100 
       
  1101             TRAP( error, OpenControllerConnectionL( KUidHqTtsPlugin ) );
       
  1102             if ( error || !IsSupportedSpeaker( aLanguage, aVoice ) )
       
  1103                 {
       
  1104                 // Try to use Klatt if Hqtts not found or specific language/speaker 
       
  1105                 // not available
       
  1106                 OpenControllerConnectionL( KUidTtsPlugin );
       
  1107                 }
       
  1108                 
       
  1109             break;
       
  1110             
       
  1111         case ETtsQualityLowPreferred:
       
  1112 
       
  1113             TRAP( error, OpenControllerConnectionL( KUidTtsPlugin ) );
       
  1114             if ( error || !IsSupportedSpeaker( aLanguage, aVoice ) )
       
  1115                 {
       
  1116                 // Try to use Hqtts if Klatt not found or specific language/speaker 
       
  1117                 // not available
       
  1118                 OpenControllerConnectionL( KUidHqTtsPlugin );
       
  1119                 }
       
  1120         
       
  1121             break;
       
  1122         }
       
  1123     }
       
  1124 
       
  1125 // -----------------------------------------------------------------------------
       
  1126 // CTtsUtilityBody::IsSupportedSpeaker
       
  1127 // 
       
  1128 // -----------------------------------------------------------------------------
       
  1129 //
       
  1130 TBool CTtsUtilityBody::IsSupportedSpeaker( TLanguage aLanguage, 
       
  1131                                            const TTtsVoice& aVoice )
       
  1132     {
       
  1133     TBool answer( EFalse );
       
  1134     
       
  1135     if ( aLanguage == KTtsUndefinedLanguage )
       
  1136         {
       
  1137         // Undefined language -> plugin can use default language and voice.
       
  1138         answer = ETrue;
       
  1139         }
       
  1140     else
       
  1141         {
       
  1142         RArray<TLanguage> languages;
       
  1143         iTtsCustomCommands.GetSupportedLanguages( languages );
       
  1144 
       
  1145         if ( languages.Find( aLanguage ) != KErrNotFound )
       
  1146             {
       
  1147             if ( aVoice == KNullDesC )
       
  1148                 {
       
  1149                 // Language found and undefined voice
       
  1150                 answer = ETrue;
       
  1151                 }
       
  1152             else
       
  1153                 {
       
  1154                 RArray<TTtsStyle> voices;
       
  1155                 iTtsCustomCommands.GetSupportedVoices( aLanguage, voices );
       
  1156                 
       
  1157                 TInt counter( 0 );
       
  1158 
       
  1159                 while ( answer == EFalse && counter < voices.Count() )
       
  1160                     {
       
  1161                     if ( voices[counter].iVoice == aVoice )
       
  1162                         {
       
  1163                         // Both language and voice are supported 
       
  1164                         // by currently loaded plugin.
       
  1165                         answer = ETrue;
       
  1166                         }
       
  1167                         
       
  1168                     counter++;
       
  1169                     }
       
  1170                         
       
  1171                 voices.Close();
       
  1172                 }
       
  1173             }
       
  1174             
       
  1175         languages.Close();
       
  1176         }
       
  1177         
       
  1178     return answer;
       
  1179     }
       
  1180     
       
  1181 // End of File