Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

androidvmdstart.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 /***************************************************************************
00009  * RCS INFORMATION:
00010  *
00011  *      $RCSfile: androidvmdstart.C,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.11 $      $Date: 2020/02/26 06:39:27 $
00014  *
00015  ***************************************************************************/
00021 // only compile this file if we're building on Android
00022 #if defined(ANDROID)
00023 #include "androidvmdstart.h"
00024 #include "vmd.h"
00025 
00026 //
00027 // VMD is wrapped in a JNI shared object and called by Java...
00028 //
00029 #include <stdio.h>
00030 #include <jni.h>
00031 
00032 #if !defined(VMD_JNI_CLASSNAME)
00033 #define VMD_JNI_CLASSNAME "edu/uiuc/VMD/VMD"
00034 #endif
00035 #if !defined(VMD_JNI_WRAPFUNC)
00036 #define VMD_JNI_WRAPFUNC Java_edu_uiuc_VMD_VMD_nativeMain
00037 #endif
00038 
00039 #define NUM_METHODS 5
00040 #define METH_logOutput 0
00041 #define METH_getNumMsgs 1
00042 #define METH_getPlatformValue 2
00043 #define METH_getMsgBlock 3
00044 #define METH_getMsgNonBlock 4
00045 
00046 struct AndroidHandle {
00047   JNIEnv *env;
00048   jobject thiz;
00049   jmethodID meths[NUM_METHODS];
00050 } global_AndHand;
00051 
00052 // ----------------------------------------------------------------------
00053 void logtojava(AndroidHandle &ah, const char *logstring)
00054 {
00055   /* this actually logs a char*, logstring */
00056   (ah.env)->CallVoidMethod(ah.thiz,
00057                         ah.meths[METH_logOutput],
00058                        (ah.env)->NewStringUTF( logstring));
00059 }
00060 
00061 /* ------------------------------------------------------------ */
00062 /* output is allocated elsewhere */
00063 /* key: FilesDir    - gets internal phone memory space for the app. The zip
00064                       file from server is unzipped to this dir                */
00065 /* key: VMDDIR      - gets internal phone memory space, where VMD files live
00066                       (currently exactly same as FilesDir                     */
00067 /* key: ExternalStorageDir  - gets SDcard memory space (global, use with care)*/
00068 char *getPlatformValue(AndroidHandle &ah, const char *key, char *output)
00069 {
00070 
00071   /* NewStringUTF makes a java string from a char* */
00072   jobject j = (ah.env)->CallObjectMethod(ah.thiz,
00073                                   ah.meths[METH_getPlatformValue],
00074                                  (ah.env)->NewStringUTF(key));
00075 
00076   const char* str = (ah.env)->GetStringUTFChars((jstring) j, NULL);
00077 
00078   strcpy(output, str);
00079 
00080   (ah.env)->ReleaseStringUTFChars((jstring) j, str);
00081   return output;
00082 }
00083 
00084 /* ------------------------------------------------------------ */
00085 /* Get string Message from Android frontend.  Blocks until message
00086  * is actually sent.
00087  * 'output' is allocated elsewhere.  
00088  * Returns pointer to 'output' as convenience.
00089  */
00090 char *getMessage(AndroidHandle &ah, char *output)
00091 {
00092   jobject j = (ah.env)->CallObjectMethod(ah.thiz,
00093                                   ah.meths[METH_getMsgBlock]);
00094 
00095   const char* str = (ah.env)->GetStringUTFChars((jstring) j, NULL);
00096 
00097   strcpy(output, str);
00098 
00099   (ah.env)->ReleaseStringUTFChars((jstring) j, str);
00100   return output;
00101 }
00102 
00103 /* ------------------------------------------------------------ */
00104 /* Get string Message from Android frontend if one is ready.
00105  * 'output' is allocated elsewhere.  Returns 'output' if message
00106  * existed.  Returns 0 (and doesn't modify 'output') if no
00107  * message was waiting. 
00108  * XXX need think about how to use
00109  */
00110 char *getMessageNonBlock(AndroidHandle &ah, char *output)
00111 {
00112   jobject j = (ah.env)->CallObjectMethod(ah.thiz,
00113                                     ah.meths[METH_getMsgNonBlock]);
00114 
00115   if (!j) {
00116     return 0;
00117   }
00118 
00119   const char* str = (ah.env)->GetStringUTFChars((jstring) j, NULL);
00120 
00121   strcpy(output, str);
00122 
00123   (ah.env)->ReleaseStringUTFChars((jstring) j, str);
00124   return output;
00125 }
00126 
00127 /* ------------------------------------------------------------ */
00128 /*  Get the number of messages that the Android frontend has queued
00129  *  up ready to be consumed by one of the getMessage fcts.
00130 */
00131 jint getNumMessages(AndroidHandle &ah)
00132 {
00133   return (ah.env)->CallIntMethod(ah.thiz,
00134                                 ah.meths[METH_getNumMsgs]);
00135 }
00136 
00137 // ----------------------------------------------------------------------
00138 /* Internally used fct called at startup to perform expensive tasks once.
00139  */
00140 void cacheAndroidMethodIDs(AndroidHandle &ah)
00141 {
00142   // cache method IDs. Could be done in fct, of course
00143   // these calls are expensive
00144   jclass clazz = (ah.env)->FindClass("edu/uiuc/VMD/VMD");
00145   ah.meths[METH_logOutput] = (ah.env)->GetMethodID(
00146                         clazz, "logOutput", "(Ljava/lang/String;)V");
00147   ah.meths[METH_getNumMsgs] = (ah.env)->GetMethodID(
00148                         clazz, "getNumMsgs", "()I");
00149   ah.meths[METH_getPlatformValue] = (ah.env)->GetMethodID(
00150                         clazz, "getPlatformValue",
00151                         "(Ljava/lang/String;)Ljava/lang/String;");
00152   ah.meths[METH_getMsgBlock] = (ah.env)->GetMethodID(
00153                         clazz, "getMsgBlock", "()Ljava/lang/String;");
00154   ah.meths[METH_getMsgNonBlock] = (ah.env)->GetMethodID(
00155                         clazz, "getMsgNonBlock", "()Ljava/lang/String;");
00156 }
00157 
00158 extern "C" {
00159 
00160 //
00161 // Wrapper function to hide use of the cached global state until
00162 // until we make appropriate changes so that the JNI launcher has
00163 // a mechanism to provide VMD with the JNI objects for use by calls
00164 // back to android APIs.
00165 //
00166 void log_android(const char *prompt, const char * msg) {
00167   char logstring[2048];
00168 
00169   strncpy(logstring, prompt, sizeof(logstring)-2);
00170   strcat(logstring, msg);
00171   strcat(logstring, "\n");
00172 
00173   logtojava(global_AndHand, logstring);
00174 }
00175 
00176 
00177 //
00178 // This is the main JNI wrapper function.
00179 // Contains startup code, neverending loop, shutdown code, etc...
00180 //
00181 void VMD_JNI_WRAPFUNC(JNIEnv* env, jobject thiz) {
00182   char* rargv[10];
00183  
00184   global_AndHand.env = env;   // XXX this is a hack!
00185   global_AndHand.thiz = thiz; // XXX this is a hack!
00186 
00187   cacheAndroidMethodIDs(global_AndHand);    // XXX this caches into a hack!
00188 
00189   fprintf(stderr, "--stderr fprintf---------------------------------\n");
00190   printf("---regular printf----------------------------\n");
00191   fflush(stdout);
00192   log_android("", "--Log event ---------------------");
00193 
00194 #if 1
00195   printf("VMD Android platform info:\n");
00196   printf("  sizeof(char): %d\n", sizeof(char));
00197   printf("  sizeof(int): %d\n", sizeof(int));
00198   printf("  sizeof(long): %d\n", sizeof(long));
00199   printf("  sizeof(void*): %d\n", sizeof(void*));
00200   fflush(stdout);
00201 #endif
00202 
00203   char tmp[8192];
00204   const char * vmddir = NULL;
00205 
00206   // set to a worst-case guess until we have something better.
00207   vmddir = "/data/data/edu.uiuc.VMD/files/vmd";
00208 
00209 #if 1
00210   // Query Android for app directories and files here...
00211   char androidappdatadir[8192];
00212 
00213   memset(androidappdatadir, 0, sizeof(androidappdatadir));
00214   getPlatformValue(global_AndHand, "FilesDir", androidappdatadir);
00215 
00216   if (strlen(androidappdatadir) > 0) {
00217 //    log_android("ANDROID APP DIR: ", androidappdatadir);
00218     strcat(androidappdatadir, "/vmd");
00219     vmddir = androidappdatadir;
00220   }
00221 #endif
00222 
00223   if (vmddir == NULL) {
00224     return; // fail/exit
00225   }
00226 
00227   if (!getenv("VMDDIR")) {
00228     setenv("VMDDIR", vmddir, 1);
00229   }
00230 
00231   if (!getenv("TCL_LIBRARY")) {
00232     strcpy(tmp, vmddir);
00233     strcat(tmp, "/scripts/tcl");
00234     setenv("TCL_LIBRARY", tmp, 1);
00235   }
00236 
00237   if (!getenv("TK_LIBRARY")) {
00238     strcpy(tmp, vmddir);
00239     strcat(tmp, "/scripts/tk");
00240     setenv("TK_LIBRARY", tmp, 1);
00241   }
00242 
00243   if (!getenv("PYTHONPATH")) {
00244     strcpy(tmp, vmddir);
00245     strcat(tmp, "/scripts/python");
00246     setenv("PYTHONPATH", tmp, 1);
00247   } else {
00248     strcpy(tmp, getenv("PYTHONPATH"));
00249     strcat(tmp, ":");
00250     strcat(tmp, vmddir);
00251     strcat(tmp, "/scripts/python");
00252     setenv("PYTHONPATH", tmp, 1);
00253   }
00254 
00255   if (!getenv("STRIDE_BIN")) {
00256     strcpy(tmp, vmddir);
00257 #if defined(ARCH_ANDROIDARMV7A)
00258     strcat(tmp, "/stride_ANDROIDARMV7A");
00259 #else
00260 #error unhandled compilation scenario
00261 #endif
00262     setenv("STRIDE_BIN", tmp, 1);
00263   }
00264 
00265   if (!getenv("SURF_BIN")) {
00266     strcpy(tmp, vmddir);
00267 #if defined(ARCH_ANDROIDARMV7A)
00268     strcat(tmp, "/surf_ANDROIDARMV7A");
00269 #else
00270 #error unhandled compilation scenario
00271 #endif
00272     setenv("SURF_BIN", tmp, 1);
00273   }
00274 
00275   if (!getenv("TACHYON_BIN")) {
00276     strcpy(tmp, vmddir);
00277 #if defined(ARCH_ANDROIDARMV7A)
00278     strcat(tmp, "/tachyon_ANDROIDARMV7A");
00279 #else
00280 #error unhandled compilation scenario
00281 #endif
00282     setenv("TACHYON_BIN", tmp, 1);
00283   }
00284 
00285   rargv[0] = (char *) "VMD.so";
00286 #if 1
00287   rargv[1] = (char *) "1e79";
00288 #elif 1
00289   rargv[1] = (char *) "/data/data/edu.uiuc.VMD/files/alanin.pdb";
00290 #else
00291   rargv[1] = (char *) "-h";
00292 #endif
00293   rargv[2] = NULL;
00294 
00295   VMDmain(2, rargv); /* launch VMD... */
00296 
00297   log_android("", "--Log event ---------------------");
00298   fprintf(stderr, "--stderr fprintf---------------------------------\n");
00299   printf("---regular printf----------------------------\n");
00300   fflush(stdout);
00301 }
00302 
00303 } // extern "C"
00304 
00305 #endif
00306 

Generated on Thu Mar 28 02:42:29 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002