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 SpeechRecognizerImplAndroid::SpeechRecognizerImplAndroid( | |
29 SpeechRecognitionEventListener* listener, | |
30 int session_id) | |
31 : SpeechRecognizer(listener, session_id), | |
32 state_(STATE_IDLE) { | |
33 } | |
34 | |
35 SpeechRecognizerImplAndroid::~SpeechRecognizerImplAndroid() { } | |
36 | |
37 void SpeechRecognizerImplAndroid::StartRecognition() { | |
38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
39 listener()->OnRecognitionStart(session_id()); | |
janx
2013/06/10 16:51:19
Primiano Tucci 2013/06/03 16:24:11
I'd like to hav
bulach
2013/06/11 07:24:48
if this is asking for my opinion, I'd say go with
janx
2013/06/12 14:47:14
Converted all
"listener()->OnSomeEvent(session_id
| |
40 SpeechRecognitionSessionConfig config_ = | |
41 SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id()); | |
42 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( | |
43 &content::SpeechRecognizerImplAndroid::StartRecognitionOnUIThread, this, | |
44 config_.continuous, config_.interim_results)); | |
45 } | |
46 | |
47 void SpeechRecognizerImplAndroid::StartRecognitionOnUIThread(bool continuous, | |
48 bool interim_results) { | |
bulach
2013/06/11 07:24:48
nit: either left-align, or keep the previous ( by
janx
2013/06/12 14:47:14
Went for \n after ( and first param indented by 4.
| |
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
50 JNIEnv* env = AttachCurrentThread(); | |
51 j_recognition_.Reset(Java_SpeechRecognition_createSpeechRecognition(env, | |
52 GetApplicationContext(), reinterpret_cast<jint>(this))); | |
53 Java_SpeechRecognition_startRecognition(env, j_recognition_.obj(), continuous, | |
54 interim_results); | |
55 } | |
56 | |
57 void SpeechRecognizerImplAndroid::AbortRecognition() { | |
58 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { | |
59 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
60 base::Bind(&content::SpeechRecognizerImplAndroid::AbortRecognition, | |
61 this)); | |
62 listener()->OnRecognitionError(session_id(), | |
bulach
2013/06/11 07:24:48
as above, perhaps better to post this task after t
janx
2013/06/12 14:47:14
Now handled in the Java side, call removed.
| |
63 SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_ABORTED)); | |
64 return; | |
65 } | |
66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
67 JNIEnv* env = AttachCurrentThread(); | |
68 if (!j_recognition_.is_null()) | |
69 Java_SpeechRecognition_abortRecognition(env, j_recognition_.obj()); | |
70 } | |
71 | |
72 void SpeechRecognizerImplAndroid::StopAudioCapture() { | |
73 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { | |
74 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
75 base::Bind(&content::SpeechRecognizerImplAndroid::StopAudioCapture, | |
76 this)); | |
77 return; | |
78 } | |
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
80 JNIEnv* env = AttachCurrentThread(); | |
81 if (!j_recognition_.is_null()) | |
82 Java_SpeechRecognition_stopRecognition(env, j_recognition_.obj()); | |
83 } | |
84 | |
85 bool SpeechRecognizerImplAndroid::IsActive() const { | |
86 return state_ != STATE_IDLE; | |
bulach
2013/06/11 07:24:48
just confirming: these are always called in the IO
janx
2013/06/12 14:47:14
Added "DCHECK(BrowserThread::CurrentlyOn(BrowserTh
| |
87 } | |
88 | |
89 bool SpeechRecognizerImplAndroid::IsCapturingAudio() const { | |
90 return state_ == STATE_CAPTURING_AUDIO; | |
91 } | |
92 | |
93 void SpeechRecognizerImplAndroid::OnAudioStart(JNIEnv* env, jobject obj) { | |
94 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
95 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
96 base::Bind(&SpeechRecognizerImplAndroid::OnAudioStart, this, env, | |
bulach
2013/06/11 07:24:48
oh, an important detail: neither env or obj are th
janx
2013/06/12 14:47:14
Fixed by sending "static_cast<JNIEnv*>(NULL), stat
| |
97 obj)); | |
98 return; | |
99 } | |
100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
101 state_ = STATE_CAPTURING_AUDIO; | |
102 listener()->OnAudioStart(session_id()); | |
103 } | |
104 | |
105 void SpeechRecognizerImplAndroid::OnSoundStart(JNIEnv* env, jobject obj) { | |
106 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
107 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
108 base::Bind(&SpeechRecognizerImplAndroid::OnSoundStart, this, env, | |
109 obj)); | |
110 return; | |
111 } | |
112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
113 listener()->OnSoundStart(session_id()); | |
114 } | |
115 | |
116 void SpeechRecognizerImplAndroid::OnSoundEnd(JNIEnv* env, jobject obj) { | |
117 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
118 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
119 base::Bind(&SpeechRecognizerImplAndroid::OnSoundEnd, this, env, obj)); | |
120 return; | |
121 } | |
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
123 listener()->OnSoundEnd(session_id()); | |
124 } | |
125 | |
126 void SpeechRecognizerImplAndroid::OnAudioEnd(JNIEnv* env, jobject obj) { | |
127 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
128 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
129 base::Bind(&SpeechRecognizerImplAndroid::OnAudioEnd, this, env, obj)); | |
130 return; | |
131 } | |
132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
133 state_ = STATE_AWAITING_FINAL_RESULT; | |
134 listener()->OnAudioEnd(session_id()); | |
135 } | |
136 | |
137 void SpeechRecognizerImplAndroid::OnRecognitionResults(JNIEnv* env, | |
138 jobject obj, jobjectArray strings, jfloatArray floats, | |
139 jboolean provisional) { | |
140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
141 std::vector<string16> options; | |
142 AppendJavaStringArrayToStringVector(env, strings, &options); | |
143 std::vector<float> scores(options.size(), 0.0); | |
144 if (floats != NULL) | |
145 JavaFloatArrayToFloatVector(env, floats, &scores); | |
146 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
147 base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread, | |
148 this, options, scores, provisional)); | |
149 } | |
150 | |
151 void SpeechRecognizerImplAndroid::OnRecognitionResultsOnIOThread( | |
152 std::vector<string16> options, std::vector<float> scores, | |
153 bool provisional) { | |
154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
155 SpeechRecognitionResults results; | |
bulach
2013/06/11 07:24:48
nit: is this copy-constructable? if so, you may wa
janx
2013/06/12 14:47:14
SpeechRecognitionResults is just a std::vector, so
| |
156 results.push_back(SpeechRecognitionResult()); | |
157 SpeechRecognitionResult& result = results.back(); | |
bulach
2013/06/11 07:24:48
CHECK_EQ(options.size(), scores.size());
janx
2013/06/12 14:47:14
Done.
| |
158 for (unsigned int i = 0; i < options.size(); i++) { | |
bulach
2013/06/11 07:24:48
nit: s/unsigned int/size_t/ and also ++i
janx
2013/06/12 14:47:14
Done.
| |
159 result.hypotheses.push_back( | |
160 SpeechRecognitionHypothesis(options[i], | |
161 static_cast<double>(scores[i]))); | |
162 } | |
163 result.is_provisional = provisional; | |
164 listener()->OnRecognitionResults(session_id(), results); | |
165 } | |
166 | |
167 void SpeechRecognizerImplAndroid::OnRecognitionError(JNIEnv* env, | |
168 jobject obj, jint error) { | |
169 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
170 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
171 base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionError, this, env, | |
172 obj, error)); | |
173 return; | |
174 } | |
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
176 SpeechRecognitionErrorCode code = | |
177 static_cast<SpeechRecognitionErrorCode>(error); | |
178 listener()->OnRecognitionError(session_id(), SpeechRecognitionError(code)); | |
179 } | |
180 | |
181 void SpeechRecognizerImplAndroid::OnRecognitionEnd(JNIEnv* env, | |
182 jobject obj) { | |
183 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
184 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
185 base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionEnd, this, env, | |
186 obj)); | |
187 return; | |
188 } | |
189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
190 state_ = STATE_IDLE; | |
191 listener()->OnRecognitionEnd(session_id()); | |
192 } | |
193 | |
194 // static | |
195 bool SpeechRecognizerImplAndroid::RegisterSpeechRecognizer(JNIEnv* env) { | |
196 return RegisterNativesImpl(env); | |
197 } | |
198 | |
199 } // namespace content | |
OLD | NEW |