Skip to content

Commit 534484d

Browse files
committed
Merge branch 'feature/taglib' into compose
2 parents 67180c5 + 553af98 commit 534484d

17 files changed

Lines changed: 211 additions & 211 deletions

File tree

.gitmodules

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
[submodule "app/src/third-party/jaudiotagger-android"]
2-
path = app/src/third-party/jaudiotagger-android
3-
url = https://github.com/hexise/jaudiotagger-android.git
1+
[submodule "third-party/taglib"]
2+
path = third-party/taglib
3+
url = ../taglib.git
4+
branch = main

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ height="80">](https://apt.izzysoft.de/packages/remix.myplayer)
5454
- [Leakcanary](https://github.com/square/leakcanary)
5555
- [ImageCropper](https://github.com/CanHub/Android-Image-Cropper)
5656
- [TinyPinyin](https://github.com/promeG/TinyPinyin)
57-
- [Jaudiotagger for Android](https://github.com/hexise/jaudiotagger-android)
57+
- [TagLib for Android](https://github.com/rRemix/taglib)
5858

5959
## Finally
6060
- Pull request is welcome

README_CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ height="80">](https://apt.izzysoft.de/packages/remix.myplayer)
5555
- [Leakcanary](https://github.com/square/leakcanary)
5656
- [ImageCropper](https://github.com/CanHub/Android-Image-Cropper)
5757
- [TinyPinyin](https://github.com/promeG/TinyPinyin)
58-
- [Jaudiotagger for Android](https://github.com/hexise/jaudiotagger-android)
58+
- [TagLib for Android](https://github.com/rRemix/taglib)
5959

6060

6161
## 最后

app/build.gradle.kts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ android {
7979
setProperty("archivesBaseName", "APlayer-v${versionName}")
8080
}
8181

82+
androidResources {
83+
localeFilters += listOf(
84+
"en",
85+
"ja",
86+
"ja-rJP",
87+
"zh",
88+
"zh-rCN",
89+
"zh-rHK",
90+
"zh-rTW"
91+
)
92+
}
93+
8294
signingConfigs {
8395
create("debugConfig") {
8496
storeFile = project.file("Debug.jks")
@@ -127,12 +139,6 @@ android {
127139
}
128140
}
129141

130-
sourceSets {
131-
getByName("main") {
132-
java.srcDir("src/third-party/jaudiotagger-android/src")
133-
}
134-
}
135-
136142
externalNativeBuild {
137143
cmake {
138144
path("CMakeLists.txt")
@@ -291,6 +297,8 @@ dependencies {
291297

292298
implementation(libs.androidx.profileinstaller)
293299
"baselineProfile"(project(":baselineprofile"))
300+
301+
implementation(project(":taglib"))
294302
}
295303

296304
// 上传mapping文件

app/proguard-rules.pro

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@
1212
-keep public class com.tencent.bugly.** { *; }
1313
-dontwarn com.tencent.bugly.**
1414

15-
# jaudiotagger
16-
# Simply keep all classes as they use reflection
17-
-keep class org.jaudiotagger.** { *; }
18-
-dontwarn org.jaudiotagger.**
19-
2015
# logback-android
2116
# https://github.com/tony19/logback-android/issues/229
2217
# They've added consumer-rules.pro, but it seems to be unused

app/src/main/java/remix/myplayer/glide/AudioFileCoverUtils.kt

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package remix.myplayer.glide
22

3-
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException
4-
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException
5-
import org.jaudiotagger.audio.mp3.MP3File
6-
import org.jaudiotagger.tag.TagException
3+
import remix.myplayer.helper.AudioTagFile
74
import java.io.ByteArrayInputStream
85
import java.io.File
96
import java.io.FileInputStream
@@ -21,19 +18,12 @@ object AudioFileCoverUtils {
2118
}
2219
// Method 1: use embedded high resolution album art if there is any
2320
try {
24-
val mp3File = MP3File(path)
25-
if (mp3File.hasID3v2Tag()) {
26-
val art = mp3File.tag.firstArtwork
27-
if (art != null) {
28-
val imageData = art.binaryData
29-
return ByteArrayInputStream(imageData)
30-
}
21+
val artwork = AudioTagFile.readFrontCover(File(path))
22+
if (artwork != null) {
23+
return ByteArrayInputStream(artwork.data)
3124
}
3225
// If there are any exceptions, we ignore them and continue to the other fallback method
33-
} catch (ignored: ReadOnlyFileException) {
34-
} catch (ignored: InvalidAudioFrameException) {
35-
} catch (ignored: TagException) {
36-
} catch (ignored: IOException) {
26+
} catch (ignored: Exception) {
3727
}
3828

3929
// Method 2: look for album art in external files
@@ -49,4 +39,4 @@ object AudioFileCoverUtils {
4939
}
5040
return null
5141
}
52-
}
42+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package remix.myplayer.helper
2+
3+
import android.os.ParcelFileDescriptor
4+
import com.kyant.taglib.AudioProperties
5+
import com.kyant.taglib.Metadata
6+
import com.kyant.taglib.Picture
7+
import com.kyant.taglib.PropertyMap
8+
import com.kyant.taglib.TagLib
9+
import java.io.File
10+
import java.io.IOException
11+
12+
/**
13+
* File-based access to audio metadata through TagLib.
14+
*
15+
* TagLib takes ownership of the supplied raw file descriptor, so every call uses a detached
16+
* duplicate and leaves the [ParcelFileDescriptor] owned by Android untouched.
17+
*/
18+
object AudioTagFile {
19+
20+
const val TITLE = "TITLE"
21+
const val ALBUM = "ALBUM"
22+
const val ARTIST = "ARTIST"
23+
const val ALBUM_ARTIST = "ALBUMARTIST"
24+
const val COMPOSER = "COMPOSER"
25+
const val GENRE = "GENRE"
26+
const val DATE = "DATE"
27+
const val TRACK_NUMBER = "TRACKNUMBER"
28+
const val DISC_NUMBER = "DISCNUMBER"
29+
const val LYRICS = "LYRICS"
30+
31+
fun readAudioProperties(file: File): AudioProperties? =
32+
withFileDescriptor(file, ParcelFileDescriptor.MODE_READ_ONLY) { fd ->
33+
TagLib.getAudioProperties(fd)
34+
}
35+
36+
fun readMetadata(file: File, readPictures: Boolean = true): Metadata? =
37+
withFileDescriptor(file, ParcelFileDescriptor.MODE_READ_ONLY) { fd ->
38+
TagLib.getMetadata(fd, readPictures)
39+
}
40+
41+
fun readFrontCover(file: File): Picture? =
42+
withFileDescriptor(file, ParcelFileDescriptor.MODE_READ_ONLY) { fd ->
43+
TagLib.getFrontCover(fd)
44+
}
45+
46+
fun savePropertyMap(file: File, propertyMap: PropertyMap): Boolean =
47+
withFileDescriptor(file, ParcelFileDescriptor.MODE_READ_WRITE) { fd ->
48+
TagLib.savePropertyMap(fd, propertyMap)
49+
}
50+
51+
fun savePictures(file: File, pictures: Array<Picture>): Boolean =
52+
withFileDescriptor(file, ParcelFileDescriptor.MODE_READ_WRITE) { fd ->
53+
TagLib.savePictures(fd, pictures)
54+
}
55+
56+
fun firstValue(propertyMap: Map<String, Array<String>>?, key: String): String =
57+
propertyMap?.get(key)?.firstOrNull().orEmpty()
58+
59+
fun setValue(propertyMap: PropertyMap, key: String, value: String) {
60+
if (value.isBlank()) {
61+
propertyMap.remove(key)
62+
} else {
63+
propertyMap[key] = arrayOf(value)
64+
}
65+
}
66+
67+
fun requireSaved(saved: Boolean, operation: String) {
68+
if (!saved) {
69+
throw IOException("TagLib failed to $operation")
70+
}
71+
}
72+
73+
private inline fun <T> withFileDescriptor(
74+
file: File,
75+
mode: Int,
76+
block: (Int) -> T
77+
): T = ParcelFileDescriptor.open(file, mode).use { descriptor ->
78+
block(descriptor.dup().detachFd())
79+
}
80+
}

0 commit comments

Comments
 (0)