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_impl.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/speech/tts_platform.h" | 13 #include "chrome/browser/speech/tts_platform.h" |
14 | 14 |
15 namespace { | 15 namespace { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 } | 95 } |
96 | 96 |
97 void Utterance::Finish() { | 97 void Utterance::Finish() { |
98 finished_ = true; | 98 finished_ = true; |
99 } | 99 } |
100 | 100 |
101 void Utterance::set_options(const base::Value* options) { | 101 void Utterance::set_options(const base::Value* options) { |
102 options_.reset(options->DeepCopy()); | 102 options_.reset(options->DeepCopy()); |
103 } | 103 } |
104 | 104 |
| 105 TtsController* TtsController::GetInstance() { |
| 106 return TtsControllerImpl::GetInstance(); |
| 107 } |
| 108 |
105 // | 109 // |
106 // TtsController | 110 // TtsControllerImpl |
107 // | 111 // |
108 | 112 |
109 // static | 113 // static |
110 TtsController* TtsController::GetInstance() { | 114 TtsControllerImpl* TtsControllerImpl::GetInstance() { |
111 return Singleton<TtsController>::get(); | 115 return Singleton<TtsControllerImpl>::get(); |
112 } | 116 } |
113 | 117 |
114 TtsController::TtsController() | 118 TtsControllerImpl::TtsControllerImpl() |
115 : current_utterance_(NULL), | 119 : current_utterance_(NULL), |
116 paused_(false), | 120 paused_(false), |
117 platform_impl_(NULL), | 121 platform_impl_(NULL), |
118 tts_engine_delegate_(NULL) { | 122 tts_engine_delegate_(NULL) { |
119 } | 123 } |
120 | 124 |
121 TtsController::~TtsController() { | 125 TtsControllerImpl::~TtsControllerImpl() { |
122 if (current_utterance_) { | 126 if (current_utterance_) { |
123 current_utterance_->Finish(); | 127 current_utterance_->Finish(); |
124 delete current_utterance_; | 128 delete current_utterance_; |
125 } | 129 } |
126 | 130 |
127 // Clear any queued utterances too. | 131 // Clear any queued utterances too. |
128 ClearUtteranceQueue(false); // Don't sent events. | 132 ClearUtteranceQueue(false); // Don't sent events. |
129 } | 133 } |
130 | 134 |
131 void TtsController::SpeakOrEnqueue(Utterance* utterance) { | 135 void TtsControllerImpl::SpeakOrEnqueue(Utterance* utterance) { |
132 // If we're paused and we get an utterance that can't be queued, | 136 // If we're paused and we get an utterance that can't be queued, |
133 // flush the queue but stay in the paused state. | 137 // flush the queue but stay in the paused state. |
134 if (paused_ && !utterance->can_enqueue()) { | 138 if (paused_ && !utterance->can_enqueue()) { |
135 Stop(); | 139 Stop(); |
136 paused_ = true; | 140 paused_ = true; |
137 return; | 141 return; |
138 } | 142 } |
139 | 143 |
140 if (paused_ || (IsSpeaking() && utterance->can_enqueue())) { | 144 if (paused_ || (IsSpeaking() && utterance->can_enqueue())) { |
141 utterance_queue_.push(utterance); | 145 utterance_queue_.push(utterance); |
142 } else { | 146 } else { |
143 Stop(); | 147 Stop(); |
144 SpeakNow(utterance); | 148 SpeakNow(utterance); |
145 } | 149 } |
146 } | 150 } |
147 | 151 |
148 void TtsController::SpeakNow(Utterance* utterance) { | 152 void TtsControllerImpl::SpeakNow(Utterance* utterance) { |
149 // Ensure we have all built-in voices loaded. This is a no-op if already | 153 // Ensure we have all built-in voices loaded. This is a no-op if already |
150 // loaded. | 154 // loaded. |
151 bool loaded_built_in = | 155 bool loaded_built_in = |
152 GetPlatformImpl()->LoadBuiltInTtsExtension(utterance->profile()); | 156 GetPlatformImpl()->LoadBuiltInTtsExtension(utterance->profile()); |
153 | 157 |
154 // Get all available voices and try to find a matching voice. | 158 // Get all available voices and try to find a matching voice. |
155 std::vector<VoiceData> voices; | 159 std::vector<VoiceData> voices; |
156 GetVoices(utterance->profile(), &voices); | 160 GetVoices(utterance->profile(), &voices); |
157 int index = GetMatchingVoice(utterance, voices); | 161 int index = GetMatchingVoice(utterance, voices); |
158 | 162 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 | 233 |
230 if (!success) { | 234 if (!success) { |
231 utterance->OnTtsEvent(TTS_EVENT_ERROR, kInvalidCharIndex, | 235 utterance->OnTtsEvent(TTS_EVENT_ERROR, kInvalidCharIndex, |
232 GetPlatformImpl()->error()); | 236 GetPlatformImpl()->error()); |
233 delete utterance; | 237 delete utterance; |
234 return; | 238 return; |
235 } | 239 } |
236 } | 240 } |
237 } | 241 } |
238 | 242 |
239 void TtsController::Stop() { | 243 void TtsControllerImpl::Stop() { |
240 paused_ = false; | 244 paused_ = false; |
241 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 245 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
242 #if !defined(OS_ANDROID) | 246 #if !defined(OS_ANDROID) |
243 if (tts_engine_delegate_) | 247 if (tts_engine_delegate_) |
244 tts_engine_delegate_->Stop(current_utterance_); | 248 tts_engine_delegate_->Stop(current_utterance_); |
245 #endif | 249 #endif |
246 } else { | 250 } else { |
247 GetPlatformImpl()->clear_error(); | 251 GetPlatformImpl()->clear_error(); |
248 GetPlatformImpl()->StopSpeaking(); | 252 GetPlatformImpl()->StopSpeaking(); |
249 } | 253 } |
250 | 254 |
251 if (current_utterance_) | 255 if (current_utterance_) |
252 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, | 256 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, |
253 std::string()); | 257 std::string()); |
254 FinishCurrentUtterance(); | 258 FinishCurrentUtterance(); |
255 ClearUtteranceQueue(true); // Send events. | 259 ClearUtteranceQueue(true); // Send events. |
256 } | 260 } |
257 | 261 |
258 void TtsController::Pause() { | 262 void TtsControllerImpl::Pause() { |
259 paused_ = true; | 263 paused_ = true; |
260 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 264 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
261 #if !defined(OS_ANDROID) | 265 #if !defined(OS_ANDROID) |
262 if (tts_engine_delegate_) | 266 if (tts_engine_delegate_) |
263 tts_engine_delegate_->Pause(current_utterance_); | 267 tts_engine_delegate_->Pause(current_utterance_); |
264 #endif | 268 #endif |
265 } else if (current_utterance_) { | 269 } else if (current_utterance_) { |
266 GetPlatformImpl()->clear_error(); | 270 GetPlatformImpl()->clear_error(); |
267 GetPlatformImpl()->Pause(); | 271 GetPlatformImpl()->Pause(); |
268 } | 272 } |
269 } | 273 } |
270 | 274 |
271 void TtsController::Resume() { | 275 void TtsControllerImpl::Resume() { |
272 paused_ = false; | 276 paused_ = false; |
273 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 277 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
274 #if !defined(OS_ANDROID) | 278 #if !defined(OS_ANDROID) |
275 if (tts_engine_delegate_) | 279 if (tts_engine_delegate_) |
276 tts_engine_delegate_->Resume(current_utterance_); | 280 tts_engine_delegate_->Resume(current_utterance_); |
277 #endif | 281 #endif |
278 } else if (current_utterance_) { | 282 } else if (current_utterance_) { |
279 GetPlatformImpl()->clear_error(); | 283 GetPlatformImpl()->clear_error(); |
280 GetPlatformImpl()->Resume(); | 284 GetPlatformImpl()->Resume(); |
281 } else { | 285 } else { |
282 SpeakNextUtterance(); | 286 SpeakNextUtterance(); |
283 } | 287 } |
284 } | 288 } |
285 | 289 |
286 void TtsController::OnTtsEvent(int utterance_id, | 290 void TtsControllerImpl::OnTtsEvent(int utterance_id, |
287 TtsEventType event_type, | 291 TtsEventType event_type, |
288 int char_index, | 292 int char_index, |
289 const std::string& error_message) { | 293 const std::string& error_message) { |
290 // We may sometimes receive completion callbacks "late", after we've | 294 // We may sometimes receive completion callbacks "late", after we've |
291 // already finished the utterance (for example because another utterance | 295 // already finished the utterance (for example because another utterance |
292 // interrupted or we got a call to Stop). This is normal and we can | 296 // interrupted or we got a call to Stop). This is normal and we can |
293 // safely just ignore these events. | 297 // safely just ignore these events. |
294 if (!current_utterance_ || utterance_id != current_utterance_->id()) { | 298 if (!current_utterance_ || utterance_id != current_utterance_->id()) { |
295 return; | 299 return; |
296 } | 300 } |
297 current_utterance_->OnTtsEvent(event_type, char_index, error_message); | 301 current_utterance_->OnTtsEvent(event_type, char_index, error_message); |
298 if (current_utterance_->finished()) { | 302 if (current_utterance_->finished()) { |
299 FinishCurrentUtterance(); | 303 FinishCurrentUtterance(); |
300 SpeakNextUtterance(); | 304 SpeakNextUtterance(); |
301 } | 305 } |
302 } | 306 } |
303 | 307 |
304 void TtsController::GetVoices(Profile* profile, | 308 void TtsControllerImpl::GetVoices(Profile* profile, |
305 std::vector<VoiceData>* out_voices) { | 309 std::vector<VoiceData>* out_voices) { |
306 #if !defined(OS_ANDROID) | 310 #if !defined(OS_ANDROID) |
307 if (profile && tts_engine_delegate_) | 311 if (profile && tts_engine_delegate_) |
308 tts_engine_delegate_->GetVoices(profile, out_voices); | 312 tts_engine_delegate_->GetVoices(profile, out_voices); |
309 #endif | 313 #endif |
310 | 314 |
311 TtsPlatformImpl* platform_impl = GetPlatformImpl(); | 315 TtsPlatformImpl* platform_impl = GetPlatformImpl(); |
312 if (platform_impl) { | 316 if (platform_impl) { |
313 // Ensure we have all built-in voices loaded. This is a no-op if already | 317 // Ensure we have all built-in voices loaded. This is a no-op if already |
314 // loaded. | 318 // loaded. |
315 platform_impl->LoadBuiltInTtsExtension(profile); | 319 platform_impl->LoadBuiltInTtsExtension(profile); |
316 if (platform_impl->PlatformImplAvailable()) | 320 if (platform_impl->PlatformImplAvailable()) |
317 platform_impl->GetVoices(out_voices); | 321 platform_impl->GetVoices(out_voices); |
318 } | 322 } |
319 } | 323 } |
320 | 324 |
321 bool TtsController::IsSpeaking() { | 325 bool TtsControllerImpl::IsSpeaking() { |
322 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); | 326 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); |
323 } | 327 } |
324 | 328 |
325 void TtsController::FinishCurrentUtterance() { | 329 void TtsControllerImpl::FinishCurrentUtterance() { |
326 if (current_utterance_) { | 330 if (current_utterance_) { |
327 if (!current_utterance_->finished()) | 331 if (!current_utterance_->finished()) |
328 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, | 332 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, |
329 std::string()); | 333 std::string()); |
330 delete current_utterance_; | 334 delete current_utterance_; |
331 current_utterance_ = NULL; | 335 current_utterance_ = NULL; |
332 } | 336 } |
333 } | 337 } |
334 | 338 |
335 void TtsController::SpeakNextUtterance() { | 339 void TtsControllerImpl::SpeakNextUtterance() { |
336 if (paused_) | 340 if (paused_) |
337 return; | 341 return; |
338 | 342 |
339 // Start speaking the next utterance in the queue. Keep trying in case | 343 // Start speaking the next utterance in the queue. Keep trying in case |
340 // one fails but there are still more in the queue to try. | 344 // one fails but there are still more in the queue to try. |
341 while (!utterance_queue_.empty() && !current_utterance_) { | 345 while (!utterance_queue_.empty() && !current_utterance_) { |
342 Utterance* utterance = utterance_queue_.front(); | 346 Utterance* utterance = utterance_queue_.front(); |
343 utterance_queue_.pop(); | 347 utterance_queue_.pop(); |
344 SpeakNow(utterance); | 348 SpeakNow(utterance); |
345 } | 349 } |
346 } | 350 } |
347 | 351 |
348 void TtsController::RetrySpeakingQueuedUtterances() { | 352 void TtsControllerImpl::RetrySpeakingQueuedUtterances() { |
349 if (current_utterance_ == NULL && !utterance_queue_.empty()) | 353 if (current_utterance_ == NULL && !utterance_queue_.empty()) |
350 SpeakNextUtterance(); | 354 SpeakNextUtterance(); |
351 } | 355 } |
352 | 356 |
353 void TtsController::ClearUtteranceQueue(bool send_events) { | 357 void TtsControllerImpl::ClearUtteranceQueue(bool send_events) { |
354 while (!utterance_queue_.empty()) { | 358 while (!utterance_queue_.empty()) { |
355 Utterance* utterance = utterance_queue_.front(); | 359 Utterance* utterance = utterance_queue_.front(); |
356 utterance_queue_.pop(); | 360 utterance_queue_.pop(); |
357 if (send_events) | 361 if (send_events) |
358 utterance->OnTtsEvent(TTS_EVENT_CANCELLED, kInvalidCharIndex, | 362 utterance->OnTtsEvent(TTS_EVENT_CANCELLED, kInvalidCharIndex, |
359 std::string()); | 363 std::string()); |
360 else | 364 else |
361 utterance->Finish(); | 365 utterance->Finish(); |
362 delete utterance; | 366 delete utterance; |
363 } | 367 } |
364 } | 368 } |
365 | 369 |
366 void TtsController::SetPlatformImpl( | 370 void TtsControllerImpl::SetPlatformImpl( |
367 TtsPlatformImpl* platform_impl) { | 371 TtsPlatformImpl* platform_impl) { |
368 platform_impl_ = platform_impl; | 372 platform_impl_ = platform_impl; |
369 } | 373 } |
370 | 374 |
371 int TtsController::QueueSize() { | 375 int TtsControllerImpl::QueueSize() { |
372 return static_cast<int>(utterance_queue_.size()); | 376 return static_cast<int>(utterance_queue_.size()); |
373 } | 377 } |
374 | 378 |
375 TtsPlatformImpl* TtsController::GetPlatformImpl() { | 379 TtsPlatformImpl* TtsControllerImpl::GetPlatformImpl() { |
376 if (!platform_impl_) | 380 if (!platform_impl_) |
377 platform_impl_ = TtsPlatformImpl::GetInstance(); | 381 platform_impl_ = TtsPlatformImpl::GetInstance(); |
378 return platform_impl_; | 382 return platform_impl_; |
379 } | 383 } |
380 | 384 |
381 int TtsController::GetMatchingVoice( | 385 int TtsControllerImpl::GetMatchingVoice( |
382 const Utterance* utterance, std::vector<VoiceData>& voices) { | 386 const Utterance* utterance, std::vector<VoiceData>& voices) { |
383 // Make two passes: the first time, do strict language matching | 387 // Make two passes: the first time, do strict language matching |
384 // ('fr-FR' does not match 'fr-CA'). The second time, do prefix | 388 // ('fr-FR' does not match 'fr-CA'). The second time, do prefix |
385 // language matching ('fr-FR' matches 'fr' and 'fr-CA') | 389 // language matching ('fr-FR' matches 'fr' and 'fr-CA') |
386 for (int pass = 0; pass < 2; ++pass) { | 390 for (int pass = 0; pass < 2; ++pass) { |
387 for (size_t i = 0; i < voices.size(); ++i) { | 391 for (size_t i = 0; i < voices.size(); ++i) { |
388 const VoiceData& voice = voices[i]; | 392 const VoiceData& voice = voices[i]; |
389 | 393 |
390 if (!utterance->extension_id().empty() && | 394 if (!utterance->extension_id().empty() && |
391 utterance->extension_id() != voice.extension_id) { | 395 utterance->extension_id() != voice.extension_id) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 continue; | 433 continue; |
430 } | 434 } |
431 | 435 |
432 return static_cast<int>(i); | 436 return static_cast<int>(i); |
433 } | 437 } |
434 } | 438 } |
435 | 439 |
436 return -1; | 440 return -1; |
437 } | 441 } |
438 | 442 |
439 void TtsController::VoicesChanged() { | 443 void TtsControllerImpl::VoicesChanged() { |
440 for (std::set<VoicesChangedDelegate*>::iterator iter = | 444 for (std::set<VoicesChangedDelegate*>::iterator iter = |
441 voices_changed_delegates_.begin(); | 445 voices_changed_delegates_.begin(); |
442 iter != voices_changed_delegates_.end(); ++iter) { | 446 iter != voices_changed_delegates_.end(); ++iter) { |
443 (*iter)->OnVoicesChanged(); | 447 (*iter)->OnVoicesChanged(); |
444 } | 448 } |
445 } | 449 } |
446 | 450 |
447 void TtsController::AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) { | 451 void TtsControllerImpl::AddVoicesChangedDelegate( |
| 452 VoicesChangedDelegate* delegate) { |
448 voices_changed_delegates_.insert(delegate); | 453 voices_changed_delegates_.insert(delegate); |
449 } | 454 } |
450 | 455 |
451 void TtsController::RemoveVoicesChangedDelegate( | 456 void TtsControllerImpl::RemoveVoicesChangedDelegate( |
452 VoicesChangedDelegate* delegate) { | 457 VoicesChangedDelegate* delegate) { |
453 voices_changed_delegates_.erase(delegate); | 458 voices_changed_delegates_.erase(delegate); |
454 } | 459 } |
455 | 460 |
456 void TtsController::SetTtsEngineDelegate( | 461 void TtsControllerImpl::SetTtsEngineDelegate( |
457 TtsEngineDelegate* delegate) { | 462 TtsEngineDelegate* delegate) { |
458 tts_engine_delegate_ = delegate; | 463 tts_engine_delegate_ = delegate; |
459 } | 464 } |
OLD | NEW |