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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 // attempt to get a voice based only on the current locale without respect | 165 // attempt to get a voice based only on the current locale without respect |
171 // to any supplied voice names. | 166 // to any supplied voice names. |
172 std::vector<VoiceData> native_voices; | 167 std::vector<VoiceData> native_voices; |
173 | 168 |
174 if (GetPlatformImpl()->PlatformImplAvailable()) | 169 if (GetPlatformImpl()->PlatformImplAvailable()) |
175 GetPlatformImpl()->GetVoices(&native_voices); | 170 GetPlatformImpl()->GetVoices(&native_voices); |
176 | 171 |
177 if (native_voices.empty() && !voices.empty()) { | 172 if (native_voices.empty() && !voices.empty()) { |
178 // TODO(dtseng): Notify extension caller of an error. | 173 // TODO(dtseng): Notify extension caller of an error. |
179 utterance->set_voice_name(""); | 174 utterance->set_voice_name(""); |
| 175 // TODO(gaochun): Replace the global variable g_browser_process with |
| 176 // GetContentClient()->browser() to eliminate the dependency of browser |
| 177 // once TTS implementation was moved to content. |
180 utterance->set_lang(g_browser_process->GetApplicationLocale()); | 178 utterance->set_lang(g_browser_process->GetApplicationLocale()); |
181 index = GetMatchingVoice(utterance, voices); | 179 index = GetMatchingVoice(utterance, voices); |
182 | 180 |
183 // If even that fails, just take the first available voice. | 181 // If even that fails, just take the first available voice. |
184 if (index == -1) | 182 if (index == -1) |
185 index = 0; | 183 index = 0; |
186 voice = voices[index]; | 184 voice = voices[index]; |
187 } else { | 185 } else { |
188 // Otherwise, simply give native voices a chance to handle this utterance. | 186 // Otherwise, simply give native voices a chance to handle this utterance. |
189 voice.native = true; | 187 voice.native = true; |
190 } | 188 } |
191 } | 189 } |
192 | 190 |
193 GetPlatformImpl()->WillSpeakUtteranceWithVoice(utterance, voice); | 191 GetPlatformImpl()->WillSpeakUtteranceWithVoice(utterance, voice); |
194 | 192 |
195 if (!voice.native) { | 193 if (!voice.native) { |
196 #if !defined(OS_ANDROID) | 194 #if !defined(OS_ANDROID) |
197 DCHECK(!voice.extension_id.empty()); | 195 DCHECK(!voice.extension_id.empty()); |
198 current_utterance_ = utterance; | 196 current_utterance_ = utterance; |
199 utterance->set_extension_id(voice.extension_id); | 197 utterance->set_extension_id(voice.extension_id); |
200 ExtensionTtsEngineSpeak(utterance, voice); | 198 if (tts_engine_delegate_) |
| 199 tts_engine_delegate_->Speak(utterance, voice); |
201 bool sends_end_event = | 200 bool sends_end_event = |
202 voice.events.find(TTS_EVENT_END) != voice.events.end(); | 201 voice.events.find(TTS_EVENT_END) != voice.events.end(); |
203 if (!sends_end_event) { | 202 if (!sends_end_event) { |
204 utterance->Finish(); | 203 utterance->Finish(); |
205 delete utterance; | 204 delete utterance; |
206 current_utterance_ = NULL; | 205 current_utterance_ = NULL; |
207 SpeakNextUtterance(); | 206 SpeakNextUtterance(); |
208 } | 207 } |
209 #endif | 208 #endif |
210 } else { | 209 } else { |
(...skipping 23 matching lines...) Expand all Loading... |
234 delete utterance; | 233 delete utterance; |
235 return; | 234 return; |
236 } | 235 } |
237 } | 236 } |
238 } | 237 } |
239 | 238 |
240 void TtsController::Stop() { | 239 void TtsController::Stop() { |
241 paused_ = false; | 240 paused_ = false; |
242 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 241 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
243 #if !defined(OS_ANDROID) | 242 #if !defined(OS_ANDROID) |
244 ExtensionTtsEngineStop(current_utterance_); | 243 if (tts_engine_delegate_) |
| 244 tts_engine_delegate_->Stop(current_utterance_); |
245 #endif | 245 #endif |
246 } else { | 246 } else { |
247 GetPlatformImpl()->clear_error(); | 247 GetPlatformImpl()->clear_error(); |
248 GetPlatformImpl()->StopSpeaking(); | 248 GetPlatformImpl()->StopSpeaking(); |
249 } | 249 } |
250 | 250 |
251 if (current_utterance_) | 251 if (current_utterance_) |
252 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, | 252 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, |
253 std::string()); | 253 std::string()); |
254 FinishCurrentUtterance(); | 254 FinishCurrentUtterance(); |
255 ClearUtteranceQueue(true); // Send events. | 255 ClearUtteranceQueue(true); // Send events. |
256 } | 256 } |
257 | 257 |
258 void TtsController::Pause() { | 258 void TtsController::Pause() { |
259 paused_ = true; | 259 paused_ = true; |
260 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 260 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
261 #if !defined(OS_ANDROID) | 261 #if !defined(OS_ANDROID) |
262 ExtensionTtsEnginePause(current_utterance_); | 262 if (tts_engine_delegate_) |
| 263 tts_engine_delegate_->Pause(current_utterance_); |
263 #endif | 264 #endif |
264 } else if (current_utterance_) { | 265 } else if (current_utterance_) { |
265 GetPlatformImpl()->clear_error(); | 266 GetPlatformImpl()->clear_error(); |
266 GetPlatformImpl()->Pause(); | 267 GetPlatformImpl()->Pause(); |
267 } | 268 } |
268 } | 269 } |
269 | 270 |
270 void TtsController::Resume() { | 271 void TtsController::Resume() { |
271 paused_ = false; | 272 paused_ = false; |
272 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 273 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
273 #if !defined(OS_ANDROID) | 274 #if !defined(OS_ANDROID) |
274 ExtensionTtsEngineResume(current_utterance_); | 275 if (tts_engine_delegate_) |
| 276 tts_engine_delegate_->Resume(current_utterance_); |
275 #endif | 277 #endif |
276 } else if (current_utterance_) { | 278 } else if (current_utterance_) { |
277 GetPlatformImpl()->clear_error(); | 279 GetPlatformImpl()->clear_error(); |
278 GetPlatformImpl()->Resume(); | 280 GetPlatformImpl()->Resume(); |
279 } else { | 281 } else { |
280 SpeakNextUtterance(); | 282 SpeakNextUtterance(); |
281 } | 283 } |
282 } | 284 } |
283 | 285 |
284 void TtsController::OnTtsEvent(int utterance_id, | 286 void TtsController::OnTtsEvent(int utterance_id, |
(...skipping 10 matching lines...) Expand all Loading... |
295 current_utterance_->OnTtsEvent(event_type, char_index, error_message); | 297 current_utterance_->OnTtsEvent(event_type, char_index, error_message); |
296 if (current_utterance_->finished()) { | 298 if (current_utterance_->finished()) { |
297 FinishCurrentUtterance(); | 299 FinishCurrentUtterance(); |
298 SpeakNextUtterance(); | 300 SpeakNextUtterance(); |
299 } | 301 } |
300 } | 302 } |
301 | 303 |
302 void TtsController::GetVoices(Profile* profile, | 304 void TtsController::GetVoices(Profile* profile, |
303 std::vector<VoiceData>* out_voices) { | 305 std::vector<VoiceData>* out_voices) { |
304 #if !defined(OS_ANDROID) | 306 #if !defined(OS_ANDROID) |
305 if (profile) | 307 if (profile && tts_engine_delegate_) |
306 GetExtensionVoices(profile, out_voices); | 308 tts_engine_delegate_->GetVoices(profile, out_voices); |
307 #endif | 309 #endif |
308 | 310 |
309 TtsPlatformImpl* platform_impl = GetPlatformImpl(); | 311 TtsPlatformImpl* platform_impl = GetPlatformImpl(); |
310 if (platform_impl) { | 312 if (platform_impl) { |
311 // Ensure we have all built-in voices loaded. This is a no-op if already | 313 // Ensure we have all built-in voices loaded. This is a no-op if already |
312 // loaded. | 314 // loaded. |
313 platform_impl->LoadBuiltInTtsExtension(profile); | 315 platform_impl->LoadBuiltInTtsExtension(profile); |
314 if (platform_impl->PlatformImplAvailable()) | 316 if (platform_impl->PlatformImplAvailable()) |
315 platform_impl->GetVoices(out_voices); | 317 platform_impl->GetVoices(out_voices); |
316 } | 318 } |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 } | 445 } |
444 | 446 |
445 void TtsController::AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) { | 447 void TtsController::AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) { |
446 voices_changed_delegates_.insert(delegate); | 448 voices_changed_delegates_.insert(delegate); |
447 } | 449 } |
448 | 450 |
449 void TtsController::RemoveVoicesChangedDelegate( | 451 void TtsController::RemoveVoicesChangedDelegate( |
450 VoicesChangedDelegate* delegate) { | 452 VoicesChangedDelegate* delegate) { |
451 voices_changed_delegates_.erase(delegate); | 453 voices_changed_delegates_.erase(delegate); |
452 } | 454 } |
| 455 |
| 456 void TtsController::SetTtsEngineDelegate( |
| 457 TtsEngineDelegate* delegate) { |
| 458 tts_engine_delegate_ = delegate; |
| 459 } |
OLD | NEW |