Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: chrome/browser/speech/tts_controller.cc

Issue 12589005: Implement web speech synthesis. (Closed) Base URL: http://git.chromium.org/chromium/src.git@webtts
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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);
tommi (sloooow) - chröme 2013/03/07 13:04:46 if finished_ is true, then should we set the event
dmazzoni 2013/03/19 17:30:22 Good idea, done.
112
113 DictionaryValue* details = new DictionaryValue();
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 } 90 }
133 91
134 void Utterance::Finish() { 92 void Utterance::Finish() {
135 finished_ = true; 93 finished_ = true;
136 } 94 }
137 95
138 void Utterance::set_options(const Value* options) { 96 void Utterance::set_options(const Value* options) {
139 options_.reset(options->DeepCopy()); 97 options_.reset(options->DeepCopy());
140 } 98 }
141 99
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 if (!current_utterance_ || utterance_id != current_utterance_->id()) 203 if (!current_utterance_ || utterance_id != current_utterance_->id())
246 return; 204 return;
247 205
248 current_utterance_->OnTtsEvent(event_type, char_index, error_message); 206 current_utterance_->OnTtsEvent(event_type, char_index, error_message);
249 if (current_utterance_->finished()) { 207 if (current_utterance_->finished()) {
250 FinishCurrentUtterance(); 208 FinishCurrentUtterance();
251 SpeakNextUtterance(); 209 SpeakNextUtterance();
252 } 210 }
253 } 211 }
254 212
255 ListValue* TtsController::GetVoices(Profile* profile) { 213 void TtsController::GetVoices(Profile* profile,
256 ListValue* result_voices = new ListValue(); 214 std::vector<VoiceData>* out_voices) {
257 TtsPlatformImpl* platform_impl = GetPlatformImpl(); 215 TtsPlatformImpl* platform_impl = GetPlatformImpl();
258 if (platform_impl && platform_impl->PlatformImplAvailable()) { 216 if (platform_impl && platform_impl->PlatformImplAvailable()) {
hans 2013/03/09 14:19:52 maybe return early instead when this false? oh, n
259 DictionaryValue* result_voice = new DictionaryValue(); 217 out_voices->push_back(VoiceData());
260 result_voice->SetString( 218 VoiceData* voice = &out_voices->back();
hans 2013/03/09 14:19:52 i would have gone for a reference here, but no big
dmazzoni 2013/03/19 17:30:22 Done.
261 constants::kVoiceNameKey, constants::kNativeVoiceName); 219 voice->name = constants::kNativeVoiceName;
262 if (!platform_impl->gender().empty()) 220 voice->gender = platform_impl->gender();
263 result_voice->SetString(constants::kGenderKey, platform_impl->gender());
264 ListValue* event_types = new ListValue();
265 221
266 // All platforms must send end events, and cancelled and interrupted 222 // All platforms must send end events, and cancelled and interrupted
267 // events are generated from the controller. 223 // events are generated from the controller.
268 DCHECK(platform_impl->SendsEvent(TTS_EVENT_END)); 224 DCHECK(platform_impl->SendsEvent(TTS_EVENT_END));
269 event_types->Append(Value::CreateStringValue(constants::kEventTypeEnd)); 225 voice->events.push_back(constants::kEventTypeEnd);
270 event_types->Append(Value::CreateStringValue( 226 voice->events.push_back(constants::kEventTypeCancelled);
271 constants::kEventTypeCancelled)); 227 voice->events.push_back(constants::kEventTypeInterrupted);
272 event_types->Append(Value::CreateStringValue(
273 constants::kEventTypeInterrupted));
274 228
275 if (platform_impl->SendsEvent(TTS_EVENT_START)) 229 if (platform_impl->SendsEvent(TTS_EVENT_START))
276 event_types->Append(Value::CreateStringValue(constants::kEventTypeStart)); 230 voice->events.push_back(constants::kEventTypeStart);
277 if (platform_impl->SendsEvent(TTS_EVENT_WORD)) 231 if (platform_impl->SendsEvent(TTS_EVENT_WORD))
278 event_types->Append(Value::CreateStringValue(constants::kEventTypeWord)); 232 voice->events.push_back(constants::kEventTypeWord);
279 if (platform_impl->SendsEvent(TTS_EVENT_SENTENCE)) 233 if (platform_impl->SendsEvent(TTS_EVENT_SENTENCE))
280 event_types->Append(Value::CreateStringValue( 234 voice->events.push_back(constants::kEventTypeSentence);
281 constants::kEventTypeSentence));
282 if (platform_impl->SendsEvent(TTS_EVENT_MARKER)) 235 if (platform_impl->SendsEvent(TTS_EVENT_MARKER))
283 event_types->Append(Value::CreateStringValue( 236 voice->events.push_back(constants::kEventTypeMarker);
284 constants::kEventTypeMarker));
285 if (platform_impl->SendsEvent(TTS_EVENT_ERROR)) 237 if (platform_impl->SendsEvent(TTS_EVENT_ERROR))
286 event_types->Append(Value::CreateStringValue( 238 voice->events.push_back(constants::kEventTypeError);
287 constants::kEventTypeError));
288 result_voice->Set(constants::kEventTypesKey, event_types);
289 result_voices->Append(result_voice);
290 } 239 }
291 240
292 GetExtensionVoices(profile, result_voices); 241 GetExtensionVoices(profile, out_voices);
293
294 return result_voices;
295 } 242 }
296 243
297 bool TtsController::IsSpeaking() { 244 bool TtsController::IsSpeaking() {
298 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking(); 245 return current_utterance_ != NULL || GetPlatformImpl()->IsSpeaking();
299 } 246 }
300 247
301 void TtsController::FinishCurrentUtterance() { 248 void TtsController::FinishCurrentUtterance() {
302 if (current_utterance_) { 249 if (current_utterance_) {
303 if (!current_utterance_->finished()) 250 if (!current_utterance_->finished())
304 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, 251 current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 290
344 int TtsController::QueueSize() { 291 int TtsController::QueueSize() {
345 return static_cast<int>(utterance_queue_.size()); 292 return static_cast<int>(utterance_queue_.size());
346 } 293 }
347 294
348 TtsPlatformImpl* TtsController::GetPlatformImpl() { 295 TtsPlatformImpl* TtsController::GetPlatformImpl() {
349 if (!platform_impl_) 296 if (!platform_impl_)
350 platform_impl_ = TtsPlatformImpl::GetInstance(); 297 platform_impl_ = TtsPlatformImpl::GetInstance();
351 return platform_impl_; 298 return platform_impl_;
352 } 299 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698