int arUtilChangeToResourcesDirectory(AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR behavior, const char *path) #endif { char *wpath; AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR behaviorW; if (behavior == AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_BEST) { #if defined(__APPLE__) behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_BUNDLE_RESOURCES_DIR; #elif defined(ANDROID) behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_APP_CACHE_DIR; #elif defined(_WIN32) || defined(__linux) behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_EXECUTABLE_DIR; #else behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_CWD; #endif } else { behaviorW = behavior; } if (behaviorW != AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_SUPPLIED_PATH) { #ifdef ANDROID wpath = arUtilGetResourcesDirectoryPath(behavior, instanceOfAndroidContext); #else wpath = arUtilGetResourcesDirectoryPath(behavior); #endif if (wpath) { if (chdir(wpath) != 0) { ARLOGe("Error: Unable to change working directory to '%s'.\n", wpath); ARLOGperror(NULL); free (wpath); return (-1); } free(wpath); } } if (path) { if (chdir(path) != 0) { ARLOGe("Error: Unable to change working directory to '%s'.\n", path); ARLOGperror(NULL); return (-1); } } return (0); }
AR2SurfaceSetT *ar2ReadSurfaceSet( const char *filename, const char *ext, ARPattHandle *pattHandle ) { AR2SurfaceSetT *surfaceSet; FILE *fp = NULL; int readMode; char buf[256], name[256]; int i, j, k; if( ext == NULL || *ext == '\0' || strcmp(ext,"fset") == 0 ) { strncpy(name, filename, sizeof(name) - 1); name[sizeof(name) - 1] = '\0'; readMode = 0; } else { char namebuf[512]; sprintf(namebuf, "%s.%s", filename, ext); if ((fp = fopen(namebuf,"r")) == NULL) { ARLOGe("Error opening file '%s': ", filename); ARLOGperror(NULL); return (NULL); } readMode = 1; } arMalloc(surfaceSet, AR2SurfaceSetT, 1); if( readMode ) { if( get_buff(buf, 256, fp) == NULL ) { fclose(fp); free(surfaceSet); return (NULL); } if( sscanf(buf, "%d", &i) != 1 ) { fclose(fp); free(surfaceSet); return (NULL); } if( i < 1 ) { fclose(fp); free(surfaceSet); return (NULL); } surfaceSet->num = i; surfaceSet->contNum = 0; } else { surfaceSet->num = 1; surfaceSet->contNum = 0; } arMalloc(surfaceSet->surface, AR2SurfaceT, surfaceSet->num); for( i = 0; i < surfaceSet->num; i++ ) { ARLOGi("\n### Surface No.%d ###\n", i+1); if( readMode ) { if( get_buff(buf, 256, fp) == NULL ) break; if( sscanf(buf, "%s", name) != 1 ) break; ar2UtilRemoveExt( name ); } ARLOGi(" Read ImageSet.\n"); surfaceSet->surface[i].imageSet = ar2ReadImageSet( name ); if( surfaceSet->surface[i].imageSet == NULL ) { ARLOGe("Error opening file '%s.iset'.\n", name); free(surfaceSet->surface); free(surfaceSet); if (fp) fclose(fp); //COVHI10426 return (NULL); } ARLOGi(" end.\n"); ARLOGi(" Read FeatureSet.\n"); surfaceSet->surface[i].featureSet = ar2ReadFeatureSet( name, "fset" ); if( surfaceSet->surface[i].featureSet == NULL ) { ARLOGe("Error opening file '%s.fset'.\n", name); ar2FreeImageSet(&surfaceSet->surface[i].imageSet); free(surfaceSet->surface); free(surfaceSet); if (fp) fclose(fp); //COVHI10426 return (NULL); } ARLOGi(" end.\n"); if (pattHandle) { ARLOGi(" Read MarkerSet.\n"); ar2UtilRemoveExt( name ); surfaceSet->surface[i].markerSet = ar2ReadMarkerSet( name, "mrk", pattHandle ); if( surfaceSet->surface[i].markerSet == NULL ) { ARLOGe("Error opening file '%s.mrk'.\n", name); ar2FreeFeatureSet(&surfaceSet->surface[i].featureSet); ar2FreeImageSet(&surfaceSet->surface[i].imageSet); free(surfaceSet->surface); free(surfaceSet); if (fp) fclose(fp); //COVHI10426 return (NULL); } ARLOGi(" end.\n"); } else { surfaceSet->surface[i].markerSet = NULL; } if (readMode) { if( get_buff(buf, 256, fp) == NULL ) break; if( sscanf(buf, "%f %f %f %f", &(surfaceSet->surface[i].trans[0][0]), &(surfaceSet->surface[i].trans[0][1]), &(surfaceSet->surface[i].trans[0][2]), &(surfaceSet->surface[i].trans[0][3])) != 4 ) { ARLOGe("Transformation matrix read error!!\n"); fclose(fp); exit(0); } if( get_buff(buf, 256, fp) == NULL ) break; if( sscanf(buf, "%f %f %f %f", &(surfaceSet->surface[i].trans[1][0]), &(surfaceSet->surface[i].trans[1][1]), &(surfaceSet->surface[i].trans[1][2]), &(surfaceSet->surface[i].trans[1][3])) != 4 ) { ARLOGe("Transformation matrix read error!!\n"); fclose(fp); exit(0); } if( get_buff(buf, 256, fp) == NULL ) break; if( sscanf(buf, "%f %f %f %f", &(surfaceSet->surface[i].trans[2][0]), &(surfaceSet->surface[i].trans[2][1]), &(surfaceSet->surface[i].trans[2][2]), &(surfaceSet->surface[i].trans[2][3])) != 4 ) { ARLOGe("Transformation matrix read error!!\n"); fclose(fp); exit(0); } } else { for( j = 0; j < 3; j++ ) { for( k = 0; k < 4; k++ ) { surfaceSet->surface[i].trans[j][k] = (j == k)? 1.0f: 0.0f; } } } arUtilMatInvf( (const float (*)[4])surfaceSet->surface[i].trans, surfaceSet->surface[i].itrans ); ar2UtilReplaceExt( name, 256, "jpg"); arMalloc( surfaceSet->surface[i].jpegName, char, 256); strncpy( surfaceSet->surface[i].jpegName, name, 256 ); } if (fp) fclose(fp); //COVHI10459 if (i < surfaceSet->num) exit(0); return surfaceSet; }
ARMultiMarkerInfoT *arMultiReadConfigFile( const char *filename, ARPattHandle *pattHandle ) { FILE *fp; ARMultiEachMarkerInfoT *marker; ARMultiMarkerInfoT *marker_info; ARdouble wpos3d[4][2]; char buf[256], pattPath[2048], dummy; int num; int patt_type = 0; int i, j; if ((fp = fopen(filename, "r")) == NULL) { ARLOGe("Error: unable to open multimarker config file '%s'.\n", filename); ARLOGperror(NULL); return NULL; } get_buff(buf, 256, fp); if( sscanf(buf, "%d", &num) != 1 ) { ARLOGe("Error processing multimarker config file '%s': First line must be number of marker configs to read.\n", filename); fclose(fp); return NULL; } ARLOGd("Reading %d markers from multimarker file '%s'\n", num, filename); arMalloc(marker, ARMultiEachMarkerInfoT, num); for( i = 0; i < num; i++ ) { get_buff(buf, 256, fp); if (sscanf(buf, #if defined(__LP64__) && !defined(__APPLE__) "%lu%c", #else "%llu%c", #endif &(marker[i].globalID), &dummy) != 1) { // Try first as matrix code. if (!pattHandle) { ARLOGe("Error processing multimarker config file '%s': pattern '%s' specified in multimarker configuration while in barcode-only mode.\n", filename, buf); goto bail; } if (!arUtilGetDirectoryNameFromPath(pattPath, filename, sizeof(pattPath), 1)) { // Get directory prefix. ARLOGe("Error processing multimarker config file '%s': Unable to determine directory name.\n", filename); goto bail; } strncat(pattPath, buf, sizeof(pattPath) - strlen(pattPath) - 1); // Add name of file to open. if ((marker[i].patt_id = arPattLoad(pattHandle, pattPath)) < 0) { ARLOGe("Error processing multimarker config file '%s': Unable to load pattern '%s'.\n", filename, pattPath); goto bail; } marker[i].patt_type = AR_MULTI_PATTERN_TYPE_TEMPLATE; patt_type |= 0x01; } else { if ((marker[i].globalID & 0xffff8000ULL) == 0ULL) marker[i].patt_id = (int)(marker[i].globalID & 0x00007fffULL); // If upper 33 bits are zero, use lower 31 bits as regular matrix code. else marker[i].patt_id = 0; ARLOGd("Marker %3d is matrix code %llu.\n", i + 1, marker[i].globalID); marker[i].patt_type = AR_MULTI_PATTERN_TYPE_MATRIX; patt_type |= 0x02; } get_buff(buf, 256, fp); if( sscanf(buf, #ifdef ARDOUBLE_IS_FLOAT "%f", #else "%lf", #endif &marker[i].width) != 1 ) { ARLOGe("Error processing multimarker config file '%s', marker definition %3d: First line must be pattern width.\n", filename, i + 1); goto bail; } j = 0; get_buff(buf, 256, fp); if( sscanf(buf, #ifdef ARDOUBLE_IS_FLOAT "%f %f %f %f", #else "%lf %lf %lf %lf", #endif &marker[i].trans[j][0], &marker[i].trans[j][1], &marker[i].trans[j][2], &marker[i].trans[j][3]) != 4 ) { // Perhaps this is an old ARToolKit v2.x multimarker file? // If so, then the next line is two values (center) and should be skipped. float t1, t2; if( sscanf(buf, "%f %f", &t1, &t2) != 2 ) { ARLOGe("Error processing multimarker config file '%s', marker definition %3d: Lines 2 - 4 must be marker transform.\n", filename, i + 1); goto bail; } } else j++; do { get_buff(buf, 256, fp); if( sscanf(buf, #ifdef ARDOUBLE_IS_FLOAT "%f %f %f %f", #else "%lf %lf %lf %lf", #endif &marker[i].trans[j][0], &marker[i].trans[j][1], &marker[i].trans[j][2], &marker[i].trans[j][3]) != 4 ) { ARLOGe("Error processing multimarker config file '%s', marker definition %3d: Lines 2 - 4 must be marker transform.\n", filename, i + 1); goto bail; } j++; } while (j < 3); arUtilMatInv( (const ARdouble (*)[4])marker[i].trans, marker[i].itrans ); wpos3d[0][0] = -marker[i].width/2.0; wpos3d[0][1] = marker[i].width/2.0; wpos3d[1][0] = marker[i].width/2.0; wpos3d[1][1] = marker[i].width/2.0; wpos3d[2][0] = marker[i].width/2.0; wpos3d[2][1] = -marker[i].width/2.0; wpos3d[3][0] = -marker[i].width/2.0; wpos3d[3][1] = -marker[i].width/2.0; for( j = 0; j < 4; j++ ) { marker[i].pos3d[j][0] = marker[i].trans[0][0] * wpos3d[j][0] + marker[i].trans[0][1] * wpos3d[j][1] + marker[i].trans[0][3]; marker[i].pos3d[j][1] = marker[i].trans[1][0] * wpos3d[j][0] + marker[i].trans[1][1] * wpos3d[j][1] + marker[i].trans[1][3]; marker[i].pos3d[j][2] = marker[i].trans[2][0] * wpos3d[j][0] + marker[i].trans[2][1] * wpos3d[j][1] + marker[i].trans[2][3]; } } fclose(fp); arMalloc(marker_info, ARMultiMarkerInfoT, 1); marker_info->marker = marker; marker_info->marker_num = num; marker_info->prevF = 0; if( (patt_type & 0x03) == 0x03 ) marker_info->patt_type = AR_MULTI_PATTERN_DETECTION_MODE_TEMPLATE_AND_MATRIX; else if( patt_type & 0x01 ) marker_info->patt_type = AR_MULTI_PATTERN_DETECTION_MODE_TEMPLATE; else marker_info->patt_type = AR_MULTI_PATTERN_DETECTION_MODE_MATRIX; marker_info->cfPattCutoff = AR_MULTI_CONFIDENCE_PATTERN_CUTOFF_DEFAULT; marker_info->cfMatrixCutoff = AR_MULTI_CONFIDENCE_MATRIX_CUTOFF_DEFAULT; return marker_info; bail: fclose(fp); free(marker); return NULL; }
char *arUtilGetResourcesDirectoryPath(AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR behavior) #endif { #ifndef _WINRT char *wpath1; char *wpath2; # ifdef _WIN32 DWORD len; # endif #endif AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR behaviorW; if (behavior == AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_BEST) { #if defined(__APPLE__) behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_BUNDLE_RESOURCES_DIR; #elif defined(ANDROID) behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_APP_CACHE_DIR; #elif defined(_WIN32) || defined(__linux) behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_EXECUTABLE_DIR; #else behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_CWD; #endif } else { behaviorW = behavior; } switch (behaviorW) { case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_EXECUTABLE_DIR: #if (defined(_WIN32) && !defined(_WINRT)) || defined(__APPLE__) || defined(__linux) arMallocClear(wpath1, char, MAXPATHLEN); # if defined(_WIN32) len = GetModuleFileName(NULL, wpath1, MAXPATHLEN); // NULL implies the current process. if (!len) { free (wpath1); return (NULL); } # elif defined(__APPLE__) uint32_t size = MAXPATHLEN; if (_NSGetExecutablePath(wpath1, &size) != 0) { free (wpath1); return (NULL); } # elif defined(__linux) ssize_t len; len = readlink("/proc/self/exe", wpath1, MAXPATHLEN - 1); // -1 as it is not NULL terminated. if (len == -1) { ARLOGperror(NULL); free (wpath1); return (NULL); } wpath1[len] = '\0'; // NULL terminate. # endif arMallocClear(wpath2, char, MAXPATHLEN); if (!arUtilGetDirectoryNameFromPath(wpath2, wpath1, MAXPATHLEN, 0)) { free (wpath1); free (wpath2); return (NULL); } free (wpath1); return (wpath2); #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_BUNDLE_RESOURCES_DIR: return (NULL); // Unsupported OS. break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_CWD: #ifndef _WINRT arMallocClear(wpath1, char, MAXPATHLEN); if (!getcwd(wpath1, MAXPATHLEN)) { free(wpath1); return (NULL); } return (wpath1); #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_USER_ROOT: #if defined(_WIN32) && !defined(_WINRT) arMallocClear(wpath1, char, MAXPATHLEN); if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, wpath1))) { free (wpath1); return (NULL); } return (wpath1); #elif defined(ANDROID) { // Make JNI calls to get the external storage directory. // To begin, get a reference to the env and attach to it. JNIEnv *env; int isAttached = 0; jthrowable exception; if (((*gJavaVM)->GetEnv(gJavaVM, (void**)&env, JNI_VERSION_1_6)) < 0) { // Couldn't get JNI environment, so this thread is native. if (((*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL)) < 0) { ARLOGe("Error: Couldn't attach to Java VM.\n"); return (NULL); } isAttached = 1; } // Get File object for the external storage directory. jclass classEnvironment = (*env)->FindClass(env, "android/os/Environment"); if (!classEnvironment) goto bailAndroid; jmethodID methodIDgetExternalStorageDirectory = (*env)->GetStaticMethodID(env, classEnvironment, "getExternalStorageDirectory", "()Ljava/io/File;"); // public static File getExternalStorageDirectory () if (!methodIDgetExternalStorageDirectory) goto bailAndroid; jobject objectFile = (*env)->CallStaticObjectMethod(env, classEnvironment, methodIDgetExternalStorageDirectory); exception = (*env)->ExceptionOccurred(env); if (exception) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } // Call method on File object to retrieve String object. jclass classFile = (*env)->GetObjectClass(env, objectFile); if (!classFile) goto bailAndroid; jmethodID methodIDgetAbsolutePath = (*env)->GetMethodID(env, classFile, "getAbsolutePath", "()Ljava/lang/String;"); if (!methodIDgetAbsolutePath) goto bailAndroid; jstring stringPath = (*env)->CallObjectMethod(env, objectFile, methodIDgetAbsolutePath); exception = (*env)->ExceptionOccurred(env); if (exception) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } // Extract a C string from the String object and copy it. const char *wpath3 = (*env)->GetStringUTFChars(env, stringPath, NULL); wpath1 = strdup(wpath3); (*env)->ReleaseStringUTFChars(env, stringPath, wpath3); goto retAndroid; bailAndroid: ARLOGe("Error: JNI call failure.\n"); wpath1 = NULL; retAndroid: if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); // Clean up. return (wpath1); } #elif defined(__linux) || defined(__APPLE__) if (!((wpath1 = getenv("HOME")))) { return (NULL); } return (strdup(wpath1)); #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_APP_CACHE_DIR: #if defined(_WIN32) return (NULL); #elif defined(ANDROID) { // Make JNI calls to get the Context's cache directory. // To begin, get a reference to the env and attach to it. JNIEnv *env; int isAttached = 0; int ret = 0; jthrowable exception; if (((*gJavaVM)->GetEnv(gJavaVM, (void**)&env, JNI_VERSION_1_6)) < 0) { // Couldn't get JNI environment, so this thread is native. if (((*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL)) < 0) { ARLOGe("Error: Couldn't attach to Java VM.\n"); return (NULL); } isAttached = 1; } // Get File object for the Context's files directory. This only works // if a subclass of Context is supplied. // e.g. JNIEXPORT void JNICALL Java_com_test_TestActivity_test(JNIEnv * env, jobject obj) // so make sure before call. jclass classOfSuppliedObject = (*env)->GetObjectClass(env, instanceOfAndroidContext); if (!classOfSuppliedObject) goto bailAndroid1; jclass classContext = (*env)->FindClass(env, "android/content/Context"); if (!classContext) goto bailAndroid1; if (!(*env)->IsInstanceOf(env, instanceOfAndroidContext, classContext)) { ARLOGe("Error: supplied object is not an instance of android/content/Context.\n"); wpath1 = NULL; // Bad parameter. goto retAndroid1; } jmethodID methodGetDir = (*env)->GetMethodID(env, classOfSuppliedObject, "getCacheDir", "()Ljava/io/File;"); // public abstract File getCacheDir(); //jmethodID methodGetDir = (*env)->GetMethodID(env, classOfSuppliedObject, "getFilesDir", "(Ljava/lang/String;)Ljava/io/File;"); // public abstract File getFilesDir(String type); if (!methodGetDir) goto bailAndroid1; jobject objectFile = (*env)->CallObjectMethod(env, instanceOfAndroidContext, methodGetDir); exception = (*env)->ExceptionOccurred(env); if (exception) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } // Call method on File object to retrieve String object. jclass classFile = (*env)->GetObjectClass(env, objectFile); if (!classFile) goto bailAndroid1; jmethodID methodIDgetAbsolutePath = (*env)->GetMethodID(env, classFile, "getAbsolutePath", "()Ljava/lang/String;"); if (!methodIDgetAbsolutePath) goto bailAndroid1; jstring stringPath = (*env)->CallObjectMethod(env, objectFile, methodIDgetAbsolutePath); exception = (*env)->ExceptionOccurred(env); if (exception) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } // Extract a C string from the String object, and chdir() to it. const char *wpath3 = (*env)->GetStringUTFChars(env, stringPath, NULL); wpath1 = strdup(wpath3); (*env)->ReleaseStringUTFChars(env, stringPath, wpath3); goto retAndroid1; bailAndroid1: ARLOGe("Error: JNI call failure.\n"); wpath1 = NULL; retAndroid1: if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); // Clean up. return (wpath1); } #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_APP_DATA_DIR: #ifdef _WINRT //auto folder = Windows::Storage::ApplicationData::Current->LocalFolder; //wpath1 = strdup(folder->Path->Data().c_str()); //return (wpath1); return (NULL); // Unsupported OS. #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_SUPPLIED_PATH: default: return (NULL); // Undefined behaviour. break; } }
char *arUtilGetResourcesDirectoryPath(AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR behavior) #endif { #ifndef _WINRT char *wpath1; char *wpath2; # ifdef _WIN32 DWORD len; # endif #endif AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR behaviorW; if (behavior == AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_BEST) { #if defined(__APPLE__) behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_BUNDLE_RESOURCES_DIR; #elif defined(ANDROID) behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_APP_CACHE_DIR; #elif defined(_WIN32) || defined(__linux) behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_EXECUTABLE_DIR; #else behaviorW = AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_CWD; #endif } else { behaviorW = behavior; } switch (behaviorW) { case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_EXECUTABLE_DIR: #if (defined(_WIN32) && !defined(_WINRT)) || defined(__APPLE__) || defined(__linux) arMallocClear(wpath1, char, MAXPATHLEN); # if defined(_WIN32) len = GetModuleFileName(NULL, wpath1, MAXPATHLEN); // NULL implies the current process. if (!len) { free (wpath1); return (NULL); } # elif defined(__APPLE__) uint32_t size = MAXPATHLEN; if (_NSGetExecutablePath(wpath1, &size) != 0) { free (wpath1); return (NULL); } # elif defined(__linux) ssize_t len; len = readlink("/proc/self/exe", wpath1, MAXPATHLEN - 1); // -1 as it is not NULL terminated. if (len == -1) { ARLOGperror(NULL); free (wpath1); return (NULL); } wpath1[len] = '\0'; // NULL terminate. # endif arMallocClear(wpath2, char, MAXPATHLEN); if (!arUtilGetDirectoryNameFromPath(wpath2, wpath1, MAXPATHLEN, 0)) { free (wpath1); free (wpath2); return (NULL); } free (wpath1); return (wpath2); #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_BUNDLE_RESOURCES_DIR: #if defined(__APPLE__) { // Change working directory to resources directory inside app bundle. wpath1 = NULL; CFURLRef pathCFURLRef = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); // Get relative path to resources directory. if (pathCFURLRef) { wpath1 = (char *)calloc(MAXPATHLEN, sizeof(char)); //getcwd(path, MAXPATHLEN); if (wpath1) { if (!CFURLGetFileSystemRepresentation(pathCFURLRef, true, (UInt8*)wpath1, MAXPATHLEN)) { // true in param 2 resolves against base. ARLOGe("Error: Unable to get file system representation of a CFURL.\n"); free(wpath1); wpath1 = NULL; } } CFRelease(pathCFURLRef); } return (wpath1); } #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_CWD: #ifndef _WINRT arMallocClear(wpath1, char, MAXPATHLEN); if (!getcwd(wpath1, MAXPATHLEN)) { free(wpath1); return (NULL); } return (wpath1); #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_USER_ROOT: #if defined(_WIN32) && !defined(_WINRT) arMallocClear(wpath1, char, MAXPATHLEN); if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, wpath1))) { free (wpath1); return (NULL); } return (wpath1); #elif defined(ANDROID) { // Make JNI calls to get the external storage directory. // To begin, get a reference to the env and attach to it. JNIEnv *env; int isAttached = 0; jthrowable exception; if (((*gJavaVM)->GetEnv(gJavaVM, (void**)&env, JNI_VERSION_1_6)) < 0) { // Couldn't get JNI environment, so this thread is native. if (((*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL)) < 0) { ARLOGe("Error: Couldn't attach to Java VM.\n"); return (NULL); } isAttached = 1; } // Get File object for the external storage directory. jclass classEnvironment = (*env)->FindClass(env, "android/os/Environment"); if (!classEnvironment) goto bailAndroid; jmethodID methodIDgetExternalStorageDirectory = (*env)->GetStaticMethodID(env, classEnvironment, "getExternalStorageDirectory", "()Ljava/io/File;"); // public static File getExternalStorageDirectory () if (!methodIDgetExternalStorageDirectory) goto bailAndroid; jobject objectFile = (*env)->CallStaticObjectMethod(env, classEnvironment, methodIDgetExternalStorageDirectory); exception = (*env)->ExceptionOccurred(env); if (exception) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } // Call method on File object to retrieve String object. jclass classFile = (*env)->GetObjectClass(env, objectFile); if (!classFile) goto bailAndroid; jmethodID methodIDgetAbsolutePath = (*env)->GetMethodID(env, classFile, "getAbsolutePath", "()Ljava/lang/String;"); if (!methodIDgetAbsolutePath) goto bailAndroid; jstring stringPath = (*env)->CallObjectMethod(env, objectFile, methodIDgetAbsolutePath); exception = (*env)->ExceptionOccurred(env); if (exception) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } // Extract a C string from the String object and copy it. const char *wpath3 = (*env)->GetStringUTFChars(env, stringPath, NULL); wpath1 = strdup(wpath3); (*env)->ReleaseStringUTFChars(env, stringPath, wpath3); goto retAndroid; bailAndroid: ARLOGe("Error: JNI call failure.\n"); wpath1 = NULL; retAndroid: if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); // Clean up. return (wpath1); } #elif defined(__APPLE__) && defined(__OBJC__) // iOS/OS X. { NSString *nssHomeDir = NSHomeDirectory(); // CoreFoundation equivalent is CFCopyHomeDirectoryURL(), iOS 6.0+ only. if (!nssHomeDir) { return (NULL); } wpath1 = strdup([nssHomeDir UTF8String]); return wpath1; } #elif defined(__linux) if (!((wpath1 = getenv("HOME")))) { return (NULL); } return (strdup(wpath1)); #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_APP_CACHE_DIR: #if defined(_WIN32) return (NULL); #elif defined(__APPLE__) // iOS/OS X. { # ifdef __OBJC__ NSURL *cacheDir = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] objectAtIndex:0]; if (!cacheDir) { return (NULL); } wpath1 = strdup([[cacheDir path] UTF8String]); # else size_t len = confstr(_CS_DARWIN_USER_CACHE_DIR, NULL, 0); if (!len) return (NULL); wpath1 = (char *)malloc(len); len = confstr(_CS_DARWIN_USER_CACHE_DIR, wpath1, len); // On OS X, returns a folder in the sandbox hierachy under /var/folders/. if (!len) return (NULL); # endif return (wpath1); } #elif defined(ANDROID) { // Make JNI calls to get the Context's cache directory. // To begin, get a reference to the env and attach to it. JNIEnv *env; int isAttached = 0; int ret = 0; jthrowable exception; if (((*gJavaVM)->GetEnv(gJavaVM, (void**)&env, JNI_VERSION_1_6)) < 0) { // Couldn't get JNI environment, so this thread is native. if (((*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL)) < 0) { ARLOGe("Error: Couldn't attach to Java VM.\n"); return (NULL); } isAttached = 1; } // Get File object for the Context's files directory. This only works // if a subclass of Context is supplied. // e.g. JNIEXPORT void JNICALL Java_com_test_TestActivity_test(JNIEnv * env, jobject obj) // so make sure before call. jclass classOfSuppliedObject = (*env)->GetObjectClass(env, instanceOfAndroidContext); if (!classOfSuppliedObject) goto bailAndroid1; jclass classContext = (*env)->FindClass(env, "android/content/Context"); if (!classContext) goto bailAndroid1; if (!(*env)->IsInstanceOf(env, instanceOfAndroidContext, classContext)) { ARLOGe("Error: supplied object is not an instance of android/content/Context.\n"); wpath1 = NULL; // Bad parameter. goto retAndroid1; } jmethodID methodGetDir = (*env)->GetMethodID(env, classOfSuppliedObject, "getCacheDir", "()Ljava/io/File;"); // public abstract File getCacheDir(); //jmethodID methodGetDir = (*env)->GetMethodID(env, classOfSuppliedObject, "getFilesDir", "(Ljava/lang/String;)Ljava/io/File;"); // public abstract File getFilesDir(String type); if (!methodGetDir) goto bailAndroid1; jobject objectFile = (*env)->CallObjectMethod(env, instanceOfAndroidContext, methodGetDir); exception = (*env)->ExceptionOccurred(env); if (exception) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } // Call method on File object to retrieve String object. jclass classFile = (*env)->GetObjectClass(env, objectFile); if (!classFile) goto bailAndroid1; jmethodID methodIDgetAbsolutePath = (*env)->GetMethodID(env, classFile, "getAbsolutePath", "()Ljava/lang/String;"); if (!methodIDgetAbsolutePath) goto bailAndroid1; jstring stringPath = (*env)->CallObjectMethod(env, objectFile, methodIDgetAbsolutePath); exception = (*env)->ExceptionOccurred(env); if (exception) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); } // Extract a C string from the String object, and chdir() to it. const char *wpath3 = (*env)->GetStringUTFChars(env, stringPath, NULL); wpath1 = strdup(wpath3); (*env)->ReleaseStringUTFChars(env, stringPath, wpath3); goto retAndroid1; bailAndroid1: ARLOGe("Error: JNI call failure.\n"); wpath1 = NULL; retAndroid1: if (isAttached) (*gJavaVM)->DetachCurrentThread(gJavaVM); // Clean up. return (wpath1); } #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_APP_DATA_DIR: #ifdef _WINRT //auto folder = Windows::Storage::ApplicationData::Current->LocalFolder; //wpath1 = strdup(folder->Path->Data().c_str()); //return (wpath1); return (NULL); // Unsupported OS. #else return (NULL); // Unsupported OS. #endif break; case AR_UTIL_RESOURCES_DIRECTORY_BEHAVIOR_USE_SUPPLIED_PATH: default: return (NULL); // Undefined behaviour. break; } }