From 05cf0f72610c91dd881baf43ecd38b61b5f0bc42 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Thu, 29 Dec 2022 21:09:35 -0700 Subject: [PATCH] music: fix music loading crash with weird genres Fix an issue where genres consisting only of whitespace crash the genre parser, and thus the music loader. Band-aid this by moving the trimming code out of splitEscaped and into maybeParseSeparators. In a future version I'll need to figure out how I want to handle these weird edge cases. --- CHANGELOG.md | 2 +- .../auxio/music/extractor/CacheExtractor.kt | 7 +++-- .../music/extractor/MetadataExtractor.kt | 4 +-- .../auxio/music/extractor/ParsingUtil.kt | 31 ++++++++++--------- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13bbff4e7..7cc7f6db2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,7 +51,7 @@ audio focus was lost - Switched to issue forms - Completed migration to reactive playback system - Refactor music backends into a unified chain of extractors -- Add bluetooth connection reciever (No functionality in app yet) +- Add bluetooth connection receiver (No functionality in app yet) ## 2.6.4 diff --git a/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheExtractor.kt b/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheExtractor.kt index f17419bc9..e9159a0db 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheExtractor.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheExtractor.kt @@ -283,8 +283,8 @@ private class CacheDatabase(context: Context) : raw.albumMusicBrainzId = cursor.getStringOrNull(albumMusicBrainzIdIndex) raw.albumName = cursor.getString(albumNameIndex) raw.albumSortName = cursor.getStringOrNull(albumSortNameIndex) - cursor.getStringOrNull(albumTypesIndex)?.parseSQLMultiValue()?.let { - raw.albumTypes = it + cursor.getStringOrNull(albumTypesIndex)?.let { + raw.albumTypes = it.parseSQLMultiValue() } cursor.getStringOrNull(artistMusicBrainzIdsIndex)?.let { @@ -387,7 +387,8 @@ private class CacheDatabase(context: Context) : * @return A list of strings corresponding to the delimited values present within the original * string. Escaped delimiters are converted back into their normal forms. */ - private fun String.parseSQLMultiValue() = splitEscaped { it == ';' } + private fun String.parseSQLMultiValue() = + splitEscaped { it == ';' } /** Defines the columns used in this database. */ private object Columns { diff --git a/app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataExtractor.kt b/app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataExtractor.kt index a0f6b1168..6603850e4 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataExtractor.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/extractor/MetadataExtractor.kt @@ -187,8 +187,8 @@ class Task(context: Context, private val raw: Song.Raw) { // Map TXXX frames differently so we can specifically index by their // descriptions. val id = tag.description?.let { "TXXX:${it.sanitize()}" } ?: tag.id.sanitize() - val values = tag.values.map { it.sanitize() } - if (values.isNotEmpty() && values.all { it.isNotEmpty() }) { + val values = tag.values.map { it.sanitize() }.filter { it.isNotEmpty() } + if (values.isNotEmpty()) { id3v2Tags[id] = values } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/extractor/ParsingUtil.kt b/app/src/main/java/org/oxycblt/auxio/music/extractor/ParsingUtil.kt index 3d6b2cc59..05a2deeb7 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/extractor/ParsingUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/extractor/ParsingUtil.kt @@ -21,6 +21,7 @@ import androidx.core.text.isDigitsOnly import java.util.UUID import org.oxycblt.auxio.music.Date import org.oxycblt.auxio.settings.Settings +import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.nonZeroOrNull /** @@ -88,7 +89,7 @@ inline fun String.splitEscaped(selector: (Char) -> Boolean): List { if (selector(a)) { // Non-escaped separator, split the string here, making sure any stray whitespace // is removed. - split.add(currentString.trim()) + split.add(currentString) currentString = "" i++ continue @@ -107,8 +108,8 @@ inline fun String.splitEscaped(selector: (Char) -> Boolean): List { } if (currentString.isNotEmpty()) { - // Had an in-progress split string that is now terminated, add it.. - split.add(currentString.trim()) + // Had an in-progress split string that is now terminated, add it. + split.add(currentString) } return split @@ -126,7 +127,7 @@ fun List.parseMultiValue(settings: Settings) = get(0).maybeParseSeparators(settings) } else { // Nothing to do. - this + this.map { it.trim() } } /** @@ -137,7 +138,7 @@ fun List.parseMultiValue(settings: Settings) = fun String.maybeParseSeparators(settings: Settings): List { // Get the separators the user desires. If null, there's nothing to do. val separators = settings.musicSeparators ?: return listOf(this) - return splitEscaped { separators.contains(it) } + return splitEscaped { separators.contains(it) }.map { it.trim() } } /** @@ -179,20 +180,20 @@ fun String.parseId3GenreNames(settings: Settings) = * @return A named genre if the field is a valid integer, "Cover" or "Remix" if the field is * "CR"/"RX" respectively, and nothing if the field is not a valid ID3v1 integer genre. */ -private fun String.parseId3v1Genre(): String? = - when { - // ID3v1 genres are a plain integer value without formatting, so in that case - // try to index the genre table with such. - isDigitsOnly() -> GENRE_TABLE.getOrNull(toInt()) - +private fun String.parseId3v1Genre(): String? { + // ID3v1 genres are a plain integer value without formatting, so in that case + // try to index the genre table with such. If this fails, then try to compare it + // to some other hard-coded values. + val numeric = toIntOrNull() ?: return when (this) { // CR and RX are not technically ID3v1, but are formatted similarly to a plain number. - this == "CR" -> "Cover" - this == "RX" -> "Remix" - - // Current name is fine. + "CR" -> "Cover" + "RX" -> "Remix" else -> null } + return GENRE_TABLE.getOrNull(numeric) +} + /** * A [Regex] that implements parsing for ID3v2's genre format. Derived from mutagen: * https://github.com/quodlibet/mutagen