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

Side by Side Diff: content/renderer/tts_dispatcher.cc

Issue 12589005: Implement web speech synthesis. (Closed) Base URL: http://git.chromium.org/chromium/src.git@webtts
Patch Set: Fresh update 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
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/tts_dispatcher.h"
6
7 #include "base/basictypes.h"
8 #include "base/utf_string_conversions.h"
9 #include "content/common/tts_messages.h"
10 #include "content/public/common/tts_utterance_request.h"
11 #include "content/renderer/render_thread_impl.h"
12 #include "content/renderer/render_view_impl.h"
13 #include "third_party/WebKit/Source/Platform/chromium/public/WebSpeechSynthesisU tterance.h"
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebSpeechSynthesisV oice.h"
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
16 #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
17
18 using WebKit::WebSpeechSynthesizerClient;
19 using WebKit::WebSpeechSynthesisUtterance;
20 using WebKit::WebSpeechSynthesisVoice;
21 using WebKit::WebString;
22 using WebKit::WebVector;
23
24 namespace content {
25
26 int TtsDispatcher::next_utterance_id_ = 1;
27
28 TtsDispatcher::TtsDispatcher(WebSpeechSynthesizerClient* client)
29 : synthesizer_client_(client),
30 main_loop_(base::MessageLoopProxy::current()) {
31 RenderThread::Get()->AddFilter(this);
32 }
33
34 TtsDispatcher::~TtsDispatcher() {
35 }
36
37 bool TtsDispatcher::OnMessageReceived(const IPC::Message& message) {
38 bool handled = true;
39 IPC_BEGIN_MESSAGE_MAP(TtsDispatcher, message)
40 IPC_MESSAGE_HANDLER(TtsMsg_SetVoiceList, OnSetVoiceList)
41 IPC_MESSAGE_HANDLER(TtsMsg_DidStartSpeaking, OnDidStartSpeaking)
42 IPC_MESSAGE_HANDLER(TtsMsg_DidFinishSpeaking, OnDidFinishSpeaking)
43 IPC_MESSAGE_HANDLER(TtsMsg_DidPauseSpeaking, OnDidPauseSpeaking)
44 IPC_MESSAGE_HANDLER(TtsMsg_DidResumeSpeaking, OnDidResumeSpeaking)
45 IPC_MESSAGE_HANDLER(TtsMsg_WordBoundary, OnWordBoundary)
46 IPC_MESSAGE_HANDLER(TtsMsg_SentenceBoundary, OnSentenceBoundary)
47 IPC_MESSAGE_HANDLER(TtsMsg_MarkerEvent, OnMarkerEvent)
48 IPC_MESSAGE_HANDLER(TtsMsg_WasInterrupted, OnWasInterrupted)
49 IPC_MESSAGE_HANDLER(TtsMsg_WasCancelled, OnWasCancelled)
50 IPC_MESSAGE_HANDLER(TtsMsg_SpeakingErrorOccurred, OnSpeakingErrorOccurred)
51 IPC_MESSAGE_UNHANDLED(handled = false)
52 IPC_END_MESSAGE_MAP()
53 return handled;
54 }
55
56 void TtsDispatcher::updateVoiceList() {
57 RenderThread::Get()->Send(new TtsHostMsg_InitializeVoiceList());
58 }
59
60 void TtsDispatcher::speak(const WebSpeechSynthesisUtterance& web_utterance) {
61 int id = next_utterance_id_++;
62
63 utterance_id_map_[id] = web_utterance;
64
65 TtsUtteranceRequest utterance;
66 utterance.id = id;
67 utterance.text = web_utterance.text().utf8();
68 utterance.lang = web_utterance.lang().utf8();
69 utterance.voice = web_utterance.voice().utf8();
70 utterance.volume = web_utterance.volume();
71 utterance.rate = web_utterance.rate();
72 utterance.pitch = web_utterance.pitch();
73 RenderThread::Get()->Send(new TtsHostMsg_Speak(utterance));
74 }
75
76 void TtsDispatcher::pause() {
77 RenderThread::Get()->Send(new TtsHostMsg_Pause());
78 }
79
80 void TtsDispatcher::resume() {
81 RenderThread::Get()->Send(new TtsHostMsg_Resume());
82 }
83
84 void TtsDispatcher::cancel() {
85 RenderThread::Get()->Send(new TtsHostMsg_Cancel());
86 }
87
88 WebSpeechSynthesisUtterance TtsDispatcher::FindUtterance(int utterance_id) {
89 base::hash_map<int, WebSpeechSynthesisUtterance>::const_iterator iter =
90 utterance_id_map_.find(utterance_id);
91 if (iter == utterance_id_map_.end())
92 return WebSpeechSynthesisUtterance();
93 return iter->second;
94 }
95
96 void TtsDispatcher::OnSetVoiceList(
97 const std::vector<content::TtsVoice>& voices) {
98 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
99 main_loop_->PostTask(
100 FROM_HERE, base::Bind(&TtsDispatcher::OnSetVoiceList, this, voices));
101 return;
102 }
103
104 WebVector<WebSpeechSynthesisVoice> out_voices(voices.size());
105 for (size_t i = 0; i < voices.size(); ++i) {
106 out_voices[i] = WebSpeechSynthesisVoice();
107 out_voices[i].setVoiceURI(WebString::fromUTF8(voices[i].voice_uri));
108 out_voices[i].setName(WebString::fromUTF8(voices[i].name));
109 out_voices[i].setLanguage(WebString::fromUTF8(voices[i].lang));
110 out_voices[i].setIsLocalService(voices[i].local_service);
111 out_voices[i].setIsDefault(voices[i].is_default);
112 }
113 synthesizer_client_->setVoiceList(out_voices);
114 }
115
116 void TtsDispatcher::OnDidStartSpeaking(int utterance_id) {
117 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
118 main_loop_->PostTask(
119 FROM_HERE, base::Bind(&TtsDispatcher::OnDidStartSpeaking, this,
120 utterance_id));
121 return;
122 }
123
124 if (utterance_id_map_.find(utterance_id) == utterance_id_map_.end())
125 return;
126
127 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
128 if (utterance.isNull())
129 return;
130
131 synthesizer_client_->didStartSpeaking(utterance);
132 }
133
134 void TtsDispatcher::OnDidFinishSpeaking(int utterance_id) {
135 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
136 main_loop_->PostTask(
137 FROM_HERE, base::Bind(&TtsDispatcher::OnDidFinishSpeaking, this,
138 utterance_id));
139 return;
140 }
141
142 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
143 if (utterance.isNull())
144 return;
145
146 synthesizer_client_->didFinishSpeaking(utterance);
147 utterance_id_map_.erase(utterance_id);
148 }
149
150 void TtsDispatcher::OnDidPauseSpeaking(int utterance_id) {
151 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
152 main_loop_->PostTask(
153 FROM_HERE, base::Bind(&TtsDispatcher::OnDidPauseSpeaking, this,
154 utterance_id));
155 return;
156 }
157
158 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
159 if (utterance.isNull())
160 return;
161
162 synthesizer_client_->didPauseSpeaking(utterance);
163 }
164
165 void TtsDispatcher::OnDidResumeSpeaking(int utterance_id) {
166 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
167 main_loop_->PostTask(
168 FROM_HERE, base::Bind(&TtsDispatcher::OnDidResumeSpeaking, this,
169 utterance_id));
170 return;
171 }
172
173 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
174 if (utterance.isNull())
175 return;
176
177 synthesizer_client_->didResumeSpeaking(utterance);
178 }
179
180 void TtsDispatcher::OnWordBoundary(int utterance_id, int char_index) {
181 CHECK(char_index >= 0);
182 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
183 main_loop_->PostTask(
184 FROM_HERE, base::Bind(&TtsDispatcher::OnWordBoundary, this,
185 utterance_id, char_index));
186 return;
187 }
188
189 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
190 if (utterance.isNull())
191 return;
192
193 synthesizer_client_->wordBoundaryEventOccurred(
194 utterance, static_cast<unsigned>(char_index));
195 }
196
197 void TtsDispatcher::OnSentenceBoundary(int utterance_id, int char_index) {
198 CHECK(char_index >= 0);
199 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
200 main_loop_->PostTask(
201 FROM_HERE, base::Bind(&TtsDispatcher::OnSentenceBoundary, this,
202 utterance_id, char_index));
203 return;
204 }
205
206 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
207 if (utterance.isNull())
208 return;
209
210 synthesizer_client_->sentenceBoundaryEventOccurred(
211 utterance, static_cast<unsigned>(char_index));
212 }
213
214 void TtsDispatcher::OnMarkerEvent(int utterance_id, int char_index) {
215 // Not supported yet.
216 }
217
218 void TtsDispatcher::OnWasInterrupted(int utterance_id) {
219 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
220 main_loop_->PostTask(
221 FROM_HERE, base::Bind(&TtsDispatcher::OnWasInterrupted, this,
222 utterance_id));
223 return;
224 }
225
226 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
227 if (utterance.isNull())
228 return;
229
230 // The web speech API doesn't support "interrupted".
231 synthesizer_client_->didFinishSpeaking(utterance);
232 utterance_id_map_.erase(utterance_id);
233 }
234
235 void TtsDispatcher::OnWasCancelled(int utterance_id) {
236 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
237 main_loop_->PostTask(
238 FROM_HERE, base::Bind(&TtsDispatcher::OnWasCancelled, this,
239 utterance_id));
240 return;
241 }
242
243 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
244 if (utterance.isNull())
245 return;
246
247 // The web speech API doesn't support "cancelled".
248 synthesizer_client_->didFinishSpeaking(utterance);
249 utterance_id_map_.erase(utterance_id);
250 }
251
252 void TtsDispatcher::OnSpeakingErrorOccurred(int utterance_id,
253 const std::string& error_message) {
254 if (MessageLoop::current() == ChildProcess::current()->io_message_loop()) {
255 main_loop_->PostTask(
256 FROM_HERE, base::Bind(&TtsDispatcher::OnSpeakingErrorOccurred, this,
257 utterance_id, error_message));
258 return;
259 }
260
261 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
262 if (utterance.isNull())
263 return;
264
265 // The web speech API doesn't support an error message.
266 synthesizer_client_->speakingErrorOccurred(utterance);
267 utterance_id_map_.erase(utterance_id);
268 }
269
270
271 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698