| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <math.h> | 5 #include <math.h> |
| 6 #include <sapi.h> | 6 #include <sapi.h> |
| 7 | 7 |
| 8 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
| 9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 static void __stdcall SpeechEventCallback(WPARAM w_param, LPARAM l_param); | 37 static void __stdcall SpeechEventCallback(WPARAM w_param, LPARAM l_param); |
| 38 | 38 |
| 39 private: | 39 private: |
| 40 ExtensionTtsPlatformImplWin(); | 40 ExtensionTtsPlatformImplWin(); |
| 41 virtual ~ExtensionTtsPlatformImplWin() {} | 41 virtual ~ExtensionTtsPlatformImplWin() {} |
| 42 | 42 |
| 43 void OnSpeechEvent(); | 43 void OnSpeechEvent(); |
| 44 | 44 |
| 45 base::win::ScopedComPtr<ISpVoice> speech_synthesizer_; | 45 base::win::ScopedComPtr<ISpVoice> speech_synthesizer_; |
| 46 bool paused_; | |
| 47 | 46 |
| 48 // These apply to the current utterance only. | 47 // These apply to the current utterance only. |
| 49 std::wstring utterance_; | 48 std::wstring utterance_; |
| 50 int utterance_id_; | 49 int utterance_id_; |
| 51 int prefix_len_; | 50 int prefix_len_; |
| 52 ULONG stream_number_; | 51 ULONG stream_number_; |
| 53 int char_position_; | 52 int char_position_; |
| 54 | 53 |
| 55 friend struct DefaultSingletonTraits<ExtensionTtsPlatformImplWin>; | 54 friend struct DefaultSingletonTraits<ExtensionTtsPlatformImplWin>; |
| 56 | 55 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 base::IntToString16(static_cast<int>(params.pitch * 10 - 10)); | 91 base::IntToString16(static_cast<int>(params.pitch * 10 - 10)); |
| 93 prefix = L"<pitch absmiddle=\"" + pitch_value + L"\">"; | 92 prefix = L"<pitch absmiddle=\"" + pitch_value + L"\">"; |
| 94 suffix = L"</pitch>"; | 93 suffix = L"</pitch>"; |
| 95 } | 94 } |
| 96 | 95 |
| 97 if (params.volume >= 0.0) { | 96 if (params.volume >= 0.0) { |
| 98 // The TTS api allows a range of 0 to 100 for speech volume. | 97 // The TTS api allows a range of 0 to 100 for speech volume. |
| 99 speech_synthesizer_->SetVolume(static_cast<uint16>(params.volume * 100)); | 98 speech_synthesizer_->SetVolume(static_cast<uint16>(params.volume * 100)); |
| 100 } | 99 } |
| 101 | 100 |
| 102 if (paused_) { | |
| 103 speech_synthesizer_->Resume(); | |
| 104 paused_ = false; | |
| 105 } | |
| 106 | |
| 107 // TODO(dmazzoni): convert SSML to SAPI xml. http://crbug.com/88072 | 101 // TODO(dmazzoni): convert SSML to SAPI xml. http://crbug.com/88072 |
| 108 | 102 |
| 109 utterance_ = UTF8ToWide(src_utterance); | 103 utterance_ = UTF8ToWide(src_utterance); |
| 110 utterance_id_ = utterance_id; | 104 utterance_id_ = utterance_id; |
| 111 char_position_ = 0; | 105 char_position_ = 0; |
| 112 std::wstring merged_utterance = prefix + utterance_ + suffix; | 106 std::wstring merged_utterance = prefix + utterance_ + suffix; |
| 113 prefix_len_ = prefix.size(); | 107 prefix_len_ = prefix.size(); |
| 114 | 108 |
| 115 | |
| 116 HRESULT result = speech_synthesizer_->Speak( | 109 HRESULT result = speech_synthesizer_->Speak( |
| 117 merged_utterance.c_str(), | 110 merged_utterance.c_str(), |
| 118 SPF_ASYNC, | 111 SPF_ASYNC, |
| 119 &stream_number_); | 112 &stream_number_); |
| 120 return (result == S_OK); | 113 return (result == S_OK); |
| 121 } | 114 } |
| 122 | 115 |
| 123 bool ExtensionTtsPlatformImplWin::StopSpeaking() { | 116 bool ExtensionTtsPlatformImplWin::StopSpeaking() { |
| 124 if (speech_synthesizer_ && !paused_) { | 117 if (speech_synthesizer_) { |
| 125 // Clear the stream number so that any further events relating to this | 118 // Clear the stream number so that any further events relating to this |
| 126 // utterance are ignored. | 119 // utterance are ignored. |
| 127 stream_number_ = 0; | 120 stream_number_ = 0; |
| 128 | 121 |
| 129 speech_synthesizer_->Pause(); | 122 if (IsSpeaking()) { |
| 130 paused_ = true; | 123 // Stop speech by speaking the empty string with the purge flag. |
| 124 speech_synthesizer_->Speak(L"", SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL); |
| 125 } |
| 131 } | 126 } |
| 132 return true; | 127 return true; |
| 133 } | 128 } |
| 134 | 129 |
| 135 bool ExtensionTtsPlatformImplWin::IsSpeaking() { | 130 bool ExtensionTtsPlatformImplWin::IsSpeaking() { |
| 136 if (speech_synthesizer_ && !paused_) { | 131 if (speech_synthesizer_) { |
| 137 SPVOICESTATUS status; | 132 SPVOICESTATUS status; |
| 138 HRESULT result = speech_synthesizer_->GetStatus(&status, NULL); | 133 HRESULT result = speech_synthesizer_->GetStatus(&status, NULL); |
| 139 if (result == S_OK) { | 134 if (result == S_OK) { |
| 140 if (status.dwRunningState == 0 || // 0 == waiting to speak | 135 if (status.dwRunningState == 0 || // 0 == waiting to speak |
| 141 status.dwRunningState == SPRS_IS_SPEAKING) { | 136 status.dwRunningState == SPRS_IS_SPEAKING) { |
| 142 return true; | 137 return true; |
| 143 } | 138 } |
| 144 } | 139 } |
| 145 } | 140 } |
| 146 return false; | 141 return false; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 char_position_ = static_cast<ULONG>(event.lParam) - prefix_len_; | 180 char_position_ = static_cast<ULONG>(event.lParam) - prefix_len_; |
| 186 controller->OnTtsEvent( | 181 controller->OnTtsEvent( |
| 187 utterance_id_, TTS_EVENT_SENTENCE, char_position_, | 182 utterance_id_, TTS_EVENT_SENTENCE, char_position_, |
| 188 std::string()); | 183 std::string()); |
| 189 break; | 184 break; |
| 190 } | 185 } |
| 191 } | 186 } |
| 192 } | 187 } |
| 193 | 188 |
| 194 ExtensionTtsPlatformImplWin::ExtensionTtsPlatformImplWin() | 189 ExtensionTtsPlatformImplWin::ExtensionTtsPlatformImplWin() |
| 195 : speech_synthesizer_(NULL), | 190 : speech_synthesizer_(NULL) { |
| 196 paused_(false) { | |
| 197 CoCreateInstance( | 191 CoCreateInstance( |
| 198 CLSID_SpVoice, | 192 CLSID_SpVoice, |
| 199 NULL, | 193 NULL, |
| 200 CLSCTX_SERVER, | 194 CLSCTX_SERVER, |
| 201 IID_ISpVoice, | 195 IID_ISpVoice, |
| 202 reinterpret_cast<void**>(&speech_synthesizer_)); | 196 reinterpret_cast<void**>(&speech_synthesizer_)); |
| 203 if (speech_synthesizer_) { | 197 if (speech_synthesizer_) { |
| 204 ULONGLONG event_mask = | 198 ULONGLONG event_mask = |
| 205 SPFEI(SPEI_START_INPUT_STREAM) | | 199 SPFEI(SPEI_START_INPUT_STREAM) | |
| 206 SPFEI(SPEI_TTS_BOOKMARK) | | 200 SPFEI(SPEI_TTS_BOOKMARK) | |
| 207 SPFEI(SPEI_WORD_BOUNDARY) | | 201 SPFEI(SPEI_WORD_BOUNDARY) | |
| 208 SPFEI(SPEI_SENTENCE_BOUNDARY) | | 202 SPFEI(SPEI_SENTENCE_BOUNDARY) | |
| 209 SPFEI(SPEI_END_INPUT_STREAM); | 203 SPFEI(SPEI_END_INPUT_STREAM); |
| 210 speech_synthesizer_->SetInterest(event_mask, event_mask); | 204 speech_synthesizer_->SetInterest(event_mask, event_mask); |
| 211 speech_synthesizer_->SetNotifyCallbackFunction( | 205 speech_synthesizer_->SetNotifyCallbackFunction( |
| 212 ExtensionTtsPlatformImplWin::SpeechEventCallback, 0, 0); | 206 ExtensionTtsPlatformImplWin::SpeechEventCallback, 0, 0); |
| 213 } | 207 } |
| 214 } | 208 } |
| 215 | 209 |
| 216 // static | 210 // static |
| 217 ExtensionTtsPlatformImplWin* ExtensionTtsPlatformImplWin::GetInstance() { | 211 ExtensionTtsPlatformImplWin* ExtensionTtsPlatformImplWin::GetInstance() { |
| 218 return Singleton<ExtensionTtsPlatformImplWin>::get(); | 212 return Singleton<ExtensionTtsPlatformImplWin>::get(); |
| 219 } | 213 } |
| 220 | 214 |
| 221 // static | 215 // static |
| 222 void ExtensionTtsPlatformImplWin::SpeechEventCallback( | 216 void ExtensionTtsPlatformImplWin::SpeechEventCallback( |
| 223 WPARAM w_param, LPARAM l_param) { | 217 WPARAM w_param, LPARAM l_param) { |
| 224 GetInstance()->OnSpeechEvent(); | 218 GetInstance()->OnSpeechEvent(); |
| 225 } | 219 } |
| OLD | NEW |