From db3547db242455e640783af2a0e6a82cd8ccef61 Mon Sep 17 00:00:00 2001 From: Gust Date: Thu, 22 Feb 2024 22:05:07 +0800 Subject: [PATCH] fix miniaudio not close error on minijvm exit --- .../c/deps/include/minial/miniaudio.h | 39 ++++++++++++++---- desktop/glfw_gui/c/jni_minial.c | 18 ++++++-- desktop/glfw_gui/java/pom.xml | 2 +- .../main/java/org/mini/media/MiniAudio.java | 2 + extlib/xgui/pom.xml | 6 +-- .../java/org/mini/glfw/GlfwCallBackImpl.java | 3 ++ .../main/java/org/mini/media/MaDevice.java | 19 +++++++++ .../java/org/mini/media/engine/MaEngine.java | 5 +++ extlib/xgui/xgui.iml | 8 ---- minijvm/c/jvm/jdwp.c | 4 +- mobile/c/gui/jni_minial.m | 18 ++++++-- mobile/c/gui/minial/miniaudio.h | 39 ++++++++++++++---- .../UserInterfaceState.xcuserstate | Bin 12253 -> 17268 bytes mobile/java/glfm_gui/pom.xml | 2 +- .../main/java/org/mini/media/MiniAudio.java | 2 + 15 files changed, 130 insertions(+), 37 deletions(-) delete mode 100644 extlib/xgui/xgui.iml diff --git a/desktop/glfw_gui/c/deps/include/minial/miniaudio.h b/desktop/glfw_gui/c/deps/include/minial/miniaudio.h index f6d01645..47332e11 100644 --- a/desktop/glfw_gui/c/deps/include/minial/miniaudio.h +++ b/desktop/glfw_gui/c/deps/include/minial/miniaudio.h @@ -1,6 +1,6 @@ /* Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. -miniaudio - v0.11.20 - TBD +miniaudio - v0.11.21 - 2023-11-15 David Reid - mackron@gmail.com @@ -3723,7 +3723,7 @@ extern "C" { #define MA_VERSION_MAJOR 0 #define MA_VERSION_MINOR 11 -#define MA_VERSION_REVISION 20 +#define MA_VERSION_REVISION 21 #define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION) #if defined(_MSC_VER) && !defined(__clang__) @@ -6716,7 +6716,8 @@ typedef enum ma_device_notification_type_stopped, ma_device_notification_type_rerouted, ma_device_notification_type_interruption_began, - ma_device_notification_type_interruption_ended + ma_device_notification_type_interruption_ended, + ma_device_notification_type_unlocked } ma_device_notification_type; typedef struct @@ -18668,6 +18669,14 @@ static void ma_device__on_notification_rerouted(ma_device* pDevice) } #endif +#if defined(MA_EMSCRIPTEN) +EMSCRIPTEN_KEEPALIVE +void ma_device__on_notification_unlocked(ma_device* pDevice) +{ + ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_unlocked)); +} +#endif + static void ma_device__on_data_inner(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount) { @@ -32797,9 +32806,9 @@ static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjec hasSupportedFormat = MA_FALSE; for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) { - ma_format format; - ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &format); - if (formatResult == MA_SUCCESS && format != ma_format_unknown) { + ma_format formatFromDescription; + ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &formatFromDescription); + if (formatResult == MA_SUCCESS && formatFromDescription != ma_format_unknown) { hasSupportedFormat = MA_TRUE; bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat; break; @@ -39800,6 +39809,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice) */ device.webaudio.close(); device.webaudio = undefined; + device.pDevice = undefined; }, pDevice->webaudio.deviceIndex); } #endif @@ -39823,6 +39833,10 @@ static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__webaudio(co */ ma_uint32 periodSizeInFrames; + if (nativeSampleRate == 0) { + nativeSampleRate = MA_DEFAULT_SAMPLE_RATE; + } + if (pDescriptor->periodSizeInFrames == 0) { if (pDescriptor->periodSizeInMilliseconds == 0) { if (performanceProfile == ma_performance_profile_low_latency) { @@ -40295,6 +40309,8 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co device.scriptNode.connect(device.webaudio.destination); } + device.pDevice = pDevice; + return miniaudio.track_device(device); }, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice); @@ -40467,8 +40483,15 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex miniaudio.unlock = function() { for(var i = 0; i < miniaudio.devices.length; ++i) { var device = miniaudio.devices[i]; - if (device != null && device.webaudio != null && device.state === 2 /* ma_device_state_started */) { - device.webaudio.resume(); + if (device != null && + device.webaudio != null && + device.state === window.miniaudio.device_state.started) { + + device.webaudio.resume().then(() => { + Module._ma_device__on_notification_unlocked(device.pDevice); + }, + (error) => {console.error("Failed to resume audiocontext", error); + }); } } miniaudio.unlock_event_types.map(function(event_type) { diff --git a/desktop/glfw_gui/c/jni_minial.c b/desktop/glfw_gui/c/jni_minial.c index 6029a3a8..7a006671 100755 --- a/desktop/glfw_gui/c/jni_minial.c +++ b/desktop/glfw_gui/c/jni_minial.c @@ -325,7 +325,7 @@ void setupCallback(Runtime *runtime, JClass *clazz) { c8 *type_s; c8 *clsname_s; if (!refers._callback_minial_on_recv_frames) { - clsname_s = "org/mini/media/AudioDevice"; + clsname_s = "org/mini/media/MADevice"; name_s = "onReceiveFrames"; type_s = "(JIJ)V"; Utf8String *clsname = env->utf8_create_part_c(clsname_s, 0, strlen(clsname_s)); @@ -337,7 +337,7 @@ void setupCallback(Runtime *runtime, JClass *clazz) { env->utf8_destory(type); } if (!refers._callback_minial_on_send_frames) { - clsname_s = "org/mini/media/AudioDevice"; + clsname_s = "org/mini/media/MADevice"; name_s = "onSendFrames"; type_s = "(JIJ)I"; Utf8String *clsname = env->utf8_create_part_c(clsname_s, 0, strlen(clsname_s)); @@ -349,7 +349,7 @@ void setupCallback(Runtime *runtime, JClass *clazz) { env->utf8_destory(type); } if (!refers._callback_minial_on_stop) { - clsname_s = "org/mini/media/AudioDevice"; + clsname_s = "org/mini/media/MADevice"; name_s = "onStop"; type_s = "(J)V"; Utf8String *clsname = env->utf8_create_part_c(clsname_s, 0, strlen(clsname_s)); @@ -504,6 +504,17 @@ int org_mini_media_MiniAudio_ma_engine_stop(Runtime *runtime, JClass *clazz) { return 0; } +int org_mini_media_MiniAudio_ma_engine_get_device(Runtime *runtime, JClass *clazz) { + JniEnv *env = runtime->jnienv; + s32 pos = 0; + ma_engine *handle_engine = (__refer) (intptr_t) env->localvar_getLong_2slot(runtime->localvar, pos); + pos += 2; + + s64 r = (s64) (intptr_t) ma_engine_get_device(handle_engine); + env->push_long(runtime->stack, r); + return 0; +} + int org_mini_media_MiniAudio_ma_engine_get_channels(Runtime *runtime, JClass *clazz) { JniEnv *env = runtime->jnienv; s32 pos = 0; @@ -905,6 +916,7 @@ static java_native_method method_minial_table[] = { {"org/mini/media/MiniAudio", "ma_engine_play_sound", "(J[B)I", org_mini_media_MiniAudio_ma_engine_play_sound}, {"org/mini/media/MiniAudio", "ma_engine_start", "(J)I", org_mini_media_MiniAudio_ma_engine_start}, {"org/mini/media/MiniAudio", "ma_engine_stop", "(J)I", org_mini_media_MiniAudio_ma_engine_stop}, + {"org/mini/media/MiniAudio", "ma_engine_get_device", "(J)J", org_mini_media_MiniAudio_ma_engine_get_device}, {"org/mini/media/MiniAudio", "ma_engine_get_channels", "(J)I", org_mini_media_MiniAudio_ma_engine_get_channels}, {"org/mini/media/MiniAudio", "ma_engine_get_sample_rate", "(J)I", org_mini_media_MiniAudio_ma_engine_get_sample_rate}, {"org/mini/media/MiniAudio", "ma_engine_get_format", "(J)I", org_mini_media_MiniAudio_ma_engine_get_format}, diff --git a/desktop/glfw_gui/java/pom.xml b/desktop/glfw_gui/java/pom.xml index 4106c114..c85ad50d 100755 --- a/desktop/glfw_gui/java/pom.xml +++ b/desktop/glfw_gui/java/pom.xml @@ -8,7 +8,7 @@ io.github.digitalgust glfw_gui ${project.groupId}:${project.artifactId} - 1.1.2 + 1.1.3 miniJVM desktop platform gui library https://github.com/digitalgust/miniJVM diff --git a/desktop/glfw_gui/java/src/main/java/org/mini/media/MiniAudio.java b/desktop/glfw_gui/java/src/main/java/org/mini/media/MiniAudio.java index 1a38c741..d3c02bb6 100755 --- a/desktop/glfw_gui/java/src/main/java/org/mini/media/MiniAudio.java +++ b/desktop/glfw_gui/java/src/main/java/org/mini/media/MiniAudio.java @@ -160,6 +160,8 @@ public class MiniAudio { public static native int ma_engine_stop(long handle_engine); + public static native long ma_engine_get_device(long handle_engine); + public static native int ma_engine_get_channels(long handle_engine); public static native int ma_engine_get_sample_rate(long handle_engine); diff --git a/extlib/xgui/pom.xml b/extlib/xgui/pom.xml index 936e4764..3132885d 100755 --- a/extlib/xgui/pom.xml +++ b/extlib/xgui/pom.xml @@ -9,7 +9,7 @@ io.github.digitalgust xgui ${project.groupId}:${project.artifactId} - 1.1.6 + 1.1.7 miniJVM mobile platform gui library https://github.com/digitalgust/miniJVM @@ -158,12 +158,12 @@ io.github.digitalgust glfw_gui - 1.1.2 + 1.1.3 io.github.digitalgust glfm_gui - 1.1.2 + 1.1.3 diff --git a/extlib/xgui/src/main/java/org/mini/glfw/GlfwCallBackImpl.java b/extlib/xgui/src/main/java/org/mini/glfw/GlfwCallBackImpl.java index 4c65f7ca..1510ff91 100644 --- a/extlib/xgui/src/main/java/org/mini/glfw/GlfwCallBackImpl.java +++ b/extlib/xgui/src/main/java/org/mini/glfw/GlfwCallBackImpl.java @@ -11,6 +11,8 @@ import org.mini.gui.GCallBack; import org.mini.gui.GForm; import org.mini.gui.GToolkit; +import org.mini.media.MaDevice; +import org.mini.media.MiniAudio; import java.io.File; @@ -191,6 +193,7 @@ public void mainLoop() { public void destroy() { nvgDeleteGL3(vg); Glfw.glfwTerminate(); + MaDevice.stopAll(); vg = 0; System.exit(0);//some thread not exit ,that will continue running } diff --git a/extlib/xgui/src/main/java/org/mini/media/MaDevice.java b/extlib/xgui/src/main/java/org/mini/media/MaDevice.java index 0c2fc874..39bf5f99 100755 --- a/extlib/xgui/src/main/java/org/mini/media/MaDevice.java +++ b/extlib/xgui/src/main/java/org/mini/media/MaDevice.java @@ -8,6 +8,7 @@ import org.mini.reflect.DirectMemObj; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; /** @@ -100,6 +101,7 @@ void checkThread() { public void finalize() { if (handle != 0) { MiniAudio.ma_device_uninit(handle); + devices.remove(handle); handle = 0; } } @@ -119,6 +121,23 @@ public static int getFormatBytes(int format) { return 0; } + public static void putDevice(long deviceHandle) { + devices.put(deviceHandle, null); + } + + public static void removeDevice(long deviceHandle) { + devices.remove(deviceHandle); + } + + public static void stopAll() { + for (Iterator it = devices.keySet().iterator(); it.hasNext(); ) { + Long deviceHanle = it.next(); + if (deviceHanle != null) { + MiniAudio.ma_device_stop(deviceHanle.longValue()); + } + } + } + /** * ================================================================================================= *

diff --git a/extlib/xgui/src/main/java/org/mini/media/engine/MaEngine.java b/extlib/xgui/src/main/java/org/mini/media/engine/MaEngine.java index ddf8bbde..65ef4ab1 100644 --- a/extlib/xgui/src/main/java/org/mini/media/engine/MaEngine.java +++ b/extlib/xgui/src/main/java/org/mini/media/engine/MaEngine.java @@ -1,5 +1,6 @@ package org.mini.media.engine; +import org.mini.media.MaDevice; import org.mini.media.MaNativeObject; import org.mini.media.MiniAudio; @@ -9,6 +10,7 @@ public class MaEngine extends MaNativeObject { int format; int channels; int ratio; + long device; public MaEngine() { handle = MiniAudio.ma_engine_init(); @@ -16,6 +18,8 @@ public MaEngine() { format = MiniAudio.ma_engine_get_format(handle); channels = MiniAudio.ma_engine_get_channels(handle); ratio = MiniAudio.ma_engine_get_sample_rate(handle); + device = MiniAudio.ma_engine_get_device(handle); + MaDevice.putDevice(device); } } @@ -72,6 +76,7 @@ public float getVolume() { public void finalize() { System.out.println("clean " + this + " " + handle); MiniAudio.ma_engine_uninit(handle); + MaDevice.removeDevice(handle); handle = 0; } diff --git a/extlib/xgui/xgui.iml b/extlib/xgui/xgui.iml deleted file mode 100644 index 056f8821..00000000 --- a/extlib/xgui/xgui.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/minijvm/c/jvm/jdwp.c b/minijvm/c/jvm/jdwp.c index f53613be..7877e1a8 100644 --- a/minijvm/c/jvm/jdwp.c +++ b/minijvm/c/jvm/jdwp.c @@ -105,7 +105,7 @@ s32 jdwp_thread_dispacher(void *para) { arraylist_remove(jdwpserver->clients, client); } } - threadSleep(10); + threadSleep(20); } jdwpserver->mode &= ~JDWP_MODE_DISPATCH; return 0; @@ -1562,7 +1562,7 @@ s32 jdwp_client_process(JdwpServer *jdwpserver, JdwpClient *client) { jdwp_packet_put(jdwpserver, res); utf8_destory(ustr); while (!jvm->thread_list->length) { - threadSleep(10); + threadSleep(20); } Runtime *mainthread = (Runtime *) arraylist_get_value(jdwpserver->jvm->thread_list, 0); if (jdwpserver->jvm->jdwp_suspend_on_start)event_on_vmstart(jdwpserver, mainthread->thrd_info->jthread); diff --git a/mobile/c/gui/jni_minial.m b/mobile/c/gui/jni_minial.m index 6029a3a8..7a006671 100755 --- a/mobile/c/gui/jni_minial.m +++ b/mobile/c/gui/jni_minial.m @@ -325,7 +325,7 @@ void setupCallback(Runtime *runtime, JClass *clazz) { c8 *type_s; c8 *clsname_s; if (!refers._callback_minial_on_recv_frames) { - clsname_s = "org/mini/media/AudioDevice"; + clsname_s = "org/mini/media/MADevice"; name_s = "onReceiveFrames"; type_s = "(JIJ)V"; Utf8String *clsname = env->utf8_create_part_c(clsname_s, 0, strlen(clsname_s)); @@ -337,7 +337,7 @@ void setupCallback(Runtime *runtime, JClass *clazz) { env->utf8_destory(type); } if (!refers._callback_minial_on_send_frames) { - clsname_s = "org/mini/media/AudioDevice"; + clsname_s = "org/mini/media/MADevice"; name_s = "onSendFrames"; type_s = "(JIJ)I"; Utf8String *clsname = env->utf8_create_part_c(clsname_s, 0, strlen(clsname_s)); @@ -349,7 +349,7 @@ void setupCallback(Runtime *runtime, JClass *clazz) { env->utf8_destory(type); } if (!refers._callback_minial_on_stop) { - clsname_s = "org/mini/media/AudioDevice"; + clsname_s = "org/mini/media/MADevice"; name_s = "onStop"; type_s = "(J)V"; Utf8String *clsname = env->utf8_create_part_c(clsname_s, 0, strlen(clsname_s)); @@ -504,6 +504,17 @@ int org_mini_media_MiniAudio_ma_engine_stop(Runtime *runtime, JClass *clazz) { return 0; } +int org_mini_media_MiniAudio_ma_engine_get_device(Runtime *runtime, JClass *clazz) { + JniEnv *env = runtime->jnienv; + s32 pos = 0; + ma_engine *handle_engine = (__refer) (intptr_t) env->localvar_getLong_2slot(runtime->localvar, pos); + pos += 2; + + s64 r = (s64) (intptr_t) ma_engine_get_device(handle_engine); + env->push_long(runtime->stack, r); + return 0; +} + int org_mini_media_MiniAudio_ma_engine_get_channels(Runtime *runtime, JClass *clazz) { JniEnv *env = runtime->jnienv; s32 pos = 0; @@ -905,6 +916,7 @@ int org_mini_media_MiniAudio_ma_sound_at_end(Runtime *runtime, JClass *clazz) { {"org/mini/media/MiniAudio", "ma_engine_play_sound", "(J[B)I", org_mini_media_MiniAudio_ma_engine_play_sound}, {"org/mini/media/MiniAudio", "ma_engine_start", "(J)I", org_mini_media_MiniAudio_ma_engine_start}, {"org/mini/media/MiniAudio", "ma_engine_stop", "(J)I", org_mini_media_MiniAudio_ma_engine_stop}, + {"org/mini/media/MiniAudio", "ma_engine_get_device", "(J)J", org_mini_media_MiniAudio_ma_engine_get_device}, {"org/mini/media/MiniAudio", "ma_engine_get_channels", "(J)I", org_mini_media_MiniAudio_ma_engine_get_channels}, {"org/mini/media/MiniAudio", "ma_engine_get_sample_rate", "(J)I", org_mini_media_MiniAudio_ma_engine_get_sample_rate}, {"org/mini/media/MiniAudio", "ma_engine_get_format", "(J)I", org_mini_media_MiniAudio_ma_engine_get_format}, diff --git a/mobile/c/gui/minial/miniaudio.h b/mobile/c/gui/minial/miniaudio.h index f6d01645..47332e11 100644 --- a/mobile/c/gui/minial/miniaudio.h +++ b/mobile/c/gui/minial/miniaudio.h @@ -1,6 +1,6 @@ /* Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. -miniaudio - v0.11.20 - TBD +miniaudio - v0.11.21 - 2023-11-15 David Reid - mackron@gmail.com @@ -3723,7 +3723,7 @@ extern "C" { #define MA_VERSION_MAJOR 0 #define MA_VERSION_MINOR 11 -#define MA_VERSION_REVISION 20 +#define MA_VERSION_REVISION 21 #define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION) #if defined(_MSC_VER) && !defined(__clang__) @@ -6716,7 +6716,8 @@ typedef enum ma_device_notification_type_stopped, ma_device_notification_type_rerouted, ma_device_notification_type_interruption_began, - ma_device_notification_type_interruption_ended + ma_device_notification_type_interruption_ended, + ma_device_notification_type_unlocked } ma_device_notification_type; typedef struct @@ -18668,6 +18669,14 @@ static void ma_device__on_notification_rerouted(ma_device* pDevice) } #endif +#if defined(MA_EMSCRIPTEN) +EMSCRIPTEN_KEEPALIVE +void ma_device__on_notification_unlocked(ma_device* pDevice) +{ + ma_device__on_notification(ma_device_notification_init(pDevice, ma_device_notification_type_unlocked)); +} +#endif + static void ma_device__on_data_inner(ma_device* pDevice, void* pFramesOut, const void* pFramesIn, ma_uint32 frameCount) { @@ -32797,9 +32806,9 @@ static ma_result ma_find_best_format__coreaudio(ma_context* pContext, AudioObjec hasSupportedFormat = MA_FALSE; for (iFormat = 0; iFormat < deviceFormatDescriptionCount; ++iFormat) { - ma_format format; - ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &format); - if (formatResult == MA_SUCCESS && format != ma_format_unknown) { + ma_format formatFromDescription; + ma_result formatResult = ma_format_from_AudioStreamBasicDescription(&pDeviceFormatDescriptions[iFormat].mFormat, &formatFromDescription); + if (formatResult == MA_SUCCESS && formatFromDescription != ma_format_unknown) { hasSupportedFormat = MA_TRUE; bestDeviceFormatSoFar = pDeviceFormatDescriptions[iFormat].mFormat; break; @@ -39800,6 +39809,7 @@ static ma_result ma_device_uninit__webaudio(ma_device* pDevice) */ device.webaudio.close(); device.webaudio = undefined; + device.pDevice = undefined; }, pDevice->webaudio.deviceIndex); } #endif @@ -39823,6 +39833,10 @@ static ma_uint32 ma_calculate_period_size_in_frames_from_descriptor__webaudio(co */ ma_uint32 periodSizeInFrames; + if (nativeSampleRate == 0) { + nativeSampleRate = MA_DEFAULT_SAMPLE_RATE; + } + if (pDescriptor->periodSizeInFrames == 0) { if (pDescriptor->periodSizeInMilliseconds == 0) { if (performanceProfile == ma_performance_profile_low_latency) { @@ -40295,6 +40309,8 @@ static ma_result ma_device_init__webaudio(ma_device* pDevice, const ma_device_co device.scriptNode.connect(device.webaudio.destination); } + device.pDevice = pDevice; + return miniaudio.track_device(device); }, pConfig->deviceType, channels, sampleRate, periodSizeInFrames, pDevice->webaudio.pIntermediaryBuffer, pDevice); @@ -40467,8 +40483,15 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex miniaudio.unlock = function() { for(var i = 0; i < miniaudio.devices.length; ++i) { var device = miniaudio.devices[i]; - if (device != null && device.webaudio != null && device.state === 2 /* ma_device_state_started */) { - device.webaudio.resume(); + if (device != null && + device.webaudio != null && + device.state === window.miniaudio.device_state.started) { + + device.webaudio.resume().then(() => { + Module._ma_device__on_notification_unlocked(device.pDevice); + }, + (error) => {console.error("Failed to resume audiocontext", error); + }); } } miniaudio.unlock_event_types.map(function(event_type) { diff --git a/mobile/iosapp/iosapp.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate b/mobile/iosapp/iosapp.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate index a53f65bc2108b60a9f4256928b67b052766d5292..07884dd722cf49396770c101d8af541f474b0dfa 100644 GIT binary patch literal 17268 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 delta 6801 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 diff --git a/mobile/java/glfm_gui/pom.xml b/mobile/java/glfm_gui/pom.xml index 29328838..813da425 100755 --- a/mobile/java/glfm_gui/pom.xml +++ b/mobile/java/glfm_gui/pom.xml @@ -8,7 +8,7 @@ io.github.digitalgust glfm_gui ${project.groupId}:${project.artifactId} - 1.1.2 + 1.1.3 miniJVM mobile platform gui library https://github.com/digitalgust/miniJVM diff --git a/mobile/java/glfm_gui/src/main/java/org/mini/media/MiniAudio.java b/mobile/java/glfm_gui/src/main/java/org/mini/media/MiniAudio.java index 1a38c741..d3c02bb6 100755 --- a/mobile/java/glfm_gui/src/main/java/org/mini/media/MiniAudio.java +++ b/mobile/java/glfm_gui/src/main/java/org/mini/media/MiniAudio.java @@ -160,6 +160,8 @@ public class MiniAudio { public static native int ma_engine_stop(long handle_engine); + public static native long ma_engine_get_device(long handle_engine); + public static native int ma_engine_get_channels(long handle_engine); public static native int ma_engine_get_sample_rate(long handle_engine);