| 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 |