Home | History | Annotate | Download | only in renderer
      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 
     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   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 
     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(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 
    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 
    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 
    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 
    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 
    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 
    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 
    167 void TtsDispatcher::OnMarkerEvent(int utterance_id, int char_index) {
    168   // Not supported yet.
    169 }
    170 
    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 
    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 
    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