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 |