613 lines · 18.1 KB · C++
RawDownload
/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine  Copyright (c) 2004 Ge Wang and Perry R. Cook.  All rights reserved.   http://chuck.stanford.edu/   http://chuck.cs.princeton.edu/  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.  You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// name: util_platforms.cpp// desc: platform-specific utilities, e.g., for Android and various//// author: Andriy Kunitsyn (kunitzin@gmail.com) | original ChuckAndroid//         Ge Wang (https://ccrma.stanford.edu/~ge/)// date: Summer 2021//-----------------------------------------------------------------------------#include "util_platforms.h"#include "util_string.h"#include "chuck_errmsg.h" #ifdef __PLATFORM_WIN32__#ifndef __CHUNREAL_ENGINE__#include <windows.h> // for win32_tmpfile()#else  // 1.5.0.0 (ge) | #chunreal  // unreal engine on windows disallows including windows.h#include "Windows/MinWindows.h"#endif // #ifndef __CHUNREAL_ENGINE__#endif // #ifdef __PLATFORM_WIN32__ #include <sys/stat.h>    //-----------------------------------------------------------------------------// name: ck_openFileAutoExt()// desc: open a file by name, first as is, and if needed concatenateing ".ck"//       this potentially modifies the contents of fname//-----------------------------------------------------------------------------FILE * ck_openFileAutoExt( std::string & filenameMutable,                           const std::string & extension ){#ifdef __ANDROID__    if( strncmp(filenameMutable.c_str(), "jar:", strlen("jar:")) == 0 )    {        int fd = 0;        if( !ChuckAndroid::copyJARURLFileToTemporary(filenameMutable.c_str(), &fd) )        {            EM_error2( 0, "unable to download from JAR URL: %s", filenameMutable.c_str() );            return NULL;        }        return fdopen(fd, "rb");    }#endif // __ANDROID__     // try opening    FILE * fd = fopen( filenameMutable.c_str(), "rb" );    // file open?    if( !fd )    {        // check if filename has extension, ignoring case        if( !extension_matches( filenameMutable, extension, TRUE ) )        {            // concat            std::string tryThis = filenameMutable + extension;            // try opening again            fd = fopen( tryThis.c_str(), "rb" );            // if successful update filename            filenameMutable = tryThis;        }    }     return fd;}    //-----------------------------------------------------------------------------// name: win32_tmpfile()// desc: replacement for broken tmpfile() on Windows Vista + 7//-----------------------------------------------------------------------------#ifdef __PLATFORM_WIN32__FILE * win32_tmpfile(){    char tmp_path[MAX_PATH];    char file_path[MAX_PATH];    FILE * file = NULL; #ifndef __CHUNREAL_ENGINE__    if( GetTempPath(256, tmp_path) == 0 )#else    // 1.5.0.0 (ge) | #chunreal explicit call ASCII version    if( GetTempPathA(256, tmp_path) == 0 )#endif        return NULL; #ifndef __CHUNREAL_ENGINE__    if( GetTempFileName(tmp_path, "mA", 0, file_path) == 0 )#else    // 1.5.0.0 (ge) | #chunreal explicit call ASCII version    if( GetTempFileNameA(tmp_path, "mA", 0, file_path) == 0 )#endif        return NULL;     file = fopen( file_path, "wb+D" );     return file;}#endif // #ifdef __PLATFORM_WIN32__    //-----------------------------------------------------------------------------// name: android_tmpfile()// desc: replacement for broken tmpfile() on Android//-----------------------------------------------------------------------------#ifdef __ANDROID__FILE * android_tmpfile(){    return ChuckAndroid::getTemporaryFile();}#endif    //-----------------------------------------------------------------------------// name: android_tmpfile()// desc: replacement for broken tmpfile() on Android//-----------------------------------------------------------------------------FILE * ck_tmpfile(){    FILE * fd = NULL;#ifdef __PLATFORM_WIN32__    fd = win32_tmpfile();#elif defined (__ANDROID__)    fd = android_tmpfile();#else    fd = tmpfile();#endif     return fd;}    //-----------------------------------------------------------------------------// name: ck_isdir()// desc: check if file is a directory//-----------------------------------------------------------------------------t_CKBOOL ck_isdir( const std::string & path ){    // shuttle    struct stat fs;    // stat the path and check flag (is path not there, also returns false)    return (stat( path.c_str(), &fs )==0 && fs.st_mode & S_IFDIR);}     //-----------------------------------------------------------------------------#ifdef __ANDROID__//-----------------------------------------------------------------------------#include <jni.h>#include <fcntl.h>#include <unistd.h>#include <string> static JavaVM * jvm_instance = NULL; JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM * vm, void * reserved ){    jvm_instance = vm;     return JNI_VERSION_1_6;} JavaVM * ChuckAndroid::getJVM(){    return jvm_instance;} //-----------------------------------------------------------------------------// name: class JNIEnvWrapper// desc: Wrapper around JNIEnv. Serves three purposes://       - releases JNIEnv and Java objects in RAII fashion//       - removes the need to get method IDs//       - throws JNIEnvWrapperException exception on Java exceptions//-----------------------------------------------------------------------------class JNIEnvWrapper{public:    JNIEnvWrapper(JavaVM * jvm);    ~JNIEnvWrapper();     bool IsValid() const;     jclass FindClass(const char * class_signature);    jobject ConstructNewObject(jclass constructed_class,        const char * constructor_signature, jobject param_1);    jobject CallObjectMethod(jobject callee, jclass callee_class,        const char * method_name, const char * method_signature);    jobject CallObjectMethod(jobject callee, jclass callee_class,        const char * method_name, const char * method_signature,        jobject param_1);    jobject CallStaticObjectMethod(jclass callee_class,        const char * method_name, const char * method_signature);    jobject CallStaticObjectMethod(jclass callee_class,        const char * method_name, const char * method_signature,        jobject param_1);    jobject CallStaticObjectMethod(jclass callee_class,        const char * method_name, const char * method_signature,        jobject param_1, jobject param_2, jobject param_3);    jint CallIntMethod(jobject callee, jclass callee_class,        const char * method_name, const char * method_signature,        jobject param_1);    void CallVoidMethod(jobject callee, jclass callee_class,        const char * method_name, const char * method_signature);     jstring NewStringUTF(const char * utf8_string);    const char * GetStringUTFChars(jstring string);    void ReleaseStringUTFChars(jstring string, const char * utf8_chars);    jbyteArray NewByteArray(size_t size);    jbyte * GetByteArrayElements(jbyteArray java_array);    void ReleaseByteArrayElements(jbyteArray java_array, jbyte * native_array); private:    void ThrowOnJavaException();    JavaVM * m_jvm = NULL;    JNIEnv * m_env = NULL;    bool m_needs_detaching = false;}; class JNIEnvWrapperException {}; JNIEnvWrapper::JNIEnvWrapper(JavaVM * jvm)    : m_jvm(jvm){    int reason = jvm->GetEnv((void **)&m_env, JNI_VERSION_1_6);    if( reason != JNI_OK && reason != JNI_EDETACHED )    {        m_env = NULL;        return;    }    if( reason == JNI_EDETACHED )    {        if( jvm->AttachCurrentThread(&m_env, NULL) != 0 )        {            m_env = NULL;            return;        }        m_needs_detaching = true;    }    if( m_env->PushLocalFrame(32) != 0 )    {        if( m_needs_detaching )        {            m_jvm->DetachCurrentThread();        }        m_env = NULL;    }} JNIEnvWrapper::~JNIEnvWrapper(){    if( m_env == NULL )    {        return;    }    m_env->PopLocalFrame(NULL);    if( m_needs_detaching )    {        m_jvm->DetachCurrentThread();    }} bool JNIEnvWrapper::IsValid() const{    return m_env != NULL;} void JNIEnvWrapper::ThrowOnJavaException(){    if( m_env->ExceptionCheck() )    {        m_env->ExceptionDescribe();        m_env->ExceptionClear();        throw JNIEnvWrapperException();    }} jclass JNIEnvWrapper::FindClass(const char * class_signature){    jclass ret = m_env->FindClass(class_signature);    ThrowOnJavaException();    return ret;} jobject JNIEnvWrapper::ConstructNewObject(jclass constructed_class,    const char * constructor_signature, jobject param_1){    jmethodID method_id = m_env->GetMethodID(constructed_class,        "<init>", constructor_signature);    ThrowOnJavaException();    jobject ret = m_env->NewObject(constructed_class, method_id,        param_1);    ThrowOnJavaException();    return ret;} jobject JNIEnvWrapper::CallObjectMethod(jobject callee, jclass callee_class,    const char * method_name, const char * method_signature){    jmethodID method_id = m_env->GetMethodID(callee_class,        method_name, method_signature);    ThrowOnJavaException();    jobject ret = m_env->CallObjectMethod(callee, method_id);    ThrowOnJavaException();    return ret;} jobject JNIEnvWrapper::CallObjectMethod(jobject callee, jclass callee_class,    const char * method_name, const char * method_signature,    jobject param_1){    jmethodID method_id = m_env->GetMethodID(callee_class,        method_name, method_signature);    ThrowOnJavaException();    jobject ret = m_env->CallObjectMethod(callee, method_id, param_1);    ThrowOnJavaException();    return ret;} jobject JNIEnvWrapper::CallStaticObjectMethod(jclass callee_class,    const char * method_name, const char * method_signature){    jmethodID method_id = m_env->GetStaticMethodID(callee_class,        method_name, method_signature);    ThrowOnJavaException();    jobject ret = m_env->CallStaticObjectMethod(callee_class, method_id);    ThrowOnJavaException();     return ret;} jobject JNIEnvWrapper::CallStaticObjectMethod(jclass callee_class,    const char * method_name, const char * method_signature, jobject param_1){    jmethodID method_id = m_env->GetStaticMethodID(callee_class,        method_name, method_signature);    ThrowOnJavaException();    jobject ret = m_env->CallStaticObjectMethod(callee_class,        method_id, param_1);    ThrowOnJavaException();     return ret;} jobject JNIEnvWrapper::CallStaticObjectMethod(jclass callee_class,    const char * method_name, const char * method_signature, jobject param_1,    jobject param_2, jobject param_3){    jmethodID method_id = m_env->GetStaticMethodID(callee_class,        method_name, method_signature);    ThrowOnJavaException();    jobject ret = m_env->CallStaticObjectMethod(callee_class, method_id,        param_1, param_2, param_3);    ThrowOnJavaException();     return ret;} jint JNIEnvWrapper::CallIntMethod(jobject callee, jclass callee_class,    const char * method_name, const char * method_signature, jobject param_1){    jmethodID method_id = m_env->GetMethodID(callee_class,        method_name, method_signature);    ThrowOnJavaException();    jint ret = m_env->CallIntMethod(callee, method_id, param_1);    ThrowOnJavaException();    return ret;} void JNIEnvWrapper::CallVoidMethod(jobject callee, jclass callee_class,    const char * method_name, const char * method_signature){    jmethodID method_id = m_env->GetMethodID(callee_class,        method_name, method_signature);    ThrowOnJavaException();    m_env->CallVoidMethod(callee, method_id);    ThrowOnJavaException();} jstring JNIEnvWrapper::NewStringUTF(const char * utf8_string){    jstring ret = m_env->NewStringUTF(utf8_string);    ThrowOnJavaException();     return ret;} const char * JNIEnvWrapper::GetStringUTFChars(jstring string){    return m_env->GetStringUTFChars(string, NULL);} void JNIEnvWrapper::ReleaseStringUTFChars(jstring string, const char * utf8_chars){    m_env->ReleaseStringUTFChars(string, utf8_chars);} jbyteArray JNIEnvWrapper::NewByteArray(size_t size){    jbyteArray ret = m_env->NewByteArray(size);    ThrowOnJavaException();     return ret;} jbyte * JNIEnvWrapper::GetByteArrayElements(jbyteArray java_array){    return m_env->GetByteArrayElements(java_array, NULL);} void JNIEnvWrapper::ReleaseByteArrayElements(jbyteArray java_array,    jbyte * native_array){    m_env->ReleaseByteArrayElements(java_array, native_array, 0);} static std::string GetTemporaryFilePath(JNIEnvWrapper& jni){    // context = android.app.ActivityThread.currentActivityThread().getApplication()    jclass thread_class = jni.FindClass("android/app/ActivityThread");    jobject current_thread = jni.CallStaticObjectMethod(thread_class,        "currentActivityThread", "()Landroid/app/ActivityThread;");    jobject context = jni.CallObjectMethod(current_thread, thread_class,        "getApplication", "()Landroid/app/Application;");     // cache_dir = context.getCacheDir()    jclass context_class = jni.FindClass("android/content/Context");    jobject cache_dir = jni.CallObjectMethod(context, context_class,        "getCacheDir", "()Ljava/io/File;");     // temp_file = java.io.File.createTempFile("chuck_temp", "", cache_dir)    jclass file_class = jni.FindClass("java/io/File");    jobject temp_file = jni.CallStaticObjectMethod(file_class, "createTempFile",        "(Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)Ljava/io/File;",        jni.NewStringUTF("chuck_temp"), jni.NewStringUTF(""), cache_dir);     // temp_file_path = temp_file.getPath()    jstring temp_file_path = (jstring)jni.CallObjectMethod(temp_file,        file_class, "getPath", "()Ljava/lang/String;");     const char * path_chars = jni.GetStringUTFChars(temp_file_path);    std::string ret = path_chars;    jni.ReleaseStringUTFChars(temp_file_path, path_chars);     return ret;} FILE * ChuckAndroid::getTemporaryFile() noexcept{    JavaVM * jvm = getJVM();    if( !jvm )    {        return NULL;    }    JNIEnvWrapper jni(jvm);    if( !jni.IsValid() )    {        return NULL;    }     try    {        const std::string temp_path = GetTemporaryFilePath(jni);        return fopen(temp_path.c_str(), "wb+");

Lines 1–500 of 613.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t