OLD | NEW |
---|---|
(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 | |
OLD | NEW |