Home | History | Annotate | Download | only in speech
      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/browser/speech/tts_message_filter.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "content/public/browser/browser_context.h"
     10 #include "content/public/browser/render_process_host.h"
     11 
     12 using content::BrowserThread;
     13 
     14 TtsMessageFilter::TtsMessageFilter(int render_process_id,
     15                                    content::BrowserContext* browser_context)
     16     : BrowserMessageFilter(TtsMsgStart),
     17       render_process_id_(render_process_id),
     18       browser_context_(browser_context),
     19       weak_ptr_factory_(this) {
     20   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     21   TtsController::GetInstance()->AddVoicesChangedDelegate(this);
     22 
     23   // Balanced in OnChannelClosingInUIThread() to keep the ref-count be non-zero
     24   // until all WeakPtr's are invalidated.
     25   AddRef();
     26 }
     27 
     28 void TtsMessageFilter::OverrideThreadForMessage(
     29     const IPC::Message& message, BrowserThread::ID* thread) {
     30   switch (message.type()) {
     31   case TtsHostMsg_InitializeVoiceList::ID:
     32   case TtsHostMsg_Speak::ID:
     33   case TtsHostMsg_Pause::ID:
     34   case TtsHostMsg_Resume::ID:
     35   case TtsHostMsg_Cancel::ID:
     36     *thread = BrowserThread::UI;
     37     break;
     38   }
     39 }
     40 
     41 bool TtsMessageFilter::OnMessageReceived(const IPC::Message& message) {
     42   bool handled = true;
     43   IPC_BEGIN_MESSAGE_MAP(TtsMessageFilter, message)
     44     IPC_MESSAGE_HANDLER(TtsHostMsg_InitializeVoiceList, OnInitializeVoiceList)
     45     IPC_MESSAGE_HANDLER(TtsHostMsg_Speak, OnSpeak)
     46     IPC_MESSAGE_HANDLER(TtsHostMsg_Pause, OnPause)
     47     IPC_MESSAGE_HANDLER(TtsHostMsg_Resume, OnResume)
     48     IPC_MESSAGE_HANDLER(TtsHostMsg_Cancel, OnCancel)
     49     IPC_MESSAGE_UNHANDLED(handled = false)
     50   IPC_END_MESSAGE_MAP()
     51   return handled;
     52 }
     53 
     54 void TtsMessageFilter::OnChannelClosing() {
     55   BrowserThread::PostTask(
     56       BrowserThread::UI, FROM_HERE,
     57       base::Bind(&TtsMessageFilter::OnChannelClosingInUIThread, this));
     58 }
     59 
     60 void TtsMessageFilter::OnDestruct() const {
     61   BrowserThread::DeleteOnUIThread::Destruct(this);
     62 }
     63 
     64 void TtsMessageFilter::OnInitializeVoiceList() {
     65   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     66   TtsController* tts_controller = TtsController::GetInstance();
     67   std::vector<VoiceData> voices;
     68   tts_controller->GetVoices(browser_context_, &voices);
     69 
     70   std::vector<TtsVoice> out_voices;
     71   out_voices.resize(voices.size());
     72   for (size_t i = 0; i < voices.size(); ++i) {
     73     TtsVoice& out_voice = out_voices[i];
     74     out_voice.voice_uri = voices[i].name;
     75     out_voice.name = voices[i].name;
     76     out_voice.lang = voices[i].lang;
     77     out_voice.local_service = !voices[i].remote;
     78     out_voice.is_default = (i == 0);
     79   }
     80   Send(new TtsMsg_SetVoiceList(out_voices));
     81 }
     82 
     83 void TtsMessageFilter::OnSpeak(const TtsUtteranceRequest& request) {
     84   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     85 
     86   scoped_ptr<Utterance> utterance(new Utterance(browser_context_));
     87   utterance->set_src_id(request.id);
     88   utterance->set_text(request.text);
     89   utterance->set_lang(request.lang);
     90   utterance->set_voice_name(request.voice);
     91   utterance->set_can_enqueue(true);
     92 
     93   UtteranceContinuousParameters params;
     94   params.rate = request.rate;
     95   params.pitch = request.pitch;
     96   params.volume = request.volume;
     97   utterance->set_continuous_parameters(params);
     98 
     99   utterance->set_event_delegate(weak_ptr_factory_.GetWeakPtr());
    100 
    101   TtsController::GetInstance()->SpeakOrEnqueue(utterance.release());
    102 }
    103 
    104 void TtsMessageFilter::OnPause() {
    105   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    106   TtsController::GetInstance()->Pause();
    107 }
    108 
    109 void TtsMessageFilter::OnResume() {
    110   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    111   TtsController::GetInstance()->Resume();
    112 }
    113 
    114 void TtsMessageFilter::OnCancel() {
    115   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    116   TtsController::GetInstance()->Stop();
    117 }
    118 
    119 void TtsMessageFilter::OnTtsEvent(Utterance* utterance,
    120                                   TtsEventType event_type,
    121                                   int char_index,
    122                                   const std::string& error_message) {
    123   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    124   switch (event_type) {
    125     case TTS_EVENT_START:
    126       Send(new TtsMsg_DidStartSpeaking(utterance->src_id()));
    127       break;
    128     case TTS_EVENT_END:
    129       Send(new TtsMsg_DidFinishSpeaking(utterance->src_id()));
    130       break;
    131     case TTS_EVENT_WORD:
    132       Send(new TtsMsg_WordBoundary(utterance->src_id(), char_index));
    133       break;
    134     case TTS_EVENT_SENTENCE:
    135       Send(new TtsMsg_SentenceBoundary(utterance->src_id(), char_index));
    136       break;
    137     case TTS_EVENT_MARKER:
    138       Send(new TtsMsg_MarkerEvent(utterance->src_id(), char_index));
    139       break;
    140     case TTS_EVENT_INTERRUPTED:
    141       Send(new TtsMsg_WasInterrupted(utterance->src_id()));
    142       break;
    143     case TTS_EVENT_CANCELLED:
    144       Send(new TtsMsg_WasCancelled(utterance->src_id()));
    145       break;
    146     case TTS_EVENT_ERROR:
    147       Send(new TtsMsg_SpeakingErrorOccurred(
    148           utterance->src_id(), error_message));
    149       break;
    150     case TTS_EVENT_PAUSE:
    151       Send(new TtsMsg_DidPauseSpeaking(utterance->src_id()));
    152       break;
    153     case TTS_EVENT_RESUME:
    154       Send(new TtsMsg_DidResumeSpeaking(utterance->src_id()));
    155       break;
    156   }
    157 }
    158 
    159 void TtsMessageFilter::OnVoicesChanged() {
    160   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    161   OnInitializeVoiceList();
    162 }
    163 
    164 void TtsMessageFilter::OnChannelClosingInUIThread() {
    165   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    166   TtsController::GetInstance()->RemoveVoicesChangedDelegate(this);
    167 
    168   weak_ptr_factory_.InvalidateWeakPtrs();
    169   Release();  // Balanced in TtsMessageFilter().
    170 }
    171 
    172 TtsMessageFilter::~TtsMessageFilter() {
    173   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    174   DCHECK(!weak_ptr_factory_.HasWeakPtrs());
    175   TtsController::GetInstance()->RemoveVoicesChangedDelegate(this);
    176 }
    177