| 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/json/json_writer.h" | |
| 12 #include "base/values.h" | 11 #include "base/values.h" |
| 13 #include "chrome/browser/extensions/event_router.h" | |
| 14 #include "chrome/browser/extensions/extension_system.h" | 12 #include "chrome/browser/extensions/extension_system.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h" | 14 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h" |
| 17 #include "chrome/browser/speech/extension_api/tts_extension_api.h" | 15 #include "chrome/browser/speech/extension_api/tts_extension_api.h" |
| 18 #include "chrome/browser/speech/extension_api/tts_extension_api_constants.h" | 16 #include "chrome/browser/speech/extension_api/tts_extension_api_constants.h" |
| 19 #include "chrome/browser/speech/tts_platform.h" | 17 #include "chrome/browser/speech/tts_platform.h" |
| 20 #include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h" | 18 #include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h" |
| 21 #include "chrome/common/extensions/extension.h" | 19 #include "chrome/common/extensions/extension.h" |
| 22 | 20 |
| 23 namespace constants = tts_extension_api_constants; | 21 namespace constants = tts_extension_api_constants; |
| 24 | 22 |
| 25 namespace { | 23 namespace { |
| 26 | |
| 27 // A value to be used to indicate that there is no char index available. | 24 // A value to be used to indicate that there is no char index available. |
| 28 const int kInvalidCharIndex = -1; | 25 const int kInvalidCharIndex = -1; |
| 26 } // namespace |
| 29 | 27 |
| 30 namespace events { | |
| 31 const char kOnEvent[] = "tts.onEvent"; | |
| 32 }; // namespace events | |
| 33 | 28 |
| 34 std::string TtsEventTypeToString(TtsEventType event_type) { | 29 bool IsFinalTtsEventType(TtsEventType event_type) { |
| 35 switch (event_type) { | 30 return (event_type == TTS_EVENT_END || |
| 36 case TTS_EVENT_START: | 31 event_type == TTS_EVENT_INTERRUPTED || |
| 37 return constants::kEventTypeStart; | 32 event_type == TTS_EVENT_CANCELLED || |
| 38 case TTS_EVENT_END: | 33 event_type == TTS_EVENT_ERROR); |
| 39 return constants::kEventTypeEnd; | |
| 40 case TTS_EVENT_WORD: | |
| 41 return constants::kEventTypeWord; | |
| 42 case TTS_EVENT_SENTENCE: | |
| 43 return constants::kEventTypeSentence; | |
| 44 case TTS_EVENT_MARKER: | |
| 45 return constants::kEventTypeMarker; | |
| 46 case TTS_EVENT_INTERRUPTED: | |
| 47 return constants::kEventTypeInterrupted; | |
| 48 case TTS_EVENT_CANCELLED: | |
| 49 return constants::kEventTypeCancelled; | |
| 50 case TTS_EVENT_ERROR: | |
| 51 return constants::kEventTypeError; | |
| 52 default: | |
| 53 NOTREACHED(); | |
| 54 return std::string(); | |
| 55 } | |
| 56 } | 34 } |
| 57 | 35 |
| 58 } // namespace | |
| 59 | 36 |
| 60 // | 37 // |
| 61 // UtteranceContinuousParameters | 38 // UtteranceContinuousParameters |
| 62 // | 39 // |
| 63 | 40 |
| 64 | 41 |
| 65 UtteranceContinuousParameters::UtteranceContinuousParameters() | 42 UtteranceContinuousParameters::UtteranceContinuousParameters() |
| 66 : rate(-1), | 43 : rate(-1), |
| 67 pitch(-1), | 44 pitch(-1), |
| 68 volume(-1) {} | 45 volume(-1) {} |
| 69 | 46 |
| 70 | 47 |
| 71 // | 48 // |
| 49 // VoiceData |
| 50 // |
| 51 |
| 52 |
| 53 VoiceData::VoiceData() {} |
| 54 |
| 55 VoiceData::~VoiceData() {} |
| 56 |
| 57 |
| 58 // |
| 72 // Utterance | 59 // Utterance |
| 73 // | 60 // |
| 74 | 61 |
| 75 // static | 62 // static |
| 76 int Utterance::next_utterance_id_ = 0; | 63 int Utterance::next_utterance_id_ = 0; |
| 77 | 64 |
| 78 Utterance::Utterance(Profile* profile) | 65 Utterance::Utterance(Profile* profile) |
| 79 : profile_(profile), | 66 : profile_(profile), |
| 80 id_(next_utterance_id_++), | 67 id_(next_utterance_id_++), |
| 81 src_id_(-1), | 68 src_id_(-1), |
| 69 event_delegate_(NULL), |
| 82 can_enqueue_(false), | 70 can_enqueue_(false), |
| 83 char_index_(0), | 71 char_index_(0), |
| 84 finished_(false) { | 72 finished_(false) { |
| 85 options_.reset(new DictionaryValue()); | 73 options_.reset(new DictionaryValue()); |
| 86 } | 74 } |
| 87 | 75 |
| 88 Utterance::~Utterance() { | 76 Utterance::~Utterance() { |
| 89 DCHECK(finished_); | 77 DCHECK(finished_); |
| 90 } | 78 } |
| 91 | 79 |
| 92 void Utterance::OnTtsEvent(TtsEventType event_type, | 80 void Utterance::OnTtsEvent(TtsEventType event_type, |
| 93 int char_index, | 81 int char_index, |
| 94 const std::string& error_message) { | 82 const std::string& error_message) { |
| 95 std::string event_type_string = TtsEventTypeToString(event_type); | |
| 96 if (char_index >= 0) | 83 if (char_index >= 0) |
| 97 char_index_ = char_index; | 84 char_index_ = char_index; |
| 98 if (event_type == TTS_EVENT_END || | 85 if (IsFinalTtsEventType(event_type)) |
| 99 event_type == TTS_EVENT_INTERRUPTED || | |
| 100 event_type == TTS_EVENT_CANCELLED || | |
| 101 event_type == TTS_EVENT_ERROR) { | |
| 102 finished_ = true; | 86 finished_ = true; |
| 103 } | |
| 104 if (desired_event_types_.size() > 0 && | |
| 105 desired_event_types_.find(event_type_string) == | |
| 106 desired_event_types_.end()) { | |
| 107 return; | |
| 108 } | |
| 109 | 87 |
| 110 if (src_id_ < 0) | 88 if (event_delegate_) |
| 111 return; | 89 event_delegate_->OnTtsEvent(this, event_type, char_index, error_message); |
| 112 | 90 if (finished_) |
| 113 DictionaryValue* details = new DictionaryValue(); | 91 event_delegate_ = NULL; |
| 114 if (char_index != kInvalidCharIndex) | |
| 115 details->SetInteger(constants::kCharIndexKey, char_index); | |
| 116 details->SetString(constants::kEventTypeKey, event_type_string); | |
| 117 if (event_type == TTS_EVENT_ERROR) { | |
| 118 details->SetString(constants::kErrorMessageKey, error_message); | |
| 119 } | |
| 120 details->SetInteger(constants::kSrcIdKey, src_id_); | |
| 121 details->SetBoolean(constants::kIsFinalEventKey, finished_); | |
| 122 | |
| 123 scoped_ptr<ListValue> arguments(new ListValue()); | |
| 124 arguments->Set(0, details); | |
| 125 | |
| 126 scoped_ptr<extensions::Event> event(new extensions::Event( | |
| 127 events::kOnEvent, arguments.Pass())); | |
| 128 event->restrict_to_profile = profile_; | |
| 129 event->event_url = src_url_; | |
| 130 extensions::ExtensionSystem::Get(profile_)->event_router()-> | |
| 131 DispatchEventToExtension(src_extension_id_, event.Pass()); | |
| 132 } | 92 } |
| 133 | 93 |
| 134 void Utterance::Finish() { | 94 void Utterance::Finish() { |
| 135 finished_ = true; | 95 finished_ = true; |
| 136 } | 96 } |
| 137 | 97 |
| 138 void Utterance::set_options(const Value* options) { | 98 void Utterance::set_options(const Value* options) { |
| 139 options_.reset(options->DeepCopy()); | 99 options_.reset(options->DeepCopy()); |
| 140 } | 100 } |
| 141 | 101 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 if (!current_utterance_ || utterance_id != current_utterance_->id()) | 205 if (!current_utterance_ || utterance_id != current_utterance_->id()) |
| 246 return; | 206 return; |
| 247 | 207 |
| 248 current_utterance_->OnTtsEvent(event_type, char_index, error_message); | 208 current_utterance_->OnTtsEvent(event_type, char_index, error_message); |
| 249 if (current_utterance_->finished()) { | 209 if (current_utterance_->finished()) { |
| 250 FinishCurrentUtterance(); | 210 FinishCurrentUtterance(); |
| 251 SpeakNextUtterance(); | 211 SpeakNextUtterance(); |
| 252 } | 212 } |
| 253 } | 213 } |
| 254 | 214 |
| 255 ListValue* TtsController::GetVoices(Profile* profile) { | 215 void TtsController::GetVoices(Profile* profile, |
| 256 ListValue* result_voices = new ListValue(); | 216 std::vector<VoiceData>* out_voices) { |
| 257 TtsPlatformImpl* platform_impl = GetPlatformImpl(); | 217 TtsPlatformImpl* platform_impl = GetPlatformImpl(); |
| 258 if (platform_impl && platform_impl->PlatformImplAvailable()) { | 218 if (platform_impl && platform_impl->PlatformImplAvailable()) { |
| 259 DictionaryValue* result_voice = new DictionaryValue(); | 219 out_voices->push_back(VoiceData()); |
| 260 result_voice->SetString( | 220 VoiceData& voice = out_voices->back(); |
| 261 constants::kVoiceNameKey, constants::kNativeVoiceName); | 221 voice.name = constants::kNativeVoiceName; |
| 262 if (!platform_impl->gender().empty()) | 222 voice.gender = platform_impl->gender(); |
| 263 result_voice->SetString(constants::kGenderKey, platform_impl->gender()); | |
| 264 ListValue* event_types = new ListValue(); | |
| 265 | 223 |
| 266 // All platforms must send end events, and cancelled and interrupted | 224 // All platforms must send end events, and cancelled and interrupted |
| 267 // events are generated from the controller. | 225 // events are generated from the controller. |
| 268 DCHECK(platform_impl->SendsEvent(TTS_EVENT_END)); | 226 DCHECK(platform_impl->SendsEvent(TTS_EVENT_END)); |
| 269 event_types->Append(Value::CreateStringValue(constants::kEventTypeEnd)); | 227 voice.events.push_back(constants::kEventTypeEnd); |
| 270 event_types->Append(Value::CreateStringValue( | 228 voice.events.push_back(constants::kEventTypeCancelled); |
| 271 constants::kEventTypeCancelled)); | 229 voice.events.push_back(constants::kEventTypeInterrupted); |
| 272 event_types->Append(Value::CreateStringValue( | |
| 273 constants::kEventTypeInterrupted)); | |
| 274 | 230 |
| 275 if (platform_impl->SendsEvent(TTS_EVENT_START)) | 231 if (platform_impl->SendsEvent(TTS_EVENT_START)) |
| 276 event_types->Append(Value::CreateStringValue(constants::kEventTypeStart)); | 232 voice.events.push_back(constants::kEventTypeStart); |
| 277 if (platform_impl->SendsEvent(TTS_EVENT_WORD)) | 233 if (platform_impl->SendsEvent(TTS_EVENT_WORD)) |
| 278 event_types->Append(Value::CreateStringValue(constants::kEventTypeWord)); | 234 voice.events.push_back(constants::kEventTypeWord); |
| 279 if (platform_impl->SendsEvent(TTS_EVENT_SENTENCE)) | 235 if (platform_impl->SendsEvent(TTS_EVENT_SENTENCE)) |
| 280 event_types->Append(Value::CreateStringValue( | 236 voice.events.push_back(constants::kEventTypeSentence); |
| 281 constants::kEventTypeSentence)); | |
| 282 if (platform_impl->SendsEvent(TTS_EVENT_MARKER)) | 237 if (platform_impl->SendsEvent(TTS_EVENT_MARKER)) |
| 283 event_types->Append(Value::CreateStringValue( | 238 voice.events.push_back(constants::kEventTypeMarker); |
| 284 constants::kEventTypeMarker)); | |
| 285 if (platform_impl->SendsEvent(TTS_EVENT_ERROR)) | 239 if (platform_impl->SendsEvent(TTS_EVENT_ERROR)) |
| 286 event_types->Append(Value::CreateStringValue( | 240 voice.events.push_back(constants::kEventTypeError); |
| 287 constants::kEventTypeError)); | |
| 288 result_voice->Set(constants::kEventTypesKey, event_types); | |
| 289 result_voices->Append(result_voice); | |
| 290 } | 241 } |
| 291 | 242 |
| 292 GetExtensionVoices(profile, result_voices); | 243 GetExtensionVoices(profile, out_voices); |
| 293 | |
| 294 return result_voices; | |
| 295 } | 244 } |
| 296 | 245 |
| 297 bool TtsController::IsSpeaking() { | 246 bool TtsController::IsSpeaking() { |
| 298 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); | 247 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); |
| 299 } | 248 } |
| 300 | 249 |
| 301 void TtsController::FinishCurrentUtterance() { | 250 void TtsController::FinishCurrentUtterance() { |
| 302 if (current_utterance_) { | 251 if (current_utterance_) { |
| 303 if (!current_utterance_->finished()) | 252 if (!current_utterance_->finished()) |
| 304 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, | 253 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 | 292 |
| 344 int TtsController::QueueSize() { | 293 int TtsController::QueueSize() { |
| 345 return static_cast<int>(utterance_queue_.size()); | 294 return static_cast<int>(utterance_queue_.size()); |
| 346 } | 295 } |
| 347 | 296 |
| 348 TtsPlatformImpl* TtsController::GetPlatformImpl() { | 297 TtsPlatformImpl* TtsController::GetPlatformImpl() { |
| 349 if (!platform_impl_) | 298 if (!platform_impl_) |
| 350 platform_impl_ = TtsPlatformImpl::GetInstance(); | 299 platform_impl_ = TtsPlatformImpl::GetInstance(); |
| 351 return platform_impl_; | 300 return platform_impl_; |
| 352 } | 301 } |
| OLD | NEW |