srsf/speechsynthesis/client/src/speechsynthesis.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:29:17 +0100
branchRCL_3
changeset 19 e36f3802f733
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Speech synthesis server, client side code
*
*/


// @todo Add better file write support to Klatt and HQ plugins
// @todo Add support for lipsync information

#include <e32svr.h>
#include <f32file.h> 
#include <s32mem.h>
#include <speechsynthesis.h>

#include "speechsynthesisclientserver.h"

// CONSTANTS

const TInt KMajorVersion = 1;
const TInt KMinorVersion = 0;
const TInt KBuildNumber  = 1;

// ----------------------------------------------------------------------------
// StartServer
// Server startup code
// ----------------------------------------------------------------------------
// 
static TInt StartServer()
    {
    RProcess server;

    TInt error = server.Create( KSpeechSynthesisServerImg, KNullDesC );

    if ( !error )
        {
        // Server started
        TRequestStatus status;
        server.Rendezvous( status );
        
        if ( status != KRequestPending )
            {
            server.Kill( KErrGeneral ); // Abort startup
            }
        else
            {
            server.Resume();            // Logon OK - start the server
            }
            
        User::WaitForRequest( status ); // Wait for start or death
        
        error = ( server.ExitType() == EExitPanic ) ? KErrGeneral : status.Int();
        
        // Close handle
        server.Close();
        }
        
    return error;
    }
    
    
// ----------------------------------------------------------------------------
// RSpeechSynthesis::RSpeechSynthesis
// Constructor
// ----------------------------------------------------------------------------
//
EXPORT_C RSpeechSynthesis::RSpeechSynthesis()
    {
    // Nothing
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::Open
// Creates a session to server
// ----------------------------------------------------------------------------
//
EXPORT_C TInt RSpeechSynthesis::Open()
    {
    const TInt KMessageSlots( 4 );  // 1 async, 1 sync, 1 cancel, 1 kernel
    
    const TVersion requiredServerVersion( KMajorVersion, 
                                          KMinorVersion, 
                                          KBuildNumber );

    // Try to create session with following parameters:
    // 1) Name of the server
    // 2) The lowest version of the server with which this client is compatible
    // 3) The number of message slots 
    TInt error = CreateSession( KSpeechSynthesisServerName, 
                                requiredServerVersion, KMessageSlots );
    
    if ( error == KErrNotFound || error == KErrServerTerminated )
        {
        // Server not running -> try to start it
        error = StartServer();
        
        if ( error == KErrNone || error == KErrAlreadyExists )
            {
            // Server startup succeeded -> try to create session to it
            error = CreateSession( KSpeechSynthesisServerName, 
                                   requiredServerVersion, KMessageSlots );

            }
        }

    return error;
    }
    
// ----------------------------------------------------------------------------
// RSpeechSynthesis::Close
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::Close()
    {
    RSessionBase::Close();  
    }
   
// ----------------------------------------------------------------------------
// RSpeechSynthesis::InitialiseSynthesis
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::InitialiseSynthesis( const TDesC& aText, 
                                                     TRequestStatus& aStatus )
    {
    if ( Handle() )
        {
        SendReceive( EPrime, TIpcArgs( &aText ), aStatus ); 
        }
    else
        {
        TRequestStatus *statusPointer = &aStatus;
        User::RequestComplete( statusPointer, KErrBadHandle );
        }
    }
    
// ----------------------------------------------------------------------------
// RSpeechSynthesis::InitialiseSynthesis
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::InitialiseSynthesis( const TDesC& aText, 
                                                     const TFileName& aFileName,
                                                     TRequestStatus& aStatus )
    {
    TRAPD( error, DoInitialiseSynthesisL( aText, aFileName, aStatus ) );
    if ( error )
        {
        TRequestStatus *statusPointer = &aStatus;
        User::RequestComplete( statusPointer, error );
        }
    }
    
// ----------------------------------------------------------------------------
// RSpeechSynthesis::InitialiseSynthesis
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::InitialiseSynthesis( const TDesC& aText,
                                                     TDes8& aDataBuffer, 
                                                     TRequestStatus& aStatus )
    {
    if ( Handle() )
        {
        SendReceive( EPrimeStreamOutput, TIpcArgs( &aText, &aDataBuffer ), aStatus ); 
        }
    else
        {
        TRequestStatus *statusPointer = &aStatus;
        User::RequestComplete( statusPointer, KErrBadHandle );
        }
    }
    
// ----------------------------------------------------------------------------
// RSpeechSynthesis::Synthesise
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::Synthesise( TRequestStatus& aStatus )
    {
    if ( Handle() )
        {
        SendReceive( ESynthesise, aStatus );
        }
    else
        {
        TRequestStatus *statusPointer = &aStatus;
        User::RequestComplete( statusPointer, KErrBadHandle );
        }
    }
    
// ----------------------------------------------------------------------------
// RSpeechSynthesis::StopL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::StopL()
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    User::LeaveIfError( SendReceive( EStopSynthesis ) ); 
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::PauseL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::PauseL()
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    User::LeaveIfError( SendReceive( EPauseSynthesis ) );
    }     

// ----------------------------------------------------------------------------
// RSpeechSynthesis::DurationL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C TTimeIntervalMicroSeconds RSpeechSynthesis::DurationL()
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    TPckgBuf<TTimeIntervalMicroSeconds> pckg;
    
    User::LeaveIfError( SendReceive( EGetDuration, TIpcArgs( &pckg ) ) ); 
    
    return pckg();
    }
    
// ----------------------------------------------------------------------------
// RSpeechSynthesis::GetLanguagesL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::GetLanguagesL( RArray<TLanguage>& aLanguages )
    {
	CleanupClosePushL( aLanguages ); 
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    TPckgBuf<TInt> pckg;
    
    User::LeaveIfError( SendReceive( EGetLanguageCount, TIpcArgs( &pckg ) ) );
    
    const TInt languageCount( pckg() );

    if ( languageCount > 0 )    
        {
        const TInt tlanguageSize( sizeof(TLanguage) );
    
        HBufC8* data = HBufC8::NewLC( languageCount * tlanguageSize );
        TPtr8 data_ptr( data->Des() );
    
        User::LeaveIfError( SendReceive( EGetLanguages, TIpcArgs( &data_ptr ) ) );
        
        for ( TInt i( 0 ); i < languageCount; i++ )
            {
            TPtr8 tmp = data_ptr.MidTPtr( i * tlanguageSize, tlanguageSize );
            
            const TLanguage* lang = (TLanguage*)tmp.Ptr();
            
            aLanguages.AppendL( *lang );
            }

        CleanupStack::PopAndDestroy( data );
        }
    CleanupStack::Pop(); 
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::GetVoicesL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::GetVoicesL( RArray<TVoice>& aVoices,
                                            TLanguage aLanguage )
    {
	CleanupClosePushL( aVoices ); 
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    TPckgBuf<TInt> pckg;
    
    User::LeaveIfError( SendReceive( EGetVoiceCount, 
                                     TIpcArgs( &pckg, aLanguage ) ) );
    
    const TInt voiceCount( pckg() );
    
    if ( voiceCount > 0 ) 
        {
        const TInt tvoiceSize( sizeof(TVoice) );
        
        HBufC8* data = HBufC8::NewLC( voiceCount * tvoiceSize );
        TPtr8 data_ptr( data->Des() );
    
        User::LeaveIfError( SendReceive( EGetVoices, TIpcArgs( &data_ptr ) ) );
        
        for ( TInt i( 0 ); i < voiceCount; i++ )
            {
            TPtr8 tmp = data_ptr.MidTPtr( i * tvoiceSize, tvoiceSize );
            
            const TVoice* voice = (TVoice*)tmp.Ptr();
            
            aVoices.AppendL( *voice );
            }
        
        CleanupStack::PopAndDestroy( data );   
        }
    CleanupStack::Pop(); 
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::VoiceL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C TVoice RSpeechSynthesis::VoiceL()
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    TPckgBuf<TVoice> pckg;
    
    User::LeaveIfError( SendReceive( EVoice, TIpcArgs( &pckg ) ) );
    
    return pckg();
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::SetVoiceL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::SetVoiceL( const TVoice& aVoice )
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    TPckgBuf<TVoice> pckg = aVoice;
    
    User::LeaveIfError( SendReceive( ESetVoice, TIpcArgs( &pckg ) ) );
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::MaxSpeakingRateL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C TInt RSpeechSynthesis::MaxSpeakingRateL()
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    TPckgBuf<TInt> pckg;
    
    User::LeaveIfError( SendReceive( EMaxSpeakingRate, TIpcArgs( &pckg ) ) );
    
    return pckg();
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::SpeakingRateL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C TInt RSpeechSynthesis::SpeakingRateL()
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    TPckgBuf<TInt> pckg;
    
    User::LeaveIfError( SendReceive( ESpeakingRate, TIpcArgs( &pckg ) ) );
    
    return pckg();
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::SetSpeakingRateL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::SetSpeakingRateL( TInt aSpeakingRate )
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    User::LeaveIfError( SendReceive( ESetSpeakingRate, 
                                     TIpcArgs( aSpeakingRate ) ) );
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::MaxVolumeL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C TInt RSpeechSynthesis::MaxVolumeL()
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    TPckgBuf<TInt> pckg;
    
    User::LeaveIfError( SendReceive( EMaxVolume, TIpcArgs( &pckg ) ) );
    
    return pckg();
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::VolumeL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C TInt RSpeechSynthesis::VolumeL()
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    TPckgBuf<TInt> pckg;
    
    User::LeaveIfError( SendReceive( EVolume, TIpcArgs( &pckg ) ) );
    
    return pckg();
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::SetVolumeL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::SetVolumeL( TInt aVolume )
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    User::LeaveIfError( SendReceive( ESetVolume, TIpcArgs( aVolume ) ) );
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::SetAudioPriorityL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::SetAudioPriorityL( TInt aPriority, 
                                                   TInt aPreference )
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    User::LeaveIfError( SendReceive( ESetAudioPriority, 
                                     TIpcArgs( aPriority, aPreference ) ) );
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::SetAudioOutputL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::SetAudioOutputL( TTtsAudioOutput aAudioOutput )
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    User::LeaveIfError( SendReceive( ESetAudioOutput, TIpcArgs( aAudioOutput ) ) );
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::CustomCommandL
// 
// ----------------------------------------------------------------------------
//
EXPORT_C void RSpeechSynthesis::CustomCommandL( TInt aCommand, TInt aValue )
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
    
    User::LeaveIfError( SendReceive( ECustomCommand, 
                                     TIpcArgs( aCommand, aValue ) ) );
    }

// ----------------------------------------------------------------------------
// RSpeechSynthesis::DoInitialiseSynthesisL
// 
// ----------------------------------------------------------------------------
//
void RSpeechSynthesis::DoInitialiseSynthesisL( const TDesC& aText, 
                                               const TFileName& aFileName, 
                                               TRequestStatus& aStatus ) 
    {
    if ( Handle() == 0 )
        {
        User::Leave( KErrBadHandle );
        }
        
    // @todo Add support for all supported audio formats 
    TFileName tmpName( aFileName );
    tmpName.LowerCase();
            
    TParse parser;
    User::LeaveIfError( parser.Set( tmpName, NULL, NULL ) );
    
    TPtrC extension = parser.Ext(); 
    
    if ( extension != _L(".raw") ) 
        {
        User::Leave( KErrArgument );
        }

    RFs fs;
    RFile file;

    User::LeaveIfError( fs.Connect() ); 
    CleanupClosePushL( fs );    
    User::LeaveIfError( fs.ShareProtected() ); 
    
    User::LeaveIfError( file.Replace( fs, aFileName, EFileWrite ) ); 
    CleanupClosePushL( file );
    
    TIpcArgs ipcArgs;
    User::LeaveIfError( file.TransferToServer( ipcArgs, KFsHandleIndex, KFileHandleIndex ) ); 
    User::LeaveIfError( SendReceive( ETransferFileHandle, ipcArgs ) );
    
    CleanupStack::PopAndDestroy( &file ); 
    CleanupStack::PopAndDestroy( &fs ); 
    
    SendReceive( EPrimeFileOutput, TIpcArgs( &aText ), aStatus ); 
    }
    
// End of file