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 WebKit::WebSpeechSynthesizerClient; 20 using WebKit::WebSpeechSynthesisUtterance; 21 using WebKit::WebSpeechSynthesisVoice; 22 using WebKit::WebString; 23 using WebKit::WebVector; 24 25 int TtsDispatcher::next_utterance_id_ = 1; 26 27 TtsDispatcher::TtsDispatcher(WebSpeechSynthesizerClient* client) 28 : synthesizer_client_(client) { 29 RenderThread::Get()->AddObserver(this); 30 } 31 32 TtsDispatcher::~TtsDispatcher() { 33 RenderThread::Get()->RemoveObserver(this); 34 } 35 36 bool TtsDispatcher::OnControlMessageReceived(const IPC::Message& message) { 37 bool handled = true; 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) 51 IPC_END_MESSAGE_MAP() 52 return handled; 53 } 54 55 void TtsDispatcher::updateVoiceList() { 56 RenderThread::Get()->Send(new TtsHostMsg_InitializeVoiceList()); 57 } 58 59 void TtsDispatcher::speak(const WebSpeechSynthesisUtterance& web_utterance) { 60 int id = next_utterance_id_++; 61 62 utterance_id_map_[id] = web_utterance; 63 64 TtsUtteranceRequest utterance; 65 utterance.id = id; 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)); 73 } 74 75 void TtsDispatcher::pause() { 76 RenderThread::Get()->Send(new TtsHostMsg_Pause()); 77 } 78 79 void TtsDispatcher::resume() { 80 RenderThread::Get()->Send(new TtsHostMsg_Resume()); 81 } 82 83 void TtsDispatcher::cancel() { 84 RenderThread::Get()->Send(new TtsHostMsg_Cancel()); 85 } 86 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(); 92 return iter->second; 93 } 94 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); 104 } 105 synthesizer_client_->setVoiceList(out_voices); 106 } 107 108 void TtsDispatcher::OnDidStartSpeaking(int utterance_id) { 109 if (utterance_id_map_.find(utterance_id) == utterance_id_map_.end()) 110 return; 111 112 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id); 113 if (utterance.isNull()) 114 return; 115 116 synthesizer_client_->didStartSpeaking(utterance); 117 } 118 119 void TtsDispatcher::OnDidFinishSpeaking(int utterance_id) { 120 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id); 121 if (utterance.isNull()) 122 return; 123 124 synthesizer_client_->didFinishSpeaking(utterance); 125 utterance_id_map_.erase(utterance_id); 126 } 127 128 void TtsDispatcher::OnDidPauseSpeaking(int utterance_id) { 129 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id); 130 if (utterance.isNull()) 131 return; 132 133 synthesizer_client_->didPauseSpeaking(utterance); 134 } 135 136 void TtsDispatcher::OnDidResumeSpeaking(int utterance_id) { 137 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id); 138 if (utterance.isNull()) 139 return; 140 141 synthesizer_client_->didResumeSpeaking(utterance); 142 } 143 144 void TtsDispatcher::OnWordBoundary(int utterance_id, int char_index) { 145 CHECK(char_index >= 0); 146 147 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id); 148 if (utterance.isNull()) 149 return; 150 151 synthesizer_client_->wordBoundaryEventOccurred( 152 utterance, static_cast<unsigned>(char_index)); 153 } 154 155 void TtsDispatcher::OnSentenceBoundary(int utterance_id, int char_index) { 156 CHECK(char_index >= 0); 157 158 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id); 159 if (utterance.isNull()) 160 return; 161 162 synthesizer_client_->sentenceBoundaryEventOccurred( 163 utterance, static_cast<unsigned>(char_index)); 164 } 165 166 void TtsDispatcher::OnMarkerEvent(int utterance_id, int char_index) { 167 // Not supported yet. 168 } 169 170 void TtsDispatcher::OnWasInterrupted(int utterance_id) { 171 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id); 172 if (utterance.isNull()) 173 return; 174 175 // The web speech API doesn't support "interrupted". 176 synthesizer_client_->didFinishSpeaking(utterance); 177 utterance_id_map_.erase(utterance_id); 178 } 179 180 void TtsDispatcher::OnWasCancelled(int utterance_id) { 181 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id); 182 if (utterance.isNull()) 183 return; 184 185 // The web speech API doesn't support "cancelled". 186 synthesizer_client_->didFinishSpeaking(utterance); 187 utterance_id_map_.erase(utterance_id); 188 } 189 190 void TtsDispatcher::OnSpeakingErrorOccurred(int utterance_id, 191 const std::string& error_message) { 192 WebSpeechSynthesisUtterance utterance = FindUtterance(utterance_id); 193 if (utterance.isNull()) 194 return; 195 196 // The web speech API doesn't support an error message. 197 synthesizer_client_->speakingErrorOccurred(utterance); 198 utterance_id_map_.erase(utterance_id); 199 } 200