Browse Source

android add native midi wrapper

Pal Lockheart 7 years ago
parent
commit
be8a6bcfae

+ 1 - 0
android/jni/src/Android.mk

@@ -16,6 +16,7 @@ LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c \
     $(wildcard $(LOCAL_PATH)/../../../adplug/*.c) $(wildcard $(LOCAL_PATH)/../../../adplug/*.cpp) \
     $(wildcard $(LOCAL_PATH)/../../../liboggvorbis/src/*.c) \
     $(wildcard $(LOCAL_PATH)/../../../libmad/*.c) \
+    $(wildcard $(LOCAL_PATH)/../../../native_midi/*.c) \
     $(wildcard $(LOCAL_PATH)/*.c) \
 
 LOCAL_CFLAGS += -std=gnu99 -DPAL_HAS_PLATFORM_SPECIFIC_UTILS

+ 78 - 0
android/jni/src/android_jni.c

@@ -1,9 +1,39 @@
 #include <jni.h>
+#include <android/log.h>
+#define TAG "sdlpal-jni"
+
+#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG,__VA_ARGS__)
+#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , TAG,__VA_ARGS__)
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO   , TAG,__VA_ARGS__)
+#define LOGW(...) __android_log_print(ANDROID_LOG_WARN   , TAG,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , TAG,__VA_ARGS__)
+
 #include "palcommon.h"
 #include "global.h"
 #include "palcfg.h"
 
 char externalStoragePath[255];
+char midiInterFile[255];
+
+JavaVM *globalVM;
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv* env;
+    if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_2) != JNI_OK) {
+        return -1;
+    }
+    globalVM = vm;
+    return JNI_VERSION_1_2;
+}
+JNIEnv *getJNIEnv() {
+    JNIEnv* env;
+    if ((*globalVM)->GetEnv(globalVM, (void**)&env, JNI_VERSION_1_2) != JNI_OK) {
+        return NULL;
+    }
+    return env;
+}
+
 /* 
  * Class:     com_codeplex_sdlpal_PalActivity 
  * Method:    setExternalStorage 
@@ -26,6 +56,54 @@ JNIEXPORT void JNICALL Java_com_codeplex_sdlpal_PalActivity_setExternalStorage(J
     strncat(externalStoragePath,"/sdlpal/",strnlen("/sdlpal/",255));
     return;  
 }
+/* 
+ * Class:     com_codeplex_sdlpal_PalActivity 
+ * Method:    setMIDIInterFile 
+ * Signature: (Ljava/lang/String;)V
+ */  
+JNIEXPORT void JNICALL Java_com_codeplex_sdlpal_PalActivity_setMIDIInterFile(JNIEnv *env, jclass cls, jstring j_str)  
+{  
+    const jchar* c_str= NULL;  
+    char* pBuff = midiInterFile;
+    memset(midiInterFile,0,sizeof(midiInterFile));
+    c_str = (*env)->GetStringCritical(env,j_str,NULL);
+    if (c_str == NULL)
+    {  
+        return;  
+    }  
+    while(*c_str)   
+    {  
+        *pBuff++ = *c_str++;  
+    }
+    //*pBuff = '\0';
+    (*env)->ReleaseStringCritical(env,j_str,c_str);
+    LOGV("JNI got midi inter filename:%s", midiInterFile);
+    return;  
+}
+
+void JNI_mediaplayer_load(){
+    JNIEnv* env=getJNIEnv();
+    jclass clazz = (*env)->FindClass(env, "com/codeplex/sdlpal/PalActivity");
+    jmethodID mid = (*env)->GetStaticMethodID(env, clazz, "JNI_mediaplayer_load", "()V");
+    (*env)->CallStaticVoidMethod(env,clazz,mid); 
+}
+void JNI_mediaplayer_play() {
+    JNIEnv* env=getJNIEnv();
+    jclass clazz = (*env)->FindClass(env, "com/codeplex/sdlpal/PalActivity");
+    jmethodID mid = (*env)->GetStaticMethodID(env, clazz, "JNI_mediaplayer_play", "()V");
+    (*env)->CallStaticVoidMethod(env,clazz,mid); 
+}
+void JNI_mediaplayer_stop() {
+    JNIEnv* env=getJNIEnv();
+    jclass clazz = (*env)->FindClass(env, "com/codeplex/sdlpal/PalActivity");
+    jmethodID mid = (*env)->GetStaticMethodID(env, clazz, "JNI_mediaplayer_stop", "()V");
+    (*env)->CallStaticVoidMethod(env,clazz,mid); 
+}
+int JNI_mediaplayer_isplaying() {
+    return 0;
+}
+void JNI_mediaplayer_setvolume(int volume) {
+}
 
 LPCSTR
 UTIL_BasePath(

+ 13 - 0
android/jni/src/android_jni.h

@@ -0,0 +1,13 @@
+#ifndef SDLPAL_JNI_H
+#define SDLPAL_JNI_H
+
+extern char externalStoragePath[255];
+extern char midiInterFile[255];
+
+void JNI_mediaplayer_load();
+void JNI_mediaplayer_play();
+void JNI_mediaplayer_stop();
+int JNI_mediaplayer_isplaying();
+void JNI_mediaplayer_setvolume(int);
+
+#endif // SDLPAL_JNI_H

+ 6 - 0
android/jni/src/pal_config.h

@@ -19,6 +19,12 @@
 # define PAL_CREDIT           "Rikku2000"
 # define PAL_PORTYEAR         "2013"
 
+#define PAL_HAS_NATIVEMIDI  1
+
+#define PAL_HAS_CONFIG_PAGE 0
+
+#define PAL_FILESYSTEM_IGNORE_CASE 1
+
 # define PAL_IS_VALID_JOYSTICK(s)  (strcmp((s), "Android Accelerometer") != 0)
 
 LPCSTR

+ 43 - 3
android/src/com/codeplex/sdlpal/PalActivity.java

@@ -3,17 +3,57 @@ package com.codeplex.sdlpal;
 import org.libsdl.app.SDLActivity;
 import android.os.*;
 import android.util.*;
+import android.media.*;
+import android.net.Uri;
+import java.io.*;
 
 public class PalActivity extends SDLActivity {
-    public static native void setExternalStorage(String str);  
+    private static final String TAG = "sdlpal-debug";
+    private static final MediaPlayer mediaPlayer = new MediaPlayer();
+    private static Uri interFileURI;
+
+    private static void JNI_mediaplayer_load(){
+        Log.v(TAG, "loading midi:" + interFileURI);
+        mediaPlayer.reset();
+        mediaPlayer.setLooping(true);
+        try{
+            mediaPlayer.setDataSource(mSingleton.getApplicationContext(), interFileURI);
+            mediaPlayer.prepare();
+        }catch(IOException e) {
+            Log.e(TAG, interFileURI.toString() + " not available for playing, check");
+        }
+    }
+
+    private static void JNI_mediaplayer_play() {
+        mediaPlayer.start();
+    }
+
+    private static void JNI_mediaplayer_stop() {
+        mediaPlayer.stop();
+    }
+
+    private static int JNI_mediaplayer_playing() {
+        return mediaPlayer.isPlaying() ? 1 : 0;
+    }
+
+    private static void JNI_mediaplayer_setvolume(int volume) {
+        mediaPlayer.setVolume((float)volume/256, (float)volume/256);
+    }
+
+    public static native void setExternalStorage(String str);
+    public static native void setMIDIInterFile(String str);
     @Override  
     public void onCreate(Bundle savedInstanceState) {  
         super.onCreate(savedInstanceState);
-//         setContentView(R.layout.main);
+        String appDataPath = mSingleton.getApplicationContext().getFilesDir().getPath();
+        String interFilePath = appDataPath+"/intermediates.midi";
+        Log.v(TAG, "java interfile path " + interFilePath);
+        interFileURI = Uri.fromFile(new File(interFilePath));
+        setMIDIInterFile(interFilePath);
         String externalStorageState = Environment.getExternalStorageState();
         if(externalStorageState.equals(Environment.MEDIA_MOUNTED)){
             setExternalStorage(Environment.getExternalStorageDirectory().getPath());
-            Log.v("sdlpal-debug", "sdcard path " + Environment.getExternalStorageDirectory().getPath());
+            Log.v(TAG, "sdcard path " + Environment.getExternalStorageDirectory().getPath());
         }
     }
 }

+ 0 - 2
macos/pal_config.h

@@ -10,8 +10,6 @@
 #  define PAL_HAS_SDLCD         1
 # endif
 
-#define PAL_HAS_NATIVEMIDI 1
-
 # define PAL_PREFIX            "./"
 # define PAL_SAVE_PREFIX       "./"
 

+ 148 - 0
native_midi/native_midi_android.c

@@ -0,0 +1,148 @@
+/*
+    native_midi_android:  Native Midi support on Android for SDLPal
+    Copyright (C) 2017  Pal Lockheart
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Pal Lockheart
+*/
+
+/* This is Android only, using MediaPlayer ( need java part work together ) */
+
+#ifdef __ANDROID__
+#include "android_jni.h"
+
+#include "SDL_config.h"
+
+#include "SDL.h"
+#include "SDL_endian.h"
+#include "native_midi.h"
+
+/* Native Midi song */
+struct _NativeMidiSong
+{
+    int _placeholder;
+    int playing;
+};
+
+static NativeMidiSong *currentsong = NULL;
+static int latched_volume = 128;
+
+int native_midi_detect()
+{
+    return 1;  /* always available. */
+}
+
+NativeMidiSong *native_midi_loadsong(const char *midifile)
+{
+    NativeMidiSong *retval = NULL;
+    SDL_RWops *rw = SDL_RWFromFile(midifile, "rb");
+    if (rw != NULL) {
+        retval = native_midi_loadsong_RW(rw);
+        SDL_RWclose(rw);
+    }
+
+    return retval;
+}
+
+NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw)
+{
+    NativeMidiSong *retval = NULL;
+    void *buf = NULL;
+    int len = 0;
+
+    if (SDL_RWseek(rw, 0, RW_SEEK_END) < 0)
+        goto fail;
+    len = SDL_RWtell(rw);
+    if (len < 0)
+        goto fail;
+    if (SDL_RWseek(rw, 0, RW_SEEK_SET) < 0)
+        goto fail;
+
+    buf = malloc(len);
+    if (buf == NULL)
+        goto fail;
+
+    if (SDL_RWread(rw, buf, len, 1) != 1)
+        goto fail;
+
+    retval = malloc(sizeof(NativeMidiSong));
+    if (retval == NULL)
+        goto fail;
+
+    memset(retval, '\0', sizeof (*retval));
+
+    FILE *fp = fopen(midiInterFile,"wb+");
+    fwrite(buf,len,1,fp);
+    fclose(fp);
+    JNI_mediaplayer_load();
+    return retval;
+
+fail:
+    return NULL;
+}
+
+void native_midi_freesong(NativeMidiSong *song)
+{
+    if (song != NULL) {
+        if (currentsong == song)
+            currentsong = NULL;
+        free(song);
+    }
+}
+
+void native_midi_start(NativeMidiSong *song)
+{
+    int vol;
+
+    if (song == NULL)
+        return;
+    
+    currentsong = song;
+    currentsong->playing = 1;
+    JNI_mediaplayer_play();
+}
+
+void native_midi_stop()
+{
+    if (currentsong) {
+        currentsong->playing = 0;
+        JNI_mediaplayer_stop();
+    }
+}
+
+int native_midi_active()
+{
+    if (currentsong == NULL)
+        return 0;
+
+    return currentsong->playing;
+}
+
+void native_midi_setvolume(int volume)
+{
+    if (latched_volume == volume)
+        return;
+
+    latched_volume = volume;
+    JNI_mediaplayer_setvolume(volume);
+}
+
+const char *native_midi_error(void)
+{
+    return "";  /* !!! FIXME */
+}
+
+#endif