OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "content/browser/speech/speech_recognizer_impl_android.h" | |
6 | |
7 #include "base/android/jni_android.h" | |
8 #include "base/android/jni_array.h" | |
9 #include "base/android/jni_string.h" | |
10 #include "base/android/scoped_java_ref.h" | |
11 #include "base/bind.h" | |
12 #include "base/utf_string_conversions.h" | |
13 #include "content/public/browser/browser_thread.h" | |
14 #include "content/public/browser/speech_recognition_event_listener.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_grammar.h" | |
18 #include "content/public/common/speech_recognition_result.h" | |
19 #include "jni/SpeechRecognition_jni.h" | |
20 | |
21 using base::android::AppendJavaStringArrayToStringVector; | |
22 using base::android::AttachCurrentThread; | |
23 using base::android::GetApplicationContext; | |
24 using base::android::JavaFloatArrayToFloatVector; | |
25 | |
26 namespace content { | |
27 | |
28 void SpeechRecognizerImplAndroid::Init(JNIEnv* env) { | |
29 RegisterNativesImpl(env); | |
30 } | |
31 | |
32 SpeechRecognizerImplAndroid::SpeechRecognizerImplAndroid( | |
33 SpeechRecognitionEventListener* listener, | |
34 int session_id) | |
35 : SpeechRecognizer(listener, session_id), | |
36 state_(STATE_IDLE) { | |
37 } | |
38 | |
39 SpeechRecognizerImplAndroid::~SpeechRecognizerImplAndroid() { } | |
40 | |
41 void SpeechRecognizerImplAndroid::StartRecognition() { | |
42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
43 listener_->OnRecognitionStart(session_id_); | |
janx
2013/06/06 09:34:55
Primiano Tucci 2013/06/03 16:24:11
I'd like to hav
| |
44 SpeechRecognitionSessionConfig config_ = | |
45 SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id_); | |
46 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
47 base::Bind(&content::SpeechRecognizerImplAndroid::StartRecognitionJNI, | |
48 this, config_.continuous, config_.interim_results)); | |
49 } | |
50 | |
51 void SpeechRecognizerImplAndroid::StartRecognitionJNI(bool continuous, | |
52 bool interim_results) { | |
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
54 j_recognition_.Reset(Java_SpeechRecognition_createSpeechRecognition( | |
55 AttachCurrentThread(), | |
56 GetApplicationContext(), | |
57 reinterpret_cast<jint>(this))); | |
58 Java_SpeechRecognition_StartRecognition(AttachCurrentThread(), | |
59 j_recognition_.obj(), continuous, interim_results); | |
60 } | |
61 | |
62 void SpeechRecognizerImplAndroid::AbortRecognition() { | |
63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
64 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
65 base::Bind(&content::SpeechRecognizerImplAndroid::AbortRecognitionJNI, | |
66 this)); | |
67 OnRecognitionError(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_ABORTED)); | |
68 } | |
69 | |
70 void SpeechRecognizerImplAndroid::AbortRecognitionJNI() { | |
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
72 if (!j_recognition_.is_null()) | |
73 Java_SpeechRecognition_AbortRecognition(AttachCurrentThread(), | |
74 j_recognition_.obj()); | |
75 } | |
76 | |
77 void SpeechRecognizerImplAndroid::StopAudioCapture() { | |
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
79 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
80 base::Bind(&content::SpeechRecognizerImplAndroid::StopRecognitionJNI, | |
81 this)); | |
82 } | |
83 | |
84 void SpeechRecognizerImplAndroid::StopRecognitionJNI() { | |
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
86 if (!j_recognition_.is_null()) | |
87 Java_SpeechRecognition_StopRecognition(AttachCurrentThread(), | |
88 j_recognition_.obj()); | |
89 } | |
90 | |
91 bool SpeechRecognizerImplAndroid::IsActive() const { | |
92 return state_ != STATE_IDLE; | |
93 } | |
94 | |
95 bool SpeechRecognizerImplAndroid::IsCapturingAudio() const { | |
96 return state_ == STATE_CAPTURING_AUDIO; | |
97 } | |
98 | |
99 void SpeechRecognizerImplAndroid::OnAudioStartJNI(JNIEnv* env, jobject obj) { | |
100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
101 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
102 base::Bind(&SpeechRecognizerImplAndroid::OnAudioStart, this)); | |
103 } | |
104 | |
105 void SpeechRecognizerImplAndroid::OnAudioStart() { | |
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
107 state_ = STATE_CAPTURING_AUDIO; | |
108 listener_->OnAudioStart(session_id_); | |
109 } | |
110 | |
111 void SpeechRecognizerImplAndroid::OnSoundStartJNI(JNIEnv* env, jobject obj) { | |
112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
113 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
114 base::Bind(&SpeechRecognizerImplAndroid::OnSoundStart, this)); | |
115 } | |
116 | |
117 void SpeechRecognizerImplAndroid::OnSoundStart() { | |
118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
119 listener_->OnSoundStart(session_id_); | |
120 } | |
121 | |
122 void SpeechRecognizerImplAndroid::OnSoundEndJNI(JNIEnv* env, jobject obj) { | |
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
124 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
125 base::Bind(&SpeechRecognizerImplAndroid::OnSoundEnd, this)); | |
126 } | |
127 | |
128 void SpeechRecognizerImplAndroid::OnSoundEnd() { | |
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
130 listener_->OnSoundEnd(session_id_); | |
131 } | |
132 | |
133 void SpeechRecognizerImplAndroid::OnAudioEndJNI(JNIEnv* env, jobject obj) { | |
134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
135 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
136 base::Bind(&SpeechRecognizerImplAndroid::OnAudioEnd, this)); | |
137 } | |
138 | |
139 void SpeechRecognizerImplAndroid::OnAudioEnd() { | |
140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
141 state_ = STATE_AWAITING_FINAL_RESULT; | |
142 listener_->OnAudioEnd(session_id_); | |
143 } | |
144 | |
145 void SpeechRecognizerImplAndroid::OnRecognitionResultsJNI(JNIEnv* env, | |
146 jobject obj, jobjectArray strings, jfloatArray floats, | |
147 jboolean provisional) { | |
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
149 std::vector<string16> options; | |
150 AppendJavaStringArrayToStringVector(env, strings, &options); | |
151 std::vector<float> scores(options.size(), 0.0); | |
152 if (floats != NULL) | |
153 JavaFloatArrayToFloatVector(env, floats, &scores); | |
154 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
155 base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionResults, | |
156 this, options, scores, provisional)); | |
157 } | |
158 | |
159 void SpeechRecognizerImplAndroid::OnRecognitionResults( | |
160 std::vector<string16> options, std::vector<float> scores, | |
161 bool provisional) { | |
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
163 SpeechRecognitionResults results; | |
164 results.push_back(SpeechRecognitionResult()); | |
165 SpeechRecognitionResult& result = results.back(); | |
166 for (unsigned int i = 0; i < options.size(); i++) { | |
167 result.hypotheses.push_back( | |
168 SpeechRecognitionHypothesis(options[i], | |
169 static_cast<double>(scores[i]))); | |
170 } | |
171 result.is_provisional = provisional; | |
172 listener_->OnRecognitionResults(session_id_, results); | |
173 } | |
174 | |
175 void SpeechRecognizerImplAndroid::OnRecognitionErrorJNI(JNIEnv* env, | |
176 jobject obj, jint error) { | |
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
178 SpeechRecognitionErrorCode code; | |
179 | |
180 // Translate Android speech recognition errors to Web Speech API errors. | |
181 // TODO(janx): Do this in SpeechRecognition.java instead. | |
182 switch(error) { | |
183 case 3: // ERROR_AUDIO | |
184 code = SPEECH_RECOGNITION_ERROR_AUDIO; | |
185 break; | |
186 case 5: // ERROR_CLIENT | |
187 code = SPEECH_RECOGNITION_ERROR_ABORTED; | |
188 break; | |
189 case 8: // ERROR_RECOGNIZER_BUSY | |
190 case 9: // ERROR_INSUFFICIENT_PERMISSIONS | |
191 code = SPEECH_RECOGNITION_ERROR_NOT_ALLOWED; | |
192 break; | |
193 case 1: // ERROR_NETWORK_TIMEOUT | |
194 case 2: // ERROR_NETWORK | |
195 case 4: // ERROR_SERVER | |
196 code = SPEECH_RECOGNITION_ERROR_NETWORK; | |
197 break; | |
198 case 7: // ERROR_NO_MATCH | |
199 code = SPEECH_RECOGNITION_ERROR_NO_MATCH; | |
200 break; | |
201 case 6: // ERROR_SPEECH_TIMEOUT | |
202 code = SPEECH_RECOGNITION_ERROR_NO_SPEECH; | |
203 break; | |
204 default: | |
205 NOTREACHED(); | |
206 return; | |
207 } | |
208 | |
209 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
210 base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionError, this, | |
211 SpeechRecognitionError(code))); | |
212 } | |
213 | |
214 void SpeechRecognizerImplAndroid::OnRecognitionError( | |
215 SpeechRecognitionError error) { | |
216 listener_->OnRecognitionError(session_id_, error); | |
217 } | |
218 | |
219 void SpeechRecognizerImplAndroid::OnRecognitionEndJNI(JNIEnv* env, | |
220 jobject obj) { | |
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
222 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
223 base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionEnd, this)); | |
224 } | |
225 | |
226 void SpeechRecognizerImplAndroid::OnRecognitionEnd() { | |
227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
228 state_ = STATE_IDLE; | |
229 listener_->OnRecognitionEnd(session_id_); | |
230 } | |
231 | |
232 } // namespace content | |
OLD | NEW |