Index: content/browser/speech/speech_recognizer_impl_android.cc |
diff --git a/content/browser/speech/speech_recognizer_impl_android.cc b/content/browser/speech/speech_recognizer_impl_android.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8251eb9eebc59fb07e2dfc56db742314e6344775 |
--- /dev/null |
+++ b/content/browser/speech/speech_recognizer_impl_android.cc |
@@ -0,0 +1,232 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/speech/speech_recognizer_impl_android.h" |
+ |
+#include "base/android/jni_android.h" |
+#include "base/android/jni_array.h" |
+#include "base/android/jni_string.h" |
+#include "base/android/scoped_java_ref.h" |
+#include "base/bind.h" |
+#include "base/utf_string_conversions.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/speech_recognition_event_listener.h" |
+#include "content/public/browser/speech_recognition_manager.h" |
+#include "content/public/browser/speech_recognition_session_config.h" |
+#include "content/public/common/speech_recognition_grammar.h" |
+#include "content/public/common/speech_recognition_result.h" |
+#include "jni/SpeechRecognition_jni.h" |
+ |
+using base::android::AppendJavaStringArrayToStringVector; |
+using base::android::AttachCurrentThread; |
+using base::android::GetApplicationContext; |
+using base::android::JavaFloatArrayToFloatVector; |
+ |
+namespace content { |
+ |
+void SpeechRecognizerImplAndroid::Init(JNIEnv* env) { |
+ RegisterNativesImpl(env); |
+} |
+ |
+SpeechRecognizerImplAndroid::SpeechRecognizerImplAndroid( |
+ SpeechRecognitionEventListener* listener, |
+ int session_id) |
+ : SpeechRecognizer(listener, session_id), |
+ state_(STATE_IDLE) { |
+} |
+ |
+SpeechRecognizerImplAndroid::~SpeechRecognizerImplAndroid() { } |
+ |
+void SpeechRecognizerImplAndroid::StartRecognition() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ listener_->OnRecognitionStart(session_id_); |
janx
2013/06/06 09:34:55
Primiano Tucci 2013/06/03 16:24:11
I'd like to hav
|
+ SpeechRecognitionSessionConfig config_ = |
+ SpeechRecognitionManager::GetInstance()->GetSessionConfig(session_id_); |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&content::SpeechRecognizerImplAndroid::StartRecognitionJNI, |
+ this, config_.continuous, config_.interim_results)); |
+} |
+ |
+void SpeechRecognizerImplAndroid::StartRecognitionJNI(bool continuous, |
+ bool interim_results) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ j_recognition_.Reset(Java_SpeechRecognition_createSpeechRecognition( |
+ AttachCurrentThread(), |
+ GetApplicationContext(), |
+ reinterpret_cast<jint>(this))); |
+ Java_SpeechRecognition_StartRecognition(AttachCurrentThread(), |
+ j_recognition_.obj(), continuous, interim_results); |
+} |
+ |
+void SpeechRecognizerImplAndroid::AbortRecognition() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&content::SpeechRecognizerImplAndroid::AbortRecognitionJNI, |
+ this)); |
+ OnRecognitionError(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_ABORTED)); |
+} |
+ |
+void SpeechRecognizerImplAndroid::AbortRecognitionJNI() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!j_recognition_.is_null()) |
+ Java_SpeechRecognition_AbortRecognition(AttachCurrentThread(), |
+ j_recognition_.obj()); |
+} |
+ |
+void SpeechRecognizerImplAndroid::StopAudioCapture() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&content::SpeechRecognizerImplAndroid::StopRecognitionJNI, |
+ this)); |
+} |
+ |
+void SpeechRecognizerImplAndroid::StopRecognitionJNI() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (!j_recognition_.is_null()) |
+ Java_SpeechRecognition_StopRecognition(AttachCurrentThread(), |
+ j_recognition_.obj()); |
+} |
+ |
+bool SpeechRecognizerImplAndroid::IsActive() const { |
+ return state_ != STATE_IDLE; |
+} |
+ |
+bool SpeechRecognizerImplAndroid::IsCapturingAudio() const { |
+ return state_ == STATE_CAPTURING_AUDIO; |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnAudioStartJNI(JNIEnv* env, jobject obj) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
+ base::Bind(&SpeechRecognizerImplAndroid::OnAudioStart, this)); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnAudioStart() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ state_ = STATE_CAPTURING_AUDIO; |
+ listener_->OnAudioStart(session_id_); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnSoundStartJNI(JNIEnv* env, jobject obj) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
+ base::Bind(&SpeechRecognizerImplAndroid::OnSoundStart, this)); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnSoundStart() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ listener_->OnSoundStart(session_id_); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnSoundEndJNI(JNIEnv* env, jobject obj) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
+ base::Bind(&SpeechRecognizerImplAndroid::OnSoundEnd, this)); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnSoundEnd() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ listener_->OnSoundEnd(session_id_); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnAudioEndJNI(JNIEnv* env, jobject obj) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
+ base::Bind(&SpeechRecognizerImplAndroid::OnAudioEnd, this)); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnAudioEnd() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ state_ = STATE_AWAITING_FINAL_RESULT; |
+ listener_->OnAudioEnd(session_id_); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnRecognitionResultsJNI(JNIEnv* env, |
+ jobject obj, jobjectArray strings, jfloatArray floats, |
+ jboolean provisional) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ std::vector<string16> options; |
+ AppendJavaStringArrayToStringVector(env, strings, &options); |
+ std::vector<float> scores(options.size(), 0.0); |
+ if (floats != NULL) |
+ JavaFloatArrayToFloatVector(env, floats, &scores); |
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
+ base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionResults, |
+ this, options, scores, provisional)); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnRecognitionResults( |
+ std::vector<string16> options, std::vector<float> scores, |
+ bool provisional) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ SpeechRecognitionResults results; |
+ results.push_back(SpeechRecognitionResult()); |
+ SpeechRecognitionResult& result = results.back(); |
+ for (unsigned int i = 0; i < options.size(); i++) { |
+ result.hypotheses.push_back( |
+ SpeechRecognitionHypothesis(options[i], |
+ static_cast<double>(scores[i]))); |
+ } |
+ result.is_provisional = provisional; |
+ listener_->OnRecognitionResults(session_id_, results); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnRecognitionErrorJNI(JNIEnv* env, |
+ jobject obj, jint error) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ SpeechRecognitionErrorCode code; |
+ |
+ // Translate Android speech recognition errors to Web Speech API errors. |
+ // TODO(janx): Do this in SpeechRecognition.java instead. |
+ switch(error) { |
+ case 3: // ERROR_AUDIO |
+ code = SPEECH_RECOGNITION_ERROR_AUDIO; |
+ break; |
+ case 5: // ERROR_CLIENT |
+ code = SPEECH_RECOGNITION_ERROR_ABORTED; |
+ break; |
+ case 8: // ERROR_RECOGNIZER_BUSY |
+ case 9: // ERROR_INSUFFICIENT_PERMISSIONS |
+ code = SPEECH_RECOGNITION_ERROR_NOT_ALLOWED; |
+ break; |
+ case 1: // ERROR_NETWORK_TIMEOUT |
+ case 2: // ERROR_NETWORK |
+ case 4: // ERROR_SERVER |
+ code = SPEECH_RECOGNITION_ERROR_NETWORK; |
+ break; |
+ case 7: // ERROR_NO_MATCH |
+ code = SPEECH_RECOGNITION_ERROR_NO_MATCH; |
+ break; |
+ case 6: // ERROR_SPEECH_TIMEOUT |
+ code = SPEECH_RECOGNITION_ERROR_NO_SPEECH; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ return; |
+ } |
+ |
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
+ base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionError, this, |
+ SpeechRecognitionError(code))); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnRecognitionError( |
+ SpeechRecognitionError error) { |
+ listener_->OnRecognitionError(session_id_, error); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnRecognitionEndJNI(JNIEnv* env, |
+ jobject obj) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
+ base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionEnd, this)); |
+} |
+ |
+void SpeechRecognizerImplAndroid::OnRecognitionEnd() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ state_ = STATE_IDLE; |
+ listener_->OnRecognitionEnd(session_id_); |
+} |
+ |
+} // namespace content |