| // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/speech/tts_message_filter.h" |
| |
| #include "base/bind.h" |
| #include "base/logging.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/speech/tts_controller.h" |
| #include "chrome/browser/speech/tts_message_filter.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/render_process_host.h" |
| |
| using content::BrowserThread; |
| |
| TtsMessageFilter::TtsMessageFilter(int render_process_id, Profile* profile) |
| : render_process_id_(render_process_id), |
| profile_(profile) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| TtsController::GetInstance()->AddVoicesChangedDelegate(this); |
| } |
| |
| void TtsMessageFilter::OverrideThreadForMessage( |
| const IPC::Message& message, BrowserThread::ID* thread) { |
| switch (message.type()) { |
| case TtsHostMsg_InitializeVoiceList::ID: |
| case TtsHostMsg_Speak::ID: |
| case TtsHostMsg_Pause::ID: |
| case TtsHostMsg_Resume::ID: |
| case TtsHostMsg_Cancel::ID: |
| *thread = BrowserThread::UI; |
| break; |
| } |
| } |
| |
| bool TtsMessageFilter::OnMessageReceived(const IPC::Message& message, |
| bool* message_was_ok) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP_EX(TtsMessageFilter, message, *message_was_ok) |
| IPC_MESSAGE_HANDLER(TtsHostMsg_InitializeVoiceList, OnInitializeVoiceList) |
| IPC_MESSAGE_HANDLER(TtsHostMsg_Speak, OnSpeak) |
| IPC_MESSAGE_HANDLER(TtsHostMsg_Pause, OnPause) |
| IPC_MESSAGE_HANDLER(TtsHostMsg_Resume, OnResume) |
| IPC_MESSAGE_HANDLER(TtsHostMsg_Cancel, OnCancel) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| } |
| |
| void TtsMessageFilter::OnChannelClosing() { |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&TtsMessageFilter::OnChannelClosingInUIThread, this)); |
| } |
| |
| void TtsMessageFilter::OnInitializeVoiceList() { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| TtsController* tts_controller = TtsController::GetInstance(); |
| std::vector<VoiceData> voices; |
| tts_controller->GetVoices(profile_, &voices); |
| |
| std::vector<TtsVoice> out_voices; |
| out_voices.resize(voices.size()); |
| for (size_t i = 0; i < voices.size(); ++i) { |
| TtsVoice& out_voice = out_voices[i]; |
| out_voice.voice_uri = voices[i].name; |
| out_voice.name = voices[i].name; |
| out_voice.lang = voices[i].lang; |
| out_voice.local_service = !voices[i].remote; |
| out_voice.is_default = (i == 0); |
| } |
| Send(new TtsMsg_SetVoiceList(out_voices)); |
| } |
| |
| void TtsMessageFilter::OnSpeak(const TtsUtteranceRequest& request) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| scoped_ptr<Utterance> utterance(new Utterance(profile_)); |
| utterance->set_src_id(request.id); |
| utterance->set_text(request.text); |
| utterance->set_lang(request.lang); |
| utterance->set_voice_name(request.voice); |
| utterance->set_can_enqueue(true); |
| |
| UtteranceContinuousParameters params; |
| params.rate = request.rate; |
| params.pitch = request.pitch; |
| params.volume = request.volume; |
| utterance->set_continuous_parameters(params); |
| |
| utterance->set_event_delegate(this); |
| |
| TtsController::GetInstance()->SpeakOrEnqueue(utterance.release()); |
| } |
| |
| void TtsMessageFilter::OnPause() { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| TtsController::GetInstance()->Pause(); |
| } |
| |
| void TtsMessageFilter::OnResume() { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| TtsController::GetInstance()->Resume(); |
| } |
| |
| void TtsMessageFilter::OnCancel() { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| TtsController::GetInstance()->Stop(); |
| } |
| |
| void TtsMessageFilter::OnTtsEvent(Utterance* utterance, |
| TtsEventType event_type, |
| int char_index, |
| const std::string& error_message) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| switch (event_type) { |
| case TTS_EVENT_START: |
| Send(new TtsMsg_DidStartSpeaking(utterance->src_id())); |
| break; |
| case TTS_EVENT_END: |
| Send(new TtsMsg_DidFinishSpeaking(utterance->src_id())); |
| break; |
| case TTS_EVENT_WORD: |
| Send(new TtsMsg_WordBoundary(utterance->src_id(), char_index)); |
| break; |
| case TTS_EVENT_SENTENCE: |
| Send(new TtsMsg_SentenceBoundary(utterance->src_id(), char_index)); |
| break; |
| case TTS_EVENT_MARKER: |
| Send(new TtsMsg_MarkerEvent(utterance->src_id(), char_index)); |
| break; |
| case TTS_EVENT_INTERRUPTED: |
| Send(new TtsMsg_WasInterrupted(utterance->src_id())); |
| break; |
| case TTS_EVENT_CANCELLED: |
| Send(new TtsMsg_WasCancelled(utterance->src_id())); |
| break; |
| case TTS_EVENT_ERROR: |
| Send(new TtsMsg_SpeakingErrorOccurred( |
| utterance->src_id(), error_message)); |
| break; |
| case TTS_EVENT_PAUSE: |
| Send(new TtsMsg_DidPauseSpeaking(utterance->src_id())); |
| break; |
| case TTS_EVENT_RESUME: |
| Send(new TtsMsg_DidResumeSpeaking(utterance->src_id())); |
| break; |
| } |
| } |
| |
| void TtsMessageFilter::OnVoicesChanged() { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| OnInitializeVoiceList(); |
| } |
| |
| void TtsMessageFilter::OnChannelClosingInUIThread() { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| TtsController::GetInstance()->RemoveVoicesChangedDelegate(this); |
| } |
| |
| TtsMessageFilter::~TtsMessageFilter() { |
| } |