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

Side by Side Diff: chrome/browser/ui/app_list/app_list_speech_recognizer.cc

Issue 676593003: Implement native speech recognition for the launcher. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix timeout. Created 6 years, 1 month 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 2014 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/ui/app_list/app_list_speech_recognizer.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/strings/string16.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/app_list/start_page_service.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/render_process_host.h"
15 #include "content/public/browser/speech_recognition_manager.h"
16 #include "content/public/browser/speech_recognition_session_config.h"
17 #include "content/public/common/speech_recognition_error.h"
18 #include "ui/app_list/speech_ui_model_observer.h"
Lei Zhang 2014/10/30 05:15:42 not used?
Anand Mistry (off Chromium) 2014/10/31 00:50:06 For SpeechRecognitionState, but also declared in t
19
20 namespace app_list {
21
22 // 5 second timeout to cancel if there's no speech heard.
23 static const int kNoSpeechTimeout = 5;
Lei Zhang 2014/10/30 05:15:42 Add "InSeconds" to the name so it's obvious you go
Anand Mistry (off Chromium) 2014/10/31 00:50:06 Done.
24
25 AppListSpeechRecognizer::AppListSpeechRecognizer(
26 StartPageService* start_page_service,
27 const std::string& locale)
28 : start_page_service_(start_page_service),
29 locale_(locale),
30 speech_timeout_(false, false),
31 session_(-1),
32 weak_factory_(this) {
33 }
34
35 AppListSpeechRecognizer::~AppListSpeechRecognizer() {
36 }
37
38 void AppListSpeechRecognizer::Start() {
39 // The speech recognizer checks to see if the request is allowed by looking
40 // up the renderer process. A renderer containing the app-list is hard-coded
41 // to be allowed.
42 // TODO(amistry): Somehow eliminate this dependency.
43 content::WebContents* contents =
44 start_page_service_->GetSpeechRecognitionContents();
45 if (!contents)
46 return;
47
48 content::BrowserThread::PostTask(
49 content::BrowserThread::IO,
50 FROM_HERE,
51 base::Bind(&AppListSpeechRecognizer::StartOnIOThread,
52 this,
53 contents->GetRenderProcessHost()->GetID(),
54 make_scoped_refptr(
55 start_page_service_->profile()->GetRequestContext())));
56 }
57
58 void AppListSpeechRecognizer::StartOnIOThread(
59 int render_process_id,
60 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
Lei Zhang 2014/10/30 05:15:42 You should add a DCHECK_CURRENTLY_ON() call here,
Anand Mistry (off Chromium) 2014/10/31 00:50:06 Done.
Lei Zhang 2014/10/31 01:18:04 An alternate strategy that may work is to have Spe
Anand Mistry (off Chromium) 2014/11/03 06:51:55 I've tried to do this, and the lifecycle is more c
61 if (session_ != -1)
62 StopOnIOThread();
63
64 content::SpeechRecognitionSessionConfig config;
65 config.language = locale_;
66 config.is_legacy_api = false;
67 config.continuous = true;
68 config.interim_results = true;
69 config.max_hypotheses = 1;
70 config.filter_profanities = true;
71 config.url_request_context_getter = url_request_context_getter;
72 config.event_listener = weak_factory_.GetWeakPtr();
73 config.initial_context.render_process_id = render_process_id;
74
75 auto speech_instance = content::SpeechRecognitionManager::GetInstance();
76 session_ = speech_instance->CreateSession(config);
77 speech_instance->StartSession(session_);
78 }
79
80 void AppListSpeechRecognizer::Stop() {
81 content::BrowserThread::PostTask(
82 content::BrowserThread::IO,
83 FROM_HERE,
84 base::Bind(&AppListSpeechRecognizer::StopOnIOThread, this));
85 }
86
87 void AppListSpeechRecognizer::StopOnIOThread() {
88 if (session_ == -1)
89 return;
90
91 // Prevent recursion.
92 int session = session_;
93 session_ = -1;
94 StopSpeechTimeout();
95 content::SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession(
96 session);
97 }
98
99 void AppListSpeechRecognizer::NotifyRecognitionStateChanged(
100 SpeechRecognitionState new_state) {
101 content::BrowserThread::PostTask(
102 content::BrowserThread::UI,
103 FROM_HERE,
104 base::Bind(&StartPageService::OnSpeechRecognitionStateChanged,
105 base::Unretained(start_page_service_),
106 new_state));
107 }
108
109 void AppListSpeechRecognizer::StartSpeechTimeout() {
110 content::BrowserThread::PostTask(
111 content::BrowserThread::UI,
112 FROM_HERE,
113 base::Bind(&base::Timer::Start,
114 base::Unretained(&speech_timeout_),
115 FROM_HERE,
116 base::TimeDelta::FromSeconds(kNoSpeechTimeout),
117 base::Bind(&AppListSpeechRecognizer::SpeechTimeout, this)));
118 }
119
120 void AppListSpeechRecognizer::StopSpeechTimeout() {
121 content::BrowserThread::PostTask(
122 content::BrowserThread::UI,
123 FROM_HERE,
124 base::Bind(&base::Timer::Stop,
125 base::Unretained(&speech_timeout_)));
126 }
127
128 void AppListSpeechRecognizer::SpeechTimeout() {
129 Stop();
130 }
131
132 void AppListSpeechRecognizer::OnRecognitionStart(int session_id) {
133 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_RECOGNIZING);
134 }
135
136 void AppListSpeechRecognizer::OnRecognitionEnd(int session_id) {
137 StopOnIOThread();
138 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_READY);
139 }
140
141 void AppListSpeechRecognizer::OnRecognitionResults(
142 int session_id, const content::SpeechRecognitionResults& results) {
143 base::string16 result_str;
144 unsigned int final_count = 0;
Lei Zhang 2014/10/30 05:15:42 use size_t
Anand Mistry (off Chromium) 2014/10/31 00:50:06 Done.
145 for (const auto& result : results) {
146 if (!result.is_provisional)
147 final_count++;
148 result_str += result.hypotheses[0].utterance;
149 }
150 StopSpeechTimeout();
151 content::BrowserThread::PostTask(
152 content::BrowserThread::UI,
153 FROM_HERE,
154 base::Bind(&StartPageService::OnSpeechResult,
155 base::Unretained(start_page_service_),
156 result_str,
157 final_count == results.size()));
158
159 // Stop the moment we have a final result.
160 if (final_count == results.size())
161 StopOnIOThread();
162 }
163
164 void AppListSpeechRecognizer::OnRecognitionError(
165 int session_id, const content::SpeechRecognitionError& error) {
166 StopOnIOThread();
167 if (error.code == content::SPEECH_RECOGNITION_ERROR_NETWORK) {
168 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_NETWORK_ERROR);
169 }
170 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_READY);
171 }
172
173 void AppListSpeechRecognizer::OnSoundStart(int session_id) {
174 StartSpeechTimeout();
175 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_IN_SPEECH);
176 }
177
178 void AppListSpeechRecognizer::OnSoundEnd(int session_id) {
179 StopOnIOThread();
180 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_RECOGNIZING);
181 }
182
183 void AppListSpeechRecognizer::OnAudioLevelsChange(
184 int session_id, float volume, float noise_volume) {
185 volume = std::max(0.0f, volume - noise_volume);
186 int16_t sound_level = static_cast<int16_t>(INT16_MAX * volume);
Lei Zhang 2014/10/30 05:15:42 can't this overflow if |volume| > 1 ?
Anand Mistry (off Chromium) 2014/10/31 00:50:06 It is defined to be in the range [0.0, 1.0]
Lei Zhang 2014/10/31 01:18:04 Add a DCHECK?
Anand Mistry (off Chromium) 2014/11/03 06:51:55 Done.
187 content::BrowserThread::PostTask(
188 content::BrowserThread::UI,
189 FROM_HERE,
190 base::Bind(&StartPageService::OnSpeechSoundLevelChanged,
191 base::Unretained(start_page_service_),
192 sound_level));
193 }
194
195 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698