| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 // attempt to get a voice based only on the current locale without respect | 160 // attempt to get a voice based only on the current locale without respect |
| 166 // to any supplied voice names. | 161 // to any supplied voice names. |
| 167 std::vector<VoiceData> native_voices; | 162 std::vector<VoiceData> native_voices; |
| 168 | 163 |
| 169 if (GetPlatformImpl()->PlatformImplAvailable()) | 164 if (GetPlatformImpl()->PlatformImplAvailable()) |
| 170 GetPlatformImpl()->GetVoices(&native_voices); | 165 GetPlatformImpl()->GetVoices(&native_voices); |
| 171 | 166 |
| 172 if (native_voices.empty() && !voices.empty()) { | 167 if (native_voices.empty() && !voices.empty()) { |
| 173 // TODO(dtseng): Notify extension caller of an error. | 168 // TODO(dtseng): Notify extension caller of an error. |
| 174 utterance->set_voice_name(""); | 169 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. |
| 175 utterance->set_lang(g_browser_process->GetApplicationLocale()); | 173 utterance->set_lang(g_browser_process->GetApplicationLocale()); |
| 176 index = GetMatchingVoice(utterance, voices); | 174 index = GetMatchingVoice(utterance, voices); |
| 177 | 175 |
| 178 // If even that fails, just take the first available voice. | 176 // If even that fails, just take the first available voice. |
| 179 if (index == -1) | 177 if (index == -1) |
| 180 index = 0; | 178 index = 0; |
| 181 voice = voices[index]; | 179 voice = voices[index]; |
| 182 } else { | 180 } else { |
| 183 // Otherwise, simply give native voices a chance to handle this utterance. | 181 // Otherwise, simply give native voices a chance to handle this utterance. |
| 184 voice.native = true; | 182 voice.native = true; |
| 185 } | 183 } |
| 186 } | 184 } |
| 187 | 185 |
| 188 GetPlatformImpl()->WillSpeakUtteranceWithVoice(utterance, voice); | 186 GetPlatformImpl()->WillSpeakUtteranceWithVoice(utterance, voice); |
| 189 | 187 |
| 190 if (!voice.native) { | 188 if (!voice.native) { |
| 191 #if !defined(OS_ANDROID) | 189 #if !defined(OS_ANDROID) |
| 192 DCHECK(!voice.extension_id.empty()); | 190 DCHECK(!voice.extension_id.empty()); |
| 193 current_utterance_ = utterance; | 191 current_utterance_ = utterance; |
| 194 utterance->set_extension_id(voice.extension_id); | 192 utterance->set_extension_id(voice.extension_id); |
| 195 ExtensionTtsEngineSpeak(utterance, voice); | 193 if (tts_engine_delegate_) |
| 194 tts_engine_delegate_->Speak(utterance, voice); |
| 196 bool sends_end_event = | 195 bool sends_end_event = |
| 197 voice.events.find(TTS_EVENT_END) != voice.events.end(); | 196 voice.events.find(TTS_EVENT_END) != voice.events.end(); |
| 198 if (!sends_end_event) { | 197 if (!sends_end_event) { |
| 199 utterance->Finish(); | 198 utterance->Finish(); |
| 200 delete utterance; | 199 delete utterance; |
| 201 current_utterance_ = NULL; | 200 current_utterance_ = NULL; |
| 202 SpeakNextUtterance(); | 201 SpeakNextUtterance(); |
| 203 } | 202 } |
| 204 #endif | 203 #endif |
| 205 } else { | 204 } else { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 230 delete utterance; | 229 delete utterance; |
| 231 return; | 230 return; |
| 232 } | 231 } |
| 233 } | 232 } |
| 234 } | 233 } |
| 235 | 234 |
| 236 void TtsController::Stop() { | 235 void TtsController::Stop() { |
| 237 paused_ = false; | 236 paused_ = false; |
| 238 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 237 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
| 239 #if !defined(OS_ANDROID) | 238 #if !defined(OS_ANDROID) |
| 240 ExtensionTtsEngineStop(current_utterance_); | 239 if (tts_engine_delegate_) |
| 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 ExtensionTtsEnginePause(current_utterance_); | 258 if (tts_engine_delegate_) |
| 259 tts_engine_delegate_->Pause(current_utterance_); |
| 259 #endif | 260 #endif |
| 260 } else if (current_utterance_) { | 261 } else if (current_utterance_) { |
| 261 GetPlatformImpl()->clear_error(); | 262 GetPlatformImpl()->clear_error(); |
| 262 GetPlatformImpl()->Pause(); | 263 GetPlatformImpl()->Pause(); |
| 263 } | 264 } |
| 264 } | 265 } |
| 265 | 266 |
| 266 void TtsController::Resume() { | 267 void TtsController::Resume() { |
| 267 paused_ = false; | 268 paused_ = false; |
| 268 if (current_utterance_ && !current_utterance_->extension_id().empty()) { | 269 if (current_utterance_ && !current_utterance_->extension_id().empty()) { |
| 269 #if !defined(OS_ANDROID) | 270 #if !defined(OS_ANDROID) |
| 270 ExtensionTtsEngineResume(current_utterance_); | 271 if (tts_engine_delegate_) |
| 272 tts_engine_delegate_->Resume(current_utterance_); |
| 271 #endif | 273 #endif |
| 272 } else if (current_utterance_) { | 274 } else if (current_utterance_) { |
| 273 GetPlatformImpl()->clear_error(); | 275 GetPlatformImpl()->clear_error(); |
| 274 GetPlatformImpl()->Resume(); | 276 GetPlatformImpl()->Resume(); |
| 275 } else { | 277 } else { |
| 276 SpeakNextUtterance(); | 278 SpeakNextUtterance(); |
| 277 } | 279 } |
| 278 } | 280 } |
| 279 | 281 |
| 280 void TtsController::OnTtsEvent(int utterance_id, | 282 void TtsController::OnTtsEvent(int utterance_id, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 291 current_utterance_->OnTtsEvent(event_type, char_index, error_message); | 293 current_utterance_->OnTtsEvent(event_type, char_index, error_message); |
| 292 if (current_utterance_->finished()) { | 294 if (current_utterance_->finished()) { |
| 293 FinishCurrentUtterance(); | 295 FinishCurrentUtterance(); |
| 294 SpeakNextUtterance(); | 296 SpeakNextUtterance(); |
| 295 } | 297 } |
| 296 } | 298 } |
| 297 | 299 |
| 298 void TtsController::GetVoices(Profile* profile, | 300 void TtsController::GetVoices(Profile* profile, |
| 299 std::vector<VoiceData>* out_voices) { | 301 std::vector<VoiceData>* out_voices) { |
| 300 #if !defined(OS_ANDROID) | 302 #if !defined(OS_ANDROID) |
| 301 if (profile) | 303 if (profile && tts_engine_delegate_) |
| 302 GetExtensionVoices(profile, out_voices); | 304 tts_engine_delegate_->GetVoices(profile, out_voices); |
| 303 #endif | 305 #endif |
| 304 | 306 |
| 305 TtsPlatformImpl* platform_impl = GetPlatformImpl(); | 307 TtsPlatformImpl* platform_impl = GetPlatformImpl(); |
| 306 if (platform_impl && platform_impl->PlatformImplAvailable()) | 308 if (platform_impl && platform_impl->PlatformImplAvailable()) |
| 307 platform_impl->GetVoices(out_voices); | 309 platform_impl->GetVoices(out_voices); |
| 308 } | 310 } |
| 309 | 311 |
| 310 bool TtsController::IsSpeaking() { | 312 bool TtsController::IsSpeaking() { |
| 311 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); | 313 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); |
| 312 } | 314 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 } | 436 } |
| 435 | 437 |
| 436 void TtsController::AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) { | 438 void TtsController::AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) { |
| 437 voices_changed_delegates_.insert(delegate); | 439 voices_changed_delegates_.insert(delegate); |
| 438 } | 440 } |
| 439 | 441 |
| 440 void TtsController::RemoveVoicesChangedDelegate( | 442 void TtsController::RemoveVoicesChangedDelegate( |
| 441 VoicesChangedDelegate* delegate) { | 443 VoicesChangedDelegate* delegate) { |
| 442 voices_changed_delegates_.erase(delegate); | 444 voices_changed_delegates_.erase(delegate); |
| 443 } | 445 } |
| 446 |
| 447 void TtsController::SetTtsEngineDelegate( |
| 448 TtsEngineDelegate* delegate) { |
| 449 tts_engine_delegate_ = delegate; |
| 450 } |
| OLD | NEW |