penguin/loopdeck

A simple player that support A-B looping for FiiO M11S

app/src/main/cpp/jni.cpp

raw ยท 2762 bytes

#include "decoder.h"
#include <jni.h>
#include <memory>
#include <stdexcept>

static Decoder* decoder(jlong handle) {
    if (!handle) throw std::runtime_error("No file is open");
    return reinterpret_cast<Decoder*>(handle);
}
static void report(JNIEnv* env, const std::exception& e) {
    env->ThrowNew(env->FindClass("java/io/IOException"), e.what());
}
extern "C" JNIEXPORT jlong JNICALL
Java_net_astropenguin_loopdeck_NativeDecoder_open(JNIEnv* env, jclass, jint fd) {
    try {
        auto d = std::make_unique<Decoder>(fd); d->open();
        return reinterpret_cast<jlong>(d.release());
    } catch (const std::exception& e) { report(env, e); return 0; }
}
extern "C" JNIEXPORT void JNICALL
Java_net_astropenguin_loopdeck_NativeDecoder_close(JNIEnv*, jclass, jlong handle) { delete reinterpret_cast<Decoder*>(handle); }
extern "C" JNIEXPORT jint JNICALL
Java_net_astropenguin_loopdeck_NativeDecoder_sourceRate(JNIEnv* env, jclass, jlong handle) {
    try { return decoder(handle)->sourceRate(); } catch (const std::exception& e) { report(env,e); return 0; }
}
extern "C" JNIEXPORT jlong JNICALL
Java_net_astropenguin_loopdeck_NativeDecoder_duration(JNIEnv* env, jclass, jlong handle) {
    try { return decoder(handle)->durationMs(); } catch (const std::exception& e) { report(env,e); return 0; }
}
extern "C" JNIEXPORT jstring JNICALL
Java_net_astropenguin_loopdeck_NativeDecoder_description(JNIEnv* env, jclass, jlong handle) {
    try { return env->NewStringUTF(decoder(handle)->description().c_str()); } catch (const std::exception& e) { report(env,e); return nullptr; }
}
extern "C" JNIEXPORT void JNICALL
Java_net_astropenguin_loopdeck_NativeDecoder_outputRate(JNIEnv* env, jclass, jlong handle, jint rate) {
    try { decoder(handle)->outputRate(rate); } catch (const std::exception& e) { report(env,e); }
}
extern "C" JNIEXPORT void JNICALL
Java_net_astropenguin_loopdeck_NativeDecoder_seek(JNIEnv* env, jclass, jlong handle, jlong frame) {
    try { decoder(handle)->seek(frame); } catch (const std::exception& e) { report(env,e); }
}
extern "C" JNIEXPORT jint JNICALL
Java_net_astropenguin_loopdeck_NativeDecoder_read(JNIEnv* env, jclass, jlong handle, jfloatArray array, jint frames) {
    try {
        auto* d = decoder(handle);
        if (frames < 0 || frames > env->GetArrayLength(array) / 2) throw std::runtime_error("Invalid PCM buffer size");
        // Avoid pinning a Java array across file IO and codec work.
        thread_local std::vector<float> scratch;
        scratch.resize(static_cast<size_t>(frames) * 2);
        int count = d->read(scratch.data(), frames);
        env->SetFloatArrayRegion(array, 0, count * 2, scratch.data());
        return count;
    } catch (const std::exception& e) { report(env,e); return 0; }
}