musikr: fix broken iostream jni integration
This commit is contained in:
parent
6f8a960ee1
commit
6fd0bd411b
9 changed files with 40 additions and 87 deletions
|
@ -0,0 +1 @@
|
|||
-keep class org.oxycblt.musikr.metadata.NativeInputStream { *; }
|
4
musikr/proguard-rules.pro
vendored
4
musikr/proguard-rules.pro
vendored
|
@ -18,4 +18,6 @@
|
|||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
-keep class org.oxycblt.musikr.metadata.NativeInputStream { *; }
|
|
@ -40,7 +40,6 @@ JVMInputStream::JVMInputStream(JNIEnv *env, jobject inputStream) : env(env), inp
|
|||
"seekFromCurrent", "(J)V");
|
||||
inputStreamSeekFromEndMethod = env->GetMethodID(inputStreamClass,
|
||||
"seekFromEnd", "(J)V");
|
||||
inputStreamClearMethod = env->GetMethodID(inputStreamClass, "clear", "()V");
|
||||
inputStreamTellMethod = env->GetMethodID(inputStreamClass, "tell", "()J");
|
||||
inputStreamLengthMethod = env->GetMethodID(inputStreamClass, "length",
|
||||
"()J");
|
||||
|
@ -107,7 +106,7 @@ void JVMInputStream::seek(TagLib::offset_t offset, Position p) {
|
|||
}
|
||||
|
||||
void JVMInputStream::clear() {
|
||||
env->CallVoidMethod(inputStream, inputStreamClearMethod);
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
TagLib::offset_t JVMInputStream::tell() const {
|
||||
|
|
|
@ -100,13 +100,11 @@ public:
|
|||
private:
|
||||
JNIEnv *env;
|
||||
jobject inputStream;
|
||||
jmethodID inputStreamNameMethod;
|
||||
jmethodID inputStreamReadBlockMethod;
|
||||
jmethodID inputStreamIsOpenMethod;
|
||||
jmethodID inputStreamSeekFromBeginningMethod;
|
||||
jmethodID inputStreamSeekFromCurrentMethod;
|
||||
jmethodID inputStreamSeekFromEndMethod;
|
||||
jmethodID inputStreamClearMethod;
|
||||
jmethodID inputStreamTellMethod;
|
||||
jmethodID inputStreamLengthMethod;
|
||||
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Auxio Project
|
||||
* AndroidInputStream.kt 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/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.musikr.metadata
|
||||
|
||||
import android.content.Context
|
||||
import java.io.FileInputStream
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
internal class AndroidInputStream(context: Context, fis: FileInputStream) : NativeInputStream {
|
||||
private val channel = fis.channel
|
||||
|
||||
override fun readBlock(length: Long): ByteArray {
|
||||
val buffer = ByteBuffer.allocate(length.toInt())
|
||||
channel.read(buffer)
|
||||
return buffer.array()
|
||||
}
|
||||
|
||||
override fun isOpen(): Boolean {
|
||||
return channel.isOpen
|
||||
}
|
||||
|
||||
override fun seekFromBeginning(offset: Long) {
|
||||
channel.position(offset)
|
||||
}
|
||||
|
||||
override fun seekFromCurrent(offset: Long) {
|
||||
channel.position(channel.position() + offset)
|
||||
}
|
||||
|
||||
override fun seekFromEnd(offset: Long) {
|
||||
channel.position(channel.size() - offset)
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
// Nothing to clear
|
||||
}
|
||||
|
||||
override fun tell() = channel.position()
|
||||
|
||||
override fun length() = channel.size()
|
||||
|
||||
fun close() {
|
||||
channel.close()
|
||||
}
|
||||
}
|
|
@ -28,14 +28,14 @@ internal interface MetadataExtractor {
|
|||
suspend fun extract(fd: ParcelFileDescriptor): Metadata?
|
||||
|
||||
companion object {
|
||||
fun from(context: Context): MetadataExtractor = MetadataExtractorImpl(context)
|
||||
fun new(): MetadataExtractor = MetadataExtractorImpl
|
||||
}
|
||||
}
|
||||
|
||||
private class MetadataExtractorImpl(private val context: Context) : MetadataExtractor {
|
||||
private object MetadataExtractorImpl : MetadataExtractor {
|
||||
override suspend fun extract(fd: ParcelFileDescriptor) =
|
||||
withContext(Dispatchers.IO) {
|
||||
val fis = FileInputStream(fd.fileDescriptor)
|
||||
TagLibJNI.open(context, fis).also { fis.close() }
|
||||
TagLibJNI.open(fis).also { fis.close() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,25 +18,39 @@
|
|||
|
||||
package org.oxycblt.musikr.metadata
|
||||
|
||||
/**
|
||||
* Java interface for the read-only methods in TagLib's IOStream API.
|
||||
*
|
||||
* The vast majority of IO shim between Taglib/KTaglib should occur here to minimize JNI calls.
|
||||
*/
|
||||
internal interface NativeInputStream {
|
||||
fun readBlock(length: Long): ByteArray
|
||||
import java.io.FileInputStream
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
fun isOpen(): Boolean
|
||||
class NativeInputStream(fis: FileInputStream) {
|
||||
private val channel = fis.channel
|
||||
|
||||
fun seekFromBeginning(offset: Long)
|
||||
fun readBlock(length: Long): ByteArray {
|
||||
val buffer = ByteBuffer.allocate(length.toInt())
|
||||
channel.read(buffer)
|
||||
return buffer.array()
|
||||
}
|
||||
|
||||
fun seekFromCurrent(offset: Long)
|
||||
fun isOpen(): Boolean {
|
||||
return channel.isOpen
|
||||
}
|
||||
|
||||
fun seekFromEnd(offset: Long)
|
||||
fun seekFromBeginning(offset: Long) {
|
||||
channel.position(offset)
|
||||
}
|
||||
|
||||
fun clear()
|
||||
fun seekFromCurrent(offset: Long) {
|
||||
channel.position(channel.position() + offset)
|
||||
}
|
||||
|
||||
fun tell(): Long
|
||||
fun seekFromEnd(offset: Long) {
|
||||
channel.position(channel.size() - offset)
|
||||
}
|
||||
|
||||
fun length(): Long
|
||||
fun tell() = channel.position()
|
||||
|
||||
fun length() = channel.size()
|
||||
|
||||
fun close() {
|
||||
channel.close()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,12 +31,12 @@ internal object TagLibJNI {
|
|||
*
|
||||
* Note: This method is blocking and should be handled as such if calling from a coroutine.
|
||||
*/
|
||||
fun open(context: Context, fis: FileInputStream): Metadata? {
|
||||
val inputStream = AndroidInputStream(context, fis)
|
||||
fun open(fis: FileInputStream): Metadata? {
|
||||
val inputStream = NativeInputStream(fis)
|
||||
val tag = openNative(inputStream)
|
||||
inputStream.close()
|
||||
return tag
|
||||
}
|
||||
|
||||
private external fun openNative(ioStream: AndroidInputStream): Metadata?
|
||||
private external fun openNative(ioStream: NativeInputStream): Metadata?
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ internal interface ExtractStep {
|
|||
fun from(context: Context, storage: Storage): ExtractStep =
|
||||
ExtractStepImpl(
|
||||
context,
|
||||
MetadataExtractor.from(context),
|
||||
MetadataExtractor.new(),
|
||||
TagParser.new(),
|
||||
storage.cache,
|
||||
storage.storedCovers)
|
||||
|
|
Loading…
Reference in a new issue