Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

520 lines
14 KiB

//
//
// Sapilayr TIP CTextToSpeech implementation.
//
//
#include "private.h"
#include "sapilayr.h"
#include "nui.h"
#include "tts.h"
// -------------------------------------------------------
//
// Implementation for CTextToSpeech
//
// -------------------------------------------------------
CTextToSpeech::CTextToSpeech(CSapiIMX *psi)
{
m_psi = psi;
m_fPlaybackInitialized = FALSE;
m_fIsInPlay = FALSE;
m_fIsInPause = FALSE;
}
CTextToSpeech::~CTextToSpeech( )
{
};
/* --------------------------------------------------------
// Function Name: _SetDictation
//
// Description: Temporally change the dictation status
// while TTS is playing.
//
//
// ----------------------------------------------------------*/
void CTextToSpeech::_SetDictation( BOOL fEnable )
{
BOOL fDictOn;
fDictOn = m_psi->GetDICTATIONSTAT_DictOnOff() && m_psi->GetOnOff() &&
!m_psi->Get_SPEECH_DISABLED_Disabled() && !m_psi->Get_SPEECH_DISABLED_DictationDisabled();
// Only when the dictation status now is On, we change the
// status based on required value.
if ( fDictOn )
{
// Temporally Enable/disable dictation.
CSpTask *psp;
m_psi->GetSpeechTask(&psp);
if (psp)
{
if (psp->m_cpDictGrammar)
{
(psp->m_cpDictGrammar)->SetDictationState(fEnable ? SPRS_ACTIVE: SPRS_INACTIVE);
}
psp->Release();
}
}
}
/* --------------------------------------------------------
// Function Name: TtsPlay
//
// Description: Play sound for currect selection or text
// in visible area.
//
//
// ----------------------------------------------------------*/
HRESULT CTextToSpeech::TtsPlay( )
{
HRESULT hr = E_FAIL;
if ( !m_psi )
return E_FAIL;
if ( !m_fPlaybackInitialized )
{
hr = m_psi->GetFunction(GUID_NULL, IID_ITfFnPlayBack, (IUnknown **)&m_cpPlayBack);
if ( hr == S_OK )
m_fPlaybackInitialized = TRUE;
}
if ( m_fPlaybackInitialized )
{
// Stop the possible previous speaking
TtsStop( );
hr = m_psi->_RequestEditSession(ESCB_TTS_PLAY, TF_ES_READWRITE);
}
return hr;
}
/* --------------------------------------------------------
// Function Name: _TtsPlay
//
// Description: Edit session callback function for
// TtsPlay (ESCB_TTS_PLAY)
// It will call ITfFnPlayBack->Play( ).
//
// ----------------------------------------------------------*/
HRESULT CTextToSpeech::_TtsPlay(TfEditCookie ec,ITfContext *pic)
{
HRESULT hr = S_OK;
CComPtr<ITfRange> cpSelRange = NULL;
BOOL fEmpty = TRUE;
BOOL fPlayed = FALSE;
hr = GetSelectionSimple(ec, pic, &cpSelRange);
if ( hr == S_OK )
cpSelRange->IsEmpty(ec, &fEmpty);
if ( hr == S_OK && !fEmpty && m_cpPlayBack)
{
hr = m_cpPlayBack->Play(cpSelRange);
fPlayed = TRUE;
}
else
{
CComPtr<ITfRange> cpRangeView;
// Get the Active View Range
hr = m_psi->_GetActiveViewRange(ec, pic, &cpRangeView);
if( hr == S_OK )
{
if ( cpSelRange )
{
LONG l;
hr = cpRangeView->CompareStart(ec, cpSelRange, TF_ANCHOR_START, &l);
if ( hr == S_OK && l > 0 )
{
// Current selection is not in current active view.
// Use Start Anchor in active view as start point.
cpSelRange.Release( );
hr = cpRangeView->Clone(&cpSelRange);
}
}
else
{
cpSelRange.Release( );
hr = cpRangeView->Clone(&cpSelRange);
}
if ( hr == S_OK && cpSelRange )
{
hr = cpSelRange->ShiftEndToRange(ec, cpRangeView, TF_ANCHOR_END);
if ( hr == S_OK )
{
cpSelRange->IsEmpty(ec, &fEmpty);
if ( hr == S_OK && !fEmpty)
{
hr = m_cpPlayBack->Play(cpSelRange);
fPlayed = TRUE;
}
}
}
}
}
if (!fPlayed )
{
CSpeechUIServer *pSpeechUIServer;
pSpeechUIServer = m_psi->GetSpeechUIServer( );
if ( pSpeechUIServer )
pSpeechUIServer->SetTtsPlayOnOff( FALSE );
}
return hr;
}
/* --------------------------------------------------------
// Function Name: TtsStop
//
// Description: Stop current TTS playing immediately
//
// update the TTS session status.
//
// ----------------------------------------------------------*/
HRESULT CTextToSpeech::TtsStop( )
{
HRESULT hr=S_OK;
if ( _IsInPlay( ) && m_psi )
{
CComPtr<ISpVoice> cpSpVoice;
CSpTask *psp;
hr = m_psi->GetSpeechTask(&psp);
if (hr == S_OK)
{
cpSpVoice = psp->_GetSpVoice( );
if ( cpSpVoice )
hr = cpSpVoice->Speak( NULL, SPF_PURGEBEFORESPEAK, NULL );
psp->Release();
_SetPlayMode(FALSE);
}
}
return hr;
}
/* --------------------------------------------------------
// Function Name: TtsPause
//
// Description: Pause current TTS playing immediately
//
// update the TTS session status.
//
// ----------------------------------------------------------*/
HRESULT CTextToSpeech::TtsPause( )
{
HRESULT hr=S_OK;
if ( _IsInPlay( ) && m_psi )
{
CComPtr<ISpVoice> cpSpVoice;
CSpTask *psp;
hr = m_psi->GetSpeechTask(&psp);
if (hr == S_OK)
{
cpSpVoice = psp->_GetSpVoice( );
if ( cpSpVoice )
hr = cpSpVoice->Pause( );
psp->Release();
_SetPauseMode(TRUE);
}
}
return hr;
}
/* --------------------------------------------------------
// Function Name: TtsResume
//
// Description: Resume previous paused playing
// update the TTS session status.
//
// ----------------------------------------------------------*/
HRESULT CTextToSpeech::TtsResume( )
{
HRESULT hr=S_OK;
if ( _IsInPause( ) && m_psi )
{
CComPtr<ISpVoice> cpSpVoice;
CSpTask *psp;
hr = m_psi->GetSpeechTask(&psp);
if (hr == S_OK)
{
cpSpVoice = psp->_GetSpVoice( );
if ( cpSpVoice )
hr = cpSpVoice->Resume( );
psp->Release();
_SetPauseMode(FALSE);
}
}
return hr;
}
/* --------------------------------------------------------
// Function Name: _IsPureCiceroIC
//
// Description: Check current IC attribute to
// determine it is PureCicero aware
// or AIMM aware.
//
// ----------------------------------------------------------*/
BOOL CTextToSpeech::_IsPureCiceroIC(ITfContext *pic)
{
BOOL fCiceroNative = FALSE;
HRESULT hr = S_OK;
if ( pic )
{
TF_STATUS tss;
hr = pic->GetStatus(&tss);
if (S_OK == hr)
{
//
// If TS_SS_TRANSITORY is not set, means it is Cicero Aware.
//
if (!(tss.dwStaticFlags & TS_SS_TRANSITORY) )
fCiceroNative = TRUE;
}
}
return fCiceroNative;
}
/* --------------------------------------------------------
// Function Name: _SetTTSButtonStatus
//
// Description: Based on current IC attribute to
// determine if to active or gray
// TTS buttons on toolbar.
//
// This function will be called under
// TIM_CODE_SETFOCUS and TIM_CODE_INITIC.
// ----------------------------------------------------------*/
HRESULT CTextToSpeech::_SetTTSButtonStatus(ITfContext *pic)
{
BOOL fCiceroNative;
HRESULT hr = S_OK;
CSpeechUIServer *pSpeechUIServer;
TraceMsg(TF_GENERAL, "CTextToSpeech::_SetTTSButtonStatus is called");
if ( !m_psi )
return E_FAIL;
fCiceroNative = _IsPureCiceroIC(pic);
pSpeechUIServer = m_psi->GetSpeechUIServer( );
if ( pSpeechUIServer )
{
pSpeechUIServer->SetTtsButtonStatus( fCiceroNative );
}
return hr;
}
/* --------------------------------------------------------
// Function Name: _HandleEventOnPlayButton
//
// Description: Handle mouse click event on Play button
// or Hotkey Windows+S.
//
// it would be called by button's OnButtonUp
// callback function, and by Hotkey handler.
//
// ----------------------------------------------------------*/
HRESULT CTextToSpeech::_HandleEventOnPlayButton( )
{
HRESULT hr = S_OK;
BOOL fTTSPlayOn;
CSpeechUIServer *pSpeechUIServer;
if ( !m_psi ) return E_FAIL;
pSpeechUIServer = m_psi->GetSpeechUIServer( );
if ( pSpeechUIServer == NULL) return E_FAIL;
fTTSPlayOn = pSpeechUIServer->GetTtsPlayOnOff( );
if ( fTTSPlayOn )
{
// It is under Play mode.
// Click this button to stop playing.
// If it is under Pause mode, the Speaker needs to be resumed first.
BOOL fTTSPauseOn;
fTTSPauseOn = pSpeechUIServer->GetTtsPauseOnOff( );
if ( fTTSPauseOn )
{
// Under pause mode
pSpeechUIServer->SetTtsPauseOnOff(FALSE);
hr = TtsResume( );
}
}
if ( (hr == S_OK) && fTTSPlayOn )
{
// It has already been in Play mode.
// click this to stop playing.
hr = TtsStop( );
}
else
{
// It is not in Playing mode.
hr = TtsPlay( );
}
pSpeechUIServer->SetTtsPlayOnOff( !fTTSPlayOn );
return hr;
}
/* --------------------------------------------------------
// Function Name: _HandleEventOnPauseButton
//
// Description: Handle mouse click event on Pause Button.
// it would be called by Pause button's
// OnLButtonUp callback function.
//
// ----------------------------------------------------------*/
HRESULT CTextToSpeech::_HandleEventOnPauseButton( )
{
HRESULT hr = S_OK;
BOOL fTTSPauseOn;
BOOL fTTSPlayOn;
CSpeechUIServer *pSpeechUIServer;
if ( !m_psi ) return E_FAIL;
pSpeechUIServer = m_psi->GetSpeechUIServer( );
if ( pSpeechUIServer == NULL) return E_FAIL;
fTTSPauseOn = pSpeechUIServer->GetTtsPauseOnOff( );
fTTSPlayOn = pSpeechUIServer->GetTtsPlayOnOff( );
if ( fTTSPauseOn )
{
// It has already been in Pause mode.
// click this to resume playing.
hr = TtsResume( );
}
else
{
// It is not in Pause mode.
if ( fTTSPlayOn )
{
hr = TtsPause( );
}
}
if ( fTTSPlayOn )
pSpeechUIServer->SetTtsPauseOnOff( !fTTSPauseOn );
else
{
// If it is not under Play mode, click Pause button should not change the status.
pSpeechUIServer->SetTtsPauseOnOff( FALSE );
}
return hr;
}
/* --------------------------------------------------------
// Function Name: SpeakNotifyCallback
//
// Description: This is callback for m_cpSpVoice in CSptask.
// Only SPEI_START_INPUT_STREAM &
// SPEI_END_INPUT_STREAM are insterested.
//
// When the input stream is over, we want
// to update the TTS buttons' toggle status
// ----------------------------------------------------------*/
void CSpTask::SpeakNotifyCallback( WPARAM wParam, LPARAM lParam )
{
USES_CONVERSION;
CSpEvent event;
CSpTask *_this = (CSpTask *)lParam;
CSapiIMX *psi = NULL;
CSpeechUIServer *pSpeechUIServer = NULL;
CComPtr<ISpVoice> cpVoice = NULL;
if ( _this )
cpVoice = _this->_GetSpVoice( );
if (!_this || !cpVoice)
{
return;
}
psi = _this->GetTip( );
if ( psi )
pSpeechUIServer = psi->GetSpeechUIServer( );
else
return;
while ( event.GetFrom(cpVoice) == S_OK )
{
switch (event.eEventId)
{
case SPEI_START_INPUT_STREAM :
TraceMsg(TF_GENERAL,"SPEI_START_INPUT_STREAM is notified");
psi->_SetPlayMode(TRUE);
// Update the toggle status for Play button.
if ( pSpeechUIServer )
pSpeechUIServer->SetTtsPlayOnOff( TRUE );
break;
case SPEI_END_INPUT_STREAM :
TraceMsg(TF_GENERAL,"SPEI_END_INPUT_STREAM is notified");
psi->_SetPlayMode(FALSE);
// Update the toggle status for Play button.
if ( pSpeechUIServer )
pSpeechUIServer->SetTtsPlayOnOff( FALSE );
break;
}
}
return;
}