• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "chrome/renderer/tts_dispatcher.h"
6 
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"
17 
18 using content::RenderThread;
19 using blink::WebSpeechSynthesizerClient;
20 using blink::WebSpeechSynthesisUtterance;
21 using blink::WebSpeechSynthesisVoice;
22 using blink::WebString;
23 using blink::WebVector;
24 
25 int TtsDispatcher::next_utterance_id_ = 1;
26 
TtsDispatcher(WebSpeechSynthesizerClient * client)27 TtsDispatcher::TtsDispatcher(WebSpeechSynthesizerClient* client)
28     : synthesizer_client_(client) {
29   RenderThread::Get()->AddObserver(this);
30 }
31 
~TtsDispatcher()32 TtsDispatcher::~TtsDispatcher() {
33   RenderThread::Get()->RemoveObserver(this);
34 }
35 
OnControlMessageReceived(const IPC::Message & message)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)
49   IPC_END_MESSAGE_MAP()
50 
51   // Always return false because there may be multiple TtsDispatchers
52   // and we want them all to have a chance to handle this message.
53   return false;
54 }
55 
updateVoiceList()56 void TtsDispatcher::updateVoiceList() {
57   RenderThread::Get()->Send(new TtsHostMsg_InitializeVoiceList());
58 }
59 
speak(const WebSpeechSynthesisUtterance & web_utterance)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 
pause()76 void TtsDispatcher::pause() {
77   RenderThread::Get()->Send(new TtsHostMsg_Pause());
78 }
79 
resume()80 void TtsDispatcher::resume() {
81   RenderThread::Get()->Send(new TtsHostMsg_Resume());
82 }
83 
cancel()84 void TtsDispatcher::cancel() {
85   RenderThread::Get()->Send(new TtsHostMsg_Cancel());
86 }
87 
FindUtterance(int utterance_id)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 
OnSetVoiceList(const std::vector<TtsVoice> & voices)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);
105   }
106   synthesizer_client_->setVoiceList(out_voices);
107 }
108 
OnDidStartSpeaking(int utterance_id)109 void TtsDispatcher::OnDidStartSpeaking(int utterance_id) {
110   if (utterance_id_map_.find(utterance_id) == utterance_id_map_.end())
111     return;
112 
113   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
114   if (utterance.isNull())
115     return;
116 
117   synthesizer_client_->didStartSpeaking(utterance);
118 }
119 
OnDidFinishSpeaking(int utterance_id)120 void TtsDispatcher::OnDidFinishSpeaking(int utterance_id) {
121   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
122   if (utterance.isNull())
123     return;
124 
125   synthesizer_client_->didFinishSpeaking(utterance);
126   utterance_id_map_.erase(utterance_id);
127 }
128 
OnDidPauseSpeaking(int utterance_id)129 void TtsDispatcher::OnDidPauseSpeaking(int utterance_id) {
130   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
131   if (utterance.isNull())
132     return;
133 
134   synthesizer_client_->didPauseSpeaking(utterance);
135 }
136 
OnDidResumeSpeaking(int utterance_id)137 void TtsDispatcher::OnDidResumeSpeaking(int utterance_id) {
138   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
139   if (utterance.isNull())
140     return;
141 
142   synthesizer_client_->didResumeSpeaking(utterance);
143 }
144 
OnWordBoundary(int utterance_id,int char_index)145 void TtsDispatcher::OnWordBoundary(int utterance_id, int char_index) {
146   CHECK(char_index >= 0);
147 
148   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
149   if (utterance.isNull())
150     return;
151 
152   synthesizer_client_->wordBoundaryEventOccurred(
153       utterance, static_cast<unsigned>(char_index));
154 }
155 
OnSentenceBoundary(int utterance_id,int char_index)156 void TtsDispatcher::OnSentenceBoundary(int utterance_id, int char_index) {
157   CHECK(char_index >= 0);
158 
159   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
160   if (utterance.isNull())
161     return;
162 
163   synthesizer_client_->sentenceBoundaryEventOccurred(
164       utterance, static_cast<unsigned>(char_index));
165 }
166 
OnMarkerEvent(int utterance_id,int char_index)167 void TtsDispatcher::OnMarkerEvent(int utterance_id, int char_index) {
168   // Not supported yet.
169 }
170 
OnWasInterrupted(int utterance_id)171 void TtsDispatcher::OnWasInterrupted(int utterance_id) {
172   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
173   if (utterance.isNull())
174     return;
175 
176   // The web speech API doesn't support "interrupted".
177   synthesizer_client_->didFinishSpeaking(utterance);
178   utterance_id_map_.erase(utterance_id);
179 }
180 
OnWasCancelled(int utterance_id)181 void TtsDispatcher::OnWasCancelled(int utterance_id) {
182   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
183   if (utterance.isNull())
184     return;
185 
186   // The web speech API doesn't support "cancelled".
187   synthesizer_client_->didFinishSpeaking(utterance);
188   utterance_id_map_.erase(utterance_id);
189 }
190 
OnSpeakingErrorOccurred(int utterance_id,const std::string & error_message)191 void TtsDispatcher::OnSpeakingErrorOccurred(int utterance_id,
192                                             const std::string& error_message) {
193   WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id);
194   if (utterance.isNull())
195     return;
196 
197   // The web speech API doesn't support an error message.
198   synthesizer_client_->speakingErrorOccurred(utterance);
199   utterance_id_map_.erase(utterance_id);
200 }
201