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.
5 #include "chrome/browser/speech/tts_message_filter.h"
8 #include "base/logging.h"
9 #include "content/public/browser/browser_context.h"
10 #include "content/public/browser/render_process_host.h"
12 using content::BrowserThread;
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),
20 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
21 TtsController::GetInstance()->AddVoicesChangedDelegate(this);
23 // Balanced in OnChannelClosingInUIThread() to keep the ref-count be non-zero
24 // until all pointers to this class are invalidated.
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;
41 bool TtsMessageFilter::OnMessageReceived(const IPC::Message& message) {
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)
54 void TtsMessageFilter::OnChannelClosing() {
55 base::AutoLock lock(mutex_);
57 BrowserThread::PostTask(
58 BrowserThread::UI, FROM_HERE,
59 base::Bind(&TtsMessageFilter::OnChannelClosingInUIThread, this));
62 bool TtsMessageFilter::Valid() {
63 base::AutoLock lock(mutex_);
67 void TtsMessageFilter::OnDestruct() const {
69 base::AutoLock lock(mutex_);
72 BrowserThread::DeleteOnUIThread::Destruct(this);
75 TtsMessageFilter::~TtsMessageFilter() {
76 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
80 void TtsMessageFilter::OnInitializeVoiceList() {
81 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82 TtsController* tts_controller = TtsController::GetInstance();
83 std::vector<VoiceData> voices;
84 tts_controller->GetVoices(browser_context_, &voices);
86 std::vector<TtsVoice> out_voices;
87 out_voices.resize(voices.size());
88 for (size_t i = 0; i < voices.size(); ++i) {
89 TtsVoice& out_voice = out_voices[i];
90 out_voice.voice_uri = voices[i].name;
91 out_voice.name = voices[i].name;
92 out_voice.lang = voices[i].lang;
93 out_voice.local_service = !voices[i].remote;
94 out_voice.is_default = (i == 0);
96 Send(new TtsMsg_SetVoiceList(out_voices));
99 void TtsMessageFilter::OnSpeak(const TtsUtteranceRequest& request) {
100 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
102 scoped_ptr<Utterance> utterance(new Utterance(browser_context_));
103 utterance->set_src_id(request.id);
104 utterance->set_text(request.text);
105 utterance->set_lang(request.lang);
106 utterance->set_voice_name(request.voice);
107 utterance->set_can_enqueue(true);
109 UtteranceContinuousParameters params;
110 params.rate = request.rate;
111 params.pitch = request.pitch;
112 params.volume = request.volume;
113 utterance->set_continuous_parameters(params);
115 utterance->set_event_delegate(this);
117 TtsController::GetInstance()->SpeakOrEnqueue(utterance.release());
120 void TtsMessageFilter::OnPause() {
121 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
122 TtsController::GetInstance()->Pause();
125 void TtsMessageFilter::OnResume() {
126 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
127 TtsController::GetInstance()->Resume();
130 void TtsMessageFilter::OnCancel() {
131 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
132 TtsController::GetInstance()->Stop();
135 void TtsMessageFilter::OnTtsEvent(Utterance* utterance,
136 TtsEventType event_type,
138 const std::string& error_message) {
142 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143 switch (event_type) {
144 case TTS_EVENT_START:
145 Send(new TtsMsg_DidStartSpeaking(utterance->src_id()));
148 Send(new TtsMsg_DidFinishSpeaking(utterance->src_id()));
151 Send(new TtsMsg_WordBoundary(utterance->src_id(), char_index));
153 case TTS_EVENT_SENTENCE:
154 Send(new TtsMsg_SentenceBoundary(utterance->src_id(), char_index));
156 case TTS_EVENT_MARKER:
157 Send(new TtsMsg_MarkerEvent(utterance->src_id(), char_index));
159 case TTS_EVENT_INTERRUPTED:
160 Send(new TtsMsg_WasInterrupted(utterance->src_id()));
162 case TTS_EVENT_CANCELLED:
163 Send(new TtsMsg_WasCancelled(utterance->src_id()));
165 case TTS_EVENT_ERROR:
166 Send(new TtsMsg_SpeakingErrorOccurred(
167 utterance->src_id(), error_message));
169 case TTS_EVENT_PAUSE:
170 Send(new TtsMsg_DidPauseSpeaking(utterance->src_id()));
172 case TTS_EVENT_RESUME:
173 Send(new TtsMsg_DidResumeSpeaking(utterance->src_id()));
178 void TtsMessageFilter::OnVoicesChanged() {
182 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
183 OnInitializeVoiceList();
186 void TtsMessageFilter::OnChannelClosingInUIThread() {
187 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
189 Release(); // Balanced in TtsMessageFilter().
192 void TtsMessageFilter::Cleanup() {
193 TtsController::GetInstance()->RemoveVoicesChangedDelegate(this);
194 TtsController::GetInstance()->RemoveUtteranceEventDelegate(this);