srsf/speechsynthesis/server/src/speechsynthesisserver.cpp
changeset 13 57b735022c18
parent 1 b13cd05eeb2f
equal deleted inserted replaced
1:b13cd05eeb2f 13:57b735022c18
     1 /*
       
     2 * Copyright (c) 2006-2008 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:  Speech synthesis server
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDES
       
    20 
       
    21 #include <AudioOutput.h>
       
    22 #include <nssttscommon.h>
       
    23 
       
    24 #include "speechsynthesisserver.h"
       
    25 
       
    26 #include "speechsynthesisclientserver.h"
       
    27 #include "speechsynthesisserverutilities.h"
       
    28 #include "speechsynthesissession.h"
       
    29 
       
    30 #include "rubydebug.h"
       
    31 
       
    32 
       
    33 // CONSTANTS
       
    34 
       
    35 // Time to wait before tts plugin is closed if no activity detected. 
       
    36 const TTimeIntervalMicroSeconds32 KTtsPluginCloseWait = 30000000; // 30 sec.
       
    37 
       
    38 // ----------------------------------------------------------------------------
       
    39 // RunServerL
       
    40 // Server startup code
       
    41 // Perform all server initialisation, in particular creation of the
       
    42 // scheduler and server and then run the scheduler
       
    43 // ----------------------------------------------------------------------------
       
    44 //  
       
    45 static void RunServerL()
       
    46     {
       
    47     RUBY_DEBUG_BLOCK( "SpeechSynthesisServer: RunServerL" );
       
    48     
       
    49     // Naming the server thread after the server helps to debug panics
       
    50     User::LeaveIfError( User::RenameThread( KSpeechSynthesisServerName ) );
       
    51 
       
    52     // Create and install the active scheduler we need
       
    53     CActiveScheduler* scheduler = new (ELeave) CActiveScheduler;
       
    54     CleanupStack::PushL( scheduler );
       
    55     CActiveScheduler::Install( scheduler );
       
    56     
       
    57     // Create the server (leave it on the cleanup stack)
       
    58     CServer2* server = CSpeechSynthesisServer::NewLC();
       
    59     
       
    60     // Initialisation complete, now signal the client
       
    61     RProcess::Rendezvous( KErrNone );
       
    62 
       
    63     RUBY_DEBUG0( "SpeechSynthesisServer: server fully running." );
       
    64     
       
    65     // Ready to run
       
    66     CActiveScheduler::Start();
       
    67     
       
    68     RUBY_DEBUG0( "SpeechSynthesisServer: server closing." );
       
    69     
       
    70     // Cleanup the server and scheduler
       
    71     CleanupStack::PopAndDestroy( server );
       
    72     CleanupStack::PopAndDestroy( scheduler );
       
    73     }
       
    74 
       
    75 // ----------------------------------------------------------------------------
       
    76 // E32Main
       
    77 // Server process entry-point
       
    78 // ----------------------------------------------------------------------------
       
    79 //
       
    80 TInt E32Main()
       
    81     {
       
    82     __UHEAP_MARK;
       
    83     
       
    84     RUBY_DEBUG0( "SpeechSynthesisServer: E32Main" );
       
    85     
       
    86     CTrapCleanup* cleanup = CTrapCleanup::New();
       
    87     
       
    88     TInt error( KErrNoMemory );
       
    89     
       
    90     if ( cleanup )
       
    91         {
       
    92         TRAP( error, RunServerL() );
       
    93         delete cleanup;
       
    94         }
       
    95         
       
    96     __UHEAP_MARKEND;
       
    97     
       
    98     return error;
       
    99     }
       
   100     
       
   101     
       
   102 // ----------------------------------------------------------------------------
       
   103 // LanguageOrder
       
   104 // Used in CSpeechSynthesisServer::GetSupportedLanguagesL()
       
   105 // ----------------------------------------------------------------------------
       
   106 // 
       
   107 static TInt LanguageOrder( const TLanguage& a, const TLanguage& b )
       
   108     {
       
   109     TInt result( 0 );
       
   110     
       
   111     if ( a < b )
       
   112         {
       
   113         result = -1;
       
   114         }
       
   115     else if ( a > b )
       
   116         {
       
   117         result = 1;
       
   118         }
       
   119 
       
   120     return result;
       
   121     }
       
   122 
       
   123 
       
   124 // ----------------------------------------------------------------------------
       
   125 // CSpeechSynthesisServer::CSpeechSynthesisServer
       
   126 // Constructor
       
   127 // ----------------------------------------------------------------------------
       
   128 inline CSpeechSynthesisServer::CSpeechSynthesisServer() :
       
   129     CPolicyServer( CActive::EPriorityStandard, 
       
   130                    KSpeechSynthesisPolicy, 
       
   131                    ESharableSessions ),
       
   132     iOpenTtsPlugin( KNullUid ),
       
   133     iSessionPriority( EMdaPriorityMin ), 
       
   134     iDefaultSpeakingRate( KTtsMaxSpeakingRate / 2 ),
       
   135     iDefaultAudioPriority( EMdaPriorityNormal ),
       
   136     iDefaultAudioPreference( EMdaPriorityPreferenceTimeAndQuality )
       
   137     {
       
   138     // Nothing
       
   139     }
       
   140     
       
   141 // ----------------------------------------------------------------------------
       
   142 // CSpeechSynthesisServer::~CSpeechSynthesisServer
       
   143 // Destructor
       
   144 // ----------------------------------------------------------------------------
       
   145 //
       
   146 CSpeechSynthesisServer::~CSpeechSynthesisServer()
       
   147     {    
       
   148     delete iTtsUtility;
       
   149     delete iShutdown;
       
   150     delete iConfigurationListener;
       
   151     delete iMMCListener; 
       
   152     
       
   153     iTtsVoiceConfigs.Close();
       
   154     
       
   155     if ( iPluginCloser )
       
   156         {
       
   157         iPluginCloser->Cancel();
       
   158         delete iPluginCloser;
       
   159         }
       
   160     }
       
   161 
       
   162 // ----------------------------------------------------------------------------
       
   163 // CSpeechSynthesisServer::NewLC
       
   164 // 
       
   165 // ----------------------------------------------------------------------------
       
   166 //
       
   167 CServer2* CSpeechSynthesisServer::NewLC()
       
   168     {
       
   169     RUBY_DEBUG0( "CSpeechSynthesisServer::NewLC" );
       
   170     
       
   171     CSpeechSynthesisServer* self = new(ELeave) CSpeechSynthesisServer();
       
   172     
       
   173     CleanupStack::PushL( self );
       
   174     self->ConstructL();
       
   175     
       
   176     return self;
       
   177     }
       
   178 
       
   179 // ----------------------------------------------------------------------------
       
   180 // CSpeechSynthesisServer::ConstructL
       
   181 // 2nd phase construction - ensure the timer and server objects are running
       
   182 // ----------------------------------------------------------------------------
       
   183 //
       
   184 void CSpeechSynthesisServer::ConstructL()
       
   185     {
       
   186     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::ConstructL" );
       
   187     
       
   188     StartL( KSpeechSynthesisServerName );
       
   189     
       
   190     iTtsUtility = CTtsUtility::NewL( *this );
       
   191     iTtsUtility->SetPriority( iDefaultAudioPriority, 
       
   192                               (TMdaPriorityPreference)iDefaultAudioPreference );
       
   193     
       
   194     // Create object for closing tts plugin when server has been idle for a while. 
       
   195     iPluginCloser = CPeriodic::NewL( CActive::EPriorityIdle );
       
   196      
       
   197     // Listens for changes in SIS installations
       
   198     iConfigurationListener = CConfigurationListener::NewL( *this );
       
   199     
       
   200     // Listens insertions and removals of MMC. 
       
   201     iMMCListener = CMMCListener::NewL( *this );
       
   202     
       
   203     UpdateSynthesisConfigurationL();
       
   204     
       
   205     // Ensure that the server still exits even if the 1st client fails to connect
       
   206     iShutdown = CShutdown::NewL();
       
   207     iShutdown->Cancel();
       
   208     iShutdown->Start();
       
   209     }
       
   210 
       
   211 // ----------------------------------------------------------------------------
       
   212 // CSpeechSynthesisServer::AddSession
       
   213 // A new session is being created
       
   214 // Cancel the shutdown timer if it was running
       
   215 // ----------------------------------------------------------------------------
       
   216 //
       
   217 void CSpeechSynthesisServer::AddSession()
       
   218     {
       
   219     RUBY_DEBUG0( "CSpeechSynthesisServer::AddSession" );
       
   220     
       
   221     iSessionCount++;
       
   222     
       
   223     iShutdown->Cancel();
       
   224     }
       
   225 
       
   226 // ----------------------------------------------------------------------------
       
   227 // CSpeechSynthesisServer::DropSession
       
   228 // A session is being destroyed
       
   229 // Start the shutdown timer if it is the last session.
       
   230 // ----------------------------------------------------------------------------
       
   231 //
       
   232 void CSpeechSynthesisServer::DropSession()
       
   233     {
       
   234     RUBY_DEBUG0( "CSpeechSynthesisServer::DropSession" );
       
   235     
       
   236     iSessionCount--;
       
   237     
       
   238     if ( iSessionCount == 0 )
       
   239         {
       
   240         iShutdown->Cancel();
       
   241         iShutdown->Start();
       
   242         }
       
   243     }
       
   244     
       
   245 // ----------------------------------------------------------------------------
       
   246 // CSpeechSynthesisServer::ReserveL
       
   247 //
       
   248 // ----------------------------------------------------------------------------
       
   249 //
       
   250 void CSpeechSynthesisServer::ReserveL( MSpeechSynthesisServerObserver* aSession )
       
   251     {
       
   252     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::ReserveL" );
       
   253     
       
   254     iPluginCloser->Cancel();
       
   255     
       
   256     if ( !iSession || iSession == aSession )
       
   257         {
       
   258         // Session is not in use or it's reserved already for this session
       
   259         iSession = aSession;
       
   260         }
       
   261     else
       
   262         {
       
   263         User::Leave( KErrInUse );
       
   264         }
       
   265     }
       
   266 
       
   267 // ----------------------------------------------------------------------------
       
   268 // CSpeechSynthesisServer::ReserveL
       
   269 //
       
   270 // ----------------------------------------------------------------------------
       
   271 //
       
   272 void CSpeechSynthesisServer::ReserveL( MSpeechSynthesisServerObserver* aSession,
       
   273                                        TInt aPriority )
       
   274     {
       
   275     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::ReserveL" );
       
   276     
       
   277     iPluginCloser->Cancel();
       
   278     
       
   279     if ( !iSession || iSession == aSession )
       
   280         {
       
   281         // Session is not in use or it's reserved already for this session
       
   282         iSession = aSession;
       
   283         
       
   284         iSessionPriority = aPriority;
       
   285         }
       
   286     else if ( aPriority > iSessionPriority )
       
   287         {
       
   288         Stop();
       
   289         
       
   290         iSession->MsssOperationAborted();
       
   291         
       
   292         iPreviousSession = iSession;
       
   293         iSession = aSession; 
       
   294         iSessionPriority = aPriority; 
       
   295         }
       
   296     else 
       
   297         {
       
   298         User::Leave( KErrInUse ); 
       
   299         }
       
   300     }
       
   301     
       
   302 // ----------------------------------------------------------------------------
       
   303 // CSpeechSynthesisServer::Release
       
   304 //
       
   305 // ----------------------------------------------------------------------------
       
   306 //
       
   307 void CSpeechSynthesisServer::Release( const MSpeechSynthesisServerObserver* aSession )
       
   308     {
       
   309     RUBY_DEBUG0( "CSpeechSynthesisServer::Release" );
       
   310     
       
   311     if ( iSession == aSession )
       
   312         {
       
   313         iPreviousSession = iSession;
       
   314         iSession = NULL; 
       
   315         iSessionPriority = EMdaPriorityMin;
       
   316         
       
   317         TRAP_IGNORE( UpdateSynthesisConfigurationIfNeededL() );
       
   318         
       
   319         iPluginCloser->Cancel();
       
   320         iPluginCloser->Start( KTtsPluginCloseWait, KTtsPluginCloseWait,
       
   321                               TCallBack( ClosePlugin, this ) );
       
   322         
       
   323         RUBY_DEBUG0( "iPluginCloser started" );
       
   324         }
       
   325     }
       
   326 
       
   327 // ----------------------------------------------------------------------------
       
   328 // CSpeechSynthesisServer::GetDefaultSettingsL
       
   329 //
       
   330 // ----------------------------------------------------------------------------
       
   331 //
       
   332 void CSpeechSynthesisServer::GetDefaultSettingsL( TVoice& aVoice, 
       
   333                                   TInt& aSpeakingRate, TInt& aMaxSpeakingRate,
       
   334                                   TInt& aVolume, TInt& aMaxVolume, 
       
   335                                   TInt& aAudioPriority, TInt& aAudioPreference,
       
   336                                   TInt& aAudioOutput )
       
   337     {
       
   338     UpdateSynthesisConfigurationIfNeededL();
       
   339     
       
   340     aVoice           = iDefaultVoice;
       
   341     aSpeakingRate    = iDefaultSpeakingRate;
       
   342     aMaxSpeakingRate = KTtsMaxSpeakingRate;
       
   343     aVolume          = iDefaultVolume;
       
   344     aMaxVolume       = iDefaultMaxVolume;
       
   345     aAudioPriority   = iDefaultAudioPriority;
       
   346     aAudioPreference = iDefaultAudioPreference;
       
   347     aAudioOutput     = RSpeechSynthesis::ETtsOutputDefault;
       
   348     }
       
   349 
       
   350 // ----------------------------------------------------------------------------
       
   351 // CSpeechSynthesisServer::GetDefaultVoiceL
       
   352 //
       
   353 // ----------------------------------------------------------------------------
       
   354 //
       
   355 void CSpeechSynthesisServer::GetDefaultVoiceL( TVoice& aVoice )
       
   356     {
       
   357     UpdateSynthesisConfigurationIfNeededL();
       
   358     
       
   359     aVoice = iDefaultVoice;
       
   360     }
       
   361 
       
   362 // ----------------------------------------------------------------------------
       
   363 // CSpeechSynthesisServer::PrimeL
       
   364 //
       
   365 // ----------------------------------------------------------------------------
       
   366 //
       
   367 void CSpeechSynthesisServer::PrimeL( const TDesC& aText )
       
   368     {
       
   369     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::PrimeL" );
       
   370     RUBY_ASSERT_DEBUG( iOpenTtsPlugin != KNullUid, User::Panic( KPanic, __LINE__ ) );
       
   371     
       
   372     iTtsUtility->OpenDesL( aText );
       
   373     }
       
   374     
       
   375 // ----------------------------------------------------------------------------
       
   376 // CSpeechSynthesisServer::PrimeL
       
   377 //
       
   378 // ----------------------------------------------------------------------------
       
   379 //
       
   380 void CSpeechSynthesisServer::PrimeL( const TDesC& aText, const RFile& aFile )
       
   381     {
       
   382     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::PrimeL" );
       
   383     RUBY_ASSERT_DEBUG( iOpenTtsPlugin != KNullUid, User::Panic( KPanic, __LINE__ ) );
       
   384 
       
   385     iTtsUtility->SetOutputFileL( aFile ); 
       
   386     iTtsUtility->OpenDesL( aText ); 
       
   387     } 
       
   388     
       
   389 // ----------------------------------------------------------------------------
       
   390 // CSpeechSynthesisServer::Synthesize
       
   391 //
       
   392 // ----------------------------------------------------------------------------
       
   393 //
       
   394 void CSpeechSynthesisServer::Synthesize()
       
   395     {
       
   396     RUBY_DEBUG0( "CSpeechSynthesisServer::Synthesize" );
       
   397     RUBY_ASSERT_DEBUG( iOpenTtsPlugin != KNullUid, User::Panic( KPanic, __LINE__ ) );
       
   398     
       
   399     iTtsUtility->Play();
       
   400     }
       
   401     
       
   402 // ----------------------------------------------------------------------------
       
   403 // CSpeechSynthesisServer::Stop
       
   404 //
       
   405 // ----------------------------------------------------------------------------
       
   406 //
       
   407 void CSpeechSynthesisServer::Stop()
       
   408     {
       
   409     RUBY_DEBUG0( "CSpeechSynthesisServer::Stop" );
       
   410 
       
   411     if ( iOpenTtsPlugin != KNullUid )
       
   412         {
       
   413         iTtsUtility->Stop();
       
   414         }
       
   415     }
       
   416     
       
   417 // ----------------------------------------------------------------------------
       
   418 // CSpeechSynthesisServer::Pause
       
   419 //
       
   420 // ----------------------------------------------------------------------------
       
   421 //
       
   422 void CSpeechSynthesisServer::Pause()
       
   423     {
       
   424     RUBY_DEBUG0( "CSpeechSynthesisServer::Pause" );
       
   425     RUBY_ASSERT_DEBUG( iOpenTtsPlugin != KNullUid, User::Panic( KPanic, __LINE__ ) );
       
   426     
       
   427     iTtsUtility->Pause(); 
       
   428     }  
       
   429 
       
   430 // ----------------------------------------------------------------------------
       
   431 // CSpeechSynthesisServer::GetSupportedLanguagesL
       
   432 //
       
   433 // ----------------------------------------------------------------------------
       
   434 //
       
   435 void CSpeechSynthesisServer::GetSupportedLanguagesL( RArray<TLanguage>& aLanguages )
       
   436     {
       
   437     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::GetSupportedLanguagesL" );
       
   438     
       
   439     UpdateSynthesisConfigurationIfNeededL();
       
   440     
       
   441     TInt error( KErrNone );    
       
   442     TLinearOrder<TLanguage> order( LanguageOrder );
       
   443     
       
   444     for( TInt i( 0 ); i < iTtsVoiceConfigs.Count(); i++ )
       
   445         {
       
   446         // Add every language only once 
       
   447         error = aLanguages.InsertInOrder( iTtsVoiceConfigs[i].iLanguage, order );
       
   448         if ( error && error != KErrAlreadyExists )
       
   449             {
       
   450             User::Leave( error );
       
   451             }
       
   452         }
       
   453     }
       
   454     
       
   455 // ----------------------------------------------------------------------------
       
   456 // CSpeechSynthesisServer::GetSupportedVoicesL
       
   457 //
       
   458 // ----------------------------------------------------------------------------
       
   459 //
       
   460 void CSpeechSynthesisServer::GetSupportedVoicesL( TLanguage aLanguage, 
       
   461                                                   RArray<TVoice>& aVoices )
       
   462     {
       
   463     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::GetSupportedVoicesL" );
       
   464     
       
   465     UpdateSynthesisConfigurationIfNeededL();
       
   466     
       
   467     TVoice voice;
       
   468     
       
   469     for( TInt i( 0 ); i < iTtsVoiceConfigs.Count(); i++ )
       
   470         {
       
   471         if ( iTtsVoiceConfigs[i].iLanguage == aLanguage )
       
   472             {
       
   473             voice.iLanguage     = iTtsVoiceConfigs[i].iLanguage;
       
   474             voice.iVoiceName    = iTtsVoiceConfigs[i].iVoiceName;
       
   475             voice.iSamplingRate = iTtsVoiceConfigs[i].iSamplingRate;
       
   476             
       
   477             aVoices.AppendL( voice );
       
   478             }
       
   479         }
       
   480     }
       
   481  
       
   482 // ----------------------------------------------------------------------------
       
   483 // CSpeechSynthesisServer::SetVoiceL
       
   484 //
       
   485 // ----------------------------------------------------------------------------
       
   486 //
       
   487 void CSpeechSynthesisServer::SetVoiceL( TVoice aVoice, TInt aSpeakingRate )
       
   488     {
       
   489     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::SetVoiceL" );
       
   490     
       
   491     UpdateSynthesisConfigurationIfNeededL();
       
   492     
       
   493     TTtsStyle newStyle;
       
   494     newStyle.iLanguage = aVoice.iLanguage;
       
   495     newStyle.iVoice    = aVoice.iVoiceName;
       
   496     newStyle.iRate     = aSpeakingRate;
       
   497     newStyle.iNlp      = ETrue;  // Turn NLP flag on, only Klatt will use it. 
       
   498             
       
   499     TInt voiceIndex( KErrNotFound );
       
   500     const TInt count ( 
       
   501     iTtsVoiceConfigs.Count() );
       
   502     TInt i( 0 );
       
   503     
       
   504     while ( i < count && voiceIndex < 0 )
       
   505         {        
       
   506         if ( iTtsVoiceConfigs[i].iLanguage == aVoice.iLanguage )
       
   507             {
       
   508             if ( aVoice.iVoiceName.Length() > 0 )
       
   509                 {
       
   510                 if ( iTtsVoiceConfigs[i].iVoiceName == aVoice.iVoiceName )
       
   511                     {
       
   512                     voiceIndex = i;
       
   513                     }
       
   514                 }
       
   515             else
       
   516                 {
       
   517                 voiceIndex = i;
       
   518                 }
       
   519             }
       
   520         
       
   521         i++;
       
   522         }
       
   523 
       
   524     if ( voiceIndex >= 0 )
       
   525         {
       
   526         if ( iOpenTtsPlugin != iTtsVoiceConfigs[voiceIndex].iPluginUid )
       
   527             {
       
   528             iTtsUtility->Close();
       
   529             iOpenTtsPlugin = KNullUid;
       
   530         
       
   531             iTtsUtility->OpenPluginL( iTtsVoiceConfigs[voiceIndex].iPluginUid );
       
   532             iOpenTtsPlugin = iTtsVoiceConfigs[voiceIndex].iPluginUid;
       
   533             }
       
   534         
       
   535         iTtsUtility->SetDefaultStyleL( newStyle );
       
   536         }
       
   537     else
       
   538         {
       
   539         User::Leave( KErrNotFound );
       
   540         }
       
   541     }
       
   542 
       
   543 // ----------------------------------------------------------------------------
       
   544 // CSpeechSynthesisServer::SetVolume
       
   545 //
       
   546 // ----------------------------------------------------------------------------
       
   547 //
       
   548 void CSpeechSynthesisServer::SetVolume( TInt aVolume )
       
   549     {
       
   550     RUBY_DEBUG0( "CSpeechSynthesisServer::SetVolumeL" );
       
   551     RUBY_ASSERT_DEBUG( iOpenTtsPlugin != KNullUid, User::Panic( KPanic, __LINE__ ) );
       
   552     
       
   553     iTtsUtility->SetVolume( aVolume );
       
   554     }
       
   555 
       
   556 // ----------------------------------------------------------------------------
       
   557 // CSpeechSynthesisServer::SetAudioPriorityL
       
   558 //
       
   559 // ----------------------------------------------------------------------------
       
   560 //
       
   561 void CSpeechSynthesisServer::SetAudioPriorityL( TInt aPriority, 
       
   562                                                 TInt aPreference )
       
   563     {
       
   564     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::SetAudioPriorityL" );
       
   565     RUBY_ASSERT_DEBUG( iOpenTtsPlugin != KNullUid, User::Panic( KPanic, __LINE__ ) );
       
   566     
       
   567     iTtsUtility->SetPriority( aPriority, (TMdaPriorityPreference)aPreference );
       
   568     }
       
   569     
       
   570 // ----------------------------------------------------------------------------
       
   571 // CSpeechSynthesisServer::SetAudioOutputL
       
   572 //
       
   573 // ----------------------------------------------------------------------------
       
   574 //
       
   575 void CSpeechSynthesisServer::SetAudioOutputL( TInt aAudioOutput )
       
   576     {
       
   577     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::SetAudioOutput" );
       
   578     RUBY_ASSERT_DEBUG( iOpenTtsPlugin != KNullUid, User::Panic( KPanic, __LINE__ ) );
       
   579     
       
   580     TMMFMessageDestinationPckg destination( iOpenTtsPlugin );
       
   581     CAudioOutput::TAudioOutputPreference output;
       
   582     
       
   583     switch ( aAudioOutput )
       
   584         {        
       
   585         case RSpeechSynthesis::ETtsOutputAll: 
       
   586             
       
   587             output = CAudioOutput::EAll;
       
   588             
       
   589             break;
       
   590 
       
   591         case RSpeechSynthesis::ETtsOutputNoOutput: 
       
   592             
       
   593             output = CAudioOutput::ENoOutput;
       
   594             
       
   595             break;
       
   596 
       
   597         case RSpeechSynthesis::ETtsOutputPrivate: 
       
   598             
       
   599             output = CAudioOutput::EPrivate;
       
   600             
       
   601             break;
       
   602 
       
   603         case RSpeechSynthesis::ETtsOutputPublic: 
       
   604             
       
   605             output = CAudioOutput::EPublic;
       
   606             
       
   607             break;
       
   608             
       
   609         default:
       
   610             
       
   611             output = CAudioOutput::ENoPreference;
       
   612         }
       
   613             
       
   614     TBuf8<2> data;
       
   615     data.AppendNum( output );    
       
   616 
       
   617     User::LeaveIfError( iTtsUtility->CustomCommandSync( destination, 
       
   618                                                         ETtsCustomCommandSetAudioOutput, 
       
   619                                                         data, KNullDesC8 ) );
       
   620     }
       
   621     
       
   622 // ----------------------------------------------------------------------------
       
   623 // CSpeechSynthesisServer::CustomCommand
       
   624 //
       
   625 // ----------------------------------------------------------------------------
       
   626 //
       
   627 TInt CSpeechSynthesisServer::CustomCommand( TInt aCommand, TInt aValue )
       
   628     {
       
   629     RUBY_DEBUG0( "" );
       
   630     
       
   631     TInt result( KErrNotReady );
       
   632     
       
   633     if ( iOpenTtsPlugin != KNullUid )
       
   634         {
       
   635         TMMFMessageDestinationPckg destination( iOpenTtsPlugin );
       
   636         
       
   637         TBuf8<16> command;
       
   638         command.AppendNum( aCommand );
       
   639         
       
   640         TBuf8<16> value;
       
   641         value.AppendNum( aValue );
       
   642     
       
   643         result = iTtsUtility->CustomCommandSync( destination, ETtsCustomCommandSetPluginParameter, 
       
   644                                                  command, value );
       
   645         }
       
   646     
       
   647     return result;
       
   648     }
       
   649     
       
   650 // ----------------------------------------------------------------------------
       
   651 // CSpeechSynthesisServer::IsVoiceValidL
       
   652 //
       
   653 // ----------------------------------------------------------------------------
       
   654 //
       
   655 TBool CSpeechSynthesisServer::IsVoiceValidL( const TVoice& aVoice )
       
   656     {
       
   657     RUBY_DEBUG0( "CSpeechSynthesisServer::IsVoiceValid" );
       
   658     
       
   659     UpdateSynthesisConfigurationIfNeededL();
       
   660     
       
   661     TBool found( EFalse );
       
   662     TInt index( 0 );
       
   663     TInt count( iTtsVoiceConfigs.Count() );
       
   664     
       
   665     while ( !found  && index < count )
       
   666         {        
       
   667         if ( iTtsVoiceConfigs[index].iLanguage == aVoice.iLanguage )
       
   668             {
       
   669             found = ETrue;
       
   670             
       
   671             if ( aVoice.iVoiceName.Length() > 0 &&
       
   672                  aVoice.iVoiceName != iTtsVoiceConfigs[index].iVoiceName )
       
   673                 {
       
   674                 // Voice name does not match
       
   675                 found = EFalse;
       
   676                 }
       
   677                 
       
   678             if ( aVoice.iSamplingRate != KErrNotFound && 
       
   679                  aVoice.iSamplingRate != iTtsVoiceConfigs[index].iSamplingRate )
       
   680                 {
       
   681                 // Sampling rate does not match
       
   682                 found = EFalse;
       
   683                 }
       
   684             }
       
   685         
       
   686         index++;
       
   687         }
       
   688 
       
   689     return found;
       
   690     }
       
   691     
       
   692 // ----------------------------------------------------------------------------
       
   693 // CSpeechSynthesisServer::McoConfigurationChanged
       
   694 // Some SIS package has been installed or removed
       
   695 // ----------------------------------------------------------------------------
       
   696 //
       
   697 void CSpeechSynthesisServer::McoConfigurationChanged()
       
   698     {
       
   699     RUBY_DEBUG0( "CSpeechSynthesisServer::McoConfigurationChanged" );
       
   700     
       
   701     iUpdateNeeded = ETrue;
       
   702     }
       
   703     
       
   704 // ----------------------------------------------------------------------------
       
   705 // CSpeechSynthesisServer::MapcCustomCommandEvent
       
   706 //
       
   707 // ----------------------------------------------------------------------------
       
   708 //
       
   709 void CSpeechSynthesisServer::MapcCustomCommandEvent( TInt /*aEvent*/, 
       
   710                                                      TInt /*aError*/ )
       
   711     {
       
   712     RUBY_ERROR0( "CSpeechSynthesisServer::MapcCustomCommandEvent" );
       
   713     
       
   714     // Not used
       
   715     }
       
   716     
       
   717 // ----------------------------------------------------------------------------
       
   718 // CSpeechSynthesisServer::MapcInitComplete
       
   719 //
       
   720 // ----------------------------------------------------------------------------
       
   721 //
       
   722 void CSpeechSynthesisServer::MapcInitComplete( TInt aError, 
       
   723         const TTimeIntervalMicroSeconds& aDuration )
       
   724     {
       
   725     RUBY_DEBUG1( "CSpeechSynthesisServer::MapcInitComplete [%x]", iSession );
       
   726     
       
   727     if ( iSession )
       
   728         {
       
   729         iSession->MsssInitComplete( aError, aDuration );
       
   730         }
       
   731     else
       
   732         {
       
   733         RUBY_ERROR1( "CSpeechSynthesisServer::MapcInitComplete - No session [%d]",
       
   734                      aError );
       
   735         }
       
   736     }
       
   737 
       
   738 // ----------------------------------------------------------------------------
       
   739 // CSpeechSynthesisServer::MapcPlayComplete
       
   740 //
       
   741 // ----------------------------------------------------------------------------
       
   742 //      
       
   743 void CSpeechSynthesisServer::MapcPlayComplete( TInt aError )
       
   744     {
       
   745     RUBY_DEBUG1( "CSpeechSynthesisServer::MapcPlayComplete [%x]", iSession );
       
   746     
       
   747     if ( iSession )
       
   748         {
       
   749         iSession->MsssPlayComplete( aError );
       
   750         }
       
   751     else
       
   752         {
       
   753         RUBY_ERROR1( "CSpeechSynthesisServer::MapcPlayComplete - No session [%d]",
       
   754                      aError );
       
   755         }
       
   756     }
       
   757 
       
   758 // ----------------------------------------------------------------------------
       
   759 // CSpeechSynthesisServer::ClosePlugin
       
   760 // 
       
   761 // ----------------------------------------------------------------------------
       
   762 //
       
   763 TInt CSpeechSynthesisServer::ClosePlugin( TAny* aAny )
       
   764     {
       
   765     CSpeechSynthesisServer* self = reinterpret_cast<CSpeechSynthesisServer*>( aAny );
       
   766 
       
   767     RUBY_DEBUG1( "Closing plugin %x", self->iOpenTtsPlugin );
       
   768     
       
   769     self->iPluginCloser->Cancel();
       
   770     
       
   771     self->iTtsUtility->Close();
       
   772     self->iOpenTtsPlugin = KNullUid;
       
   773     
       
   774     return KErrNone;
       
   775     }
       
   776 
       
   777 // ----------------------------------------------------------------------------
       
   778 // CSpeechSynthesisServer::PreviousSession
       
   779 // 
       
   780 // ----------------------------------------------------------------------------
       
   781 //
       
   782 const MSpeechSynthesisServerObserver* CSpeechSynthesisServer::PreviousSession()
       
   783     {
       
   784     RUBY_DEBUG1( "iPreviousSession = %x", iPreviousSession );
       
   785     
       
   786     return iPreviousSession;
       
   787     }
       
   788 
       
   789 // ----------------------------------------------------------------------------
       
   790 // CSpeechSynthesisServer::ClosePlugin
       
   791 // 
       
   792 // ----------------------------------------------------------------------------
       
   793 //
       
   794 void CSpeechSynthesisServer::ClosePlugin()
       
   795     {
       
   796     RUBY_DEBUG0( "" );
       
   797     
       
   798     iPluginCloser->Cancel();
       
   799     
       
   800     iTtsUtility->Close();
       
   801     iOpenTtsPlugin = KNullUid;
       
   802     }
       
   803         
       
   804 // ----------------------------------------------------------------------------
       
   805 // CSpeechSynthesisServer::NewSessionL
       
   806 // Create a new client session.
       
   807 // ----------------------------------------------------------------------------
       
   808 //
       
   809 CSession2* CSpeechSynthesisServer::NewSessionL( const TVersion& /*aVersion*/, 
       
   810                                                 const RMessage2& /*aMessage*/ ) const
       
   811     {
       
   812     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::NewSessionL" );
       
   813     
       
   814     return new( ELeave ) CSpeechSynthesisSession();
       
   815     }
       
   816 
       
   817 // ----------------------------------------------------------------------------
       
   818 // CSpeechSynthesisServer::CustomSecurityCheckL
       
   819 // Custom access policy check
       
   820 // ----------------------------------------------------------------------------
       
   821 //
       
   822 CPolicyServer::TCustomResult CSpeechSynthesisServer::CustomSecurityCheckL( 
       
   823     const RMessage2& aMsg, TInt& /*aAction*/, TSecurityInfo& aMissing )
       
   824     {
       
   825     RUBY_DEBUG_BLOCK( "" );
       
   826     
       
   827     CPolicyServer::TCustomResult result( CPolicyServer::EFail ); 
       
   828     
       
   829     if ( aMsg.Function() == ESetAudioOutput )
       
   830         {
       
   831         if ( aMsg.Int0() == RSpeechSynthesis::ETtsOutputAll && 
       
   832              !aMsg.HasCapability( ECapabilityWriteDeviceData, 
       
   833                                   __PLATSEC_DIAGNOSTIC_STRING("Missing WriteDeviceData") ) )
       
   834             {
       
   835             result = CPolicyServer::EFail;
       
   836             
       
   837             aMissing.iCaps = ECapabilityWriteDeviceData;
       
   838             }
       
   839         else
       
   840             {
       
   841             result = CPolicyServer::EPass;
       
   842             }
       
   843         }
       
   844     
       
   845     return result;
       
   846     }
       
   847 
       
   848 // ----------------------------------------------------------------------------
       
   849 // CSpeechSynthesisServer::UpdateSynthesisConfigurationIfNeededL
       
   850 // 
       
   851 // ----------------------------------------------------------------------------
       
   852 //
       
   853 void CSpeechSynthesisServer::UpdateSynthesisConfigurationIfNeededL()
       
   854     {
       
   855     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::UpdateSynthesisConfigurationIfNeededL" );
       
   856     
       
   857     if ( iUpdateNeeded )
       
   858         {
       
   859         RUBY_DEBUG0( "Update needed!" );
       
   860         
       
   861         if ( iSession )
       
   862             {
       
   863             RUBY_DEBUG0( "Cannot update - iSession not NULL" );
       
   864             }
       
   865         else            
       
   866             {
       
   867             UpdateSynthesisConfigurationL();
       
   868             
       
   869             iUpdateNeeded = EFalse;
       
   870             }
       
   871         }
       
   872     }
       
   873     
       
   874 // ----------------------------------------------------------------------------
       
   875 // CSpeechSynthesisServer::UpdateSynthesisConfigurationL
       
   876 // 
       
   877 // ----------------------------------------------------------------------------
       
   878 //
       
   879 void CSpeechSynthesisServer::UpdateSynthesisConfigurationL()
       
   880     {
       
   881     RUBY_DEBUG_BLOCK( "CSpeechSynthesisServer::UpdateSynthesisConfigurationL" );
       
   882     
       
   883     iPluginCloser->Cancel();
       
   884     
       
   885     RArray<TLanguage> languages;
       
   886     CleanupClosePushL( languages );
       
   887     
       
   888     RArray<TTtsStyle> ttsVoices;
       
   889     CleanupClosePushL( ttsVoices );
       
   890     
       
   891     TVoiceConfiguration cnfg;
       
   892     
       
   893     TBool defaultsVoiceSet( EFalse );
       
   894     
       
   895     // UI language is selected as a default language if it is supported 
       
   896     TLanguage defaultLanguage( User::Language() ); 
       
   897 
       
   898     RArray<TUid> ttsPlugins;
       
   899     CleanupClosePushL( ttsPlugins ); 
       
   900     
       
   901     // Plugins are listed in priority order (highest first)
       
   902     iTtsUtility->ListPluginsL( ttsPlugins );    
       
   903     iTtsVoiceConfigs.Reset();
       
   904     
       
   905     // Loop all plugins
       
   906     for ( TInt i( 0 ); i < ttsPlugins.Count(); i++  )
       
   907         {
       
   908         cnfg.iPluginUid = ttsPlugins[i];
       
   909         
       
   910         iTtsUtility->Close();
       
   911         iOpenTtsPlugin = KNullUid;
       
   912         
       
   913         iTtsUtility->OpenPluginL( ttsPlugins[i] );
       
   914         iOpenTtsPlugin = ttsPlugins[i];
       
   915         
       
   916         iTtsUtility->GetSupportedLanguagesL( languages );
       
   917 
       
   918         if ( i == 0 )
       
   919             {
       
   920             // Maximum volume is same for all plugins. 
       
   921             iDefaultMaxVolume = iTtsUtility->MaxVolume();
       
   922             iDefaultVolume = iDefaultMaxVolume / 2;
       
   923             }
       
   924 
       
   925         // Loop supported languages
       
   926         for ( TInt j( 0 ); j < languages.Count(); j++ )
       
   927             {
       
   928             cnfg.iLanguage = languages[j];
       
   929 
       
   930             iTtsUtility->GetSupportedVoicesL( languages[j], ttsVoices ); 
       
   931             
       
   932             // Loop supported voices
       
   933             for ( TInt k( 0 ); k < ttsVoices.Count(); k++ )
       
   934                 {
       
   935                 cnfg.iVoiceName    = ttsVoices[k].iVoice;
       
   936                 cnfg.iSamplingRate = ttsVoices[k].iSamplingRate;
       
   937                 
       
   938                 iTtsVoiceConfigs.AppendL( cnfg );
       
   939 
       
   940                 if ( !defaultsVoiceSet && cnfg.iLanguage == defaultLanguage )
       
   941                     {
       
   942                     // Default voice is not set yet -> set it now
       
   943                     defaultsVoiceSet = ETrue;
       
   944                     
       
   945                     iDefaultVoice.iLanguage     = cnfg.iLanguage;
       
   946                     iDefaultVoice.iVoiceName    = cnfg.iVoiceName;
       
   947                     iDefaultVoice.iSamplingRate = cnfg.iSamplingRate;
       
   948                     }
       
   949                 }
       
   950             
       
   951             ttsVoices.Reset();
       
   952             }
       
   953         
       
   954         languages.Reset();
       
   955         }
       
   956     
       
   957     CleanupStack::PopAndDestroy( &ttsPlugins );
       
   958     CleanupStack::PopAndDestroy( &ttsVoices );
       
   959     CleanupStack::PopAndDestroy( &languages );
       
   960     
       
   961     if ( !defaultsVoiceSet && iTtsVoiceConfigs.Count() > 0 )
       
   962         {
       
   963         iDefaultVoice.iLanguage     = iTtsVoiceConfigs[0].iLanguage;
       
   964         iDefaultVoice.iVoiceName    = iTtsVoiceConfigs[0].iVoiceName;
       
   965         iDefaultVoice.iSamplingRate = iTtsVoiceConfigs[0].iSamplingRate;
       
   966         } 
       
   967     
       
   968     if ( !iSession )
       
   969         {
       
   970         iPluginCloser->Start( KTtsPluginCloseWait, KTtsPluginCloseWait,
       
   971                               TCallBack( ClosePlugin, this ) );
       
   972         
       
   973         RUBY_DEBUG0( "iPluginCloser started" );
       
   974         }
       
   975     }
       
   976 
       
   977 // End of file