diff --git a/CHANGELOG.md b/CHANGELOG.md index fa466a8bc..11e08ad80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,8 @@ ## dev #### What's Improved -- Tags formatted as `artistssort` or `albumartistssort` are now recognized by Auxio -- Non-english digit strings are now sorted better +- `artistssort`, `albumartistssort`, and `album_artists` tags are now recognized +- Non-english digit strings are sorted more correctly - Reduced visual loading time #### What's Fixed @@ -12,6 +12,7 @@ - Fixed selection not updating when playlists are changed - Fixed duplicate albums appearing in certain cases - Fixed ReplayGain adjustment not applying at the start of a song in certain cases +- Music cache is no longer migrated between devices ## 3.1.1 diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverUri.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverUri.kt index 4aadf932e..5e32d09ff 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverUri.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverUri.kt @@ -23,9 +23,10 @@ import android.net.Uri /** * Bundle of [Uri] information used in [CoverExtractor] to ensure consistent [Uri] use when loading * images. + * * @param mediaStore The album cover [Uri] obtained from MediaStore. - * @param song The [Uri] of the first song (by track) of the album, which can also be used to - * obtain an album cover. + * @param song The [Uri] of the first song (by track) of the album, which can also be used to obtain + * an album cover. * @author Alexander Capehart (OxygenCobalt) */ data class CoverUri(val mediaStore: Uri, val song: Uri) diff --git a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt index 5a70dc578..45034582d 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt @@ -123,6 +123,8 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu val artistGrouping = mutableMapOf>() val genreGrouping = mutableMapOf>() + // TODO: Use comparators here + // All music information is grouped as it is indexed by other components. for (rawSong in rawSongs) { val song = SongImpl(rawSong, musicSettings) @@ -150,11 +152,13 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu // Since albums are grouped fuzzily, we pick the song with the earliest track to // use for album information to ensure consistent metadata and UIDs. Fall back to // the name otherwise. - val trackLower = + val higherPriority = song.track != null && - (prioritized.track == null || song.track < prioritized.track) - val nameLower = song.name < prioritized.name - if (trackLower || nameLower) { + (prioritized.track == null || + song.track < prioritized.track || + (song.track == prioritized.track && song.name < prioritized.name)) + + if (higherPriority) { albumBody.raw = PrioritizedRaw(song.rawAlbum, song) } } else { @@ -187,8 +191,8 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu // Genre information from higher songs in ascending alphabetical order are // prioritized. val prioritized = genreBody.raw.src - val nameLower = song.name < prioritized.name - if (nameLower) { + val higherPriority = song.name < prioritized.name + if (higherPriority) { genreBody.raw = PrioritizedRaw(rawGenre, song) } } else { @@ -217,11 +221,14 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu // Album information from later dates is prioritized, as it is more // likely to contain the "modern" name of the artist if the information // really is in-consistent. Fall back to the name otherwise. - val dateEarlier = + val prioritize = album.dates != null && - (prioritized.dates == null || album.dates < prioritized.dates) - val nameLower = album.name < prioritized.name - if (dateEarlier || nameLower) { + (prioritized.dates == null || + album.dates > prioritized.dates || + (album.dates == prioritized.dates && + album.name < prioritized.name)) + + if (prioritize) { body.raw = PrioritizedRaw(rawArtist, album) } } @@ -243,6 +250,8 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu } } +// TODO: Avoid redundant data creation + class DeviceLibraryImpl( override val songs: Set, override val albums: Set, diff --git a/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt b/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt index 69569fb19..5d9eebcbc 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt @@ -141,7 +141,9 @@ private class TagWorkerImpl( textFrames["TALB"]?.let { rawSong.albumName = it.first() } textFrames["TSOA"]?.let { rawSong.albumSortName = it.first() } (textFrames["TXXX:musicbrainz album type"] - ?: textFrames["TXXX:releasetype"] ?: textFrames["GRP1"]) + ?: textFrames["TXXX:releasetype"] ?: + // This is a non-standard iTunes extension + textFrames["GRP1"]) ?.let { rawSong.releaseTypes = it } // Artist @@ -158,15 +160,17 @@ private class TagWorkerImpl( rawSong.albumArtistNames = it } (textFrames["TXXX:albumartistssort"] - ?: textFrames["TXXX:albumartists_sort"] ?: textFrames["TSO2"]) + ?: textFrames["TXXX:albumartists_sort"] ?: textFrames["TXXX:albumartistsort"] + // This is a non-standard iTunes extension + ?: textFrames["TSO2"]) ?.let { rawSong.albumArtistSortNames = it } // Genre textFrames["TCON"]?.let { rawSong.genreNames = it } // Compilation Flag - (textFrames["TCMP"] - ?: textFrames["TXXX:compilation"] ?: textFrames["TXXX:itunescompilation"]) + (textFrames["TCMP"] // This is a non-standard itunes extension + ?: textFrames["TXXX:compilation"] ?: textFrames["TXXX:itunescompilation"]) ?.let { // Ignore invalid instances of this tag if (it.size != 1 || it[0] != "1") return@let @@ -175,6 +179,7 @@ private class TagWorkerImpl( rawSong.albumArtistNames.ifEmpty { COMPILATION_ALBUM_ARTISTS } rawSong.releaseTypes = rawSong.releaseTypes.ifEmpty { COMPILATION_RELEASE_TYPES } } + // ReplayGain information textFrames["TXXX:replaygain_track_gain"]?.parseReplayGainAdjustment()?.let { rawSong.replayGainTrackAdjustment = it @@ -262,7 +267,9 @@ private class TagWorkerImpl( // Album artist comments["musicbrainz_albumartistid"]?.let { rawSong.albumArtistMusicBrainzIds = it } - (comments["albumartists"] ?: comments["albumartist"])?.let { rawSong.albumArtistNames = it } + (comments["albumartists"] ?: comments["album_artists"] ?: comments["albumartist"])?.let { + rawSong.albumArtistNames = it + } (comments["albumartistssort"] ?: comments["albumartists_sort"] ?: comments["albumartistsort"]) ?.let { rawSong.albumArtistSortNames = it }