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