From b306456d46d6fb145835e13beac792568cec725a Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Sat, 22 Feb 2025 21:00:59 -0700 Subject: [PATCH] musikr: fix hang on metadata extraction When files read all the way to EOF. --- musikr/src/main/cpp/JInputStream.cpp | 29 ++++++++++++------- musikr/src/main/cpp/JInputStream.h | 1 + .../musikr/metadata/NativeInputStream.kt | 7 ++--- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/musikr/src/main/cpp/JInputStream.cpp b/musikr/src/main/cpp/JInputStream.cpp index 8c729a8db..b003b9eda 100644 --- a/musikr/src/main/cpp/JInputStream.cpp +++ b/musikr/src/main/cpp/JInputStream.cpp @@ -34,7 +34,7 @@ JInputStream::JInputStream(JNIEnv *env, jobject jInputStream) : env(env), jInput jmethodID jInputStreamNameMethod = jInputStreamClass.method("name", "()Ljava/lang/String;"); jInputStreamReadBlockMethod = jInputStreamClass.method("readBlock", - "(Ljava/nio/ByteBuffer;)Z"); + "(Ljava/nio/ByteBuffer;)I"); jInputStreamIsOpenMethod = jInputStreamClass.method("isOpen", "()Z"); jInputStreamSeekFromBeginningMethod = jInputStreamClass.method( "seekFromBeginning", "(J)Z"); @@ -58,22 +58,31 @@ TagLib::FileName /* const char * */JInputStream::name() const { return _name.toCString(true); } -TagLib::ByteVector JInputStream::readBlock(size_t length) { - // We have to invert the buffer allocation here siits not a perfect system (vykeen instead of korvax0 but i warped all over the hub and i dont think its possible to find a "perfect" purple system like you would withnce the JVM ByteBuffer allocation system - // uses a bugged caching mechanism that leaks memory if used in multithreaded contexts. - TagLib::ByteVector buf { static_cast(length), 0 }; +jint JInputStream::readBlockImpl(TagLib::ByteVector &buf) { jobject wrappedByteBuffer = env->NewDirectByteBuffer(buf.data(), buf.size()); if (wrappedByteBuffer == nullptr) { throw std::runtime_error("Failed to wrap ByteBuffer"); } - JObjectRef byteBuffer = { env, wrappedByteBuffer }; - jboolean result = env->CallBooleanMethod(jInputStream, - jInputStreamReadBlockMethod, *byteBuffer); - if (!result) { + JObjectRef byteBuffer { env, wrappedByteBuffer }; + jint read = env->CallIntMethod(jInputStream, jInputStreamReadBlockMethod, + *byteBuffer); + return read; +} + +TagLib::ByteVector JInputStream::readBlock(size_t length) { + // We have to invert the buffer allocation here + TagLib::ByteVector buf { static_cast(length), 0 }; + jint read = readBlockImpl(buf); + if (read >= 0) { + buf.resize(read); + return buf; + } else if (read == -1) { + buf.resize(0); + return buf; + } else { throw std::runtime_error("Failed to read block, see logs"); } - return buf; } void JInputStream::writeBlock(const TagLib::ByteVector &data) { diff --git a/musikr/src/main/cpp/JInputStream.h b/musikr/src/main/cpp/JInputStream.h index 026e6c3c3..5245dbe96 100644 --- a/musikr/src/main/cpp/JInputStream.h +++ b/musikr/src/main/cpp/JInputStream.h @@ -124,6 +124,7 @@ private: jmethodID jInputStreamSeekFromEndMethod; jmethodID jInputStreamTellMethod; jmethodID jInputStreamLengthMethod; + jint readBlockImpl(TagLib::ByteVector &buf); }; #endif //AUXIO_JINPUTSTREAM_H diff --git a/musikr/src/main/java/org/oxycblt/musikr/metadata/NativeInputStream.kt b/musikr/src/main/java/org/oxycblt/musikr/metadata/NativeInputStream.kt index b8c22fb24..c7486e220 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/metadata/NativeInputStream.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/metadata/NativeInputStream.kt @@ -28,13 +28,12 @@ internal class NativeInputStream(private val deviceFile: DeviceFile, fis: FileIn fun name() = requireNotNull(deviceFile.path.name) - fun readBlock(buf: ByteBuffer): Boolean { + fun readBlock(buf: ByteBuffer): Int { try { - channel.read(buf) - return true + return channel.read(buf) } catch (e: Exception) { Log.d("NativeInputStream", "Error reading block", e) - return false + return -2 } }