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.
This commit is contained in:
parent
6db50a0e45
commit
05cf0f7261
4 changed files with 23 additions and 21 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String> {
|
|||
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<String> {
|
|||
}
|
||||
|
||||
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<String>.parseMultiValue(settings: Settings) =
|
|||
get(0).maybeParseSeparators(settings)
|
||||
} else {
|
||||
// Nothing to do.
|
||||
this
|
||||
this.map { it.trim() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,7 +138,7 @@ fun List<String>.parseMultiValue(settings: Settings) =
|
|||
fun String.maybeParseSeparators(settings: Settings): List<String> {
|
||||
// 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 {
|
||||
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.
|
||||
isDigitsOnly() -> GENRE_TABLE.getOrNull(toInt())
|
||||
|
||||
// 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
|
||||
|
|
Loading…
Reference in a new issue