musikr: fix hang on metadata extraction
When files read all the way to EOF.
This commit is contained in:
parent
1d44ce5d71
commit
b306456d46
3 changed files with 23 additions and 14 deletions
|
|
@ -34,7 +34,7 @@ JInputStream::JInputStream(JNIEnv *env, jobject jInputStream) : env(env), jInput
|
||||||
jmethodID jInputStreamNameMethod = jInputStreamClass.method("name",
|
jmethodID jInputStreamNameMethod = jInputStreamClass.method("name",
|
||||||
"()Ljava/lang/String;");
|
"()Ljava/lang/String;");
|
||||||
jInputStreamReadBlockMethod = jInputStreamClass.method("readBlock",
|
jInputStreamReadBlockMethod = jInputStreamClass.method("readBlock",
|
||||||
"(Ljava/nio/ByteBuffer;)Z");
|
"(Ljava/nio/ByteBuffer;)I");
|
||||||
jInputStreamIsOpenMethod = jInputStreamClass.method("isOpen", "()Z");
|
jInputStreamIsOpenMethod = jInputStreamClass.method("isOpen", "()Z");
|
||||||
jInputStreamSeekFromBeginningMethod = jInputStreamClass.method(
|
jInputStreamSeekFromBeginningMethod = jInputStreamClass.method(
|
||||||
"seekFromBeginning", "(J)Z");
|
"seekFromBeginning", "(J)Z");
|
||||||
|
|
@ -58,22 +58,31 @@ TagLib::FileName /* const char * */JInputStream::name() const {
|
||||||
return _name.toCString(true);
|
return _name.toCString(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TagLib::ByteVector JInputStream::readBlock(size_t length) {
|
jint JInputStream::readBlockImpl(TagLib::ByteVector &buf) {
|
||||||
// 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<unsigned int>(length), 0 };
|
|
||||||
jobject wrappedByteBuffer = env->NewDirectByteBuffer(buf.data(),
|
jobject wrappedByteBuffer = env->NewDirectByteBuffer(buf.data(),
|
||||||
buf.size());
|
buf.size());
|
||||||
if (wrappedByteBuffer == nullptr) {
|
if (wrappedByteBuffer == nullptr) {
|
||||||
throw std::runtime_error("Failed to wrap ByteBuffer");
|
throw std::runtime_error("Failed to wrap ByteBuffer");
|
||||||
}
|
}
|
||||||
JObjectRef byteBuffer = { env, wrappedByteBuffer };
|
JObjectRef byteBuffer { env, wrappedByteBuffer };
|
||||||
jboolean result = env->CallBooleanMethod(jInputStream,
|
jint read = env->CallIntMethod(jInputStream, jInputStreamReadBlockMethod,
|
||||||
jInputStreamReadBlockMethod, *byteBuffer);
|
*byteBuffer);
|
||||||
if (!result) {
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
TagLib::ByteVector JInputStream::readBlock(size_t length) {
|
||||||
|
// We have to invert the buffer allocation here
|
||||||
|
TagLib::ByteVector buf { static_cast<unsigned int>(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");
|
throw std::runtime_error("Failed to read block, see logs");
|
||||||
}
|
}
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JInputStream::writeBlock(const TagLib::ByteVector &data) {
|
void JInputStream::writeBlock(const TagLib::ByteVector &data) {
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,7 @@ private:
|
||||||
jmethodID jInputStreamSeekFromEndMethod;
|
jmethodID jInputStreamSeekFromEndMethod;
|
||||||
jmethodID jInputStreamTellMethod;
|
jmethodID jInputStreamTellMethod;
|
||||||
jmethodID jInputStreamLengthMethod;
|
jmethodID jInputStreamLengthMethod;
|
||||||
|
jint readBlockImpl(TagLib::ByteVector &buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //AUXIO_JINPUTSTREAM_H
|
#endif //AUXIO_JINPUTSTREAM_H
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,12 @@ internal class NativeInputStream(private val deviceFile: DeviceFile, fis: FileIn
|
||||||
|
|
||||||
fun name() = requireNotNull(deviceFile.path.name)
|
fun name() = requireNotNull(deviceFile.path.name)
|
||||||
|
|
||||||
fun readBlock(buf: ByteBuffer): Boolean {
|
fun readBlock(buf: ByteBuffer): Int {
|
||||||
try {
|
try {
|
||||||
channel.read(buf)
|
return channel.read(buf)
|
||||||
return true
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("NativeInputStream", "Error reading block", e)
|
Log.d("NativeInputStream", "Error reading block", e)
|
||||||
return false
|
return -2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue