diff --git a/musikr/src/main/cpp/CMakeLists.txt b/musikr/src/main/cpp/CMakeLists.txt
index dd0db4101..23bb28d13 100644
--- a/musikr/src/main/cpp/CMakeLists.txt
+++ b/musikr/src/main/cpp/CMakeLists.txt
@@ -45,9 +45,13 @@ set_target_properties(
add_library(${CMAKE_PROJECT_NAME} SHARED
# List C/C++ source files with relative paths to this CMakeLists.txt.
taglib_jni.cpp
- JVMInputStream.cpp
- JVMTagMap.cpp
- JVMMetadataBuilder.cpp
+ JInputStream.cpp
+ JTagMap.cpp
+ JMetadataBuilder.cpp
+ JClassRef.cpp
+ JObjectRef.cpp
+ JStringRef.cpp
+ JByteArrayRef.cpp
)
target_link_options(${CMAKE_PROJECT_NAME}
# @Tolriq found that these flags can reduce the size of the linked
diff --git a/musikr/src/main/cpp/JByteArrayRef.cpp b/musikr/src/main/cpp/JByteArrayRef.cpp
new file mode 100644
index 000000000..297d9d859
--- /dev/null
+++ b/musikr/src/main/cpp/JByteArrayRef.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2025 Auxio Project
+ * JByteArrayRef.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 .
+ */
+
+#include "JByteArrayRef.h"
+
+JByteArrayRef::JByteArrayRef(JNIEnv *env, TagLib::ByteVector &data) : env(env) {
+ auto size = static_cast(data.size());
+ array = env->NewByteArray(size);
+ env->SetByteArrayRegion(array, 0, static_cast(size),
+ reinterpret_cast(data.data()));
+}
+
+JByteArrayRef::JByteArrayRef(JNIEnv *env, jbyteArray array) : env(env), array(
+ array) {
+}
+
+JByteArrayRef::~JByteArrayRef() {
+ env->DeleteLocalRef(array);
+}
+
+TagLib::ByteVector JByteArrayRef::copy() {
+ jsize length = env->GetArrayLength(array);
+ auto data = env->GetByteArrayElements(array, nullptr);
+ TagLib::ByteVector byteVector(reinterpret_cast(data), length);
+ env->ReleaseByteArrayElements(array, data, JNI_ABORT);
+ return byteVector;
+}
+
+jbyteArray& JByteArrayRef::operator*() {
+ return array;
+}
+
diff --git a/musikr/src/main/cpp/JByteArrayRef.h b/musikr/src/main/cpp/JByteArrayRef.h
new file mode 100644
index 000000000..02ce6e032
--- /dev/null
+++ b/musikr/src/main/cpp/JByteArrayRef.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2025 Auxio Project
+ * JByteArrayRef.h 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 .
+ */
+
+#ifndef AUXIO_JBYTEARRAYREF_H
+#define AUXIO_JBYTEARRAYREF_H
+
+#include
+#include
+
+class JByteArrayRef {
+public:
+ JByteArrayRef(JNIEnv *env, TagLib::ByteVector &data);
+ JByteArrayRef(JNIEnv *env, jbyteArray array);
+
+ ~JByteArrayRef();
+
+ JByteArrayRef(const JByteArrayRef&) = delete;
+
+ JByteArrayRef& operator=(const JByteArrayRef&) = delete;
+
+ TagLib::ByteVector copy();
+
+ jbyteArray& operator*();
+
+private:
+ JNIEnv *env;
+ jbyteArray array;
+};
+
+#endif //AUXIO_JBYTEARRAYREF_H
diff --git a/musikr/src/main/cpp/JClassRef.cpp b/musikr/src/main/cpp/JClassRef.cpp
new file mode 100644
index 000000000..8bf38a3b5
--- /dev/null
+++ b/musikr/src/main/cpp/JClassRef.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2025 Auxio Project
+ * JClassRef.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 .
+ */
+
+#include "JClassRef.h"
+JClassRef::JClassRef(JNIEnv *env, const char *classpath) : env(env) {
+ clazz = env->FindClass(classpath);
+}
+
+JClassRef::~JClassRef() {
+ env->DeleteLocalRef(clazz);
+}
+
+jmethodID JClassRef::method(const char *name, const char *signature) {
+ return env->GetMethodID(clazz, name, signature);
+}
+
+jclass& JClassRef::operator*() {
+ return clazz;
+}
diff --git a/musikr/src/main/cpp/JClassRef.h b/musikr/src/main/cpp/JClassRef.h
new file mode 100644
index 000000000..b9c5336b1
--- /dev/null
+++ b/musikr/src/main/cpp/JClassRef.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2025 Auxio Project
+ * JClassRef.h 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 .
+ */
+
+#ifndef AUXIO_JCLASSREF_H
+#define AUXIO_JCLASSREF_H
+
+#include
+
+class JClassRef {
+public:
+ JClassRef(JNIEnv *env, const char *classpath);
+
+ ~JClassRef();
+
+ JClassRef(const JClassRef&) = delete;
+
+ JClassRef& operator=(const JClassRef&) = delete;
+
+ // Only exists to work around a broken lint that doesn't
+ // realize that this class is a smart pointer to jclass.
+ jmethodID method(const char *name, const char *signature);
+
+ jclass& operator*();
+
+private:
+ JNIEnv *env;
+ jclass clazz;
+};
+
+#endif //AUXIO_JCLASSREF_H
diff --git a/musikr/src/main/cpp/JInputStream.cpp b/musikr/src/main/cpp/JInputStream.cpp
new file mode 100644
index 000000000..14693d394
--- /dev/null
+++ b/musikr/src/main/cpp/JInputStream.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2024 Auxio Project
+ * JInputStream.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 .
+ */
+
+#include "JInputStream.h"
+
+#include
+
+#include "JClassRef.h"
+#include "JByteArrayRef.h"
+
+JInputStream::JInputStream(JNIEnv *env, jobject jInputStream) : env(env), jInputStream(
+ jInputStream) {
+ JClassRef jInputStreamClass = { env,
+ "org/oxycblt/musikr/metadata/NativeInputStream" };
+ if (!env->IsInstanceOf(jInputStream, *jInputStreamClass)) {
+ throw std::runtime_error("oStream is not an instance of TagLibOStream");
+ }
+ jInputStreamReadBlockMethod = jInputStreamClass.method("readBlock",
+ "(J)[B");
+ jInputStreamIsOpenMethod = jInputStreamClass.method("isOpen", "()Z");
+ jInputStreamSeekFromBeginningMethod = jInputStreamClass.method(
+ "seekFromBeginning", "(J)Z");
+ jInputStreamSeekFromCurrentMethod = jInputStreamClass.method(
+ "seekFromCurrent", "(J)Z");
+ jInputStreamSeekFromEndMethod = jInputStreamClass.method("seekFromEnd",
+ "(J)Z");
+ jInputStreamTellMethod = jInputStreamClass.method("tell", "()J");
+ jInputStreamLengthMethod = jInputStreamClass.method("length", "()J");
+}
+
+JInputStream::~JInputStream() {
+ // The implicit assumption is that inputStream is managed by the owner,
+ // so we don't need to delete any references here
+}
+
+TagLib::FileName JInputStream::name() const {
+ // Not actually used except in FileRef, can safely ignore.
+ return "";
+}
+
+TagLib::ByteVector JInputStream::readBlock(size_t length) {
+ // Do manual memory management here since we don't to avoid the added abstraction
+ // overhead of a smart JByteArrayRef.
+ auto data = env->CallObjectMethod(jInputStream, jInputStreamReadBlockMethod,
+ static_cast(length));
+ if (data == nullptr) {
+ throw std::runtime_error("Failed to read block, see logs");
+ }
+ JByteArrayRef jByteArray = { env, reinterpret_cast(data) };
+ return jByteArray.copy();
+}
+
+void JInputStream::writeBlock(const TagLib::ByteVector &data) {
+ throw std::runtime_error("Not implemented");
+}
+
+void JInputStream::insert(const TagLib::ByteVector &data,
+ TagLib::offset_t start, size_t replace) {
+ throw std::runtime_error("Not implemented");
+}
+
+void JInputStream::removeBlock(TagLib::offset_t start, size_t length) {
+ throw std::runtime_error("Not implemented");
+}
+
+bool JInputStream::readOnly() const {
+ return true;
+}
+
+bool JInputStream::isOpen() const {
+ return env->CallBooleanMethod(jInputStream, jInputStreamIsOpenMethod);
+}
+
+void JInputStream::seek(TagLib::offset_t offset, Position p) {
+ auto joffset = static_cast(std::llround(offset));
+ jboolean result;
+ switch (p) {
+ case Beginning:
+ result = env->CallBooleanMethod(jInputStream,
+ jInputStreamSeekFromBeginningMethod, joffset);
+ break;
+ case Current:
+ result = env->CallBooleanMethod(jInputStream,
+ jInputStreamSeekFromCurrentMethod, joffset);
+ break;
+ case End:
+ result = env->CallBooleanMethod(jInputStream,
+ jInputStreamSeekFromEndMethod, joffset);
+ break;
+ }
+ if (!result) {
+ throw std::runtime_error("Failed to seek, see logs");
+ }
+}
+
+void JInputStream::clear() {
+ // Nothing to do
+}
+
+TagLib::offset_t JInputStream::tell() const {
+ jlong jposition = env->CallLongMethod(jInputStream, jInputStreamTellMethod);
+ if (jposition == INT64_MIN) {
+ throw std::runtime_error("Failed to get position, see logs");
+ }
+ return static_cast(jposition);
+}
+
+TagLib::offset_t JInputStream::length() {
+ jlong jlength = env->CallLongMethod(jInputStream, jInputStreamLengthMethod);
+ if (jlength == INT64_MIN) {
+ throw std::runtime_error("Failed to get length, see logs");
+ }
+ return static_cast(jlength);
+}
+
+void JInputStream::truncate(TagLib::offset_t length) {
+ throw std::runtime_error("Not implemented");
+}
+
diff --git a/musikr/src/main/cpp/JVMInputStream.h b/musikr/src/main/cpp/JInputStream.h
similarity index 82%
rename from musikr/src/main/cpp/JVMInputStream.h
rename to musikr/src/main/cpp/JInputStream.h
index f89e39d3b..084f9dc31 100644
--- a/musikr/src/main/cpp/JVMInputStream.h
+++ b/musikr/src/main/cpp/JInputStream.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2024 Auxio Project
- * JVMInputStream.h is part of Auxio.
+ * JInputStream.h 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
@@ -16,21 +16,22 @@
* along with this program. If not, see .
*/
-#ifndef AUXIO_JVMINPUTSTREAM_H
-#define AUXIO_JVMINPUTSTREAM_H
+#ifndef AUXIO_JINPUTSTREAM_H
+#define AUXIO_JINPUTSTREAM_H
#include
+#include "JObjectRef.h"
#include "taglib/tiostream.h"
-class JVMInputStream: public TagLib::IOStream {
+class JInputStream: public TagLib::IOStream {
public:
- JVMInputStream(JNIEnv *env, jobject inputStream);
+ JInputStream(JNIEnv *env, jobject jInputStream);
- ~JVMInputStream();
+ ~JInputStream();
- JVMInputStream(const JVMInputStream&) = delete;
- JVMInputStream& operator=(const JVMInputStream&) = delete;
+ JInputStream(const JInputStream&) = delete;
+ JInputStream& operator=(const JInputStream&) = delete;
/*!
* Returns the stream name in the local file system encoding.
@@ -113,15 +114,14 @@ public:
private:
JNIEnv *env;
- jobject inputStream;
- jmethodID inputStreamReadBlockMethod;
- jmethodID inputStreamIsOpenMethod;
- jmethodID inputStreamSeekFromBeginningMethod;
- jmethodID inputStreamSeekFromCurrentMethod;
- jmethodID inputStreamSeekFromEndMethod;
- jmethodID inputStreamTellMethod;
- jmethodID inputStreamLengthMethod;
-
+ jobject jInputStream;
+ jmethodID jInputStreamReadBlockMethod;
+ jmethodID jInputStreamIsOpenMethod;
+ jmethodID jInputStreamSeekFromBeginningMethod;
+ jmethodID jInputStreamSeekFromCurrentMethod;
+ jmethodID jInputStreamSeekFromEndMethod;
+ jmethodID jInputStreamTellMethod;
+ jmethodID jInputStreamLengthMethod;
};
-#endif //AUXIO_JVMINPUTSTREAM_H
+#endif //AUXIO_JINPUTSTREAM_H
diff --git a/musikr/src/main/cpp/JVMMetadataBuilder.cpp b/musikr/src/main/cpp/JMetadataBuilder.cpp
similarity index 74%
rename from musikr/src/main/cpp/JVMMetadataBuilder.cpp
rename to musikr/src/main/cpp/JMetadataBuilder.cpp
index e0e4996eb..f7aa61457 100644
--- a/musikr/src/main/cpp/JVMMetadataBuilder.cpp
+++ b/musikr/src/main/cpp/JMetadataBuilder.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2024 Auxio Project
- * JVMMetadataBuilder.cpp is part of Auxio.
+ * JMetadataBuilder.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
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-#include "JVMMetadataBuilder.h"
+#include "JMetadataBuilder.h"
#include "util.h"
@@ -26,15 +26,20 @@
#include
-JVMMetadataBuilder::JVMMetadataBuilder(JNIEnv *env) : env(env), id3v2(env), xiph(
+#include "JObjectRef.h"
+#include "JClassRef.h"
+#include "JStringRef.h"
+#include "JByteArrayRef.h"
+
+JMetadataBuilder::JMetadataBuilder(JNIEnv *env) : env(env), id3v2(env), xiph(
env), mp4(env), cover(), properties(nullptr) {
}
-void JVMMetadataBuilder::setMimeType(const std::string_view type) {
- this->mimeType = type;
+void JMetadataBuilder::setMimeType(TagLib::String type) {
+ mimeType = type;
}
-void JVMMetadataBuilder::setId3v1(TagLib::ID3v1::Tag &tag) {
+void JMetadataBuilder::setId3v1(TagLib::ID3v1::Tag &tag) {
id3v2.add_id("TIT2", tag.title());
id3v2.add_id("TPE1", tag.artist());
id3v2.add_id("TALB", tag.album());
@@ -46,7 +51,7 @@ void JVMMetadataBuilder::setId3v1(TagLib::ID3v1::Tag &tag) {
}
}
-void JVMMetadataBuilder::setId3v2(TagLib::ID3v2::Tag &tag) {
+void JMetadataBuilder::setId3v2(TagLib::ID3v2::Tag &tag) {
// We want to ideally find the front cover, fall back to the first picture otherwise.
std::optional firstPic;
std::optional frontCoverPic;
@@ -89,7 +94,7 @@ void JVMMetadataBuilder::setId3v2(TagLib::ID3v2::Tag &tag) {
}
}
-void JVMMetadataBuilder::setXiph(TagLib::Ogg::XiphComment &tag) {
+void JMetadataBuilder::setXiph(TagLib::Ogg::XiphComment &tag) {
for (auto field : tag.fieldListMap()) {
auto key = field.first.upper();
auto values = field.second;
@@ -100,7 +105,7 @@ void JVMMetadataBuilder::setXiph(TagLib::Ogg::XiphComment &tag) {
}
template
-void mp4AddImpl(JVMTagMap &map, TagLib::String &itemName, T itemValue) {
+void mp4AddImpl(JTagMap &map, TagLib::String &itemName, T itemValue) {
if (itemName.startsWith("----")) {
// Split this into it's atom name and description
auto split = itemName.find(':');
@@ -112,7 +117,7 @@ void mp4AddImpl(JVMTagMap &map, TagLib::String &itemName, T itemValue) {
}
}
-void JVMMetadataBuilder::setMp4(TagLib::MP4::Tag &tag) {
+void JMetadataBuilder::setMp4(TagLib::MP4::Tag &tag) {
auto map = tag.itemMap();
std::optional < TagLib::MP4::CoverArt > firstCover;
for (auto item : map) {
@@ -165,7 +170,7 @@ void JVMMetadataBuilder::setMp4(TagLib::MP4::Tag &tag) {
}
}
-void JVMMetadataBuilder::setFlacPictures(
+void JMetadataBuilder::setFlacPictures(
TagLib::List &pics) {
// Find the front cover image. If it doesn't exist, fall back to the first image.
for (auto pic : pics) {
@@ -179,44 +184,33 @@ void JVMMetadataBuilder::setFlacPictures(
}
}
-void JVMMetadataBuilder::setProperties(TagLib::AudioProperties *properties) {
+void JMetadataBuilder::setProperties(TagLib::AudioProperties *properties) {
this->properties = properties;
}
-jobject JVMMetadataBuilder::build() {
- jclass propertiesClass = env->FindClass(
- "org/oxycblt/musikr/metadata/Properties");
- jmethodID propertiesInit = env->GetMethodID(propertiesClass, "",
+jobject JMetadataBuilder::build() {
+ JClassRef jPropertiesClass { env, "org/oxycblt/musikr/metadata/Properties" };
+ jmethodID jPropertiesInitMethod = jPropertiesClass.method("",
"(Ljava/lang/String;JII)V");
- jstring jmimeType = env->NewStringUTF(mimeType.data());
- jobject propertiesObj = env->NewObject(propertiesClass, propertiesInit,
- jmimeType, (jlong) properties->lengthInMilliseconds(),
- properties->bitrate(), properties->sampleRate());
- env->DeleteLocalRef(jmimeType);
- env->DeleteLocalRef(propertiesClass);
+ JStringRef jMimeType { env, this->mimeType };
- jclass metadataClass = env->FindClass(
- "org/oxycblt/musikr/metadata/Metadata");
- jmethodID metadataInit = env->GetMethodID(metadataClass, "",
+ JObjectRef jProperties { env, env->NewObject(*jPropertiesClass,
+ jPropertiesInitMethod, *jMimeType,
+ (jlong) properties->lengthInMilliseconds(), properties->bitrate(),
+ properties->sampleRate()) };
+
+ JClassRef jMetadataClass { env, "org/oxycblt/musikr/metadata/Metadata" };
+ jmethodID jMetadataInitMethod = jMetadataClass.method("",
"(Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;[BLorg/"
"oxycblt/musikr/metadata/Properties;)V");
- jobject id3v2Map = id3v2.getObject();
- jobject xiphMap = xiph.getObject();
- jobject mp4Map = mp4.getObject();
- jbyteArray coverArray = nullptr;
+ auto jId3v2Map = id3v2.getObject();
+ auto jXiphMap = xiph.getObject();
+ auto jMp4Map = mp4.getObject();
if (cover.has_value()) {
- auto coverSize = static_cast(cover->size());
- coverArray = env->NewByteArray(coverSize);
- env->SetByteArrayRegion(coverArray, 0, coverSize,
- reinterpret_cast(cover->data()));
+ JByteArrayRef jCoverArray { env, cover.value() };
+ return env->NewObject(*jMetadataClass, jMetadataInitMethod, **jId3v2Map,
+ **jXiphMap, **jMp4Map, *jCoverArray, *jProperties);
}
- jobject metadataObj = env->NewObject(metadataClass, metadataInit, id3v2Map,
- xiphMap, mp4Map, coverArray, propertiesObj);
- env->DeleteLocalRef(propertiesObj);
- env->DeleteLocalRef(metadataClass);
- env->DeleteLocalRef(coverArray);
- env->DeleteLocalRef(id3v2Map);
- env->DeleteLocalRef(xiphMap);
- env->DeleteLocalRef(mp4Map);
- return metadataObj;
+ return env->NewObject(*jMetadataClass, jMetadataInitMethod, **jId3v2Map,
+ **jXiphMap, **jMp4Map, nullptr, *jProperties);
}
diff --git a/musikr/src/main/cpp/JVMMetadataBuilder.h b/musikr/src/main/cpp/JMetadataBuilder.h
similarity index 78%
rename from musikr/src/main/cpp/JVMMetadataBuilder.h
rename to musikr/src/main/cpp/JMetadataBuilder.h
index 1ee52db3a..7bca6cbbb 100644
--- a/musikr/src/main/cpp/JVMMetadataBuilder.h
+++ b/musikr/src/main/cpp/JMetadataBuilder.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2024 Auxio Project
- * JVMMetadataBuilder.h is part of Auxio.
+ * JMetadataBuilder.h 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
@@ -16,8 +16,8 @@
* along with this program. If not, see .
*/
-#ifndef AUXIO_JVMMETADATABUILDER_H
-#define AUXIO_JVMMETADATABUILDER_H
+#ifndef AUXIO_JMETADATABUILDER_H
+#define AUXIO_JMETADATABUILDER_H
#include
#include
@@ -29,13 +29,13 @@
#include "taglib/mp4tag.h"
#include "taglib/audioproperties.h"
-#include "JVMTagMap.h"
+#include "JTagMap.h"
-class JVMMetadataBuilder {
+class JMetadataBuilder {
public:
- JVMMetadataBuilder(JNIEnv *env);
+ JMetadataBuilder(JNIEnv *env);
- void setMimeType(const std::string_view type);
+ void setMimeType(TagLib::String type);
void setId3v1(TagLib::ID3v1::Tag &tag);
void setId3v2(TagLib::ID3v2::Tag &tag);
void setXiph(TagLib::Ogg::XiphComment &tag);
@@ -48,14 +48,14 @@ public:
private:
JNIEnv *env;
- std::string_view mimeType;
+ TagLib::String mimeType;
std::optional cover;
TagLib::AudioProperties *properties;
- JVMTagMap id3v2;
- JVMTagMap xiph;
- JVMTagMap mp4;
+ JTagMap id3v2;
+ JTagMap xiph;
+ JTagMap mp4;
};
-#endif //AUXIO_JVMMETADATABUILDER_H
+#endif //AUXIO_JMETADATABUILDER_H
diff --git a/musikr/src/main/cpp/JObjectRef.cpp b/musikr/src/main/cpp/JObjectRef.cpp
new file mode 100644
index 000000000..9d6914cbf
--- /dev/null
+++ b/musikr/src/main/cpp/JObjectRef.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 Auxio Project
+ * JObjectRef.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 .
+ */
+
+#include "JObjectRef.h"
+
+JObjectRef::JObjectRef(JNIEnv *env, jobject object) : env(env), object(object) {
+}
+
+JObjectRef::~JObjectRef() {
+ env->DeleteLocalRef(object);
+}
+
+jobject& JObjectRef::operator*() {
+ return object;
+}
diff --git a/musikr/src/main/cpp/JObjectRef.h b/musikr/src/main/cpp/JObjectRef.h
new file mode 100644
index 000000000..affc383e5
--- /dev/null
+++ b/musikr/src/main/cpp/JObjectRef.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2025 Auxio Project
+ * JObjectRef.h 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 .
+ */
+
+#ifndef AUXIO_JOBJECTREF_H
+#define AUXIO_JOBJECTREF_H
+
+#include
+#include
+#include
+#include "JObjectRef.h"
+
+class JObjectRef {
+public:
+ JObjectRef(JNIEnv *env, jobject object);
+
+ ~JObjectRef();
+
+ JObjectRef(const JObjectRef&) = delete;
+
+ JObjectRef& operator=(const JObjectRef&) = delete;
+
+ jobject& operator*();
+
+private:
+ JNIEnv *env;
+ jobject object;
+};
+
+#endif //AUXIO_JOBJECTREF_H
diff --git a/musikr/src/main/cpp/JStringRef.cpp b/musikr/src/main/cpp/JStringRef.cpp
new file mode 100644
index 000000000..e6b1bf71d
--- /dev/null
+++ b/musikr/src/main/cpp/JStringRef.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2025 Auxio Project
+ * JStringRef.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 .
+ */
+
+#include "JStringRef.h"
+#include "util.h"
+
+JStringRef::JStringRef(JNIEnv *env, const TagLib::String string) {
+ this->env = env;
+ this->string = env->NewStringUTF(string.toCString(true));
+}
+
+JStringRef::~JStringRef() {
+ env->DeleteLocalRef(string);
+}
+
+jstring& JStringRef::operator*() {
+ return string;
+}
diff --git a/musikr/src/main/cpp/JStringRef.h b/musikr/src/main/cpp/JStringRef.h
new file mode 100644
index 000000000..ffe4ab8ad
--- /dev/null
+++ b/musikr/src/main/cpp/JStringRef.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2025 Auxio Project
+ * JStringRef.h 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 .
+ */
+
+#ifndef AUXIO_JSTRINGREF_H
+#define AUXIO_JSTRINGREF_H
+
+#include
+#include
+
+class JStringRef {
+public:
+ JStringRef(JNIEnv *env, TagLib::String string);
+
+ ~JStringRef();
+
+ JStringRef(const JStringRef&) = delete;
+
+ JStringRef& operator=(const JStringRef&) = delete;
+
+ jstring& operator*();
+
+private:
+ JNIEnv *env;
+ jstring string;
+};
+
+#endif //AUXIO_JSTRINGREF_H
diff --git a/musikr/src/main/cpp/JTagMap.cpp b/musikr/src/main/cpp/JTagMap.cpp
new file mode 100644
index 000000000..f229f3387
--- /dev/null
+++ b/musikr/src/main/cpp/JTagMap.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2024 Auxio Project
+ * JTagMap.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 .
+ */
+
+#include "JTagMap.h"
+
+#include "JStringRef.h"
+
+JTagMap::JTagMap(JNIEnv *env) : env(env) {
+ auto jTagMapClass = std::make_unique < JClassRef
+ > (env, "org/oxycblt/musikr/metadata/NativeTagMap");
+ auto jTagMapInitMethod = jTagMapClass->method("", "()V");
+ jTagMap = std::move(
+ std::make_unique < JObjectRef
+ > (env, env->NewObject(**jTagMapClass, jTagMapInitMethod)));
+ jTagMapAddIdSingleMethod = jTagMapClass->method("addID",
+ "(Ljava/lang/String;Ljava/lang/String;)V");
+ jTagMapAddIdListMethod = jTagMapClass->method("addID",
+ "(Ljava/lang/String;Ljava/util/List;)V");
+ jTagMapAddCustomSingleMethod = jTagMapClass->method("addCustom",
+ "(Ljava/lang/String;Ljava/lang/String;)V");
+ jTagMapAddCustomListMethod = jTagMapClass->method("addCustom",
+ "(Ljava/lang/String;Ljava/util/List;)V");
+ jTagMapAddCombinedSingleMethod = jTagMapClass->method("addCombined",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+ jTagMapAddCombinedListMethod = jTagMapClass->method("addCombined",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)V");
+ jTagMapGetObjectMethod = jTagMapClass->method("getObject",
+ "()Ljava/util/Map;");
+
+ jArrayListClass = std::make_unique < JClassRef
+ > (env, "java/util/ArrayList");
+ jArrayListInitMethod = jArrayListClass->method("", "()V");
+ jArrayListAddMethod = jArrayListClass->method("add",
+ "(Ljava/lang/Object;)Z");
+}
+
+void JTagMap::add_id(const TagLib::String id, const TagLib::String value) {
+ JStringRef jId { env, id };
+ JStringRef jValue { env, value };
+ env->CallVoidMethod(**jTagMap, jTagMapAddIdSingleMethod, *jId, *jValue);
+}
+
+void JTagMap::add_id(const TagLib::String id, const TagLib::StringList values) {
+ JStringRef jId { env, id };
+ JObjectRef jValues { env, env->NewObject(**jArrayListClass,
+ jArrayListInitMethod) };
+ for (auto &value : values) {
+ JStringRef jValue { env, value };
+ env->CallBooleanMethod(*jValues, jArrayListAddMethod, *jValue);
+ }
+ env->CallVoidMethod(**jTagMap, jTagMapAddIdListMethod, *jId, *jValues);
+}
+
+void JTagMap::add_custom(const TagLib::String description,
+ const TagLib::String value) {
+ JStringRef jDescription { env, description };
+ JStringRef jValue { env, value };
+ env->CallVoidMethod(**jTagMap, jTagMapAddCustomSingleMethod, *jDescription,
+ *jValue);
+}
+
+void JTagMap::add_custom(const TagLib::String description,
+ const TagLib::StringList values) {
+ JStringRef jDescription { env, description };
+ JObjectRef jValues { env, env->NewObject(**jArrayListClass,
+ jArrayListInitMethod) };
+ for (auto &value : values) {
+ JStringRef jValue { env, value };
+ env->CallBooleanMethod(*jValues, jArrayListAddMethod, *jValue);
+ }
+ env->CallVoidMethod(**jTagMap, jTagMapAddCustomListMethod, *jDescription,
+ *jValues);
+}
+
+void JTagMap::add_combined(const TagLib::String id,
+ const TagLib::String description, const TagLib::String value) {
+ JStringRef jId { env, id };
+ JStringRef jDescription { env, description };
+ JStringRef jValue { env, value };
+ env->CallVoidMethod(**jTagMap, jTagMapAddCombinedSingleMethod, *jId,
+ *jDescription, *jValue);
+}
+
+void JTagMap::add_combined(const TagLib::String id,
+ const TagLib::String description, const TagLib::StringList values) {
+ JStringRef jId { env, id };
+ JStringRef jDescription { env, description };
+ JObjectRef jValues { env, env->NewObject(**jArrayListClass,
+ jArrayListInitMethod) };
+ for (auto &value : values) {
+ JStringRef jValue { env, value };
+ env->CallBooleanMethod(*jValues, jArrayListAddMethod, *jValue);
+ }
+ env->CallVoidMethod(**jTagMap, jTagMapAddCombinedListMethod, *jId,
+ *jDescription, *jValues);
+}
+
+std::unique_ptr JTagMap::getObject() {
+ return std::move(
+ std::make_unique < JObjectRef
+ > (env, env->CallObjectMethod(**jTagMap,
+ jTagMapGetObjectMethod)));
+}
diff --git a/musikr/src/main/cpp/JVMTagMap.h b/musikr/src/main/cpp/JTagMap.h
similarity index 62%
rename from musikr/src/main/cpp/JVMTagMap.h
rename to musikr/src/main/cpp/JTagMap.h
index 2462ef2ff..95293db7b 100644
--- a/musikr/src/main/cpp/JVMTagMap.h
+++ b/musikr/src/main/cpp/JTagMap.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2024 Auxio Project
- * JVMTagMap.h is part of Auxio.
+ * JTagMap.h 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
@@ -16,21 +16,23 @@
* along with this program. If not, see .
*/
-#ifndef AUXIO_JVMTAGMAP_H
-#define AUXIO_JVMTAGMAP_H
+#ifndef AUXIO_JTAGMAP_H
+#define AUXIO_JTAGMAP_H
#include
#include
#include
#include
-class JVMTagMap {
-public:
- JVMTagMap(JNIEnv *env);
- ~JVMTagMap();
+#include "JObjectRef.h"
+#include "JClassRef.h"
- JVMTagMap(const JVMTagMap&) = delete;
- JVMTagMap& operator=(const JVMTagMap&) = delete;
+class JTagMap {
+public:
+ JTagMap(JNIEnv *env);
+
+ JTagMap(const JTagMap&) = delete;
+ JTagMap& operator=(const JTagMap&) = delete;
void add_id(TagLib::String id, TagLib::String value);
void add_id(TagLib::String id, TagLib::StringList values);
@@ -43,21 +45,23 @@ public:
void add_combined(TagLib::String id, TagLib::String description,
TagLib::StringList values);
- jobject getObject();
+ std::unique_ptr getObject();
private:
JNIEnv *env;
- jobject tagMap;
- jmethodID tagMapAddIdSingleMethod;
- jmethodID tagMapAddIdListMethod;
- jmethodID tagMapAddCustomSingleMethod;
- jmethodID tagMapAddCustomListMethod;
- jmethodID tagMapAddCombinedSingleMethod;
- jmethodID tagMapAddCombinedListMethod;
- jmethodID tagMapGetObjectMethod;
- jclass arrayListClass;
- jmethodID arrayListInitMethod;
- jmethodID arrayListAddMethod;
+
+ std::unique_ptr jTagMap;
+ jmethodID jTagMapAddIdSingleMethod;
+ jmethodID jTagMapAddIdListMethod;
+ jmethodID jTagMapAddCustomSingleMethod;
+ jmethodID jTagMapAddCustomListMethod;
+ jmethodID jTagMapAddCombinedSingleMethod;
+ jmethodID jTagMapAddCombinedListMethod;
+ jmethodID jTagMapGetObjectMethod;
+
+ std::unique_ptr jArrayListClass;
+ jmethodID jArrayListInitMethod;
+ jmethodID jArrayListAddMethod;
};
-#endif //AUXIO_JVMTAGMAP_H
+#endif //AUXIO_JTAGMAP_H
diff --git a/musikr/src/main/cpp/JVMInputStream.cpp b/musikr/src/main/cpp/JVMInputStream.cpp
deleted file mode 100644
index 19e07d8a1..000000000
--- a/musikr/src/main/cpp/JVMInputStream.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2024 Auxio Project
- * JVMInputStream.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 .
- */
-
-#include "JVMInputStream.h"
-
-#include
-
-// TODO: Handle stream exceptions
-JVMInputStream::JVMInputStream(JNIEnv *env, jobject inputStream) : env(env), inputStream(
- inputStream) {
- jclass inputStreamClass = env->FindClass(
- "org/oxycblt/musikr/metadata/NativeInputStream");
- if (!env->IsInstanceOf(inputStream, inputStreamClass)) {
- throw std::runtime_error("oStream is not an instance of TagLibOStream");
- }
- inputStreamReadBlockMethod = env->GetMethodID(inputStreamClass, "readBlock",
- "(J)[B");
- inputStreamIsOpenMethod = env->GetMethodID(inputStreamClass, "isOpen",
- "()Z");
- inputStreamSeekFromBeginningMethod = env->GetMethodID(inputStreamClass,
- "seekFromBeginning", "(J)Z");
- inputStreamSeekFromCurrentMethod = env->GetMethodID(inputStreamClass,
- "seekFromCurrent", "(J)Z");
- inputStreamSeekFromEndMethod = env->GetMethodID(inputStreamClass,
- "seekFromEnd", "(J)Z");
- inputStreamTellMethod = env->GetMethodID(inputStreamClass, "tell", "()J");
- inputStreamLengthMethod = env->GetMethodID(inputStreamClass, "length",
- "()J");
- env->DeleteLocalRef(inputStreamClass);
-}
-
-JVMInputStream::~JVMInputStream() {
- // The implicit assumption is that inputStream is managed by the owner,
- // so we don't need to delete any references here
-}
-
-TagLib::FileName JVMInputStream::name() const {
- // Not actually used except in FileRef, can safely ignore.
- return "";
-}
-
-TagLib::ByteVector JVMInputStream::readBlock(size_t length) {
- auto data = (jbyteArray) env->CallObjectMethod(inputStream,
- inputStreamReadBlockMethod, static_cast(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(dataBytes),
- dataLength);
- env->ReleaseByteArrayElements(data, dataBytes, JNI_ABORT);
- env->DeleteLocalRef(data);
- return byteVector;
-}
-
-void JVMInputStream::writeBlock(const TagLib::ByteVector &data) {
- throw std::runtime_error("Not implemented");
-}
-
-void JVMInputStream::insert(const TagLib::ByteVector &data,
- TagLib::offset_t start, size_t replace) {
- throw std::runtime_error("Not implemented");
-}
-
-void JVMInputStream::removeBlock(TagLib::offset_t start, size_t length) {
- throw std::runtime_error("Not implemented");
-}
-
-bool JVMInputStream::readOnly() const {
- return true;
-}
-
-bool JVMInputStream::isOpen() const {
- return env->CallBooleanMethod(inputStream, inputStreamIsOpenMethod);
-}
-
-void JVMInputStream::seek(TagLib::offset_t offset, Position p) {
- auto joffset = static_cast(std::llround(offset));
- jboolean result;
- switch (p) {
- case Beginning:
- result = env->CallBooleanMethod(inputStream,
- inputStreamSeekFromBeginningMethod, joffset);
- break;
- case Current:
- result = env->CallBooleanMethod(inputStream,
- inputStreamSeekFromCurrentMethod, joffset);
- break;
- case End:
- result = env->CallBooleanMethod(inputStream,
- inputStreamSeekFromEndMethod, joffset);
- break;
- }
- if (!result) {
- throw std::runtime_error("Failed to seek, see logs");
- }
-}
-
-void JVMInputStream::clear() {
- // Nothing to do
-}
-
-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(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(jlength);
-}
-
-void JVMInputStream::truncate(TagLib::offset_t length) {
- throw std::runtime_error("Not implemented");
-}
diff --git a/musikr/src/main/cpp/JVMTagMap.cpp b/musikr/src/main/cpp/JVMTagMap.cpp
deleted file mode 100644
index 526aaf643..000000000
--- a/musikr/src/main/cpp/JVMTagMap.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2024 Auxio Project
- * JVMTagMap.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 .
- */
-
-#include "JVMTagMap.h"
-
-#include "util.h"
-
-JVMTagMap::JVMTagMap(JNIEnv *env) : env(env) {
- jclass tagMapClass = env->FindClass(
- "org/oxycblt/musikr/metadata/NativeTagMap");
- jmethodID init = env->GetMethodID(tagMapClass, "", "()V");
- tagMap = env->NewObject(tagMapClass, init);
- tagMapAddIdSingleMethod = env->GetMethodID(tagMapClass, "addID",
- "(Ljava/lang/String;Ljava/lang/String;)V");
- tagMapAddIdListMethod = env->GetMethodID(tagMapClass, "addID",
- "(Ljava/lang/String;Ljava/util/List;)V");
- tagMapAddCustomSingleMethod = env->GetMethodID(tagMapClass, "addCustom",
- "(Ljava/lang/String;Ljava/lang/String;)V");
- tagMapAddCustomListMethod = env->GetMethodID(tagMapClass, "addCustom",
- "(Ljava/lang/String;Ljava/util/List;)V");
- tagMapAddCombinedSingleMethod = env->GetMethodID(tagMapClass, "addCombined",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
- tagMapAddCombinedListMethod = env->GetMethodID(tagMapClass, "addCombined",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)V");
- tagMapGetObjectMethod = env->GetMethodID(tagMapClass, "getObject",
- "()Ljava/util/Map;");
- env->DeleteLocalRef(tagMapClass);
-
- arrayListClass = env->FindClass("java/util/ArrayList");
- arrayListInitMethod = env->GetMethodID(arrayListClass, "", "()V");
- arrayListAddMethod = env->GetMethodID(arrayListClass, "add",
- "(Ljava/lang/Object;)Z");
-}
-
-JVMTagMap::~JVMTagMap() {
- env->DeleteLocalRef(tagMap);
- env->DeleteLocalRef(arrayListClass);
-}
-
-void JVMTagMap::add_id(const TagLib::String id, const TagLib::String value) {
- jstring jid = env->NewStringUTF(id.toCString(true));
- jstring jvalue = env->NewStringUTF(value.toCString(true));
- env->CallVoidMethod(tagMap, tagMapAddIdSingleMethod, jid, jvalue);
- env->DeleteLocalRef(jid);
- env->DeleteLocalRef(jvalue);
-}
-
-void JVMTagMap::add_id(const TagLib::String id,
- const TagLib::StringList values) {
- jstring jid = env->NewStringUTF(id.toCString(true));
- jobject jvalues = env->NewObject(arrayListClass, arrayListInitMethod);
- for (auto &item : values) {
- jstring jvalue = env->NewStringUTF(item.toCString(true));
- env->CallBooleanMethod(jvalues, arrayListAddMethod, jvalue);
- env->DeleteLocalRef(jvalue);
- }
- env->CallVoidMethod(tagMap, tagMapAddIdListMethod, jid, jvalues);
- env->DeleteLocalRef(jid);
-}
-
-void JVMTagMap::add_custom(const TagLib::String description,
- const TagLib::String value) {
- jstring jdescription = env->NewStringUTF(description.toCString(true));
- jstring jvalue = env->NewStringUTF(value.toCString(true));
- env->CallVoidMethod(tagMap, tagMapAddCustomSingleMethod, jdescription,
- jvalue);
- env->DeleteLocalRef(jdescription);
- env->DeleteLocalRef(jvalue);
-}
-
-void JVMTagMap::add_custom(const TagLib::String description,
- const TagLib::StringList values) {
- jstring jid = env->NewStringUTF(description.toCString(true));
- jobject jvalues = env->NewObject(arrayListClass, arrayListInitMethod);
- for (auto &item : values) {
- jstring jvalue = env->NewStringUTF(item.toCString(true));
- env->CallBooleanMethod(jvalues, arrayListAddMethod, jvalue);
- env->DeleteLocalRef(jvalue);
- }
- env->CallVoidMethod(tagMap, tagMapAddCustomListMethod, jid, jvalues);
- env->DeleteLocalRef(jid);
- env->DeleteLocalRef(jvalues);
-}
-
-void JVMTagMap::add_combined(const TagLib::String id,
- const TagLib::String description, const TagLib::String value) {
- jstring jid = env->NewStringUTF(id.toCString(true));
- jstring jdescription = env->NewStringUTF(description.toCString(true));
- jstring jvalue = env->NewStringUTF(value.toCString(true));
- env->CallVoidMethod(tagMap, tagMapAddCombinedSingleMethod, jid,
- jdescription, jvalue);
- env->DeleteLocalRef(jid);
- env->DeleteLocalRef(jdescription);
- env->DeleteLocalRef(jvalue);
-}
-
-void JVMTagMap::add_combined(const TagLib::String id,
- const TagLib::String description, const TagLib::StringList values) {
- jstring jid = env->NewStringUTF(id.toCString(true));
- jstring jdescription = env->NewStringUTF(description.toCString(true));
- jobject jvalues = env->NewObject(arrayListClass, arrayListInitMethod);
- for (auto &item : values) {
- jstring jvalue = env->NewStringUTF(item.toCString(true));
- env->CallBooleanMethod(jvalues, arrayListAddMethod, jvalue);
- env->DeleteLocalRef(jvalue);
- }
- env->CallVoidMethod(tagMap, tagMapAddCombinedListMethod, jid, jdescription,
- jvalues);
- env->DeleteLocalRef(jid);
- env->DeleteLocalRef(jdescription);
- env->DeleteLocalRef(jvalues);
-}
-
-jobject JVMTagMap::getObject() {
- return env->CallObjectMethod(tagMap, tagMapGetObjectMethod);
-}
diff --git a/musikr/src/main/cpp/taglib_jni.cpp b/musikr/src/main/cpp/taglib_jni.cpp
index a0c393c2c..2bc040ea0 100644
--- a/musikr/src/main/cpp/taglib_jni.cpp
+++ b/musikr/src/main/cpp/taglib_jni.cpp
@@ -18,8 +18,8 @@
#include
#include
-#include "JVMInputStream.h"
-#include "JVMMetadataBuilder.h"
+#include "JInputStream.h"
+#include "JMetadataBuilder.h"
#include "util.h"
#include "taglib/fileref.h"
@@ -35,65 +35,65 @@ Java_org_oxycblt_musikr_metadata_TagLibJNI_openNative(JNIEnv *env,
jobject /* this */,
jobject inputStream) {
try {
- JVMInputStream stream {env, inputStream};
- TagLib::FileRef fileRef {&stream};
+ JInputStream jStream {env, inputStream};
+ TagLib::FileRef fileRef {&jStream};
if (fileRef.isNull()) {
LOGE("Error opening file");
return nullptr;
}
TagLib::File *file = fileRef.file();
- JVMMetadataBuilder builder {env};
+ JMetadataBuilder jBuilder {env};
if (auto *mpegFile = dynamic_cast(file)) {
- builder.setMimeType("audio/mpeg");
+ jBuilder.setMimeType("audio/mpeg");
auto id3v1Tag = mpegFile->ID3v1Tag();
if (id3v1Tag != nullptr) {
- builder.setId3v1(*id3v1Tag);
+ jBuilder.setId3v1(*id3v1Tag);
}
auto id3v2Tag = mpegFile->ID3v2Tag();
if (id3v2Tag != nullptr) {
- builder.setId3v2(*id3v2Tag);
+ jBuilder.setId3v2(*id3v2Tag);
}
} else if (auto *mp4File = dynamic_cast(file)) {
- builder.setMimeType("audio/mp4");
+ jBuilder.setMimeType("audio/mp4");
auto tag = mp4File->tag();
if (tag != nullptr) {
- builder.setMp4(*tag);
+ jBuilder.setMp4(*tag);
}
} else if (auto *flacFile = dynamic_cast(file)) {
- builder.setMimeType("audio/flac");
+ jBuilder.setMimeType("audio/flac");
auto id3v1Tag = flacFile->ID3v1Tag();
if (id3v1Tag != nullptr) {
- builder.setId3v1(*id3v1Tag);
+ jBuilder.setId3v1(*id3v1Tag);
}
auto id3v2Tag = flacFile->ID3v2Tag();
if (id3v2Tag != nullptr) {
- builder.setId3v2(*id3v2Tag);
+ jBuilder.setId3v2(*id3v2Tag);
}
auto xiphComment = flacFile->xiphComment();
if (xiphComment != nullptr) {
- builder.setXiph(*xiphComment);
+ jBuilder.setXiph(*xiphComment);
}
auto pics = flacFile->pictureList();
- builder.setFlacPictures(pics);
+ jBuilder.setFlacPictures(pics);
} else if (auto *opusFile = dynamic_cast(file)) {
- builder.setMimeType("audio/opus");
+ jBuilder.setMimeType("audio/opus");
auto tag = opusFile->tag();
if (tag != nullptr) {
- builder.setXiph(*tag);
+ jBuilder.setXiph(*tag);
}
} else if (auto *vorbisFile =
dynamic_cast(file)) {
- builder.setMimeType("audio/vorbis");
+ jBuilder.setMimeType("audio/vorbis");
auto tag = vorbisFile->tag();
if (tag != nullptr) {
- builder.setXiph(*tag);
+ jBuilder.setXiph(*tag);
}
} else if (auto *wavFile = dynamic_cast(file)) {
- builder.setMimeType("audio/wav");
+ jBuilder.setMimeType("audio/wav");
auto tag = wavFile->ID3v2Tag();
if (tag != nullptr) {
- builder.setId3v2(*tag);
+ jBuilder.setId3v2(*tag);
}
} else {
// While taglib supports other formats, ExoPlayer does not. Ignore them.
@@ -101,8 +101,8 @@ Java_org_oxycblt_musikr_metadata_TagLibJNI_openNative(JNIEnv *env,
return nullptr;
}
- builder.setProperties(file->audioProperties());
- return builder.build();
+ jBuilder.setProperties(file->audioProperties());
+ return jBuilder.build();
} catch (std::runtime_error e) {
LOGD("Error opening file: %s", e.what());
return nullptr;