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