android_speech_srec_Recognizer.cpp revision abbfd2c3d63580a0fdde5a0480f4ec6dd34e1fcf
1/*---------------------------------------------------------------------------*
2 *  android_speech_srec_Recognizer.cpp                                                              *
3 *                                                                           *
4 *  Copyright 2007 Nuance Communciations, Inc.                               *
5 *                                                                           *
6 *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7 *  you may not use this file except in compliance with the License.         *
8 *                                                                           *
9 *  You may obtain a copy of the License at                                  *
10 *      http://www.apache.org/licenses/LICENSE-2.0                           *
11 *                                                                           *
12 *  Unless required by applicable law or agreed to in writing, software      *
13 *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 *  See the License for the specific language governing permissions and      *
16 *  limitations under the License.                                           *
17 *                                                                           *
18 *---------------------------------------------------------------------------*/
19
20
21#include <string.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <jni.h>
25
26#define LOG_TAG "srec_jni"
27#include "utils/Log.h"
28
29#include "passert.h"
30#include "ESR_CommandLine.h"
31#include "ESR_Session.h"
32#include "LCHAR.h"
33#include "PFile.h"
34#include "PFileSystem.h"
35#include "PANSIFileSystem.h"
36//#include "PMemoryFileSystem.h"
37#include "plog.h"
38#include "pmemory.h"
39#include "ptypes.h"
40#include "SR_Grammar.h"
41#include "SR_Recognizer.h"
42#include "SR_RecognizerImpl.h"
43#include "SR_RecognizerResult.h"
44#include "SR_Session.h"
45#include "SR_Vocabulary.h"
46#include "SR_AcousticState.h"
47#include "SR_Nametag.h"
48#include "PStackSize.h"
49
50
51
52//
53// helper function to throw an exception
54//
55static void JNU_ThrowByName(JNIEnv *env, const char* name, const char* msg) {
56    jclass cls = env->FindClass(name);
57    if (cls != NULL) {
58        env->ThrowNew(cls, msg);
59    }
60    env->DeleteLocalRef(cls);
61}
62
63static void unimplemented(JNIEnv* env) {
64    JNU_ThrowByName(env, "java/lang/IllegalStateException", "unimplemented!!!");
65}
66
67static void checkEsrError(JNIEnv* env, ESR_ReturnCode esr_status) {
68    if (esr_status != ESR_SUCCESS) {
69        JNU_ThrowByName(env, "java/lang/IllegalStateException", ESR_rc2str(esr_status));
70    }
71}
72
73
74///////////////////////////////////////////////////////////////////////////
75// PMem JNI implementations
76///////////////////////////////////////////////////////////////////////////
77
78static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_PMemInit
79        (JNIEnv *env, jclass clazz) {
80    checkEsrError(env, PMemInit());
81}
82
83static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_PMemShutdown
84        (JNIEnv *env, jclass clazz) {
85    checkEsrError(env, PMemShutdown());
86}
87
88
89//////////////////////////////////////////////////////////////////////////
90// SR_Session JNI implementations
91//////////////////////////////////////////////////////////////////////////
92
93static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1SessionCreate
94        (JNIEnv *env, jclass clazz, jstring fileName) {
95    // TODO: check for fileName NPE
96    const char* fn = env->GetStringUTFChars(fileName, 0);
97    checkEsrError(env, SR_SessionCreate(fn));  // TODO: can I post this before freeing the string?
98    env->ReleaseStringUTFChars(fileName, fn);
99}
100
101static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1SessionDestroy
102        (JNIEnv *env, jclass clazz) {
103    checkEsrError(env, SR_SessionDestroy());
104}
105
106
107//////////////////////////////////////////////////////////////////////////
108// SR_Recognizer JNI implementations
109//////////////////////////////////////////////////////////////////////////
110
111static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerStart
112        (JNIEnv *env, jclass clazz, jint recognizer) {
113    checkEsrError(env, SR_RecognizerStart((SR_Recognizer*)recognizer));
114}
115
116static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerStop
117        (JNIEnv *env, jclass clazz, jint recognizer) {
118    checkEsrError(env, SR_RecognizerStop((SR_Recognizer*)recognizer));
119}
120
121static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerCreate
122        (JNIEnv *env, jclass clazz) {
123    SR_Recognizer* recognizer = NULL;
124    // TODO: do we need to clean up the recognizer if this fails?
125    checkEsrError(env, SR_RecognizerCreate(&recognizer));
126    return (jint)recognizer;
127}
128
129static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerDestroy
130        (JNIEnv *env, jclass clazz, jint recognizer) {
131    checkEsrError(env, SR_RecognizerDestroy((SR_Recognizer*)recognizer));
132    return;
133}
134
135static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerSetup
136        (JNIEnv *env, jclass clazz, jint recognizer) {
137    checkEsrError(env, SR_RecognizerSetup((SR_Recognizer*)recognizer));
138    return;
139}
140
141static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerUnsetup
142        (JNIEnv *env, jclass clazz, jint recognizer) {
143    checkEsrError(env, SR_RecognizerUnsetup((SR_Recognizer*)recognizer));
144    return;
145}
146
147static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerIsSetup
148        (JNIEnv *env, jclass clazz, jint recognizer) {
149    ESR_BOOL rtn = ESR_FALSE;
150    checkEsrError(env, SR_RecognizerIsSetup((SR_Recognizer*)recognizer, &rtn));
151    return rtn;
152}
153
154static JNIEXPORT jstring JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerGetParameter
155  (JNIEnv *env, jclass clazz, jint recognizer, jstring key) {
156    unimplemented(env);
157    return 0;
158}
159
160static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerGetSize_1tParameter
161  (JNIEnv *env, jclass clazz, jint recognizer, jstring key) {
162    unimplemented(env);
163    return 0;
164}
165
166static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerGetBoolParameter
167  (JNIEnv *env, jclass clazz, jint recognizer, jstring key) {
168    unimplemented(env);
169    return JNI_FALSE;
170}
171
172static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerSetParameter
173  (JNIEnv *env, jclass clazz, jint recognizer, jstring key, jstring value) {
174    unimplemented(env);
175    return;
176}
177
178static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerSetSize_1tParameter
179  (JNIEnv *env, jclass clazz, jint recognizer, jstring key, jint value) {
180    unimplemented(env);
181    return;
182}
183
184static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerSetBoolParameter
185  (JNIEnv *env, jclass clazz, jint recognizer, jstring key , jboolean value) {
186    unimplemented(env);
187    return;
188}
189
190static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerSetupRule
191        (JNIEnv *env, jclass clazz, jint recognizer, jint grammar, jstring ruleName) {
192    const char* rn = env->GetStringUTFChars(ruleName, 0);
193    checkEsrError(env, SR_RecognizerSetupRule((SR_Recognizer*)recognizer, (SR_Grammar*)grammar, rn));
194    env->ReleaseStringUTFChars(ruleName, rn);
195}
196
197static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerHasSetupRules
198        (JNIEnv *env, jclass clazz, jint recognizer) {
199    ESR_BOOL rtn = ESR_FALSE;
200    checkEsrError(env, SR_RecognizerHasSetupRules((SR_Recognizer*)recognizer, &rtn));
201    return rtn;
202}
203
204static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerActivateRule
205        (JNIEnv *env, jclass clazz, jint recognizer, jint grammar, jstring ruleName, jint weight) {
206    const char* rn = env->GetStringUTFChars(ruleName, 0);
207    checkEsrError(env, SR_RecognizerActivateRule((SR_Recognizer*)recognizer, (SR_Grammar*)grammar, rn, weight));
208    env->ReleaseStringUTFChars(ruleName, rn);
209}
210
211static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerDeactivateRule
212        (JNIEnv *env, jclass clazz, jint recognizer, jint grammar, jstring ruleName) {
213    const char* rn = env->GetStringUTFChars(ruleName, 0);
214    checkEsrError(env, SR_RecognizerDeactivateRule((SR_Recognizer*)recognizer, (SR_Grammar*)grammar, rn));
215    env->ReleaseStringUTFChars(ruleName, rn);
216}
217
218static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerDeactivateAllRules
219        (JNIEnv *env, jclass clazz, jint recognizer) {
220    checkEsrError(env, SR_RecognizerDeactivateAllRules((SR_Recognizer*)recognizer));
221}
222
223static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerIsActiveRule
224        (JNIEnv *env, jclass clazz, jint recognizer, jint grammar, jstring ruleName) {
225    ESR_BOOL rtn = ESR_FALSE;
226    const char* rn = env->GetStringUTFChars(ruleName, 0);
227    checkEsrError(env, SR_RecognizerIsActiveRule((SR_Recognizer*)recognizer, (SR_Grammar*)grammar, rn, &rtn));
228    env->ReleaseStringUTFChars(ruleName, rn);
229    return rtn;
230}
231
232static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerCheckGrammarConsistency
233        (JNIEnv *env, jclass clazz, jint recognizer, jint grammar) {
234    ESR_BOOL rtn = ESR_FALSE;
235    checkEsrError(env, SR_RecognizerCheckGrammarConsistency((SR_Recognizer*)recognizer, (SR_Grammar*)grammar, &rtn));
236    return rtn;
237}
238
239static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerPutAudio
240        (JNIEnv *env, jclass clazz, jint recognizer, jbyteArray audio, jint offset, jint length, jboolean isLast) {
241    // set the length
242    jbyte buffer[1024];
243    if (length > (int)sizeof(buffer)) length = sizeof(buffer);
244    size_t samples = length / sizeof(asr_int16_t);
245    length = samples * sizeof(asr_int16_t);
246
247    // fetch data from java
248    env->GetByteArrayRegion(audio, offset, length, buffer);
249
250    // put the samples into the recognizer
251    checkEsrError(env, SR_RecognizerPutAudio((SR_Recognizer*)recognizer,
252            (asr_int16_t*)buffer, &samples, isLast ? ESR_TRUE : ESR_FALSE));
253    if (samples != length / sizeof(asr_int16_t)) {
254        checkEsrError(env, ESR_READ_ERROR);
255        return 0;
256    }
257
258    return samples * sizeof(asr_int16_t);
259}
260
261static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerAdvance
262        (JNIEnv *env, jclass clazz, jint recognizer) {
263    SR_RecognizerStatus status = SR_RECOGNIZER_EVENT_INVALID;
264    SR_RecognizerResultType type = SR_RECOGNIZER_RESULT_TYPE_INVALID;
265    SR_RecognizerResult* recognizerResult = NULL;
266    checkEsrError(env, SR_RecognizerAdvance((SR_Recognizer*)recognizer, &status, &type, &recognizerResult));
267    return status;
268}
269
270static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalClipping
271        (JNIEnv *env, jclass clazz, jint recognizer) {
272    ESR_BOOL rtn = ESR_FALSE;
273    checkEsrError(env, SR_RecognizerIsSignalClipping((SR_Recognizer*)recognizer, &rtn));
274    return rtn;
275}
276
277static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalDCOffset
278        (JNIEnv *env, jclass clazz, jint recognizer) {
279    ESR_BOOL rtn = ESR_FALSE;
280    checkEsrError(env, SR_RecognizerIsSignalDCOffset((SR_Recognizer*)recognizer, &rtn));
281    return rtn;
282}
283
284static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalNoisy
285        (JNIEnv *env, jclass clazz, jint recognizer) {
286    ESR_BOOL rtn = ESR_FALSE;
287    checkEsrError(env, SR_RecognizerIsSignalNoisy((SR_Recognizer*)recognizer, &rtn));
288    return rtn;
289}
290
291static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalTooQuiet
292        (JNIEnv *env, jclass clazz, jint recognizer) {
293    ESR_BOOL rtn = ESR_FALSE;
294    checkEsrError(env, SR_RecognizerIsSignalTooQuiet((SR_Recognizer*)recognizer, &rtn));
295    return rtn;
296}
297
298static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalTooFewSamples
299        (JNIEnv *env, jclass clazz, jint recognizer) {
300    ESR_BOOL rtn = ESR_FALSE;
301    checkEsrError(env, SR_RecognizerIsSignalTooFewSamples((SR_Recognizer*)recognizer, &rtn));
302    return rtn;
303}
304
305static JNIEXPORT jboolean JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalTooManySamples
306        (JNIEnv *env, jclass clazz, jint recognizer) {
307    ESR_BOOL rtn = ESR_FALSE;
308    checkEsrError(env, SR_RecognizerIsSignalTooManySamples((SR_Recognizer*)recognizer, &rtn));
309    return rtn;
310}
311
312
313//////////////////////////////////////////////////////////////////////////
314// SR_AcousticState JNI implementations
315//////////////////////////////////////////////////////////////////////////
316
317static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1AcousticStateReset
318        (JNIEnv *env, jclass clazz, jint recognizer) {
319    checkEsrError(env, SR_AcousticStateReset((SR_Recognizer*)recognizer));
320}
321
322static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1AcousticStateSet
323        (JNIEnv *env, jclass clazz, jint recognizer, jstring state) {
324    const char* st = env->GetStringUTFChars(state, 0);
325    checkEsrError(env, SR_AcousticStateSet((SR_Recognizer*)recognizer, st));
326    env->ReleaseStringUTFChars(state, st);
327}
328
329static JNIEXPORT jstring JNICALL Java_android_speech_srec_Recognizer_SR_1AcousticStateGet
330        (JNIEnv *env, jclass clazz, jint recognizer) {
331    char rtn[1000];
332    size_t rtnLength = sizeof(rtn) - 1;
333    ESR_ReturnCode esr_status = SR_AcousticStateGet((SR_Recognizer*)recognizer, rtn, &rtnLength);
334    if (esr_status) {
335        checkEsrError(env, esr_status);
336        return NULL;
337    }
338    rtn[rtnLength] = 0;
339    return env->NewStringUTF(rtn);
340}
341
342
343//////////////////////////////////////////////////////////////////////////
344// SR_Grammar JNI implementations
345//////////////////////////////////////////////////////////////////////////
346
347static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarCompile
348        (JNIEnv *env, jclass clazz, jint grammar) {
349    checkEsrError(env, SR_GrammarCompile((SR_Grammar*)grammar));
350}
351
352static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarAddWordToSlot
353        (JNIEnv *env, jclass clazz, jint grammar, jstring slot, jstring word, jstring pronunciation, jint weight, jstring tag) {
354    const char* sl = 0;
355    const char* wo = 0;
356    const char* pr = 0;
357    const char* ta = 0;
358    if ((sl = env->GetStringUTFChars(slot, 0)) &&
359            (wo = env->GetStringUTFChars(word, 0)) &&
360            (!pronunciation || (pr = env->GetStringUTFChars(pronunciation, 0))) &&
361            (ta = env->GetStringUTFChars(tag, 0))) {
362        checkEsrError(env, SR_GrammarAddWordToSlot((SR_Grammar*)grammar, sl, wo, pr, weight, ta));
363    }
364    if (ta) env->ReleaseStringUTFChars(tag, ta);
365    if (pr) env->ReleaseStringUTFChars(pronunciation, pr);
366    if (wo) env->ReleaseStringUTFChars(word, wo);
367    if (sl) env->ReleaseStringUTFChars(slot, sl);
368}
369
370static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarResetAllSlots
371        (JNIEnv *env, jclass clazz, jint grammar) {
372    checkEsrError(env, SR_GrammarResetAllSlots((SR_Grammar*)grammar));
373}
374
375static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarSetupVocabulary
376        (JNIEnv *env, jclass clazz, jint grammar, jint vocabulary) {
377    checkEsrError(env, SR_GrammarSetupVocabulary((SR_Grammar*)grammar, (SR_Vocabulary*)vocabulary));
378}
379
380static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarSetupRecognizer
381        (JNIEnv *env, jclass clazz, jint grammar, jint recognizer) {
382    checkEsrError(env, SR_GrammarSetupRecognizer((SR_Grammar*)grammar, (SR_Recognizer*)recognizer));
383}
384
385static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarUnsetupRecognizer
386        (JNIEnv *env, jclass clazz, jint grammar) {
387    checkEsrError(env, SR_GrammarUnsetupRecognizer((SR_Grammar*)grammar));
388}
389
390static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarCreate
391        (JNIEnv *env, jclass clazz) {
392    SR_Grammar* grammar = 0;
393    checkEsrError(env, SR_GrammarCreate(&grammar));
394    return (jint)grammar;
395}
396
397static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarDestroy
398        (JNIEnv *env, jclass clazz, jint grammar) {
399    checkEsrError(env, SR_GrammarDestroy((SR_Grammar*)grammar));
400}
401
402static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarLoad
403        (JNIEnv *env, jclass clazz, jstring fileName) {
404    // TODO: check for fileName NPE
405    SR_Grammar* grammar = 0;
406    const char* fn = env->GetStringUTFChars(fileName, 0);
407    checkEsrError(env, SR_GrammarLoad(fn, &grammar));
408    env->ReleaseStringUTFChars(fileName, fn);
409    return (jint)grammar;
410}
411
412static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarSave
413        (JNIEnv *env, jclass clazz, jint grammar, jstring fileName) {
414    const char* fn = env->GetStringUTFChars(fileName, 0);
415    checkEsrError(env, SR_GrammarSave((SR_Grammar*)grammar, fn));
416    env->ReleaseStringUTFChars(fileName, fn);
417}
418
419static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarAllowOnly
420        (JNIEnv *env, jclass clazz, jint grammar, jstring transcription) {
421    const char* tr = env->GetStringUTFChars(transcription, 0);
422    checkEsrError(env, SR_GrammarSave((SR_Grammar*)grammar, tr));
423    env->ReleaseStringUTFChars(transcription, tr);
424}
425
426static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1GrammarAllowAll
427        (JNIEnv *env, jclass clazz, jint grammar) {
428    checkEsrError(env, SR_GrammarAllowAll((SR_Grammar*)grammar));
429}
430
431
432//////////////////////////////////////////////////////////////////////////
433// SR_Vocabulary JNI implementations
434//////////////////////////////////////////////////////////////////////////
435
436static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_SR_1VocabularyLoad
437        (JNIEnv *env, jclass clazz) {
438    char filename[P_PATH_MAX];
439    size_t flen = sizeof(filename) - 1;
440    checkEsrError(env, ESR_SessionGetLCHAR ( L("cmdline.vocabulary"), filename, &flen ));
441    filename[sizeof(filename) - 1] = 0;
442    // TODO: do we need to clean up the recognizer if this fails?
443    SR_Vocabulary* vocabulary = NULL;
444    checkEsrError(env, SR_VocabularyLoad(filename, &vocabulary));
445    return (jint)vocabulary;
446}
447
448static JNIEXPORT void JNICALL Java_android_speech_srec_Recognizer_SR_1VocabularyDestroy
449        (JNIEnv *env, jclass clazz, jint vocabulary) {
450    // TODO: do we need to clean up the recognizer if this fails?
451    checkEsrError(env, SR_VocabularyDestroy((SR_Vocabulary*)vocabulary));
452}
453
454static JNIEXPORT jstring JNICALL Java_android_speech_srec_Recognizer_SR_1VocabularyGetPronunciation
455        (JNIEnv *env, jclass clazz, jint vocabulary, jstring word) {
456    char rtn[1000];
457    size_t rtnLength = sizeof(rtn) - 1;
458    const char* wo = env->GetStringUTFChars(word, 0);
459    ESR_ReturnCode esr_status = SR_VocabularyGetPronunciation((SR_Vocabulary*)vocabulary, wo, rtn, &rtnLength);
460    env->ReleaseStringUTFChars(word, wo);
461    if (esr_status) {
462        checkEsrError(env, esr_status);
463        return NULL;
464    }
465    rtn[rtnLength] = 0;
466    return env->NewStringUTF(rtn);
467}
468
469
470//////////////////////////////////////////////////////////////////////////
471// SR_RecognizerResult JNI implementations
472//////////////////////////////////////////////////////////////////////////
473
474static JNIEXPORT jbyteArray JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetWaveform
475        (JNIEnv *env, jclass clazz, jint recognizer) {
476    unimplemented(env);
477    return 0;
478}
479
480static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetSize
481        (JNIEnv *env, jclass clazz, jint recognizer) {
482    size_t size = 0;
483    checkEsrError(env, SR_RecognizerResultGetSize(((SR_RecognizerImpl*)recognizer)->result, &size));
484    return size;
485}
486
487static JNIEXPORT jint JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetKeyCount
488        (JNIEnv *env, jclass clazz, jint recognizer, jint nbest) {
489    size_t size = 0;
490    checkEsrError(env, SR_RecognizerResultGetKeyCount(((SR_RecognizerImpl*)recognizer)->result, nbest, &size));
491    return size;
492}
493
494static JNIEXPORT jobjectArray JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetKeyList
495        (JNIEnv *env, jclass clazz, jint recognizer, jint nbest) {
496    unimplemented(env);
497    return NULL;
498}
499
500static JNIEXPORT jstring JNICALL Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetValue
501        (JNIEnv *env, jclass clazz, jint recognizer, jint nbest, jstring key) {
502    char rtn[1000];
503    size_t rtnLength = sizeof(rtn) - 1;
504    const char* ke = env->GetStringUTFChars(key, 0);
505    ESR_ReturnCode esr_status = SR_RecognizerResultGetValue(((SR_RecognizerImpl*)recognizer)->result, nbest, ke, rtn, &rtnLength);
506    env->ReleaseStringUTFChars(key, ke);
507    if (esr_status) {
508        checkEsrError(env, esr_status);
509        return NULL;
510    }
511    rtn[rtnLength] = 0;
512    return env->NewStringUTF(rtn);
513}
514
515
516/*
517 * Table of methods associated with a single class.
518 */
519static JNINativeMethod gMethods[] = {
520    /* name, signature, funcPtr */
521    // PMem
522    {"PMemInit",                           "()V",                     (void*)Java_android_speech_srec_Recognizer_PMemInit},
523    {"PMemShutdown",                       "()V",                     (void*)Java_android_speech_srec_Recognizer_PMemShutdown},
524    // SR_Session
525    {"SR_SessionCreate",                   "(Ljava/lang/String;)V",   (void*)Java_android_speech_srec_Recognizer_SR_1SessionCreate},
526    {"SR_SessionDestroy",                  "()V",                     (void*)Java_android_speech_srec_Recognizer_SR_1SessionDestroy},
527    // SR_Recognizer
528    {"SR_RecognizerStart",                 "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerStart},
529    {"SR_RecognizerStop",                  "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerStop},
530    {"SR_RecognizerCreate",                "()I",                     (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerCreate},
531    {"SR_RecognizerDestroy",               "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerDestroy},
532    {"SR_RecognizerSetup",                 "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerSetup},
533    {"SR_RecognizerUnsetup",               "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerUnsetup},
534    {"SR_RecognizerIsSetup",               "(I)Z",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerIsSetup},
535    {"SR_RecognizerGetParameter",          "(ILjava/lang/String;)Ljava/lang/String;", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerGetParameter},
536    {"SR_RecognizerGetSize_tParameter",    "(ILjava/lang/String;)I",  (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerGetSize_1tParameter},
537    {"SR_RecognizerGetBoolParameter",      "(ILjava/lang/String;)Z",  (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerGetBoolParameter},
538    {"SR_RecognizerSetParameter",          "(ILjava/lang/String;Ljava/lang/String;)V", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerSetParameter},
539    {"SR_RecognizerSetSize_tParameter",    "(ILjava/lang/String;I)V", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerSetSize_1tParameter},
540    {"SR_RecognizerSetBoolParameter",      "(ILjava/lang/String;Z)V", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerSetBoolParameter},
541    {"SR_RecognizerSetupRule",             "(IILjava/lang/String;)V", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerSetupRule},
542    {"SR_RecognizerHasSetupRules",         "(I)Z",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerHasSetupRules},
543    {"SR_RecognizerActivateRule",          "(IILjava/lang/String;I)V", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerActivateRule},
544    {"SR_RecognizerDeactivateRule",        "(IILjava/lang/String;)V", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerDeactivateRule},
545    {"SR_RecognizerDeactivateAllRules",    "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerDeactivateAllRules},
546    {"SR_RecognizerIsActiveRule",          "(IILjava/lang/String;)Z", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerIsActiveRule},
547    {"SR_RecognizerCheckGrammarConsistency", "(II)Z",                 (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerCheckGrammarConsistency},
548    {"SR_RecognizerPutAudio",              "(I[BIIZ)I",               (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerPutAudio},
549    {"SR_RecognizerAdvance",               "(I)I",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerAdvance},
550    {"SR_RecognizerIsSignalClipping",      "(I)Z",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalClipping},
551    {"SR_RecognizerIsSignalDCOffset",      "(I)Z",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalDCOffset},
552    {"SR_RecognizerIsSignalNoisy",         "(I)Z",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalNoisy},
553    {"SR_RecognizerIsSignalTooQuiet",      "(I)Z",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalTooQuiet},
554    {"SR_RecognizerIsSignalTooFewSamples", "(I)Z",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalTooFewSamples},
555    {"SR_RecognizerIsSignalTooManySamples", "(I)Z",                   (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerIsSignalTooManySamples},
556    // SR_AcousticState
557    {"SR_AcousticStateReset",               "(I)V",                   (void*)Java_android_speech_srec_Recognizer_SR_1AcousticStateReset},
558    {"SR_AcousticStateSet",                 "(ILjava/lang/String;)V", (void*)Java_android_speech_srec_Recognizer_SR_1AcousticStateSet},
559    {"SR_AcousticStateGet",                 "(I)Ljava/lang/String;",  (void*)Java_android_speech_srec_Recognizer_SR_1AcousticStateGet},
560    // SR_Grammar
561    {"SR_GrammarCompile",                  "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1GrammarCompile},
562    {"SR_GrammarAddWordToSlot",            "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V", (void*)Java_android_speech_srec_Recognizer_SR_1GrammarAddWordToSlot},
563    {"SR_GrammarResetAllSlots",            "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1GrammarResetAllSlots},
564    {"SR_GrammarSetupVocabulary",          "(II)V",                   (void*)Java_android_speech_srec_Recognizer_SR_1GrammarSetupVocabulary},
565    {"SR_GrammarSetupRecognizer",          "(II)V",                   (void*)Java_android_speech_srec_Recognizer_SR_1GrammarSetupRecognizer},
566    {"SR_GrammarUnsetupRecognizer",        "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1GrammarUnsetupRecognizer},
567    {"SR_GrammarCreate",                   "()I",                     (void*)Java_android_speech_srec_Recognizer_SR_1GrammarCreate},
568    {"SR_GrammarDestroy",                  "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1GrammarDestroy},
569    {"SR_GrammarLoad",                     "(Ljava/lang/String;)I",   (void*)Java_android_speech_srec_Recognizer_SR_1GrammarLoad},
570    {"SR_GrammarSave",                     "(ILjava/lang/String;)V",  (void*)Java_android_speech_srec_Recognizer_SR_1GrammarSave},
571    {"SR_GrammarAllowOnly",                "(ILjava/lang/String;)V",  (void*)Java_android_speech_srec_Recognizer_SR_1GrammarAllowOnly},
572    {"SR_GrammarAllowAll",                 "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1GrammarAllowAll},
573    // SR_Vocabulary
574    {"SR_VocabularyLoad",                  "()I",                     (void*)Java_android_speech_srec_Recognizer_SR_1VocabularyLoad},
575    {"SR_VocabularyDestroy",               "(I)V",                    (void*)Java_android_speech_srec_Recognizer_SR_1VocabularyDestroy},
576    {"SR_VocabularyGetPronunciation",      "(ILjava/lang/String;)Ljava/lang/String;",  (void*)Java_android_speech_srec_Recognizer_SR_1VocabularyGetPronunciation},
577    // SR_RecognizerResult
578    {"SR_RecognizerResultGetWaveform",     "(I)[B",                   (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetWaveform},
579    {"SR_RecognizerResultGetSize",         "(I)I",                    (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetSize},
580    {"SR_RecognizerResultGetKeyCount",     "(II)I",                   (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetKeyCount},
581    {"SR_RecognizerResultGetKeyList",      "(II)[Ljava/lang/String;", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetKeyList},
582    {"SR_RecognizerResultGetValue",        "(IILjava/lang/String;)Ljava/lang/String;", (void*)Java_android_speech_srec_Recognizer_SR_1RecognizerResultGetValue},
583};
584
585/*
586 * Returns the JNI version on success, -1 on failure.
587 */
588jint register_android_speech_srec_Recognizer(JavaVM* vm, void* reserved)
589{
590    JNIEnv* env = NULL;
591    jclass clazz = NULL;
592    const char* className = "android/speech/srec/Recognizer";
593
594    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
595        LOGE("ERROR: GetEnv failed\n");
596        return -1;
597    }
598    assert(env != NULL);
599
600    clazz = env->FindClass(className);
601    if (clazz == NULL) {
602        LOGE("Native registration unable to find class '%s'\n", className);
603        return -1;
604    }
605    if (env->RegisterNatives(clazz, gMethods,
606            sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
607        LOGE("RegisterNatives failed for '%s'\n", className);
608        return -1;
609    }
610
611    /* success -- return valid version number */
612    return JNI_VERSION_1_4;
613}
614
615
616extern jint register_android_speech_srec_MicrophoneInputStream(JavaVM* vm, void* reserved);
617
618jint JNI_OnLoad(JavaVM* vm, void* reserved)
619{
620    if (register_android_speech_srec_MicrophoneInputStream(vm, reserved) != JNI_VERSION_1_4 ||
621        register_android_speech_srec_Recognizer(vm, reserved) != JNI_VERSION_1_4) return -1;
622    return JNI_VERSION_1_4;
623}
624