musikr: bubblewrap nativeinputstream
Try to avoid exceptions cascading and bringing down the app.
This commit is contained in:
parent
b81ecf44c0
commit
3aae8ea534
2 changed files with 70 additions and 20 deletions
|
@ -34,11 +34,11 @@ JVMInputStream::JVMInputStream(JNIEnv *env, jobject inputStream) : env(env), inp
|
|||
inputStreamIsOpenMethod = env->GetMethodID(inputStreamClass, "isOpen",
|
||||
"()Z");
|
||||
inputStreamSeekFromBeginningMethod = env->GetMethodID(inputStreamClass,
|
||||
"seekFromBeginning", "(J)V");
|
||||
"seekFromBeginning", "(J)Z");
|
||||
inputStreamSeekFromCurrentMethod = env->GetMethodID(inputStreamClass,
|
||||
"seekFromCurrent", "(J)V");
|
||||
"seekFromCurrent", "(J)Z");
|
||||
inputStreamSeekFromEndMethod = env->GetMethodID(inputStreamClass,
|
||||
"seekFromEnd", "(J)V");
|
||||
"seekFromEnd", "(J)Z");
|
||||
inputStreamTellMethod = env->GetMethodID(inputStreamClass, "tell", "()J");
|
||||
inputStreamLengthMethod = env->GetMethodID(inputStreamClass, "length",
|
||||
"()J");
|
||||
|
@ -58,6 +58,9 @@ TagLib::FileName JVMInputStream::name() const {
|
|||
TagLib::ByteVector JVMInputStream::readBlock(size_t length) {
|
||||
auto data = (jbyteArray) env->CallObjectMethod(inputStream,
|
||||
inputStreamReadBlockMethod, length);
|
||||
if (data == nullptr) {
|
||||
throw std::runtime_error("Failed to read block, see logs");
|
||||
}
|
||||
jsize dataLength = env->GetArrayLength(data);
|
||||
auto dataBytes = env->GetByteArrayElements(data, nullptr);
|
||||
TagLib::ByteVector byteVector(reinterpret_cast<const char*>(dataBytes),
|
||||
|
@ -89,19 +92,24 @@ bool JVMInputStream::isOpen() const {
|
|||
|
||||
void JVMInputStream::seek(TagLib::offset_t offset, Position p) {
|
||||
auto joffset = static_cast<jlong>(std::llround(offset));
|
||||
jboolean result;
|
||||
switch (p) {
|
||||
case Beginning:
|
||||
env->CallVoidMethod(inputStream, inputStreamSeekFromBeginningMethod,
|
||||
joffset);
|
||||
result = env->CallBooleanMethod(inputStream,
|
||||
inputStreamSeekFromBeginningMethod, joffset);
|
||||
break;
|
||||
case Current:
|
||||
env->CallVoidMethod(inputStream, inputStreamSeekFromCurrentMethod,
|
||||
joffset);
|
||||
result = env->CallBooleanMethod(inputStream,
|
||||
inputStreamSeekFromCurrentMethod, joffset);
|
||||
break;
|
||||
case End:
|
||||
env->CallVoidMethod(inputStream, inputStreamSeekFromEndMethod, joffset);
|
||||
result = env->CallBooleanMethod(inputStream,
|
||||
inputStreamSeekFromEndMethod, joffset);
|
||||
break;
|
||||
}
|
||||
if (!result) {
|
||||
throw std::runtime_error("Failed to seek, see logs");
|
||||
}
|
||||
}
|
||||
|
||||
void JVMInputStream::clear() {
|
||||
|
@ -110,11 +118,17 @@ void JVMInputStream::clear() {
|
|||
|
||||
TagLib::offset_t JVMInputStream::tell() const {
|
||||
jlong jposition = env->CallLongMethod(inputStream, inputStreamTellMethod);
|
||||
if (jposition == INT64_MIN) {
|
||||
throw std::runtime_error("Failed to get position, see logs");
|
||||
}
|
||||
return static_cast<TagLib::offset_t>(jposition);
|
||||
}
|
||||
|
||||
TagLib::offset_t JVMInputStream::length() {
|
||||
jlong jlength = env->CallLongMethod(inputStream, inputStreamLengthMethod);
|
||||
if (jlength == INT64_MIN) {
|
||||
throw std::runtime_error("Failed to get length, see logs");
|
||||
}
|
||||
return static_cast<TagLib::offset_t>(jlength);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,37 +18,73 @@
|
|||
|
||||
package org.oxycblt.musikr.metadata
|
||||
|
||||
import android.util.Log
|
||||
import java.io.FileInputStream
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
internal class NativeInputStream(fis: FileInputStream) {
|
||||
private val channel = fis.channel
|
||||
|
||||
fun readBlock(length: Long): ByteArray {
|
||||
val buffer = ByteBuffer.allocate(length.toInt())
|
||||
channel.read(buffer)
|
||||
return buffer.array()
|
||||
fun readBlock(length: Long): ByteArray? {
|
||||
try {
|
||||
val buffer = ByteBuffer.allocate(length.toInt())
|
||||
channel.read(buffer)
|
||||
return buffer.array()
|
||||
} catch (e: Exception) {
|
||||
Log.d("NativeInputStream", "Error reading block", e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
fun isOpen(): Boolean {
|
||||
return channel.isOpen
|
||||
}
|
||||
|
||||
fun seekFromBeginning(offset: Long) {
|
||||
channel.position(offset)
|
||||
fun seekFromBeginning(offset: Long): Boolean {
|
||||
try {
|
||||
channel.position(offset)
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.d("NativeInputStream", "Error seeking from beginning", e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fun seekFromCurrent(offset: Long) {
|
||||
channel.position(channel.position() + offset)
|
||||
fun seekFromCurrent(offset: Long): Boolean {
|
||||
try {
|
||||
channel.position(channel.position() + offset)
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.d("NativeInputStream", "Error seeking from current", e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fun seekFromEnd(offset: Long) {
|
||||
channel.position(channel.size() + offset)
|
||||
fun seekFromEnd(offset: Long): Boolean {
|
||||
try {
|
||||
channel.position(channel.size() + offset)
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.d("NativeInputStream", "Error seeking from end", e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fun tell() = channel.position()
|
||||
fun tell() =
|
||||
try {
|
||||
channel.position()
|
||||
} catch (e: Exception) {
|
||||
Log.d("NativeInputStream", "Error getting position", e)
|
||||
Long.MIN_VALUE
|
||||
}
|
||||
|
||||
fun length() = channel.size()
|
||||
fun length() =
|
||||
try {
|
||||
channel.size()
|
||||
} catch (e: Exception) {
|
||||
Log.d("NativeInputStream", "Error getting length", e)
|
||||
Long.MIN_VALUE
|
||||
}
|
||||
|
||||
fun close() {
|
||||
channel.close()
|
||||
|
|
Loading…
Reference in a new issue