extern "C" long Android_JNI_FileSeek(SDL_RWops* ctx, long offset, int whence) { long newPosition; switch (whence) { case RW_SEEK_SET: newPosition = offset; break; case RW_SEEK_CUR: newPosition = ctx->hidden.androidio.position + offset; break; case RW_SEEK_END: newPosition = ctx->hidden.androidio.size + offset; break; default: SDL_SetError("Unknown value for 'whence'"); return -1; } if (newPosition < 0) { newPosition = 0; } if (newPosition > ctx->hidden.androidio.size) { newPosition = ctx->hidden.androidio.size; } long movement = newPosition - ctx->hidden.androidio.position; jobject inputStream = (jobject)ctx->hidden.androidio.inputStreamRef; if (movement > 0) { unsigned char buffer[1024]; // The easy case where we're seeking forwards while (movement > 0) { long amount = (long) sizeof (buffer); if (amount > movement) { amount = movement; } size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount); if (result <= 0) { // Failed to read/skip the required amount, so fail return -1; } movement -= result; } } else if (movement < 0) { // We can't seek backwards so we have to reopen the file and seek // forwards which obviously isn't very efficient Android_JNI_FileClose(ctx, false); Android_JNI_FileOpen(ctx); Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET); } ctx->hidden.androidio.position = newPosition; return ctx->hidden.androidio.position; }
extern "C" Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence) { Sint64 newPosition; switch (whence) { case RW_SEEK_SET: newPosition = offset; break; case RW_SEEK_CUR: newPosition = ctx->hidden.androidio.position + offset; break; case RW_SEEK_END: newPosition = ctx->hidden.androidio.size + offset; break; default: SDL_SetError("Unknown value for 'whence'"); return -1; } /* Validate the new position */ if (newPosition < 0) { SDL_Error(SDL_EFSEEK); return -1; } if (newPosition > ctx->hidden.androidio.size) { newPosition = ctx->hidden.androidio.size; } Sint64 movement = newPosition - ctx->hidden.androidio.position; if (movement > 0) { unsigned char buffer[4096]; // The easy case where we're seeking forwards while (movement > 0) { Sint64 amount = sizeof (buffer); if (amount > movement) { amount = movement; } size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount); if (result <= 0) { // Failed to read/skip the required amount, so fail return -1; } movement -= result; } } else if (movement < 0) { // We can't seek backwards so we have to reopen the file and seek // forwards which obviously isn't very efficient Android_JNI_FileClose(ctx, false); Android_JNI_FileOpen(ctx); Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET); } return ctx->hidden.androidio.position; }
SDL_RWops * SDL_RWFromFile(const char *file, const char *mode) { SDL_RWops *rwops = NULL; #ifdef HAVE_STDIO_H FILE *fp = NULL; #endif if (!file || !*file || !mode || !*mode) { SDL_SetError("SDL_RWFromFile(): No file or no mode specified"); return NULL; } #if defined(ANDROID) && 0 rwops = SDL_AllocRW(); if (!rwops) return NULL; /* SDL_SetError already setup by SDL_AllocRW() */ if (Android_JNI_FileOpen(rwops, file, mode) < 0) { SDL_FreeRW(rwops); return NULL; } rwops->seek = Android_JNI_FileSeek; rwops->read = Android_JNI_FileRead; rwops->write = Android_JNI_FileWrite; rwops->close = Android_JNI_FileClose; #elif defined(__WIN32__) rwops = SDL_AllocRW(); if (!rwops) return NULL; /* SDL_SetError already setup by SDL_AllocRW() */ if (windows_file_open(rwops, file, mode) < 0) { SDL_FreeRW(rwops); return NULL; } rwops->seek = windows_file_seek; rwops->read = windows_file_read; rwops->write = windows_file_write; rwops->close = windows_file_close; #elif HAVE_STDIO_H #ifdef __APPLE__ fp = SDL_OpenFPFromBundleOrFallback(file, mode); #else fp = fopen(file, mode); #endif if (fp == NULL) { SDL_SetError("Couldn't open %s", file); } else { rwops = SDL_RWFromFP(fp, 1); } #else SDL_SetError("SDL not compiled with stdio support"); #endif /* !HAVE_STDIO_H */ return (rwops); }
extern "C" int Android_JNI_FileOpen(SDL_RWops* ctx, const char* fileName, const char*) { if (!ctx) { return -1; } jstring fileNameJString = mEnv->NewStringUTF(fileName); ctx->hidden.androidio.fileName = fileNameJString; ctx->hidden.androidio.fileNameRef = mEnv->NewGlobalRef(fileNameJString); ctx->hidden.androidio.inputStreamRef = NULL; mEnv->DeleteLocalRef(fileNameJString); return Android_JNI_FileOpen(ctx); }
extern "C" int Android_JNI_FileOpen(SDL_RWops* ctx, const char* fileName, const char*) { LocalReferenceHolder refs; if (!refs.init(mEnv)) { return -1; } if (!ctx) { return -1; } jstring fileNameJString = mEnv->NewStringUTF(fileName); ctx->hidden.androidio.fileNameRef = mEnv->NewGlobalRef(fileNameJString); ctx->hidden.androidio.inputStreamRef = NULL; return Android_JNI_FileOpen(ctx); }
extern "C" int Android_JNI_FileOpen(SDL_RWops* ctx, const char* fileName, const char*) { LocalReferenceHolder refs(__FUNCTION__); JNIEnv *mEnv = Android_JNI_GetEnv(); if (!refs.init(mEnv)) { return -1; } if (!ctx) { return -1; } jstring fileNameJString = mEnv->NewStringUTF(fileName); ctx->hidden.androidio.fileNameRef = mEnv->NewGlobalRef(fileNameJString); ctx->hidden.androidio.inputStreamRef = NULL; ctx->hidden.androidio.readableByteChannelRef = NULL; ctx->hidden.androidio.readMethod = NULL; return Android_JNI_FileOpen(ctx); }
extern "C" int Android_JNI_FileOpen(SDL_RWops* ctx, const char* fileName, const char*) { JNIEnv *env = 0; if (!ctx) { return -1; } if (mJavaVM->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE("Failed to get the environment using GetEnv(); assuming main thread"); env = mEnv; } jstring fileNameJString = env->NewStringUTF(fileName); ctx->hidden.androidio.fileName = fileNameJString; ctx->hidden.androidio.fileNameRef = env->NewGlobalRef(fileNameJString); ctx->hidden.androidio.inputStreamRef = NULL; env->DeleteLocalRef(fileNameJString); return Android_JNI_FileOpen(ctx); }
SDL_RWops * SDL_RWFromFile(const char *file, const char *mode) { SDL_RWops *rwops = NULL; if (!file || !*file || !mode || !*mode) { SDL_SetError("SDL_RWFromFile(): No file or no mode specified"); return NULL; } #if defined(ANDROID) #ifdef HAVE_STDIO_H /* Try to open the file on the filesystem first */ if (*file == '/') { FILE *fp = fopen(file, mode); if (fp) { return SDL_RWFromFP(fp, 1); } } else { /* Try opening it from internal storage if it's a relative path */ char *path; FILE *fp; path = SDL_stack_alloc(char, PATH_MAX); if (path) { SDL_snprintf(path, PATH_MAX, "%s/%s", SDL_AndroidGetInternalStoragePath(), file); fp = fopen(path, mode); SDL_stack_free(path); if (fp) { return SDL_RWFromFP(fp, 1); } } } #endif /* HAVE_STDIO_H */ /* Try to open the file from the asset system */ rwops = SDL_AllocRW(); if (!rwops) return NULL; /* SDL_SetError already setup by SDL_AllocRW() */ if (Android_JNI_FileOpen(rwops, file, mode) < 0) { SDL_FreeRW(rwops); return NULL; } rwops->size = Android_JNI_FileSize; rwops->seek = Android_JNI_FileSeek; rwops->read = Android_JNI_FileRead; rwops->write = Android_JNI_FileWrite; rwops->close = Android_JNI_FileClose; #elif defined(__WIN32__) rwops = SDL_AllocRW(); if (!rwops) return NULL; /* SDL_SetError already setup by SDL_AllocRW() */ if (windows_file_open(rwops, file, mode) < 0) { SDL_FreeRW(rwops); return NULL; } rwops->size = windows_file_size; rwops->seek = windows_file_seek; rwops->read = windows_file_read; rwops->write = windows_file_write; rwops->close = windows_file_close; #elif HAVE_STDIO_H { #ifdef __APPLE__ FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode); #else FILE *fp = fopen(file, mode); #endif if (fp == NULL) { SDL_SetError("Couldn't open %s", file); } else { rwops = SDL_RWFromFP(fp, 1); } } #else SDL_SetError("SDL not compiled with stdio support"); #endif /* !HAVE_STDIO_H */ return (rwops); }