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

Side by Side Diff: chrome/browser/speech/chrome_speech_input_manager.cc

Issue 7838028: Refactor SpeechInputManager between chrome/ and content/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: " Created 9 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/speech/chrome_speech_input_manager.h" 5 #include "chrome/browser/speech/chrome_speech_input_manager.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/synchronization/lock.h" 9 #include "base/synchronization/lock.h"
10 #include "base/threading/thread_restrictions.h" 10 #include "base/threading/thread_restrictions.h"
11 #include "base/utf_string_conversions.h" 11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/prefs/pref_service.h" 13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/tab_contents/tab_util.h" 14 #include "chrome/browser/tab_contents/tab_util.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/pref_names.h" 15 #include "chrome/common/pref_names.h"
17 #include "content/browser/browser_thread.h" 16 #include "content/browser/browser_thread.h"
18 #include "grit/generated_resources.h" 17 #include "grit/generated_resources.h"
19 #include "media/audio/audio_manager.h" 18 #include "media/audio/audio_manager.h"
20 #include "ui/base/l10n/l10n_util.h" 19 #include "ui/base/l10n/l10n_util.h"
21 20
22 #if defined(OS_WIN) 21 #if defined(OS_WIN)
23 #include "chrome/installer/util/wmi.h" 22 #include "chrome/installer/util/wmi.h"
24 #endif 23 #endif
25 24
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 base::AutoLock lock(lock_); 69 base::AutoLock lock(lock_);
71 return value_; 70 return value_;
72 } 71 }
73 72
74 bool can_report_metrics() { 73 bool can_report_metrics() {
75 base::AutoLock lock(lock_); 74 base::AutoLock lock(lock_);
76 return can_report_metrics_; 75 return can_report_metrics_;
77 } 76 }
78 77
79 private: 78 private:
79 friend class base::RefCountedThreadSafe<OptionalRequestInfo>;
80
81 ~OptionalRequestInfo() {}
82
80 base::Lock lock_; 83 base::Lock lock_;
81 std::string value_; 84 std::string value_;
82 bool can_report_metrics_; 85 bool can_report_metrics_;
83 86
84 DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo); 87 DISALLOW_COPY_AND_ASSIGN(OptionalRequestInfo);
85 }; 88 };
86 89
87 ChromeSpeechInputManager::SpeechInputRequest::SpeechInputRequest() { 90 ChromeSpeechInputManager::SpeechInputRequest::SpeechInputRequest() {
88 } 91 }
89 92
90 ChromeSpeechInputManager::SpeechInputRequest::~SpeechInputRequest() { 93 ChromeSpeechInputManager::SpeechInputRequest::~SpeechInputRequest() {
91 } 94 }
92 95
93 ChromeSpeechInputManager* ChromeSpeechInputManager::GetInstance() { 96 ChromeSpeechInputManager* ChromeSpeechInputManager::GetInstance() {
94 return Singleton<ChromeSpeechInputManager>::get(); 97 return Singleton<ChromeSpeechInputManager>::get();
95 } 98 }
96 99
97 ChromeSpeechInputManager::ChromeSpeechInputManager() 100 ChromeSpeechInputManager::ChromeSpeechInputManager()
98 : recording_caller_id_(0), 101 : bubble_controller_(new SpeechInputBubbleController(
99 bubble_controller_(new SpeechInputBubbleController(
100 ALLOW_THIS_IN_INITIALIZER_LIST(this))) { 102 ALLOW_THIS_IN_INITIALIZER_LIST(this))) {
101 } 103 }
102 104
103 ChromeSpeechInputManager::~ChromeSpeechInputManager() { 105 ChromeSpeechInputManager::~ChromeSpeechInputManager() {
104 while (requests_.begin() != requests_.end())
105 CancelRecognition(requests_.begin()->first);
106 } 106 }
107 107
108 bool ChromeSpeechInputManager::HasPendingRequest(int caller_id) const { 108 void ChromeSpeechInputManager::CreateBubble(
109 return requests_.find(caller_id) != requests_.end();
110 }
111
112 SpeechInputManagerDelegate* ChromeSpeechInputManager::GetDelegate(
113 int caller_id) const {
114 return requests_.find(caller_id)->second.delegate;
115 }
116
117 void ChromeSpeechInputManager::StartRecognition(
118 SpeechInputManagerDelegate* delegate,
119 int caller_id, 109 int caller_id,
120 int render_process_id, 110 int render_process_id,
121 int render_view_id, 111 int render_view_id,
122 const gfx::Rect& element_rect, 112 const gfx::Rect& element_rect) {
123 const std::string& language, 113 bubble_controller_->CreateBubble(caller_id, render_process_id,
124 const std::string& grammar, 114 render_view_id, element_rect);
125 const std::string& origin_url) { 115 }
126 DCHECK(!HasPendingRequest(caller_id));
127 116
128 bubble_controller_->CreateBubble(caller_id, render_process_id, render_view_id, 117 void ChromeSpeechInputManager::FetchRequestInfo() {
129 element_rect);
130
131 if (!optional_request_info_.get()) { 118 if (!optional_request_info_.get()) {
132 optional_request_info_ = new OptionalRequestInfo(); 119 optional_request_info_ = new OptionalRequestInfo();
133 // Since hardware info is optional with speech input requests, we start an 120 // Since hardware info is optional with speech input requests, we start an
134 // asynchronous fetch here and move on with recording audio. This first 121 // asynchronous fetch here and move on with recording audio. This first
135 // speech input request would send an empty string for hardware info and 122 // speech input request would send an empty string for hardware info and
136 // subsequent requests may have the hardware info available if the fetch 123 // subsequent requests may have the hardware info available if the fetch
137 // completed before them. This way we don't end up stalling the user with 124 // completed before them. This way we don't end up stalling the user with
138 // a long wait and disk seeks when they click on a UI element and start 125 // a long wait and disk seeks when they click on a UI element and start
139 // speaking. 126 // speaking.
140 optional_request_info_->Refresh(); 127 optional_request_info_->Refresh();
141 } 128 }
142 129 request_info_ = optional_request_info_->value();
Satish 2011/09/12 12:23:05 instead of directly setting the member vars of the
allanwoj 2011/09/19 18:30:38 Done.
143 SpeechInputRequest* request = &requests_[caller_id]; 130 can_report_metrics_ = optional_request_info_->can_report_metrics();
144 request->delegate = delegate;
145 request->recognizer = new SpeechRecognizer(
146 this, caller_id, language, grammar, censor_results(),
147 optional_request_info_->value(),
148 optional_request_info_->can_report_metrics() ? origin_url : "");
149 request->is_active = false;
150
151 StartRecognitionForRequest(caller_id);
152 } 131 }
153 132
154 void ChromeSpeechInputManager::StartRecognitionForRequest(int caller_id) { 133 void ChromeSpeechInputManager::NoMicBubbleMessage(int caller_id) {
155 DCHECK(HasPendingRequest(caller_id)); 134 bubble_controller_->SetBubbleMessage(
156 135 caller_id, l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_NO_MIC));
157 // If we are currently recording audio for another caller, abort that cleanly.
158 if (recording_caller_id_)
159 CancelRecognitionAndInformDelegate(recording_caller_id_);
160
161 if (!AudioManager::GetAudioManager()->HasAudioInputDevices()) {
162 bubble_controller_->SetBubbleMessage(
163 caller_id, l10n_util::GetStringUTF16(IDS_SPEECH_INPUT_NO_MIC));
164 } else {
165 recording_caller_id_ = caller_id;
166 requests_[caller_id].is_active = true;
167 requests_[caller_id].recognizer->StartRecording();
168 bubble_controller_->SetBubbleWarmUpMode(caller_id);
169 }
170 } 136 }
171 137
172 void ChromeSpeechInputManager::CancelRecognition(int caller_id) { 138 void ChromeSpeechInputManager::SetBubbleWarmUpMode(int caller_id) {
173 DCHECK(HasPendingRequest(caller_id)); 139 bubble_controller_->SetBubbleWarmUpMode(caller_id);
174 if (requests_[caller_id].is_active) 140 }
175 requests_[caller_id].recognizer->CancelRecognition(); 141
176 requests_.erase(caller_id); 142 void ChromeSpeechInputManager::CloseBubble(int caller_id) {
177 if (recording_caller_id_ == caller_id)
178 recording_caller_id_ = 0;
179 bubble_controller_->CloseBubble(caller_id); 143 bubble_controller_->CloseBubble(caller_id);
180 } 144 }
181 145
182 void ChromeSpeechInputManager::CancelAllRequestsWithDelegate( 146 void ChromeSpeechInputManager::SetBubbleRecognizingMode(int caller_id) {
183 SpeechInputManagerDelegate* delegate) {
184 SpeechRecognizerMap::iterator it = requests_.begin();
185 while (it != requests_.end()) {
186 if (it->second.delegate == delegate) {
187 CancelRecognition(it->first);
188 // This map will have very few elements so it is simpler to restart.
189 it = requests_.begin();
190 } else {
191 ++it;
192 }
193 }
194 }
195
196 void ChromeSpeechInputManager::StopRecording(int caller_id) {
197 DCHECK(HasPendingRequest(caller_id));
198 requests_[caller_id].recognizer->StopRecording();
199 }
200
201 void ChromeSpeechInputManager::SetRecognitionResult(
202 int caller_id, bool error, const SpeechInputResultArray& result) {
203 DCHECK(HasPendingRequest(caller_id));
204 GetDelegate(caller_id)->SetRecognitionResult(caller_id, result);
205 }
206
207 void ChromeSpeechInputManager::DidCompleteRecording(int caller_id) {
208 DCHECK(recording_caller_id_ == caller_id);
209 DCHECK(HasPendingRequest(caller_id));
210 recording_caller_id_ = 0;
211 GetDelegate(caller_id)->DidCompleteRecording(caller_id);
212 bubble_controller_->SetBubbleRecognizingMode(caller_id); 147 bubble_controller_->SetBubbleRecognizingMode(caller_id);
213 } 148 }
214 149
215 void ChromeSpeechInputManager::DidCompleteRecognition(int caller_id) { 150 void ChromeSpeechInputManager::SetBubbleRecordingMode(int caller_id) {
216 GetDelegate(caller_id)->DidCompleteRecognition(caller_id); 151 bubble_controller_->SetBubbleRecordingMode(caller_id);
217 requests_.erase(caller_id);
218 bubble_controller_->CloseBubble(caller_id);
219 } 152 }
220 153
221 void ChromeSpeechInputManager::OnRecognizerError( 154 void ChromeSpeechInputManager::SetBubbleInputVolume(
155 int caller_id, float volume, float noise_volume) {
156 bubble_controller_->SetBubbleInputVolume(caller_id, volume, noise_volume);
157 }
158
159 void ChromeSpeechInputManager::HandleRecognizerError(
222 int caller_id, SpeechRecognizer::ErrorCode error) { 160 int caller_id, SpeechRecognizer::ErrorCode error) {
223 if (caller_id == recording_caller_id_)
224 recording_caller_id_ = 0;
225
226 requests_[caller_id].is_active = false;
227
228 struct ErrorMessageMapEntry { 161 struct ErrorMessageMapEntry {
229 SpeechRecognizer::ErrorCode error; 162 SpeechRecognizer::ErrorCode error;
230 int message_id; 163 int message_id;
231 }; 164 };
232 ErrorMessageMapEntry error_message_map[] = { 165 ErrorMessageMapEntry error_message_map[] = {
233 { 166 {
234 SpeechRecognizer::RECOGNIZER_ERROR_CAPTURE, IDS_SPEECH_INPUT_MIC_ERROR 167 SpeechRecognizer::RECOGNIZER_ERROR_CAPTURE, IDS_SPEECH_INPUT_MIC_ERROR
235 }, { 168 }, {
236 SpeechRecognizer::RECOGNIZER_ERROR_NO_SPEECH, IDS_SPEECH_INPUT_NO_SPEECH 169 SpeechRecognizer::RECOGNIZER_ERROR_NO_SPEECH, IDS_SPEECH_INPUT_NO_SPEECH
237 }, { 170 }, {
238 SpeechRecognizer::RECOGNIZER_ERROR_NO_RESULTS, IDS_SPEECH_INPUT_NO_RESULTS 171 SpeechRecognizer::RECOGNIZER_ERROR_NO_RESULTS, IDS_SPEECH_INPUT_NO_RESULTS
239 }, { 172 }, {
240 SpeechRecognizer::RECOGNIZER_ERROR_NETWORK, IDS_SPEECH_INPUT_NET_ERROR 173 SpeechRecognizer::RECOGNIZER_ERROR_NETWORK, IDS_SPEECH_INPUT_NET_ERROR
241 } 174 }
242 }; 175 };
243 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(error_message_map); ++i) { 176 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(error_message_map); ++i) {
244 if (error_message_map[i].error == error) { 177 if (error_message_map[i].error == error) {
245 bubble_controller_->SetBubbleMessage( 178 bubble_controller_->SetBubbleMessage(
246 caller_id, 179 caller_id,
247 l10n_util::GetStringUTF16(error_message_map[i].message_id)); 180 l10n_util::GetStringUTF16(error_message_map[i].message_id));
248 return; 181 return;
249 } 182 }
250 } 183 }
251 184
252 NOTREACHED() << "unknown error " << error; 185 NOTREACHED() << "unknown error " << error;
253 } 186 }
254 187
255 void ChromeSpeechInputManager::DidStartReceivingAudio(int caller_id) {
256 DCHECK(HasPendingRequest(caller_id));
257 DCHECK(recording_caller_id_ == caller_id);
258 bubble_controller_->SetBubbleRecordingMode(caller_id);
259 }
260
261 void ChromeSpeechInputManager::DidCompleteEnvironmentEstimation(int caller_id) {
262 DCHECK(HasPendingRequest(caller_id));
263 DCHECK(recording_caller_id_ == caller_id);
264 }
265
266 void ChromeSpeechInputManager::SetInputVolume(int caller_id, float volume,
267 float noise_volume) {
268 DCHECK(HasPendingRequest(caller_id));
269 DCHECK_EQ(recording_caller_id_, caller_id);
270
271 bubble_controller_->SetBubbleInputVolume(caller_id, volume, noise_volume);
272 }
273
274 void ChromeSpeechInputManager::CancelRecognitionAndInformDelegate(
275 int caller_id) {
276 SpeechInputManagerDelegate* cur_delegate = GetDelegate(caller_id);
277 CancelRecognition(caller_id);
278 cur_delegate->DidCompleteRecording(caller_id);
279 cur_delegate->DidCompleteRecognition(caller_id);
280 }
281
282 void ChromeSpeechInputManager::InfoBubbleButtonClicked( 188 void ChromeSpeechInputManager::InfoBubbleButtonClicked(
283 int caller_id, SpeechInputBubble::Button button) { 189 int caller_id, SpeechInputBubble::Button button) {
284 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
285 // Ignore if the caller id was not in our active recognizers list because the 191 // Ignore if the caller id was not in our active recognizers list because the
286 // user might have clicked more than once, or recognition could have been 192 // user might have clicked more than once, or recognition could have been
287 // cancelled due to other reasons before the user click was processed. 193 // cancelled due to other reasons before the user click was processed.
288 if (!HasPendingRequest(caller_id)) 194 if (!HasPendingRequest(caller_id))
289 return; 195 return;
290 196
291 if (button == SpeechInputBubble::BUTTON_CANCEL) { 197 if (button == SpeechInputBubble::BUTTON_CANCEL) {
292 CancelRecognitionAndInformDelegate(caller_id); 198 CancelRecognitionAndInformDelegate(caller_id);
293 } else if (button == SpeechInputBubble::BUTTON_TRY_AGAIN) { 199 } else if (button == SpeechInputBubble::BUTTON_TRY_AGAIN) {
294 StartRecognitionForRequest(caller_id); 200 StartRecognitionForRequest(caller_id);
295 } 201 }
296 } 202 }
297 203
298 void ChromeSpeechInputManager::InfoBubbleFocusChanged(int caller_id) { 204 void ChromeSpeechInputManager::InfoBubbleFocusChanged(int caller_id) {
299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
300 // Ignore if the caller id was not in our active recognizers list because the 206 OnFocusChanged(caller_id);
301 // user might have clicked more than once, or recognition could have been
302 // ended due to other reasons before the user click was processed.
303 if (HasPendingRequest(caller_id)) {
304 // If this is an ongoing recording or if we were displaying an error message
305 // to the user, abort it since user has switched focus. Otherwise
306 // recognition has started and keep that going so user can start speaking to
307 // another element while this gets the results in parallel.
308 if (recording_caller_id_ == caller_id || !requests_[caller_id].is_active) {
309 CancelRecognitionAndInformDelegate(caller_id);
310 }
311 }
312 } 207 }
313 208
314 } // namespace speech_input 209 } // namespace speech_input
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698