00001 #ifndef PHIDGET_JNI_H
00002 #define PHIDGET_JNI_H
00003
00004 #include <jni.h>
00005
00006 #ifdef _ANDROID
00007 #define JNIEnvPtr const struct JNINativeInterface ***
00008 #else
00009 #define JNIEnvPtr void **
00010 #endif
00011
00012 extern JavaVM *ph_vm;
00013
00014 extern jclass phidget_class;
00015 extern jmethodID phidget_cons;
00016
00017 extern jclass ph_exception_class;
00018 extern jmethodID ph_exception_cons;
00019
00020 extern jclass attachEvent_class;
00021 extern jmethodID attachEvent_cons;
00022
00023 extern jclass detachEvent_class;
00024 extern jmethodID detachEvent_cons;
00025
00026 extern jclass errorEvent_class;
00027 extern jmethodID errorEvent_cons;
00028
00029 extern jclass serverConnectEvent_class;
00030 extern jmethodID serverConnectEvent_cons;
00031
00032 extern jclass serverDisconnectEvent_class;
00033 extern jmethodID serverDisconnectEvent_cons;
00034
00035 void com_phidgets_Phidget_OnLoad(JNIEnv *);
00036 void com_phidgets_AccelerometerPhidget_OnLoad(JNIEnv *);
00037 void com_phidgets_AdvancedServoPhidget_OnLoad(JNIEnv *);
00038 void com_phidgets_AnalogPhidget_OnLoad(JNIEnv *);
00039 void com_phidgets_BridgePhidget_OnLoad(JNIEnv *);
00040 void com_phidgets_EncoderPhidget_OnLoad(JNIEnv *);
00041 void com_phidgets_FrequencyCounterPhidget_OnLoad(JNIEnv *);
00042 void com_phidgets_GPSPhidget_OnLoad(JNIEnv *);
00043 void com_phidgets_InterfaceKitPhidget_OnLoad(JNIEnv *);
00044 void com_phidgets_IRPhidget_OnLoad(JNIEnv *);
00045 void com_phidgets_LEDPhidget_OnLoad(JNIEnv *);
00046 void com_phidgets_MotorControlPhidget_OnLoad(JNIEnv *);
00047 void com_phidgets_PHSensorPhidget_OnLoad(JNIEnv *);
00048 void com_phidgets_RFIDPhidget_OnLoad(JNIEnv *);
00049 void com_phidgets_ServoPhidget_OnLoad(JNIEnv *);
00050 void com_phidgets_SpatialPhidget_OnLoad(JNIEnv *);
00051 void com_phidgets_StepperPhidget_OnLoad(JNIEnv *);
00052 void com_phidgets_TemperatureSensorPhidget_OnLoad(JNIEnv *);
00053 void com_phidgets_TextLCDPhidget_OnLoad(JNIEnv *);
00054 void com_phidgets_TextLEDPhidget_OnLoad(JNIEnv *);
00055 void com_phidgets_WeightSensorPhidget_OnLoad(JNIEnv *);
00056 void com_phidgets_Manager_OnLoad(JNIEnv *);
00057 void com_phidgets_Dictionary_OnLoad(JNIEnv *);
00058 void com_phidgets_DictionaryKeyListener_OnLoad(JNIEnv *);
00059
00060 #ifdef _ANDROID
00061 extern int AndroidUsbJarAvailable;
00062 int com_phidgets_usb_Manager_OnLoad(JNIEnv *);
00063 int com_phidgets_usb_Phidget_OnLoad(JNIEnv *);
00064 #endif
00065
00066 jlong updateGlobalRef(JNIEnv *env, jobject obj, jfieldID fid, jboolean b);
00067
00068 #define JNI_ABORT_STDERR(...) \
00069 do { \
00070 LOG_STDERR(PHIDGET_LOG_CRITICAL, __VA_ARGS__); \
00071 (*env)->ExceptionDescribe(env); \
00072 (*env)->ExceptionClear(env); \
00073 abort(); \
00074 } while(0)
00075
00076 #define EVENT_VARS(event, Event) static jmethodID event##Event_cons; \
00077 static jmethodID fire##Event##_mid; \
00078 static jclass event##Event_class; \
00079 static jfieldID native##Event##Handler_fid;
00080
00081 #define JNI_LOAD(name, Pname) \
00082 extern jfieldID handle_fid; \
00083 static jclass name##_class; \
00084 void com_phidgets_##Pname##Phidget_OnLoad(JNIEnv *env) \
00085 { \
00086 if (!(name##_class = (*env)->FindClass(env, "com/phidgets/" #Pname "Phidget"))) \
00087 JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/" #Pname "Phidget"); \
00088 if (!(name##_class = (jclass)(*env)->NewGlobalRef(env, name##_class))) \
00089 JNI_ABORT_STDERR("Couldn't create NewGlobalRef " #name "_class"); \
00090
00091 #define EVENT_VAR_SETUP(name, event, Event, parameters, returntype) \
00092 if (!(event##Event_class = (*env)->FindClass(env, "com/phidgets/event/" #Event "Event"))) \
00093 JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/event/" #Event "Event"); \
00094 if (!(event##Event_class = (jclass)(*env)->NewGlobalRef(env, event##Event_class))) \
00095 JNI_ABORT_STDERR("Couldn't create global ref " #event "Event_class"); \
00096 if (!(fire##Event##_mid = (*env)->GetMethodID(env, name##_class, "fire" #Event , "(Lcom/phidgets/event/" #Event "Event;)" #returntype ))) \
00097 JNI_ABORT_STDERR("Please install the latest Phidget Library. Couldn't get method ID fire" #Event); \
00098 if (!(event##Event_cons = (*env)->GetMethodID(env, event##Event_class, "<init>", "(Lcom/phidgets/Phidget;" #parameters ")" #returntype ))) \
00099 JNI_ABORT_STDERR("Couldn't get method ID <init> from " #event "Event_class"); \
00100 if (!(native##Event##Handler_fid = (*env)->GetFieldID(env, name##_class, "native" #Event "Handler", "J"))) \
00101 JNI_ABORT_STDERR("Couldn't get Field ID native" #Event "Handler from " #name "_class");
00102
00103 #define PH_THROW(errno) { \
00104 jobject eobj; \
00105 jstring edesc; \
00106 \
00107 if (!(edesc = (*env)->NewStringUTF(env, CPhidget_strerror(errno)))) \
00108 JNI_ABORT_STDERR("Couldn't get NewStringUTF"); \
00109 if (!(eobj = (*env)->NewObject(env, ph_exception_class, ph_exception_cons, errno, edesc))) \
00110 JNI_ABORT_STDERR("Couldn't get NewObject ph_exception_class"); \
00111 (*env)->DeleteLocalRef (env, edesc); \
00112 (*env)->Throw(env, (jthrowable)eobj); \
00113 \
00114 }
00115
00116 #define JNI_INDEXED_SETFUNC(pname, fname, lfname, type) \
00117 JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_set##fname(JNIEnv *env, jobject obj, jint index, type v) \
00118 { \
00119 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t)(*env)->GetLongField(env, obj, handle_fid); \
00120 int error; \
00121 if ((error = CPhidget##pname##_set##lfname(h, index, v))) \
00122 PH_THROW(error); \
00123 }
00124
00125 #define JNI_SETFUNC(pname, fname, lfname, type) \
00126 JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_set##fname(JNIEnv *env, jobject obj, type v) \
00127 { \
00128 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
00129 (*env)->GetLongField(env, obj, handle_fid); \
00130 int error; \
00131 if ((error = CPhidget##pname##_set##lfname(h, v))) \
00132 PH_THROW(error); \
00133 }
00134
00135 #define JNI_INDEXED_GETFUNC(pname, fname, lfname, type) \
00136 JNIEXPORT type JNICALL Java_com_phidgets_##pname##Phidget_get##fname(JNIEnv *env, jobject obj, jint index) \
00137 { \
00138 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
00139 (*env)->GetLongField(env, obj, handle_fid); \
00140 int error; \
00141 type v; \
00142 if ((error = CPhidget##pname##_get##lfname(h, index, &v))) \
00143 PH_THROW(error); \
00144 return v; \
00145 }
00146
00147 #define JNI_INDEXED_GETFUNCBOOL(pname, fname, lfname) \
00148 JNIEXPORT jboolean JNICALL Java_com_phidgets_##pname##Phidget_get##fname(JNIEnv *env, jobject obj, jint index) \
00149 { \
00150 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
00151 (*env)->GetLongField(env, obj, handle_fid); \
00152 int error; \
00153 int v; \
00154 if ((error = CPhidget##pname##_get##lfname(h, index, &v))) \
00155 PH_THROW(error); \
00156 if (v) return 1; \
00157 return 0; \
00158 }
00159
00160 #define JNI_GETFUNC(pname, fname, lfname, type) \
00161 JNIEXPORT type JNICALL Java_com_phidgets_##pname##Phidget_get##fname (JNIEnv *env, jobject obj) \
00162 { \
00163 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
00164 (*env)->GetLongField( env, obj, handle_fid); \
00165 int error; \
00166 type no; \
00167 if ((error = CPhidget##pname##_get##lfname(h, &no))) \
00168 PH_THROW(error); \
00169 return no; \
00170 }
00171
00172 #define JNI_GETFUNCBOOL(pname, fname, lfname) \
00173 JNIEXPORT jboolean JNICALL Java_com_phidgets_##pname##Phidget_get##fname (JNIEnv *env, jobject obj) \
00174 { \
00175 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
00176 (*env)->GetLongField( env, obj, handle_fid); \
00177 int error; \
00178 int no; \
00179 if ((error = CPhidget##pname##_get##lfname(h, &no))) \
00180 PH_THROW(error); \
00181 if(no) return 1; \
00182 return 0; \
00183 }
00184
00185 #define JNI_CREATE(Pname) \
00186 JNIEXPORT jlong JNICALL Java_com_phidgets_##Pname##Phidget_create(JNIEnv *env, jclass cls) \
00187 { \
00188 CPhidget##Pname##Handle phid; \
00189 int error; \
00190 if ((error = CPhidget##Pname##_create(&phid)) != EPHIDGET_OK) { \
00191 PH_THROW(error); \
00192 return 0; \
00193 } \
00194 return (jlong)(uintptr_t)phid; \
00195 }
00196
00197 #define EVENT_HANDLER(pname, event, Event, cphidgetSetHandlerFunc, type) \
00198 static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, type); \
00199 JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_enable##Event##Events(JNIEnv *env, jobject obj, jboolean b) \
00200 { \
00201 jlong gr = updateGlobalRef(env, obj, native##Event##Handler_fid, b); \
00202 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
00203 (*env)->GetLongField(env, obj, handle_fid); \
00204 cphidgetSetHandlerFunc(h, b ? event##_handler : 0, \
00205 (void *)(uintptr_t)gr); \
00206 } \
00207 \
00208 static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, type v) \
00209 { \
00210 JNIEnv *env; \
00211 jobject obj; \
00212 jobject event##Ev; \
00213 \
00214 if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL)) \
00215 JNI_ABORT_STDERR("Couldn't AttachCurrentThread"); \
00216 \
00217 obj = (jobject)arg; \
00218 \
00219 if (!(event##Ev = (*env)->NewObject(env, event##Event_class, event##Event_cons, obj, v))) \
00220 return -1; \
00221 (*env)->CallVoidMethod(env, obj, fire##Event##_mid, event##Ev); \
00222 (*env)->DeleteLocalRef(env, event##Ev); \
00223 \
00224 return 0; \
00225 }
00226
00227 #define EVENT_HANDLER_INDEXED(pname, event, Event, cphidgetSetHandlerFunc, type) \
00228 static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, int, type); \
00229 JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_enable##Event##Events(JNIEnv *env, jobject obj, jboolean b) \
00230 { \
00231 jlong gr = updateGlobalRef(env, obj, native##Event##Handler_fid, b); \
00232 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
00233 (*env)->GetLongField(env, obj, handle_fid); \
00234 cphidgetSetHandlerFunc(h, b ? event##_handler : 0, \
00235 (void *)(uintptr_t)gr); \
00236 } \
00237 \
00238 static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, int index, type v) \
00239 { \
00240 JNIEnv *env; \
00241 jobject obj; \
00242 jobject event##Ev; \
00243 \
00244 if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL)) \
00245 JNI_ABORT_STDERR("Couldn't AttachCurrentThread"); \
00246 \
00247 obj = (jobject)arg; \
00248 \
00249 if (!(event##Ev = (*env)->NewObject(env, event##Event_class, event##Event_cons, obj, index, v))) \
00250 return -1; \
00251 (*env)->CallVoidMethod(env, obj, fire##Event##_mid, event##Ev); \
00252 (*env)->DeleteLocalRef(env, event##Ev); \
00253 \
00254 return 0; \
00255 }
00256
00257 #define EVENT_HANDLER_INDEXED2(pname, event, Event, cphidgetSetHandlerFunc, type, type2) \
00258 static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, int, type, type2); \
00259 JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_enable##Event##Events(JNIEnv *env, jobject obj, jboolean b) \
00260 { \
00261 jlong gr = updateGlobalRef(env, obj, native##Event##Handler_fid, b); \
00262 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
00263 (*env)->GetLongField(env, obj, handle_fid); \
00264 cphidgetSetHandlerFunc(h, b ? event##_handler : 0, \
00265 (void *)(uintptr_t)gr); \
00266 } \
00267 \
00268 static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, int index, type v, type2 w) \
00269 { \
00270 JNIEnv *env; \
00271 jobject obj; \
00272 jobject event##Ev; \
00273 \
00274 if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL)) \
00275 JNI_ABORT_STDERR("Couldn't AttachCurrentThread"); \
00276 \
00277 obj = (jobject)arg; \
00278 \
00279 if (!(event##Ev = (*env)->NewObject(env, event##Event_class, \
00280 event##Event_cons, obj, index, v, w))) \
00281 return -1; \
00282 (*env)->CallVoidMethod(env, obj, fire##Event##_mid, event##Ev); \
00283 (*env)->DeleteLocalRef(env, event##Ev); \
00284 \
00285 return 0; \
00286 }
00287
00288 #define EVENT_HANDLER_3(pname, event, Event, cphidgetSetHandlerFunc, type, type2, type3) \
00289 static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, type, type2, type3); \
00290 JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_enable##Event##Events(JNIEnv *env, jobject obj, jboolean b) \
00291 { \
00292 jlong gr = updateGlobalRef(env, obj, native##Event##Handler_fid, b); \
00293 CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
00294 (*env)->GetLongField(env, obj, handle_fid); \
00295 cphidgetSetHandlerFunc(h, b ? event##_handler : 0, \
00296 (void *)(uintptr_t)gr); \
00297 } \
00298 \
00299 static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, type v, type2 w, type3 x) \
00300 { \
00301 JNIEnv *env; \
00302 jobject obj; \
00303 jobject event##Ev; \
00304 \
00305 if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL)) \
00306 JNI_ABORT_STDERR("Couldn't AttachCurrentThread"); \
00307 \
00308 obj = (jobject)arg; \
00309 \
00310 if (!(event##Ev = (*env)->NewObject(env, event##Event_class, \
00311 event##Event_cons, obj, v, w, x))) \
00312 return -1; \
00313 (*env)->CallVoidMethod(env, obj, fire##Event##_mid, event##Ev); \
00314 (*env)->DeleteLocalRef(env, event##Ev); \
00315 \
00316 return 0; \
00317 }
00318
00319
00320 #endif