Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(908)

Side by Side Diff: content/browser/speech/speech_input_manager_impl.cc

Issue 9568002: Renamed speech input implementation from to speech_recognition_*. The namespace has been renamed fr… (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebased from master. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "content/browser/speech/speech_input_manager_impl.h"
6
7 #include "base/bind.h"
8 #include "content/browser/browser_main_loop.h"
9 #include "content/browser/renderer_host/render_view_host_impl.h"
10 #include "content/browser/speech/speech_input_dispatcher_host.h"
11 #include "content/browser/speech/speech_recognizer_impl.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/content_browser_client.h"
14 #include "content/public/browser/render_view_host_delegate.h"
15 #include "content/public/browser/resource_context.h"
16 #include "content/public/browser/speech_input_manager_delegate.h"
17 #include "content/public/browser/speech_input_preferences.h"
18 #include "content/public/common/view_type.h"
19
20 using content::BrowserMainLoop;
21 using content::BrowserThread;
22 using content::SpeechInputManagerDelegate;
23
24 content::SpeechInputManager* content::SpeechInputManager::GetInstance() {
25 return speech_input::SpeechInputManagerImpl::GetInstance();
26 }
27
28 namespace speech_input {
29
30 struct SpeechInputManagerImpl::SpeechInputParams {
31 SpeechInputParams(SpeechInputDispatcherHost* delegate,
32 int caller_id,
33 int render_process_id,
34 int render_view_id,
35 const gfx::Rect& element_rect,
36 const std::string& language,
37 const std::string& grammar,
38 const std::string& origin_url,
39 net::URLRequestContextGetter* context_getter,
40 content::SpeechInputPreferences* speech_input_prefs)
41 : delegate(delegate),
42 caller_id(caller_id),
43 render_process_id(render_process_id),
44 render_view_id(render_view_id),
45 element_rect(element_rect),
46 language(language),
47 grammar(grammar),
48 origin_url(origin_url),
49 context_getter(context_getter),
50 speech_input_prefs(speech_input_prefs) {
51 }
52
53 SpeechInputDispatcherHost* delegate;
54 int caller_id;
55 int render_process_id;
56 int render_view_id;
57 gfx::Rect element_rect;
58 std::string language;
59 std::string grammar;
60 std::string origin_url;
61 net::URLRequestContextGetter* context_getter;
62 content::SpeechInputPreferences* speech_input_prefs;
63 };
64
65 SpeechInputManagerImpl* SpeechInputManagerImpl::GetInstance() {
66 return Singleton<SpeechInputManagerImpl>::get();
67 }
68
69 SpeechInputManagerImpl::SpeechInputManagerImpl()
70 : can_report_metrics_(false),
71 recording_caller_id_(0) {
72 delegate_ =
73 content::GetContentClient()->browser()->GetSpeechInputManagerDelegate();
74 }
75
76 SpeechInputManagerImpl::~SpeechInputManagerImpl() {
77 while (requests_.begin() != requests_.end())
78 CancelRecognition(requests_.begin()->first);
79 }
80
81 bool SpeechInputManagerImpl::HasAudioInputDevices() {
82 return BrowserMainLoop::GetAudioManager()->HasAudioInputDevices();
83 }
84
85 bool SpeechInputManagerImpl::IsRecordingInProcess() {
86 return BrowserMainLoop::GetAudioManager()->IsRecordingInProcess();
87 }
88
89 string16 SpeechInputManagerImpl::GetAudioInputDeviceModel() {
90 return BrowserMainLoop::GetAudioManager()->GetAudioInputDeviceModel();
91 }
92
93 bool SpeechInputManagerImpl::HasPendingRequest(int caller_id) const {
94 return requests_.find(caller_id) != requests_.end();
95 }
96
97 SpeechInputDispatcherHost* SpeechInputManagerImpl::GetDelegate(
98 int caller_id) const {
99 return requests_.find(caller_id)->second.delegate;
100 }
101
102 void SpeechInputManagerImpl::ShowAudioInputSettings() {
103 // Since AudioManager::ShowAudioInputSettings can potentially launch external
104 // processes, do that in the FILE thread to not block the calling threads.
105 if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
106 BrowserThread::PostTask(
107 BrowserThread::FILE, FROM_HERE,
108 base::Bind(&SpeechInputManagerImpl::ShowAudioInputSettings,
109 base::Unretained(this)));
110 return;
111 }
112
113 AudioManager* audio_manager = BrowserMainLoop::GetAudioManager();
114 DCHECK(audio_manager->CanShowAudioInputSettings());
115 if (audio_manager->CanShowAudioInputSettings())
116 audio_manager->ShowAudioInputSettings();
117 }
118
119 void SpeechInputManagerImpl::StartRecognition(
120 SpeechInputDispatcherHost* delegate,
121 int caller_id,
122 int render_process_id,
123 int render_view_id,
124 const gfx::Rect& element_rect,
125 const std::string& language,
126 const std::string& grammar,
127 const std::string& origin_url,
128 net::URLRequestContextGetter* context_getter,
129 content::SpeechInputPreferences* speech_input_prefs) {
130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
131 BrowserThread::PostTask(
132 BrowserThread::UI, FROM_HERE,
133 base::Bind(
134 &SpeechInputManagerImpl::CheckRenderViewTypeAndStartRecognition,
135 base::Unretained(this),
136 SpeechInputParams(
137 delegate, caller_id, render_process_id, render_view_id,
138 element_rect, language, grammar, origin_url, context_getter,
139 speech_input_prefs)));
140 }
141
142 void SpeechInputManagerImpl::CheckRenderViewTypeAndStartRecognition(
143 const SpeechInputParams& params) {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145
146 RenderViewHostImpl* render_view_host = RenderViewHostImpl::FromID(
147 params.render_process_id, params.render_view_id);
148 if (!render_view_host || !render_view_host->GetDelegate())
149 return;
150
151 // For host delegates other than TabContents we can't reliably show a popup,
152 // including the speech input bubble. In these cases for privacy reasons we
153 // don't want to start recording if the user can't be properly notified.
154 // An example of this is trying to show the speech input bubble within an
155 // extension popup: http://crbug.com/92083. In these situations the speech
156 // input extension API should be used instead.
157 if (render_view_host->GetDelegate()->GetRenderViewType() ==
158 content::VIEW_TYPE_TAB_CONTENTS) {
159 BrowserThread::PostTask(
160 BrowserThread::IO, FROM_HERE,
161 base::Bind(&SpeechInputManagerImpl::ProceedStartingRecognition,
162 base::Unretained(this), params));
163 }
164 }
165
166 void SpeechInputManagerImpl::ProceedStartingRecognition(
167 const SpeechInputParams& params) {
168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
169 DCHECK(!HasPendingRequest(params.caller_id));
170
171 if (delegate_) {
172 delegate_->ShowRecognitionRequested(
173 params.caller_id, params.render_process_id, params.render_view_id,
174 params.element_rect);
175 delegate_->GetRequestInfo(&can_report_metrics_, &request_info_);
176 }
177
178 SpeechInputRequest* request = &requests_[params.caller_id];
179 request->delegate = params.delegate;
180 request->recognizer = new SpeechRecognizerImpl(
181 this, params.caller_id, params.language, params.grammar,
182 params.context_getter, params.speech_input_prefs->FilterProfanities(),
183 request_info_, can_report_metrics_ ? params.origin_url : "");
184 request->is_active = false;
185
186 StartRecognitionForRequest(params.caller_id);
187 }
188
189 void SpeechInputManagerImpl::StartRecognitionForRequest(int caller_id) {
190 SpeechRecognizerMap::iterator request = requests_.find(caller_id);
191 if (request == requests_.end()) {
192 NOTREACHED();
193 return;
194 }
195
196 // We should not currently be recording for the caller.
197 CHECK(recording_caller_id_ != caller_id);
198
199 // If we are currently recording audio for another caller, abort that cleanly.
200 if (recording_caller_id_)
201 CancelRecognitionAndInformDelegate(recording_caller_id_);
202
203 if (!HasAudioInputDevices()) {
204 if (delegate_) {
205 delegate_->ShowMicError(
206 caller_id, SpeechInputManagerDelegate::MIC_ERROR_NO_DEVICE_AVAILABLE);
207 }
208 } else if (IsRecordingInProcess()) {
209 if (delegate_) {
210 delegate_->ShowMicError(
211 caller_id, SpeechInputManagerDelegate::MIC_ERROR_DEVICE_IN_USE);
212 }
213 } else {
214 recording_caller_id_ = caller_id;
215 requests_[caller_id].is_active = true;
216 requests_[caller_id].recognizer->StartRecording();
217 if (delegate_)
218 delegate_->ShowWarmUp(caller_id);
219 }
220 }
221
222 void SpeechInputManagerImpl::CancelRecognitionForRequest(int caller_id) {
223 // Ignore if the caller id was not in our active recognizers list because the
224 // user might have clicked more than once, or recognition could have been
225 // ended due to other reasons before the user click was processed.
226 if (!HasPendingRequest(caller_id))
227 return;
228
229 CancelRecognitionAndInformDelegate(caller_id);
230 }
231
232 void SpeechInputManagerImpl::FocusLostForRequest(int caller_id) {
233 // See above comment.
234 if (!HasPendingRequest(caller_id))
235 return;
236
237 // If this is an ongoing recording or if we were displaying an error message
238 // to the user, abort it since user has switched focus. Otherwise
239 // recognition has started and keep that going so user can start speaking to
240 // another element while this gets the results in parallel.
241 if (recording_caller_id_ == caller_id || !requests_[caller_id].is_active)
242 CancelRecognitionAndInformDelegate(caller_id);
243 }
244
245 void SpeechInputManagerImpl::CancelRecognition(int caller_id) {
246 DCHECK(HasPendingRequest(caller_id));
247 if (requests_[caller_id].is_active)
248 requests_[caller_id].recognizer->CancelRecognition();
249 requests_.erase(caller_id);
250 if (recording_caller_id_ == caller_id)
251 recording_caller_id_ = 0;
252 if (delegate_)
253 delegate_->DoClose(caller_id);
254 }
255
256 void SpeechInputManagerImpl::CancelAllRequestsWithDelegate(
257 SpeechInputDispatcherHost* delegate) {
258 SpeechRecognizerMap::iterator it = requests_.begin();
259 while (it != requests_.end()) {
260 if (it->second.delegate == delegate) {
261 CancelRecognition(it->first);
262 // This map will have very few elements so it is simpler to restart.
263 it = requests_.begin();
264 } else {
265 ++it;
266 }
267 }
268 }
269
270 void SpeechInputManagerImpl::StopRecording(int caller_id) {
271 // No pending requests on extension popups.
272 if (!HasPendingRequest(caller_id))
273 return;
274
275 requests_[caller_id].recognizer->StopRecording();
276 }
277
278 void SpeechInputManagerImpl::SetRecognitionResult(
279 int caller_id, const content::SpeechInputResult& result) {
280 DCHECK(HasPendingRequest(caller_id));
281 GetDelegate(caller_id)->SetRecognitionResult(caller_id, result);
282 }
283
284 void SpeechInputManagerImpl::DidCompleteRecording(int caller_id) {
285 DCHECK(recording_caller_id_ == caller_id);
286 DCHECK(HasPendingRequest(caller_id));
287 recording_caller_id_ = 0;
288 GetDelegate(caller_id)->DidCompleteRecording(caller_id);
289 if (delegate_)
290 delegate_->ShowRecognizing(caller_id);
291 }
292
293 void SpeechInputManagerImpl::DidCompleteRecognition(int caller_id) {
294 GetDelegate(caller_id)->DidCompleteRecognition(caller_id);
295 requests_.erase(caller_id);
296 if (delegate_)
297 delegate_->DoClose(caller_id);
298 }
299
300 void SpeechInputManagerImpl::DidStartReceivingSpeech(int caller_id) {
301 }
302
303 void SpeechInputManagerImpl::DidStopReceivingSpeech(int caller_id) {
304 }
305
306 void SpeechInputManagerImpl::OnRecognizerError(
307 int caller_id, content::SpeechInputError error) {
308 if (caller_id == recording_caller_id_)
309 recording_caller_id_ = 0;
310 requests_[caller_id].is_active = false;
311 if (delegate_)
312 delegate_->ShowRecognizerError(caller_id, error);
313 }
314
315 void SpeechInputManagerImpl::DidStartReceivingAudio(int caller_id) {
316 DCHECK(HasPendingRequest(caller_id));
317 DCHECK(recording_caller_id_ == caller_id);
318 if (delegate_)
319 delegate_->ShowRecording(caller_id);
320 }
321
322 void SpeechInputManagerImpl::DidCompleteEnvironmentEstimation(int caller_id) {
323 DCHECK(HasPendingRequest(caller_id));
324 DCHECK(recording_caller_id_ == caller_id);
325 }
326
327 void SpeechInputManagerImpl::SetInputVolume(int caller_id, float volume,
328 float noise_volume) {
329 DCHECK(HasPendingRequest(caller_id));
330 DCHECK_EQ(recording_caller_id_, caller_id);
331 if (delegate_)
332 delegate_->ShowInputVolume(caller_id, volume, noise_volume);
333 }
334
335 void SpeechInputManagerImpl::CancelRecognitionAndInformDelegate(
336 int caller_id) {
337 SpeechInputDispatcherHost* cur_delegate = GetDelegate(caller_id);
338 CancelRecognition(caller_id);
339 cur_delegate->DidCompleteRecording(caller_id);
340 cur_delegate->DidCompleteRecognition(caller_id);
341 }
342
343 SpeechInputManagerImpl::SpeechInputRequest::SpeechInputRequest()
344 : delegate(NULL),
345 is_active(false) {
346 }
347
348 SpeechInputManagerImpl::SpeechInputRequest::~SpeechInputRequest() {
349 }
350
351 } // namespace speech_input
OLDNEW
« no previous file with comments | « content/browser/speech/speech_input_manager_impl.h ('k') | content/browser/speech/speech_recognition_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698