OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/speech/tts_controller.h" | 5 #include "chrome/browser/speech/tts_controller.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/float_util.h" | 10 #include "base/float_util.h" |
11 #include "base/values.h" | 11 #include "base/values.h" |
12 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
13 #include "chrome/browser/profiles/profile.h" | |
14 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h" | |
15 #include "chrome/browser/speech/extension_api/tts_extension_api.h" | |
16 #include "chrome/browser/speech/tts_platform.h" | 13 #include "chrome/browser/speech/tts_platform.h" |
17 #include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h" | |
18 #include "extensions/browser/extension_system.h" | |
19 #include "extensions/common/extension.h" | |
20 | 14 |
21 namespace { | 15 namespace { |
22 // A value to be used to indicate that there is no char index available. | 16 // A value to be used to indicate that there is no char index available. |
23 const int kInvalidCharIndex = -1; | 17 const int kInvalidCharIndex = -1; |
24 | 18 |
25 // Given a language/region code of the form 'fr-FR', returns just the basic | 19 // Given a language/region code of the form 'fr-FR', returns just the basic |
26 // language portion, e.g. 'fr'. | 20 // language portion, e.g. 'fr'. |
27 std::string TrimLanguageCode(std::string lang) { | 21 std::string TrimLanguageCode(std::string lang) { |
28 if (lang.size() >= 5 && lang[2] == '-') | 22 if (lang.size() >= 5 && lang[2] == '-') |
29 return lang.substr(0, 2); | 23 return lang.substr(0, 2); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 // | 107 // |
114 | 108 |
115 // static | 109 // static |
116 TtsController* TtsController::GetInstance() { | 110 TtsController* TtsController::GetInstance() { |
117 return Singleton<TtsController>::get(); | 111 return Singleton<TtsController>::get(); |
118 } | 112 } |
119 | 113 |
120 TtsController::TtsController() | 114 TtsController::TtsController() |
121 : current_utterance_(NULL), | 115 : current_utterance_(NULL), |
122 paused_(false), | 116 paused_(false), |
123 platform_impl_(NULL) { | 117 platform_impl_(NULL), |
| 118 tts_engine_delegate_(NULL) { |
124 } | 119 } |
125 | 120 |
126 TtsController::~TtsController() { | 121 TtsController::~TtsController() { |
127 if (current_utterance_) { | 122 if (current_utterance_) { |
128 current_utterance_->Finish(); | 123 current_utterance_->Finish(); |
129 delete current_utterance_; | 124 delete current_utterance_; |
130 } | 125 } |
131 | 126 |
132 // Clear any queued utterances too. | 127 // Clear any queued utterances too. |
133 ClearUtteranceQueue(false); // Don't sent events. | 128 ClearUtteranceQueue(false); // Don't sent events. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 // attempt to get a voice based only on the current locale without respect | 160 // attempt to get a voice based only on the current locale without respect |
166 // to any supplied voice names. | 161 // to any supplied voice names. |
167 std::vector<VoiceData> native_voices; | 162 std::vector<VoiceData> native_voices; |
168 | 163 |
169 if (GetPlatformImpl()->PlatformImplAvailable()) | 164 if (GetPlatformImpl()->PlatformImplAvailable()) |
170 GetPlatformImpl()->GetVoices(&native_voices); | 165 GetPlatformImpl()->GetVoices(&native_voices); |
171 | 166 |
172 if (native_voices.empty() && !voices.empty()) { | 167 if (native_voices.empty() && !voices.empty()) { |
173 // TODO(dtseng): Notify extension caller of an error. | 168 // TODO(dtseng): Notify extension caller of an error. |
174 utterance->set_voice_name(""); | 169 utterance->set_voice_name(""); |
| 170 // TODO(gaochun): Replace the global variable g_browser_process with |
| 171 // GetContentClient()->browser() to eliminate the dependency of browser |
| 172 // once TTS implementation was moved to content. |
175 utterance->set_lang(g_browser_process->GetApplicationLocale()); | 173 utterance->set_lang(g_browser_process->GetApplicationLocale()); |
176 index = GetMatchingVoice(utterance, voices); | 174 index = GetMatchingVoice(utterance, voices); |
177 | 175 |
178 // If even that fails, just take the first available voice. | 176 // If even that fails, just take the first available voice. |
179 if (index == -1) | 177 if (index == -1) |
180 index = 0; | 178 index = 0; |
181 voice = voices[index]; | 179 voice = voices[index]; |
182 } else { | 180 } else { |
183 // Otherwise, simply give native voices a chance to handle this utterance. | 181 // Otherwise, simply give native voices a chance to handle this utterance. |
184 voice.native = true; | 182 voice.native = true; |
185 } | 183 } |
186 } | 184 } |
187 | 185 |
188 GetPlatformImpl()->WillSpeakUtteranceWithVoice(utterance, voice); | 186 GetPlatformImpl()->WillSpeakUtteranceWithVoice(utterance, voice); |
189 | 187 |
190 if (!voice.native) { | 188 if (!voice.native) { |
191 #if !defined(OS_ANDROID) | 189 #if !defined(OS_ANDROID) |
192 DCHECK(!voice.extension_id.empty()); | 190 DCHECK(!voice.extension_id.empty()); |
193 current_utterance_ = utterance; | 191 current_utterance_ = utterance; |
194 utterance->set_extension_id(voice.extension_id); | 192 utterance->set_extension_id(voice.extension_id); |
195 ExtensionTtsEngineSpeak(utterance, voice); | 193 if (tts_engine_delegate_) |
| 194 tts_engine_delegate_->Speak(utterance, voice); |
196 bool sends_end_event = | 195 bool sends_end_event = |
197 voice.events.find(TTS_EVENT_END) != voice.events.end(); | 196 voice.events.find(TTS_EVENT_END) != voice.events.end(); |
198 if (!sends_end_event) { | 197 if (!sends_end_event) { |
199 utterance->Finish(); | 198 utterance->Finish(); |
200 delete utterance; | 199 delete utterance; |
201 current_utterance_ = NULL; | 200 current_utterance_ = NULL; |
202 SpeakNextUtterance(); | 201 SpeakNextUtterance(); |
203 } | 202 } |
204 #endif | 203 #endif |
205 } else { | 204 } else { |
(...skipping 24 matching lines...) Expand all Loading... |
230 delete utterance; | 229 delete utterance; |
231 return; | 230 return; |
232 } | 231 } |
233 } | 232 } |
234 } | 233 } |
235 | 234 |
236 void TtsController::Stop() { | 235 void TtsController::Stop() { |
237 paused_ = false; | 236 paused_ = false; |
238 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 237 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
239 #if !defined(OS_ANDROID) | 238 #if !defined(OS_ANDROID) |
240 ExtensionTtsEngineStop(current_utterance_); | 239 if (tts_engine_delegate_) |
| 240 tts_engine_delegate_->Stop(current_utterance_); |
241 #endif | 241 #endif |
242 } else { | 242 } else { |
243 GetPlatformImpl()->clear_error(); | 243 GetPlatformImpl()->clear_error(); |
244 GetPlatformImpl()->StopSpeaking(); | 244 GetPlatformImpl()->StopSpeaking(); |
245 } | 245 } |
246 | 246 |
247 if (current_utterance_) | 247 if (current_utterance_) |
248 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, | 248 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, |
249 std::string()); | 249 std::string()); |
250 FinishCurrentUtterance(); | 250 FinishCurrentUtterance(); |
251 ClearUtteranceQueue(true); // Send events. | 251 ClearUtteranceQueue(true); // Send events. |
252 } | 252 } |
253 | 253 |
254 void TtsController::Pause() { | 254 void TtsController::Pause() { |
255 paused_ = true; | 255 paused_ = true; |
256 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 256 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
257 #if !defined(OS_ANDROID) | 257 #if !defined(OS_ANDROID) |
258 ExtensionTtsEnginePause(current_utterance_); | 258 if (tts_engine_delegate_) |
| 259 tts_engine_delegate_->Pause(current_utterance_); |
259 #endif | 260 #endif |
260 } else if (current_utterance_) { | 261 } else if (current_utterance_) { |
261 GetPlatformImpl()->clear_error(); | 262 GetPlatformImpl()->clear_error(); |
262 GetPlatformImpl()->Pause(); | 263 GetPlatformImpl()->Pause(); |
263 } | 264 } |
264 } | 265 } |
265 | 266 |
266 void TtsController::Resume() { | 267 void TtsController::Resume() { |
267 paused_ = false; | 268 paused_ = false; |
268 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 269 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
269 #if !defined(OS_ANDROID) | 270 #if !defined(OS_ANDROID) |
270 ExtensionTtsEngineResume(current_utterance_); | 271 if (tts_engine_delegate_) |
| 272 tts_engine_delegate_->Resume(current_utterance_); |
271 #endif | 273 #endif |
272 } else if (current_utterance_) { | 274 } else if (current_utterance_) { |
273 GetPlatformImpl()->clear_error(); | 275 GetPlatformImpl()->clear_error(); |
274 GetPlatformImpl()->Resume(); | 276 GetPlatformImpl()->Resume(); |
275 } else { | 277 } else { |
276 SpeakNextUtterance(); | 278 SpeakNextUtterance(); |
277 } | 279 } |
278 } | 280 } |
279 | 281 |
280 void TtsController::OnTtsEvent(int utterance_id, | 282 void TtsController::OnTtsEvent(int utterance_id, |
(...skipping 10 matching lines...) Expand all Loading... |
291 current_utterance_->OnTtsEvent(event_type, char_index, error_message); | 293 current_utterance_->OnTtsEvent(event_type, char_index, error_message); |
292 if (current_utterance_->finished()) { | 294 if (current_utterance_->finished()) { |
293 FinishCurrentUtterance(); | 295 FinishCurrentUtterance(); |
294 SpeakNextUtterance(); | 296 SpeakNextUtterance(); |
295 } | 297 } |
296 } | 298 } |
297 | 299 |
298 void TtsController::GetVoices(Profile* profile, | 300 void TtsController::GetVoices(Profile* profile, |
299 std::vector<VoiceData>* out_voices) { | 301 std::vector<VoiceData>* out_voices) { |
300 #if !defined(OS_ANDROID) | 302 #if !defined(OS_ANDROID) |
301 if (profile) | 303 if (profile && tts_engine_delegate_) |
302 GetExtensionVoices(profile, out_voices); | 304 tts_engine_delegate_->GetVoices(profile, out_voices); |
303 #endif | 305 #endif |
304 | 306 |
305 TtsPlatformImpl* platform_impl = GetPlatformImpl(); | 307 TtsPlatformImpl* platform_impl = GetPlatformImpl(); |
306 if (platform_impl && platform_impl->PlatformImplAvailable()) | 308 if (platform_impl && platform_impl->PlatformImplAvailable()) |
307 platform_impl->GetVoices(out_voices); | 309 platform_impl->GetVoices(out_voices); |
308 } | 310 } |
309 | 311 |
310 bool TtsController::IsSpeaking() { | 312 bool TtsController::IsSpeaking() { |
311 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); | 313 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); |
312 } | 314 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 } | 436 } |
435 | 437 |
436 void TtsController::AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) { | 438 void TtsController::AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) { |
437 voices_changed_delegates_.insert(delegate); | 439 voices_changed_delegates_.insert(delegate); |
438 } | 440 } |
439 | 441 |
440 void TtsController::RemoveVoicesChangedDelegate( | 442 void TtsController::RemoveVoicesChangedDelegate( |
441 VoicesChangedDelegate* delegate) { | 443 VoicesChangedDelegate* delegate) { |
442 voices_changed_delegates_.erase(delegate); | 444 voices_changed_delegates_.erase(delegate); |
443 } | 445 } |
| 446 |
| 447 void TtsController::SetTtsEngineDelegate( |
| 448 TtsEngineDelegate* delegate) { |
| 449 tts_engine_delegate_ = delegate; |
| 450 } |
OLD | NEW |