diff --git a/CHANGELOG.md b/CHANGELOG.md index 6273ed786..738d9a66e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ at the cost of longer loading times - Added support for sort tags [#172, dependent on this feature] - Added support for date tags, including more fine-grained dates [#159, dependent on this feature] - Added support for release types signifying EPs, Singles, Compilations, and more [#158, dependent on this feature] + - Added basic awareness of multi-value vorbis tags [#197, dependent on this feature] - Added Last Added sorting - Search now takes sort tags and file names in account [#184] diff --git a/README.md b/README.md index 9ad42ddf1..3b2e13ab4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

A simple, rational music player for android.

- Latest version + Latest Version Releases @@ -11,7 +11,7 @@ - Minimum SDK + Minimum SDK Version

Changelog | FAQ | Licenses | Contributing | Architecture

diff --git a/app/src/main/java/org/oxycblt/auxio/music/Music.kt b/app/src/main/java/org/oxycblt/auxio/music/Music.kt index a0c174ae1..c4d512211 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Music.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Music.kt @@ -493,8 +493,9 @@ sealed class ReleaseType { } companion object { - fun parse(type: String): ReleaseType { - val types = type.split('+') + fun parse(type: String) = parse(type.split('+')) + + fun parse(types: List): ReleaseType { val primary = types[0].trim() // Primary types should be the first one in sequence. The spec makes no mention of @@ -523,8 +524,8 @@ sealed class ReleaseType { secondary.equals("compilation", true) -> Compilation secondary.equals("soundtrack", true) -> Soundtrack secondary.equals("mixtape/street", true) -> Mixtape - secondary.equals("live", true) -> target(Refinement.REMIX) - secondary.equals("remix", true) -> target(Refinement.LIVE) + secondary.equals("live", true) -> target(Refinement.LIVE) + secondary.equals("remix", true) -> target(Refinement.REMIX) else -> target(null) } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt index e90c3b5f3..ce4cee322 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt @@ -103,6 +103,9 @@ fun String.parseSortName() = /** Shortcut to parse an [ReleaseType] from a string */ fun String.parseReleaseType() = ReleaseType.parse(this) +/** Shortcut to parse a [ReleaseType] from a list of strings */ +fun List.parseReleaseType() = ReleaseType.parse(this) + /** * Decodes the genre name from an ID3(v2) constant. See [GENRE_TABLE] for the genre constant map * that Auxio uses. diff --git a/app/src/main/java/org/oxycblt/auxio/music/system/ExoPlayerBackend.kt b/app/src/main/java/org/oxycblt/auxio/music/system/ExoPlayerBackend.kt index 6cfee8e7e..78fd42247 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/system/ExoPlayerBackend.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/system/ExoPlayerBackend.kt @@ -170,7 +170,7 @@ class Task(context: Context, private val audio: MediaStoreBackend.Audio) { private fun completeAudio(metadata: Metadata) { val id3v2Tags = mutableMapOf() - val vorbisTags = mutableMapOf() + val vorbisTags = mutableMapOf>() // ExoPlayer only exposes ID3v2 and Vorbis metadata, which constitutes the vast majority // of audio formats. Load both of these types of tags into separate maps, letting the @@ -189,7 +189,11 @@ class Task(context: Context, private val audio: MediaStoreBackend.Audio) { val id = tag.key.sanitize().uppercase() val value = tag.value.sanitize() if (value.isNotEmpty()) { - vorbisTags[id] = value + if (vorbisTags.containsKey(id)) { + vorbisTags[id]!!.add(value) + } else { + vorbisTags[id] = mutableListOf(value) + } } } } @@ -274,16 +278,16 @@ class Task(context: Context, private val audio: MediaStoreBackend.Audio) { } } - private fun populateVorbis(tags: Map) { + private fun populateVorbis(tags: Map>) { // (Sort) Title - tags["TITLE"]?.let { audio.title = it } - tags["TITLESORT"]?.let { audio.sortTitle = it } + tags["TITLE"]?.let { audio.title = it[0] } + tags["TITLESORT"]?.let { audio.sortTitle = it[0] } // Track - tags["TRACKNUMBER"]?.parsePositionNum()?.let { audio.track = it } + tags["TRACKNUMBER"]?.run { get(0).parsePositionNum() }?.let { audio.track = it } // Disc - tags["DISCNUMBER"]?.parsePositionNum()?.let { audio.disc = it } + tags["DISCNUMBER"]?.run { get(0).parsePositionNum() }?.let { audio.disc = it } // Vorbis dates are less complicated, but there are still several types // Our hierarchy for dates is as such: @@ -291,24 +295,25 @@ class Task(context: Context, private val audio: MediaStoreBackend.Audio) { // 2. Date, as it is the most common date type // 3. Year, as old vorbis tags tended to use this (I know this because it's the only // tag that android supports, so it must be 15 years old or more!) - (tags["ORIGINALDATE"]?.parseTimestamp() - ?: tags["DATE"]?.parseTimestamp() ?: tags["YEAR"]?.parseYear()) + (tags["ORIGINALDATE"]?.run { get(0).parseTimestamp() } + ?: tags["DATE"]?.run { get(0).parseTimestamp() } + ?: tags["YEAR"]?.run { get(0).parseYear() }) ?.let { audio.date = it } // (Sort) Album - tags["ALBUM"]?.let { audio.album = it } - tags["ALBUMSORT"]?.let { audio.sortAlbum = it } + tags["ALBUM"]?.let { audio.album = it.joinToString() } + tags["ALBUMSORT"]?.let { audio.sortAlbum = it.joinToString() } // (Sort) Artist - tags["ARTIST"]?.let { audio.artist = it } - tags["ARTISTSORT"]?.let { audio.sortArtist = it } + tags["ARTIST"]?.let { audio.artist = it.joinToString() } + tags["ARTISTSORT"]?.let { audio.sortArtist = it.joinToString() } // (Sort) Album artist - tags["ALBUMARTIST"]?.let { audio.albumArtist = it } - tags["ALBUMARTISTSORT"]?.let { audio.sortAlbumArtist = it } + tags["ALBUMARTIST"]?.let { audio.albumArtist = it.joinToString() } + tags["ALBUMARTISTSORT"]?.let { audio.sortAlbumArtist = it.joinToString() } // Genre, no ID3 rules here - tags["GENRE"]?.let { audio.genre = it } + tags["GENRE"]?.let { audio.genre = it.joinToString() } // Release type tags["RELEASETYPE"]?.parseReleaseType()?.let { audio.releaseType = it }