mirror of
https://github.com/kichikuou/system3-sdl2.git
synced 2026-10-02 11:58:01 +03:00
Android: MIDI support
This commit is contained in:
@@ -79,7 +79,7 @@ class GameActivity : SDLActivity() {
|
||||
@Suppress("unused") fun cddaStart(track: Int, loop: Boolean) = cdda.start(track, loop)
|
||||
@Suppress("unused") fun cddaStop() = cdda.stop()
|
||||
@Suppress("unused") fun cddaCurrentPosition() = cdda.currentPosition()
|
||||
@Suppress("unused") fun midiStart(buf: ByteArray, loop: Int) = midi.start(buf, loop)
|
||||
@Suppress("unused") fun midiStart(buf: ByteArray, loop: Boolean) = midi.start(buf, loop)
|
||||
@Suppress("unused") fun midiStop() = midi.stop()
|
||||
@Suppress("unused") fun midiCurrentPosition() = midi.currentPosition()
|
||||
}
|
||||
@@ -152,13 +152,13 @@ private class MidiPlayer {
|
||||
private var playing = false
|
||||
private var playerPaused = false
|
||||
|
||||
fun start(buf: ByteArray, loop: Int) {
|
||||
fun start(buf: ByteArray, loop: Boolean) {
|
||||
val url = "data:audio/midi;base64," + Base64.encodeToString(buf, Base64.DEFAULT)
|
||||
try {
|
||||
player.apply {
|
||||
reset()
|
||||
setDataSource(url)
|
||||
isLooping = loop == 0
|
||||
isLooping = loop
|
||||
prepare()
|
||||
start()
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ add_library(common INTERFACE)
|
||||
if (ANDROID)
|
||||
add_library(system3 SHARED)
|
||||
|
||||
set(SRC_MAKO sys/mako_midi.cpp)
|
||||
set(SRC_PLATFORM
|
||||
linux/nact_linux.cpp
|
||||
android/mako.cpp
|
||||
|
||||
+68
-22
@@ -1,14 +1,44 @@
|
||||
#include <memory>
|
||||
#include <SDL.h>
|
||||
#include <android/log.h>
|
||||
#include <jni.h>
|
||||
#include "mako.h"
|
||||
#include "mako_midi.h"
|
||||
|
||||
MAKO::MAKO(NACT* parent, const char* playlist)
|
||||
: current_music(0)
|
||||
, next_loop(0)
|
||||
class JNILocalFrame {
|
||||
public:
|
||||
JNILocalFrame(int n) :
|
||||
env_((JNIEnv*)SDL_AndroidGetJNIEnv()),
|
||||
context_((jobject)SDL_AndroidGetActivity())
|
||||
{
|
||||
if (env_->PushLocalFrame(n) < 0) {
|
||||
ERROR("Failed to allocate JVM local references");
|
||||
env_ = NULL;
|
||||
}
|
||||
}
|
||||
~JNILocalFrame() {
|
||||
if (env_)
|
||||
env_->PopLocalFrame(NULL);
|
||||
}
|
||||
JNIEnv* env() { return env_; }
|
||||
jobject context() { return context_; }
|
||||
jmethodID GetMethodID(const char* name, const char* sig) {
|
||||
return env_->GetMethodID(env_->GetObjectClass(context_), name, sig);
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
jobject context_;
|
||||
};
|
||||
|
||||
MAKO::MAKO(NACT* parent, const char* playlist) :
|
||||
current_music(0),
|
||||
next_loop(0),
|
||||
nact(parent)
|
||||
{
|
||||
strcpy(amus, "AMUS.DAT");
|
||||
for (int i = 1; i <= 99; i++)
|
||||
cd_track[i] = i;
|
||||
cd_track[i] = 0;
|
||||
}
|
||||
|
||||
void MAKO::play_music(int page)
|
||||
@@ -16,17 +46,33 @@ void MAKO::play_music(int page)
|
||||
if (current_music == page)
|
||||
return;
|
||||
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
if (env->PushLocalFrame(16) < 0) {
|
||||
__android_log_write(ANDROID_LOG_ERROR, "system3",
|
||||
"Failed to allocate JVM local references");
|
||||
JNILocalFrame jni(16);
|
||||
if (!jni.env())
|
||||
return;
|
||||
|
||||
int track = page < 100 ? cd_track[page] : 0;
|
||||
if (track) {
|
||||
jmethodID mid = jni.GetMethodID("cddaStart", "(IZ)V");
|
||||
jni.env()->CallVoidMethod(jni.context(), mid, track + 1, next_loop ? 0 : 1);
|
||||
} else {
|
||||
auto midi = std::make_unique<MAKOMidi>(nact, amus);
|
||||
if (!midi->load_mml(page)) {
|
||||
WARNING("load_mml(%d) failed", page);
|
||||
return;
|
||||
}
|
||||
midi->load_mda(page);
|
||||
std::vector<uint8_t> smf = midi->generate_smf(next_loop);
|
||||
jbyteArray array = jni.env()->NewByteArray(smf.size());
|
||||
if (!array) {
|
||||
WARNING("Failed to allocate an array");
|
||||
return;
|
||||
}
|
||||
jbyte *buf = jni.env()->GetByteArrayElements(array, NULL);
|
||||
memcpy(buf, smf.data(), smf.size());
|
||||
jni.env()->ReleaseByteArrayElements(array, buf, 0);
|
||||
jmethodID mid = jni.GetMethodID("midiStart", "([BZ)V");
|
||||
jni.env()->CallVoidMethod(jni.context(), mid, array, next_loop ? 0 : 1);
|
||||
}
|
||||
jobject context = (jobject)SDL_AndroidGetActivity();
|
||||
jmethodID mid = env->GetMethodID(env->GetObjectClass(context),
|
||||
"cddaStart", "(IZ)V");
|
||||
env->CallVoidMethod(context, mid, cd_track[page] + 1, next_loop ? 0 : 1);
|
||||
env->PopLocalFrame(NULL);
|
||||
|
||||
current_music = page;
|
||||
next_loop = 0;
|
||||
@@ -37,17 +83,17 @@ void MAKO::stop_music()
|
||||
if (!current_music)
|
||||
return;
|
||||
|
||||
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();
|
||||
if (env->PushLocalFrame(16) < 0) {
|
||||
__android_log_write(ANDROID_LOG_ERROR, "system3",
|
||||
"Failed to allocate JVM local references");
|
||||
JNILocalFrame jni(16);
|
||||
if (!jni.env())
|
||||
return;
|
||||
|
||||
if (current_music < 100 && cd_track[current_music]) {
|
||||
jmethodID mid = jni.GetMethodID("cddaStop", "()V");
|
||||
jni.env()->CallVoidMethod(jni.context(), mid);
|
||||
} else {
|
||||
jmethodID mid = jni.GetMethodID("midiStop", "()V");
|
||||
jni.env()->CallVoidMethod(jni.context(), mid);
|
||||
}
|
||||
jobject context = (jobject)SDL_AndroidGetActivity();
|
||||
jmethodID mid = env->GetMethodID(env->GetObjectClass(context),
|
||||
"cddaStop", "()V");
|
||||
env->CallVoidMethod(context, mid);
|
||||
env->PopLocalFrame(NULL);
|
||||
|
||||
current_music = 0;
|
||||
}
|
||||
|
||||
+3
-3
@@ -41,11 +41,11 @@ typedef int32_t int32;
|
||||
#ifdef __ANDROID__
|
||||
|
||||
#define ERROR(fmt, ...) \
|
||||
__android_log_vprint(ANDROID_LOG_ERROR, "(%s:%d): " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
__android_log_print(ANDROID_LOG_ERROR, "System3", "(%s:%d): " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#define WARNING(fmt, ...) \
|
||||
__android_log_vprint(ANDROID_LOG_WARN, "(%s:%d): " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
__android_log_print(ANDROID_LOG_WARN, "System3", "(%s:%d): " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#define NOTICE(fmt, ...) \
|
||||
__android_log_vprint(ANDROID_LOG_INFO, fmt, ##__VA_ARGS__)
|
||||
__android_log_print(ANDROID_LOG_INFO, "System3", fmt, ##__VA_ARGS__)
|
||||
|
||||
#else // __ANDROID__
|
||||
|
||||
|
||||
@@ -91,6 +91,9 @@ public:
|
||||
int current_music;
|
||||
int next_loop; // Y19
|
||||
int cd_track[100]; // Z
|
||||
|
||||
private:
|
||||
NACT* nact;
|
||||
};
|
||||
|
||||
#endif // EMSCRIPTEN
|
||||
|
||||
Reference in New Issue
Block a user