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.
5 #include "chrome/renderer/tts_dispatcher.h"
7 #include "base/basictypes.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/common/tts_messages.h"
10 #include "chrome/common/tts_utterance_request.h"
11 #include "content/public/renderer/render_thread.h"
12 #include "third_party/WebKit/public/platform/WebCString.h"
13 #include "third_party/WebKit/public/platform/WebSpeechSynthesisUtterance.h"
14 #include "third_party/WebKit/public/platform/WebSpeechSynthesisVoice.h"
15 #include "third_party/WebKit/public/platform/WebString.h"
16 #include "third_party/WebKit/public/platform/WebVector.h"
18 using content::RenderThread
;
19 using blink::WebSpeechSynthesizerClient
;
20 using blink::WebSpeechSynthesisUtterance
;
21 using blink::WebSpeechSynthesisVoice
;
22 using blink::WebString
;
23 using blink::WebVector
;
25 int TtsDispatcher::next_utterance_id_
= 1;
27 TtsDispatcher::TtsDispatcher(WebSpeechSynthesizerClient
* client
)
28 : synthesizer_client_(client
) {
29 RenderThread::Get()->AddObserver(this);
32 TtsDispatcher::~TtsDispatcher() {
33 RenderThread::Get()->RemoveObserver(this);
36 bool TtsDispatcher::OnControlMessageReceived(const IPC::Message
& message
) {
37 IPC_BEGIN_MESSAGE_MAP(TtsDispatcher
, message
)
38 IPC_MESSAGE_HANDLER(TtsMsg_SetVoiceList
, OnSetVoiceList
)
39 IPC_MESSAGE_HANDLER(TtsMsg_DidStartSpeaking
, OnDidStartSpeaking
)
40 IPC_MESSAGE_HANDLER(TtsMsg_DidFinishSpeaking
, OnDidFinishSpeaking
)
41 IPC_MESSAGE_HANDLER(TtsMsg_DidPauseSpeaking
, OnDidPauseSpeaking
)
42 IPC_MESSAGE_HANDLER(TtsMsg_DidResumeSpeaking
, OnDidResumeSpeaking
)
43 IPC_MESSAGE_HANDLER(TtsMsg_WordBoundary
, OnWordBoundary
)
44 IPC_MESSAGE_HANDLER(TtsMsg_SentenceBoundary
, OnSentenceBoundary
)
45 IPC_MESSAGE_HANDLER(TtsMsg_MarkerEvent
, OnMarkerEvent
)
46 IPC_MESSAGE_HANDLER(TtsMsg_WasInterrupted
, OnWasInterrupted
)
47 IPC_MESSAGE_HANDLER(TtsMsg_WasCancelled
, OnWasCancelled
)
48 IPC_MESSAGE_HANDLER(TtsMsg_SpeakingErrorOccurred
, OnSpeakingErrorOccurred
)
51 // Always return false because there may be multiple TtsDispatchers
52 // and we want them all to have a chance to handle this message.
56 void TtsDispatcher::updateVoiceList() {
57 RenderThread::Get()->Send(new TtsHostMsg_InitializeVoiceList());
60 void TtsDispatcher::speak(const WebSpeechSynthesisUtterance
& web_utterance
) {
61 int id
= next_utterance_id_
++;
63 utterance_id_map_
[id
] = web_utterance
;
65 TtsUtteranceRequest utterance
;
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
));
76 void TtsDispatcher::pause() {
77 RenderThread::Get()->Send(new TtsHostMsg_Pause());
80 void TtsDispatcher::resume() {
81 RenderThread::Get()->Send(new TtsHostMsg_Resume());
84 void TtsDispatcher::cancel() {
85 RenderThread::Get()->Send(new TtsHostMsg_Cancel());
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();
96 void TtsDispatcher::OnSetVoiceList(const std::vector
<TtsVoice
>& voices
) {
97 WebVector
<WebSpeechSynthesisVoice
> out_voices(voices
.size());
98 for (size_t i
= 0; i
< voices
.size(); ++i
) {
99 out_voices
[i
] = WebSpeechSynthesisVoice();
100 out_voices
[i
].setVoiceURI(WebString::fromUTF8(voices
[i
].voice_uri
));
101 out_voices
[i
].setName(WebString::fromUTF8(voices
[i
].name
));
102 out_voices
[i
].setLanguage(WebString::fromUTF8(voices
[i
].lang
));
103 out_voices
[i
].setIsLocalService(voices
[i
].local_service
);
104 out_voices
[i
].setIsDefault(voices
[i
].is_default
);
106 synthesizer_client_
->setVoiceList(out_voices
);
109 void TtsDispatcher::OnDidStartSpeaking(int utterance_id
) {
110 if (utterance_id_map_
.find(utterance_id
) == utterance_id_map_
.end())
113 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
114 if (utterance
.isNull())
117 synthesizer_client_
->didStartSpeaking(utterance
);
120 void TtsDispatcher::OnDidFinishSpeaking(int utterance_id
) {
121 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
122 if (utterance
.isNull())
125 synthesizer_client_
->didFinishSpeaking(utterance
);
126 utterance_id_map_
.erase(utterance_id
);
129 void TtsDispatcher::OnDidPauseSpeaking(int utterance_id
) {
130 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
131 if (utterance
.isNull())
134 synthesizer_client_
->didPauseSpeaking(utterance
);
137 void TtsDispatcher::OnDidResumeSpeaking(int utterance_id
) {
138 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
139 if (utterance
.isNull())
142 synthesizer_client_
->didResumeSpeaking(utterance
);
145 void TtsDispatcher::OnWordBoundary(int utterance_id
, int char_index
) {
146 CHECK(char_index
>= 0);
148 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
149 if (utterance
.isNull())
152 synthesizer_client_
->wordBoundaryEventOccurred(
153 utterance
, static_cast<unsigned>(char_index
));
156 void TtsDispatcher::OnSentenceBoundary(int utterance_id
, int char_index
) {
157 CHECK(char_index
>= 0);
159 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
160 if (utterance
.isNull())
163 synthesizer_client_
->sentenceBoundaryEventOccurred(
164 utterance
, static_cast<unsigned>(char_index
));
167 void TtsDispatcher::OnMarkerEvent(int utterance_id
, int char_index
) {
168 // Not supported yet.
171 void TtsDispatcher::OnWasInterrupted(int utterance_id
) {
172 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
173 if (utterance
.isNull())
176 // The web speech API doesn't support "interrupted".
177 synthesizer_client_
->didFinishSpeaking(utterance
);
178 utterance_id_map_
.erase(utterance_id
);
181 void TtsDispatcher::OnWasCancelled(int utterance_id
) {
182 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
183 if (utterance
.isNull())
186 // The web speech API doesn't support "cancelled".
187 synthesizer_client_
->didFinishSpeaking(utterance
);
188 utterance_id_map_
.erase(utterance_id
);
191 void TtsDispatcher::OnSpeakingErrorOccurred(int utterance_id
,
192 const std::string
& error_message
) {
193 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
194 if (utterance
.isNull())
197 // The web speech API doesn't support an error message.
198 synthesizer_client_
->speakingErrorOccurred(utterance
);
199 utterance_id_map_
.erase(utterance_id
);