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 WebKit::WebSpeechSynthesizerClient
;
20 using WebKit::WebSpeechSynthesisUtterance
;
21 using WebKit::WebSpeechSynthesisVoice
;
22 using WebKit::WebString
;
23 using WebKit::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
) {
38 IPC_BEGIN_MESSAGE_MAP(TtsDispatcher
, message
)
39 IPC_MESSAGE_HANDLER(TtsMsg_SetVoiceList
, OnSetVoiceList
)
40 IPC_MESSAGE_HANDLER(TtsMsg_DidStartSpeaking
, OnDidStartSpeaking
)
41 IPC_MESSAGE_HANDLER(TtsMsg_DidFinishSpeaking
, OnDidFinishSpeaking
)
42 IPC_MESSAGE_HANDLER(TtsMsg_DidPauseSpeaking
, OnDidPauseSpeaking
)
43 IPC_MESSAGE_HANDLER(TtsMsg_DidResumeSpeaking
, OnDidResumeSpeaking
)
44 IPC_MESSAGE_HANDLER(TtsMsg_WordBoundary
, OnWordBoundary
)
45 IPC_MESSAGE_HANDLER(TtsMsg_SentenceBoundary
, OnSentenceBoundary
)
46 IPC_MESSAGE_HANDLER(TtsMsg_MarkerEvent
, OnMarkerEvent
)
47 IPC_MESSAGE_HANDLER(TtsMsg_WasInterrupted
, OnWasInterrupted
)
48 IPC_MESSAGE_HANDLER(TtsMsg_WasCancelled
, OnWasCancelled
)
49 IPC_MESSAGE_HANDLER(TtsMsg_SpeakingErrorOccurred
, OnSpeakingErrorOccurred
)
50 IPC_MESSAGE_UNHANDLED(handled
= false)
55 void TtsDispatcher::updateVoiceList() {
56 RenderThread::Get()->Send(new TtsHostMsg_InitializeVoiceList());
59 void TtsDispatcher::speak(const WebSpeechSynthesisUtterance
& web_utterance
) {
60 int id
= next_utterance_id_
++;
62 utterance_id_map_
[id
] = web_utterance
;
64 TtsUtteranceRequest utterance
;
66 utterance
.text
= web_utterance
.text().utf8();
67 utterance
.lang
= web_utterance
.lang().utf8();
68 utterance
.voice
= web_utterance
.voice().utf8();
69 utterance
.volume
= web_utterance
.volume();
70 utterance
.rate
= web_utterance
.rate();
71 utterance
.pitch
= web_utterance
.pitch();
72 RenderThread::Get()->Send(new TtsHostMsg_Speak(utterance
));
75 void TtsDispatcher::pause() {
76 RenderThread::Get()->Send(new TtsHostMsg_Pause());
79 void TtsDispatcher::resume() {
80 RenderThread::Get()->Send(new TtsHostMsg_Resume());
83 void TtsDispatcher::cancel() {
84 RenderThread::Get()->Send(new TtsHostMsg_Cancel());
87 WebSpeechSynthesisUtterance
TtsDispatcher::FindUtterance(int utterance_id
) {
88 base::hash_map
<int, WebSpeechSynthesisUtterance
>::const_iterator iter
=
89 utterance_id_map_
.find(utterance_id
);
90 if (iter
== utterance_id_map_
.end())
91 return WebSpeechSynthesisUtterance();
95 void TtsDispatcher::OnSetVoiceList(const std::vector
<TtsVoice
>& voices
) {
96 WebVector
<WebSpeechSynthesisVoice
> out_voices(voices
.size());
97 for (size_t i
= 0; i
< voices
.size(); ++i
) {
98 out_voices
[i
] = WebSpeechSynthesisVoice();
99 out_voices
[i
].setVoiceURI(WebString::fromUTF8(voices
[i
].voice_uri
));
100 out_voices
[i
].setName(WebString::fromUTF8(voices
[i
].name
));
101 out_voices
[i
].setLanguage(WebString::fromUTF8(voices
[i
].lang
));
102 out_voices
[i
].setIsLocalService(voices
[i
].local_service
);
103 out_voices
[i
].setIsDefault(voices
[i
].is_default
);
105 synthesizer_client_
->setVoiceList(out_voices
);
108 void TtsDispatcher::OnDidStartSpeaking(int utterance_id
) {
109 if (utterance_id_map_
.find(utterance_id
) == utterance_id_map_
.end())
112 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
113 if (utterance
.isNull())
116 synthesizer_client_
->didStartSpeaking(utterance
);
119 void TtsDispatcher::OnDidFinishSpeaking(int utterance_id
) {
120 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
121 if (utterance
.isNull())
124 synthesizer_client_
->didFinishSpeaking(utterance
);
125 utterance_id_map_
.erase(utterance_id
);
128 void TtsDispatcher::OnDidPauseSpeaking(int utterance_id
) {
129 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
130 if (utterance
.isNull())
133 synthesizer_client_
->didPauseSpeaking(utterance
);
136 void TtsDispatcher::OnDidResumeSpeaking(int utterance_id
) {
137 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
138 if (utterance
.isNull())
141 synthesizer_client_
->didResumeSpeaking(utterance
);
144 void TtsDispatcher::OnWordBoundary(int utterance_id
, int char_index
) {
145 CHECK(char_index
>= 0);
147 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
148 if (utterance
.isNull())
151 synthesizer_client_
->wordBoundaryEventOccurred(
152 utterance
, static_cast<unsigned>(char_index
));
155 void TtsDispatcher::OnSentenceBoundary(int utterance_id
, int char_index
) {
156 CHECK(char_index
>= 0);
158 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
159 if (utterance
.isNull())
162 synthesizer_client_
->sentenceBoundaryEventOccurred(
163 utterance
, static_cast<unsigned>(char_index
));
166 void TtsDispatcher::OnMarkerEvent(int utterance_id
, int char_index
) {
167 // Not supported yet.
170 void TtsDispatcher::OnWasInterrupted(int utterance_id
) {
171 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
172 if (utterance
.isNull())
175 // The web speech API doesn't support "interrupted".
176 synthesizer_client_
->didFinishSpeaking(utterance
);
177 utterance_id_map_
.erase(utterance_id
);
180 void TtsDispatcher::OnWasCancelled(int utterance_id
) {
181 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
182 if (utterance
.isNull())
185 // The web speech API doesn't support "cancelled".
186 synthesizer_client_
->didFinishSpeaking(utterance
);
187 utterance_id_map_
.erase(utterance_id
);
190 void TtsDispatcher::OnSpeakingErrorOccurred(int utterance_id
,
191 const std::string
& error_message
) {
192 WebSpeechSynthesisUtterance utterance
= FindUtterance(utterance_id
);
193 if (utterance
.isNull())
196 // The web speech API doesn't support an error message.
197 synthesizer_client_
->speakingErrorOccurred(utterance
);
198 utterance_id_map_
.erase(utterance_id
);