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
|
JVMInputStream.cpp
|
||||||
JVMTagMap.cpp
|
JVMTagMap.cpp
|
||||||
JVMMetadataBuilder.cpp
|
JVMMetadataBuilder.cpp
|
||||||
|
util.cpp
|
||||||
)
|
)
|
||||||
target_link_options(${CMAKE_PROJECT_NAME}
|
target_link_options(${CMAKE_PROJECT_NAME}
|
||||||
# @Tolriq found that these flags can reduce the size of the linked
|
# @Tolriq found that these flags can reduce the size of the linked
|
||||||
|
|
|
@ -17,32 +17,42 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "JVMInputStream.h"
|
#include "JVMInputStream.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
// TODO: Handle stream exceptions
|
// TODO: Handle stream exceptions
|
||||||
JVMInputStream::JVMInputStream(JNIEnv *env, jobject inputStream) : env(env), inputStream(
|
JVMInputStream::JVMInputStream(JNIEnv *env, jobject inputStream) : env(env), inputStream(
|
||||||
inputStream) {
|
inputStream) {
|
||||||
if (!env->IsInstanceOf(inputStream,
|
TRY(auto isNativeInputStream = env->IsInstanceOf(inputStream,
|
||||||
env->FindClass("org/oxycblt/musikr/metadata/NativeInputStream"))) {
|
env->FindClass("org/oxycblt/musikr/metadata/NativeInputStream")))
|
||||||
|
if (!isNativeInputStream) {
|
||||||
throw std::runtime_error("oStream is not an instance of TagLibOStream");
|
throw std::runtime_error("oStream is not an instance of TagLibOStream");
|
||||||
}
|
}
|
||||||
jclass inputStreamClass = env->FindClass(
|
TRY(jclass inputStreamClass = env->FindClass(
|
||||||
"org/oxycblt/musikr/metadata/NativeInputStream");
|
"org/oxycblt/musikr/metadata/NativeInputStream"));
|
||||||
inputStreamReadBlockMethod = env->GetMethodID(inputStreamClass, "readBlock",
|
TRY(
|
||||||
"(J)[B");
|
inputStreamReadBlockMethod = env->GetMethodID(inputStreamClass,
|
||||||
inputStreamIsOpenMethod = env->GetMethodID(inputStreamClass, "isOpen",
|
"readBlock", "(J)[B"));
|
||||||
"()Z");
|
TRY(
|
||||||
inputStreamSeekFromBeginningMethod = env->GetMethodID(inputStreamClass,
|
inputStreamIsOpenMethod = env->GetMethodID(inputStreamClass,
|
||||||
"seekFromBeginning", "(J)V");
|
"isOpen", "()Z"));
|
||||||
inputStreamSeekFromCurrentMethod = env->GetMethodID(inputStreamClass,
|
TRY(
|
||||||
"seekFromCurrent", "(J)V");
|
inputStreamSeekFromBeginningMethod = env->GetMethodID(
|
||||||
inputStreamSeekFromEndMethod = env->GetMethodID(inputStreamClass,
|
inputStreamClass, "seekFromBeginning", "(J)V"));
|
||||||
"seekFromEnd", "(J)V");
|
TRY(
|
||||||
inputStreamTellMethod = env->GetMethodID(inputStreamClass, "tell", "()J");
|
inputStreamSeekFromCurrentMethod = env->GetMethodID(
|
||||||
inputStreamLengthMethod = env->GetMethodID(inputStreamClass, "length",
|
inputStreamClass, "seekFromCurrent", "(J)V"));
|
||||||
"()J");
|
TRY(
|
||||||
env->DeleteLocalRef(inputStreamClass);
|
inputStreamSeekFromEndMethod = env->GetMethodID(inputStreamClass,
|
||||||
|
"seekFromEnd", "(J)V"));
|
||||||
|
TRY(
|
||||||
|
inputStreamTellMethod = env->GetMethodID(inputStreamClass, "tell",
|
||||||
|
"()J"));
|
||||||
|
TRY(
|
||||||
|
inputStreamLengthMethod = env->GetMethodID(inputStreamClass,
|
||||||
|
"length", "()J"));
|
||||||
|
TRY(env->DeleteLocalRef(inputStreamClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
JVMInputStream::~JVMInputStream() {
|
JVMInputStream::~JVMInputStream() {
|
||||||
|
@ -56,13 +66,15 @@ TagLib::FileName JVMInputStream::name() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
TagLib::ByteVector JVMInputStream::readBlock(size_t length) {
|
TagLib::ByteVector JVMInputStream::readBlock(size_t length) {
|
||||||
auto data = (jbyteArray) env->CallObjectMethod(inputStream,
|
TRY(auto data = (jbyteArray) env->CallObjectMethod(inputStream,
|
||||||
inputStreamReadBlockMethod, length);
|
inputStreamReadBlockMethod, length));
|
||||||
jsize dataLength = env->GetArrayLength(data);
|
// Check for an exception
|
||||||
auto dataBytes = env->GetByteArrayElements(data, nullptr);
|
// 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),
|
TagLib::ByteVector byteVector(reinterpret_cast<const char*>(dataBytes),
|
||||||
dataLength);
|
dataLength);
|
||||||
env->ReleaseByteArrayElements(data, dataBytes, JNI_ABORT);
|
TRY(env->ReleaseByteArrayElements(data, dataBytes, JNI_ABORT));
|
||||||
return byteVector;
|
return byteVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,15 +96,17 @@ bool JVMInputStream::readOnly() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JVMInputStream::isOpen() 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) {
|
void JVMInputStream::seek(TagLib::offset_t offset, Position p) {
|
||||||
auto joffset = static_cast<jlong>(std::llround(offset));
|
auto joffset = static_cast<jlong>(std::llround(offset));
|
||||||
switch (p) {
|
switch (p) {
|
||||||
case Beginning:
|
case Beginning:
|
||||||
env->CallVoidMethod(inputStream, inputStreamSeekFromBeginningMethod,
|
TRY(
|
||||||
joffset);
|
env->CallVoidMethod(inputStream,
|
||||||
|
inputStreamSeekFromBeginningMethod, joffset));
|
||||||
break;
|
break;
|
||||||
case Current:
|
case Current:
|
||||||
env->CallVoidMethod(inputStream, inputStreamSeekFromCurrentMethod,
|
env->CallVoidMethod(inputStream, inputStreamSeekFromCurrentMethod,
|
||||||
|
@ -109,12 +123,12 @@ void JVMInputStream::clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
TagLib::offset_t JVMInputStream::tell() const {
|
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);
|
return static_cast<TagLib::offset_t>(jposition);
|
||||||
}
|
}
|
||||||
|
|
||||||
TagLib::offset_t JVMInputStream::length() {
|
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);
|
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(...) \
|
#define LOGD(...) \
|
||||||
((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
|
((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
|
#endif //AUXIO_UTIL_H
|
||||||
|
|
Loading…
Reference in a new issue