musikr: bubblewrap jvminputstream
Should help me ID some error.
This commit is contained in:
parent
71aa887438
commit
b6d80189ca
4 changed files with 79 additions and 28 deletions
|
@ -48,6 +48,7 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
|||
JVMInputStream.cpp
|
||||
JVMTagMap.cpp
|
||||
JVMMetadataBuilder.cpp
|
||||
util.cpp
|
||||
)
|
||||
target_link_options(${CMAKE_PROJECT_NAME}
|
||||
# @Tolriq found that these flags can reduce the size of the linked
|
||||
|
|
|
@ -17,32 +17,42 @@
|
|||
*/
|
||||
|
||||
#include "JVMInputStream.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// TODO: Handle stream exceptions
|
||||
JVMInputStream::JVMInputStream(JNIEnv *env, jobject inputStream) : env(env), inputStream(
|
||||
inputStream) {
|
||||
if (!env->IsInstanceOf(inputStream,
|
||||
env->FindClass("org/oxycblt/musikr/metadata/NativeInputStream"))) {
|
||||
TRY(auto isNativeInputStream = env->IsInstanceOf(inputStream,
|
||||
env->FindClass("org/oxycblt/musikr/metadata/NativeInputStream")))
|
||||
if (!isNativeInputStream) {
|
||||
throw std::runtime_error("oStream is not an instance of TagLibOStream");
|
||||
}
|
||||
jclass inputStreamClass = env->FindClass(
|
||||
"org/oxycblt/musikr/metadata/NativeInputStream");
|
||||
inputStreamReadBlockMethod = env->GetMethodID(inputStreamClass, "readBlock",
|
||||
"(J)[B");
|
||||
inputStreamIsOpenMethod = env->GetMethodID(inputStreamClass, "isOpen",
|
||||
"()Z");
|
||||
inputStreamSeekFromBeginningMethod = env->GetMethodID(inputStreamClass,
|
||||
"seekFromBeginning", "(J)V");
|
||||
inputStreamSeekFromCurrentMethod = env->GetMethodID(inputStreamClass,
|
||||
"seekFromCurrent", "(J)V");
|
||||
TRY(jclass inputStreamClass = env->FindClass(
|
||||
"org/oxycblt/musikr/metadata/NativeInputStream"));
|
||||
TRY(
|
||||
inputStreamReadBlockMethod = env->GetMethodID(inputStreamClass,
|
||||
"readBlock", "(J)[B"));
|
||||
TRY(
|
||||
inputStreamIsOpenMethod = env->GetMethodID(inputStreamClass,
|
||||
"isOpen", "()Z"));
|
||||
TRY(
|
||||
inputStreamSeekFromBeginningMethod = env->GetMethodID(
|
||||
inputStreamClass, "seekFromBeginning", "(J)V"));
|
||||
TRY(
|
||||
inputStreamSeekFromCurrentMethod = env->GetMethodID(
|
||||
inputStreamClass, "seekFromCurrent", "(J)V"));
|
||||
TRY(
|
||||
inputStreamSeekFromEndMethod = env->GetMethodID(inputStreamClass,
|
||||
"seekFromEnd", "(J)V");
|
||||
inputStreamTellMethod = env->GetMethodID(inputStreamClass, "tell", "()J");
|
||||
inputStreamLengthMethod = env->GetMethodID(inputStreamClass, "length",
|
||||
"()J");
|
||||
env->DeleteLocalRef(inputStreamClass);
|
||||
"seekFromEnd", "(J)V"));
|
||||
TRY(
|
||||
inputStreamTellMethod = env->GetMethodID(inputStreamClass, "tell",
|
||||
"()J"));
|
||||
TRY(
|
||||
inputStreamLengthMethod = env->GetMethodID(inputStreamClass,
|
||||
"length", "()J"));
|
||||
TRY(env->DeleteLocalRef(inputStreamClass));
|
||||
}
|
||||
|
||||
JVMInputStream::~JVMInputStream() {
|
||||
|
@ -56,13 +66,15 @@ TagLib::FileName JVMInputStream::name() const {
|
|||
}
|
||||
|
||||
TagLib::ByteVector JVMInputStream::readBlock(size_t length) {
|
||||
auto data = (jbyteArray) env->CallObjectMethod(inputStream,
|
||||
inputStreamReadBlockMethod, length);
|
||||
jsize dataLength = env->GetArrayLength(data);
|
||||
auto dataBytes = env->GetByteArrayElements(data, nullptr);
|
||||
TRY(auto data = (jbyteArray) env->CallObjectMethod(inputStream,
|
||||
inputStreamReadBlockMethod, length));
|
||||
// Check for an exception
|
||||
// If we don't do this, data == nullptr and the remaining calls crash.
|
||||
TRY(jsize dataLength = env->GetArrayLength(data));
|
||||
TRY(auto dataBytes = env->GetByteArrayElements(data, nullptr));
|
||||
TagLib::ByteVector byteVector(reinterpret_cast<const char*>(dataBytes),
|
||||
dataLength);
|
||||
env->ReleaseByteArrayElements(data, dataBytes, JNI_ABORT);
|
||||
TRY(env->ReleaseByteArrayElements(data, dataBytes, JNI_ABORT));
|
||||
return byteVector;
|
||||
}
|
||||
|
||||
|
@ -84,15 +96,17 @@ bool JVMInputStream::readOnly() const {
|
|||
}
|
||||
|
||||
bool JVMInputStream::isOpen() const {
|
||||
return env->CallBooleanMethod(inputStream, inputStreamIsOpenMethod);
|
||||
TRY(auto result = env->CallBooleanMethod(inputStream, inputStreamIsOpenMethod));
|
||||
return result;
|
||||
}
|
||||
|
||||
void JVMInputStream::seek(TagLib::offset_t offset, Position p) {
|
||||
auto joffset = static_cast<jlong>(std::llround(offset));
|
||||
switch (p) {
|
||||
case Beginning:
|
||||
env->CallVoidMethod(inputStream, inputStreamSeekFromBeginningMethod,
|
||||
joffset);
|
||||
TRY(
|
||||
env->CallVoidMethod(inputStream,
|
||||
inputStreamSeekFromBeginningMethod, joffset));
|
||||
break;
|
||||
case Current:
|
||||
env->CallVoidMethod(inputStream, inputStreamSeekFromCurrentMethod,
|
||||
|
@ -109,12 +123,12 @@ void JVMInputStream::clear() {
|
|||
}
|
||||
|
||||
TagLib::offset_t JVMInputStream::tell() const {
|
||||
jlong jposition = env->CallLongMethod(inputStream, inputStreamTellMethod);
|
||||
TRY(jlong jposition = env->CallLongMethod(inputStream, inputStreamTellMethod));
|
||||
return static_cast<TagLib::offset_t>(jposition);
|
||||
}
|
||||
|
||||
TagLib::offset_t JVMInputStream::length() {
|
||||
jlong jlength = env->CallLongMethod(inputStream, inputStreamLengthMethod);
|
||||
TRY(jlong jlength = env->CallLongMethod(inputStream, inputStreamLengthMethod));
|
||||
return static_cast<TagLib::offset_t>(jlength);
|
||||
}
|
||||
|
||||
|
|
30
musikr/src/main/cpp/util.cpp
Normal file
30
musikr/src/main/cpp/util.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Auxio Project
|
||||
* util.cpp is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
void jni_check(JNIEnv *env) {
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
throw std::runtime_error(
|
||||
"An exception occurred in a JNI call, see logcat");
|
||||
}
|
||||
}
|
|
@ -28,4 +28,10 @@
|
|||
#define LOGD(...) \
|
||||
((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
|
||||
|
||||
void jni_check(JNIEnv *env);
|
||||
|
||||
#define TRY(block) \
|
||||
block; \
|
||||
jni_check(env);
|
||||
|
||||
#endif //AUXIO_UTIL_H
|
||||
|
|
Loading…
Reference in a new issue