diff --git a/CMakeLists.txt b/CMakeLists.txt index 00cdfea7..60e91431 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,12 +21,18 @@ else() target_sources(mcpelauncher-client PRIVATE src/cpuid.cpp src/cpuid.h src/xbox_shutdown_patch.cpp src/xbox_shutdown_patch.h src/texel_aa_patch.cpp src/texel_aa_patch.h) endif() -find_package(PulseAudio) +if(TARGET SDL3::SDL3) + target_sources(mcpelauncher-client PRIVATE src/jni/sdl3audio.cpp src/jni/sdl3audio.h) + target_link_libraries(mcpelauncher-client SDL3::SDL3) + target_compile_definitions(mcpelauncher-client PRIVATE HAVE_SDL3AUDIO) +else() + find_package(PulseAudio) -if (PULSEAUDIO_FOUND AND PULSEAUDIOSIMPLE_FOUND) - target_sources(mcpelauncher-client PRIVATE src/jni/pulseaudio.cpp src/jni/pulseaudio.h) - target_link_libraries(mcpelauncher-client ${PULSEAUDIO_LIBRARIES} ${PULSEAUDIOSIMPLE_LIBRARIES}) - target_compile_definitions(mcpelauncher-client PRIVATE HAVE_PULSEAUDIO) + if (PULSEAUDIO_FOUND AND PULSEAUDIOSIMPLE_FOUND) + target_sources(mcpelauncher-client PRIVATE src/jni/pulseaudio.cpp src/jni/pulseaudio.h) + target_link_libraries(mcpelauncher-client ${PULSEAUDIO_LIBRARIES} ${PULSEAUDIOSIMPLE_LIBRARIES}) + target_compile_definitions(mcpelauncher-client PRIVATE HAVE_PULSEAUDIO) + endif() endif() option(XAL_WEBVIEW_USE_CLI "use cli for login to xboxlive" OFF) diff --git a/src/fake_looper.cpp b/src/fake_looper.cpp index 2d4d1ebd..985e9ed4 100644 --- a/src/fake_looper.cpp +++ b/src/fake_looper.cpp @@ -111,6 +111,15 @@ void FakeLooper::attachInputQueue(int ident, ALooper_callbackFunc callback, void int FakeLooper::pollAll(int timeoutMillis, int *outFd, int *outEvents, void **outData) { associatedWindowCallbacks->startSendEvents(); + if(textInput != jniSupport->getTextInputHandler().isEnabled()) { + textInput = jniSupport->getTextInputHandler().isEnabled(); + if(textInput) { + associatedWindow->startTextInput(); + } else { + associatedWindow->stopTextInput(); + } + } + if(androidEvent) { pollfd f; f.fd = androidEvent.fd; diff --git a/src/fake_looper.h b/src/fake_looper.h index 6125530d..d3cc0012 100644 --- a/src/fake_looper.h +++ b/src/fake_looper.h @@ -12,6 +12,7 @@ class FakeLooper { static JniSupport *jniSupport; static thread_local std::unique_ptr currentLooper; bool prepared = false; + bool textInput = false; struct EventEntry { int fd, ident, events; diff --git a/src/jni/jni_descriptors.cpp b/src/jni/jni_descriptors.cpp index c49a3073..edfc491c 100644 --- a/src/jni/jni_descriptors.cpp +++ b/src/jni/jni_descriptors.cpp @@ -9,6 +9,9 @@ #ifdef HAVE_PULSEAUDIO #include "pulseaudio.h" #endif +#ifdef HAVE_SDL3AUDIO +#include "sdl3audio.h" +#endif #include "java_types.h" #include "accounts.h" #include "ecdsa.h" @@ -308,7 +311,7 @@ BEGIN_NATIVE_DESCRIPTOR(HTTPResponse){Function<&HTTPResponse::getStatus>{}, "get {Constructor{}}, END_NATIVE_DESCRIPTOR -#ifdef HAVE_PULSEAUDIO +#if defined(HAVE_PULSEAUDIO) || defined(HAVE_SDL3AUDIO) BEGIN_NATIVE_DESCRIPTOR(AudioDevice){Constructor{}}, {Function<&AudioDevice::init>{}, "init"}, {Function<&AudioDevice::write>{}, "write"}, diff --git a/src/jni/jni_support.cpp b/src/jni/jni_support.cpp index c1dbece4..7a762f9b 100644 --- a/src/jni/jni_support.cpp +++ b/src/jni/jni_support.cpp @@ -12,6 +12,9 @@ #ifdef HAVE_PULSEAUDIO #include "pulseaudio.h" #endif +#ifdef HAVE_SDL3AUDIO +#include "sdl3audio.h" +#endif #include "accounts.h" #include "ecdsa.h" #include "webview.h" @@ -101,7 +104,7 @@ void JniSupport::registerJniClasses() { vm.registerClass(); -#ifdef HAVE_PULSEAUDIO +#if defined(HAVE_PULSEAUDIO) || defined(HAVE_SDL3AUDIO) vm.registerClass(); #endif } diff --git a/src/jni/sdl3audio.cpp b/src/jni/sdl3audio.cpp new file mode 100644 index 00000000..6e93f3b9 --- /dev/null +++ b/src/jni/sdl3audio.cpp @@ -0,0 +1,45 @@ +#include "sdl3audio.h" +#include +#include +#include +AudioDevice::AudioDevice() { + s = nullptr; + SDL_Init(SDL_INIT_AUDIO); +} + +AudioDevice::~AudioDevice() { + SDL_QuitSubSystem(SDL_INIT_AUDIO); +} + +FakeJni::JBoolean AudioDevice::init(FakeJni::JInt channels, FakeJni::JInt samplerate, FakeJni::JInt c, FakeJni::JInt d) { + if(s != NULL) { + GameWindowManager::getManager()->getErrorHandler()->onError("sdl3audio failed", "sdl3audio already initialized"); + } + SDL_AudioSpec spec; + spec.channels = channels; + spec.format = SDL_AUDIO_S16LE; + spec.freq = samplerate; + maxBufferLen = c * d * channels * 2; + s = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, nullptr, nullptr); + if(s == NULL) { + auto errormsg = SDL_GetError(); + GameWindowManager::getManager()->getErrorHandler()->onError("sdl3audio failed", std::string("sdl3audio SDL_OpenAudioDeviceStream failed, audio will be unavailable: ") + (errormsg ? errormsg : "No message from sdl3audio")); + return false; + } + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(s)); + return true; +} + +void AudioDevice::write(std::shared_ptr data, FakeJni::JInt length) { + SDL_PutAudioStreamData(s, data->getArray(), length); + // SDL3 cannot set any max buf size and fmod doesn't feeding data with the correct rate without it + // appeared as silence and a queue overflow + while(SDL_GetAudioStreamQueued(s) > maxBufferLen) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } +} + +void AudioDevice::close() { + SDL_DestroyAudioStream(s); + s = nullptr; +} diff --git a/src/jni/sdl3audio.h b/src/jni/sdl3audio.h new file mode 100644 index 00000000..7f947428 --- /dev/null +++ b/src/jni/sdl3audio.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +class AudioDevice : public FakeJni::JObject { + SDL_AudioStream* s; + int maxBufferLen; + +public: + DEFINE_CLASS_NAME("org/fmod/AudioDevice") + + AudioDevice(); + ~AudioDevice(); + + FakeJni::JBoolean init(FakeJni::JInt channels, FakeJni::JInt samplerate, FakeJni::JInt c, FakeJni::JInt d); + + void write(std::shared_ptr data, FakeJni::JInt length); + + void close(); +};