Main Page | Namespace List | File List | Namespace Members | File Members

voce.h

Go to the documentation of this file.
00001 /*************************************************************************
00002  *                                                                       *
00003  * Voce                                                                  *
00004  * Copyright (C) 2005                                                    *
00005  * Tyler Streeter  tylerstreeter@gmail.com                               *
00006  * All rights reserved.                                                  *
00007  * Web: voce.sourceforge.net                                             *
00008  *                                                                       *
00009  * This library is free software; you can redistribute it and/or         *
00010  * modify it under the terms of EITHER:                                  *
00011  *   (1) The GNU Lesser General Public License as published by the Free  *
00012  *       Software Foundation; either version 2.1 of the License, or (at  *
00013  *       your option) any later version. The text of the GNU Lesser      *
00014  *       General Public License is included with this library in the     *
00015  *       file license-LGPL.txt.                                          *
00016  *   (2) The BSD-style license that is included with this library in     *
00017  *       the file license-BSD.txt.                                       *
00018  *                                                                       *
00019  * This library is distributed in the hope that it will be useful,       *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
00022  * license-LGPL.txt and license-BSD.txt for more details.                *
00023  *                                                                       *
00024  *************************************************************************/ 
00025 
00026 #ifndef VOCE_H
00027 #define VOCE_H
00028 
00029 // This file contains a C++ interface for Voce's Java functions.  All of 
00030 // the Java methods in Voce's API are instance methods, so we don't need 
00031 // to handle class methods here.  For documentation on the specific 
00032 // functions, refer to the API documentation for the Java source.
00033 
00034 #include <jni.h>
00035 #include <iostream>
00036 #include <string>
00037 
00039 namespace voce
00040 {
00041 #ifdef WIN32
00042 const std::string pathSeparator = ";";
00043 #else
00044 const std::string pathSeparator = ":";
00045 #endif
00046 
00048         namespace internal
00049         {
00051                 JNIEnv* gEnv = NULL;
00052 
00054                 JavaVM *gJVM = NULL;
00055 
00057                 jclass gClass = NULL;
00058 
00061                 jmethodID gInitID = NULL;
00062                 jmethodID gDestroyID = NULL;
00063                 jmethodID gSynthesizeID = NULL;
00064                 jmethodID gStopSynthesizingID = NULL;
00065                 jmethodID gGetRecognizerQueueSizeID = NULL;
00066                 jmethodID gPopRecognizedStringID = NULL;
00067                 jmethodID gSetRecognizerEnabledID = NULL;
00068                 jmethodID gIsRecognizerEnabledID = NULL;
00069 
00071                 const std::string gClassName = "voce/SpeechInterface";
00072 
00075                 void log(const std::string& msgType, const std::string& msg)
00076                 {
00077                         std::cout << "[Voce";
00078 
00079                         if (std::string("") != msgType)
00080                         {
00081                                 std::cout << " " << msgType;
00082                         }
00083 
00084                         std::cout << "] " << msg << std::endl;
00085                 }
00086 
00089                 jmethodID loadJavaMethodID(const std::string& functionName, 
00090                         const std::string& functionSignature)
00091                 {
00092                         if (!gEnv)
00093                         {
00094                                 log("ERROR", "Method ID cannot be found for function: " 
00095                                         + functionName + " before initialization.");
00096                                 return 0;
00097                         }
00098 
00099                         // Call the JNI function GetStaticMethodID, which performs a 
00100                         // lookup for the given Java method.  The lookup is based on 
00101                         // the name of the method as well as the method signature.  If 
00102                         // the method does not exist, GetStaticMethodID 
00103                         // returns zero (0). An immediate return from the native method 
00104                         // at that point causes a NoSuchMethodError to be thrown in the 
00105                         // Java application code.  Note that the JNI uses the method 
00106                         // signature to denote the return type of a Java method. The 
00107                         // signature (I)V, for example, denotes a Java method that takes 
00108                         // one argument of type int and has a return type void. The 
00109                         // general form of a method signature argument is: 
00110                         // "(argument-types)return-type".
00111                         jmethodID methodID = gEnv->GetStaticMethodID(gClass, 
00112                                 functionName.c_str(), functionSignature.c_str());
00113 
00114                         if (0 == methodID)
00115                         {
00116                                 log("ERROR", "Invalid Java method ID requested for: " 
00117                                         + functionName + ".  Function call ignored.");
00118                                 return 0;
00119                         }
00120 
00121                         return methodID;
00122                 }
00123         }
00124 
00132         void init(const std::string& vocePath, bool initSynthesis, 
00133                 bool initRecognition, const std::string& grammarPath, 
00134                 const std::string& grammarName)
00135         {
00136                 // Setup the Java virtual machine.
00137                 JavaVMInitArgs vm_args;
00138                 memset(&vm_args, 0, sizeof(vm_args));
00139                 vm_args.version = JNI_VERSION_1_4;
00140 
00141                 long status = 0;
00142 
00143                 // If recognition is being used, we need to increase the max heap 
00144                 // size.
00145                 if (initRecognition)
00146                 {
00147                         vm_args.nOptions = 2;
00148 
00149                         // Setup the VM options.
00150                         // TODO: check out other options to be used here, like disabling the 
00151                         // JIT compiler.
00152                         JavaVMOption options[2];
00153 
00154                         // Add the required Java class paths.
00155                         std::string classPathString = "-Djava.class.path=";
00156                         classPathString += vocePath;
00157                         classPathString += "/voce.jar";
00158                         char s[1024];
00159                         sprintf(s, classPathString.c_str());
00160                         options[0].optionString = s;
00161                         options[0].extraInfo = NULL;
00162 
00163                         // Add an option to increase the max heap size.
00164                         options[1].optionString = "-Xmx256m";
00165                         options[1].extraInfo = NULL;
00166                         //options[1].optionString = "-Djava.compiler=NONE"; // Disable JIT.
00167                         //options[1].optionString = "-verbose:gc,class,jni";
00168                         vm_args.options = options;
00169                         //vm_args.ignoreUnrecognized = JNI_FALSE;
00170 
00171                         // Create the VM.
00172                         status = JNI_CreateJavaVM(&internal::gJVM, 
00173                                 (void**)&internal::gEnv, &vm_args);
00174                 }
00175                 else
00176                 {
00177                         vm_args.nOptions = 1;
00178 
00179                         // Setup the VM options.
00180                         // TODO: check out other options to be used here, like disabling the 
00181                         // JIT compiler.
00182                         JavaVMOption options[1];
00183 
00184                         // Add the required Java class paths.
00185                         std::string classPathString = "-Djava.class.path=";
00186                         classPathString += vocePath;
00187                         classPathString += "/voce.jar";
00188                         char s[1024];
00189                         sprintf(s, classPathString.c_str());
00190                         options[0].optionString = s;
00191                         options[0].extraInfo = NULL;
00192                         //options[1].optionString = "-Djava.compiler=NONE"; // Disable JIT.
00193                         //options[1].optionString = "-verbose:gc,class,jni";
00194                         vm_args.options = options;
00195                         //vm_args.ignoreUnrecognized = JNI_FALSE;
00196 
00197                         // Create the VM.
00198                         status = JNI_CreateJavaVM(&internal::gJVM, 
00199                                 (void**)&internal::gEnv, &vm_args);
00200                 }
00201 
00202                 if (status < 0)
00203                 {
00204                         internal::log("ERROR", "Java virtual machine cannot be created");
00205                         return;
00206                 }
00207 
00208                 internal::log("", "Java virtual machine created");
00209 
00210                 // Find the main Voce class by name.
00211                 jclass c = internal::gEnv->FindClass(internal::gClassName.c_str());
00212 
00213                 if (0 == c)
00214                 {
00215                         internal::log("ERROR", "The requested Java class: " 
00216                                 + internal::gClassName + " could not be found.  \
00217 Make sure the class path correctly points to the Voce classes.");
00218                         return;
00219                 }
00220 
00221                 // Store a global reference so the class won't go out of 
00222                 // scope and get destroyed.
00223                 internal::gClass = (jclass)internal::gEnv->NewGlobalRef(c);
00224 
00225                 // Cache the global method ID references for the various 
00226                 // functions.  This should save lookup time.
00227                 internal::gInitID = internal::loadJavaMethodID("init", 
00228                         "(Ljava/lang/String;ZZLjava/lang/String;Ljava/lang/String;)V");
00229                 internal::gDestroyID = internal::loadJavaMethodID("destroy", "()V");
00230                 internal::gSynthesizeID = internal::loadJavaMethodID("synthesize", 
00231                         "(Ljava/lang/String;)V");
00232                 internal::gStopSynthesizingID = internal::loadJavaMethodID(
00233                         "stopSynthesizing", "()V");
00234                 internal::gGetRecognizerQueueSizeID = internal::loadJavaMethodID(
00235                         "getRecognizerQueueSize", "()I");
00236                 internal::gPopRecognizedStringID = internal::loadJavaMethodID(
00237                         "popRecognizedString", "()Ljava/lang/String;");
00238                 internal::gSetRecognizerEnabledID = internal::loadJavaMethodID(
00239                         "setRecognizerEnabled", "(Z)V");
00240                 internal::gIsRecognizerEnabledID = internal::loadJavaMethodID(
00241                         "isRecognizerEnabled", "()Z");
00242 
00243                 // Convert the C++ strings to Java strings.
00244                 jstring jStrVocePath = internal::gEnv->NewStringUTF(
00245                         vocePath.c_str());
00246                 jstring jStrGrammarPath = internal::gEnv->NewStringUTF(
00247                         grammarPath.c_str());
00248                 jstring jStrGrammarName = internal::gEnv->NewStringUTF(
00249                         grammarName.c_str());
00250 
00251                 // Initialize the Java Voce stuff.
00252                 internal::gEnv->CallStaticVoidMethod(internal::gClass, 
00253                         internal::gInitID, jStrVocePath, initSynthesis, initRecognition, 
00254                         jStrGrammarPath, jStrGrammarName);
00255         }
00256 
00259         void destroy()
00260         {
00261                 if (!internal::gEnv)
00262                 {
00263                         internal::log("warning", "destroy called before \
00264 initialization.  Request will be ignored.");
00265                         return;
00266                 }
00267 
00268                 // Destroy the Java Voce stuff.
00269                 internal::gEnv->CallStaticVoidMethod(internal::gClass, 
00270                         internal::gDestroyID);
00271 
00272                 // Destroy the global reference to the main Voce Java class and to 
00273                 // the various global method ID references.
00274                 internal::gEnv->DeleteGlobalRef((jobject)internal::gClass);
00275                 internal::gEnv->DeleteGlobalRef((jobject)internal::gInitID);
00276                 internal::gEnv->DeleteGlobalRef((jobject)internal::gDestroyID);
00277                 internal::gEnv->DeleteGlobalRef((jobject)internal::gSynthesizeID);
00278                 internal::gEnv->DeleteGlobalRef(
00279                         (jobject)internal::gStopSynthesizingID);
00280                 internal::gEnv->DeleteGlobalRef(
00281                         (jobject)internal::gGetRecognizerQueueSizeID);
00282                 internal::gEnv->DeleteGlobalRef(
00283                         (jobject)internal::gPopRecognizedStringID);
00284                 internal::gEnv->DeleteGlobalRef(
00285                         (jobject)internal::gSetRecognizerEnabledID);
00286                 internal::gEnv->DeleteGlobalRef(
00287                         (jobject)internal::gIsRecognizerEnabledID);
00288 
00289                 if (internal::gJVM)
00290                 {
00291                         // Destroy the virtual machine.
00292                         internal::gJVM->DestroyJavaVM();
00293                         internal::log("", "Java virtual machine destroyed");
00294                 }
00295         }
00296 
00298         void synthesize(const std::string& message)
00299         {
00300                 if (!internal::gEnv)
00301                 {
00302                         internal::log("warning", "synthesize called before \
00303 initialization.  Request will be ignored.");
00304                 }
00305 
00306                 // Convert the C++ string to a Java string.
00307                 jstring jstr = internal::gEnv->NewStringUTF(message.c_str());
00308 
00309                 // Call the Java method.
00310                 internal::gEnv->CallStaticVoidMethod(internal::gClass, 
00311                         internal::gSynthesizeID, jstr);
00312         }
00313 
00316         void stopSynthesizing()
00317         {
00318                 if (!internal::gEnv)
00319                 {
00320                         internal::log("warning", "synthesize called before \
00321 initialization.  Request will be ignored.");
00322                 }
00323 
00324                 // Call the Java method.
00325                 internal::gEnv->CallStaticVoidMethod(internal::gClass, 
00326                         internal::gStopSynthesizingID);
00327         }
00328 
00331         int getRecognizerQueueSize()
00332         {
00333                 if (!internal::gEnv)
00334                 {
00335                         internal::log("warning", "getRecognizerQueueSize called before \
00336 initialization.  Request will be ignored.");
00337                 }
00338 
00339                 // Call the Java method.
00340                 return internal::gEnv->CallStaticIntMethod(internal::gClass, 
00341                         internal::gGetRecognizerQueueSizeID);
00342         }
00343 
00346         std::string popRecognizedString()
00347         {
00348                 if (!internal::gEnv)
00349                 {
00350                         internal::log("warning", "popRecognizedString called before \
00351 initialization.  Request will be ignored.");
00352                 }
00353 
00354                 // Call the Java method.
00355                 jstring jstr = (jstring)internal::gEnv->CallStaticObjectMethod(
00356                         internal::gClass, internal::gPopRecognizedStringID);
00357 
00358                 // Convert string from Java to C++.  Be sure to release memory 
00359                 // when finished.
00360 
00361                 //char buf[128];
00362                 const char* tempStr = internal::gEnv->GetStringUTFChars(jstr, 0);
00363                 std::string cppStr = tempStr;
00364                 //printf("%s", str);
00365                 internal::gEnv->ReleaseStringUTFChars(jstr, tempStr);
00366 
00367                 return cppStr;
00368         }
00369 
00371         void setRecognizerEnabled(bool e)
00372         {
00373                 if (!internal::gEnv)
00374                 {
00375                         internal::log("warning", "setRecognizerEnabled called before \
00376 initialization.  Request will be ignored.");
00377                 }
00378 
00379                 // Call the Java method.
00380                 internal::gEnv->CallStaticIntMethod(internal::gClass, 
00381                         internal::gSetRecognizerEnabledID, e);
00382         }
00383 
00385         bool isRecognizerEnabled()
00386         {
00387                 if (!internal::gEnv)
00388                 {
00389                         internal::log("warning", "isRecognizerEnabled called before \
00390 initialization.  Request will be ignored.");
00391                 }
00392 
00393                 // Call the Java method.
00394                 jboolean b = internal::gEnv->CallStaticBooleanMethod(internal::gClass, 
00395                         internal::gIsRecognizerEnabledID);
00396 
00397                 if (JNI_FALSE == b)
00398                 {
00399                         return false;
00400                 }
00401                 else
00402                 {
00403                         return true;
00404                 }
00405         }
00406 }
00407 
00408 #endif

Generated on Wed Aug 3 16:23:08 2005 for Voce C++ API by  doxygen 1.4.1