From 5bc5afa1621f2624e3f7f77c7b63a3d56dce2db8 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Thu, 2 Jun 2022 17:05:42 -0600 Subject: [PATCH] fastlane: fix image metadata Fix slight screenshot discrepancies where shot7 would show the old song sub-heading. --- CHANGELOG.md | 2 ++ .../org/oxycblt/auxio/home/HomeFragment.kt | 1 + .../org/oxycblt/auxio/image/Components.kt | 2 +- .../org/oxycblt/auxio/music/MusicStore.kt | 1 - .../auxio/music/indexer/ExoPlayerBackend.kt | 14 +++++++------- .../oxycblt/auxio/music/indexer/Indexer.kt | 9 +-------- .../en-US/images/phoneScreenshots/shot7.png | Bin 252435 -> 251120 bytes 7 files changed, 12 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 933cb04ed..24ae76407 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,11 +12,13 @@ - Fixed bug where music would be incorrectly reloaded on a hot restart - Fixed issue where the album/artist/genre would not be correctly restored - Fixed issue where items would not highlight properly in the detail UI +- Fixed hypothetical issue where widget would cause an OOM on large devices #### Dev/Meta - New translations [yurical -> Korean, qwerty287 -> German] - Switched from `LiveData` to `StateFlow` - Use `notifyItemChanged` instead of directly mutating `ViewHolder` instances. +- Added highly experimental ExoPlayer metadata backend (not enabled in-app) ## v2.3.0 diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index 3bda40104..74d8f385e 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -321,6 +321,7 @@ class HomeFragment : ViewBindingFragment(), Toolbar.OnMenuI } private fun handleLoadEvent(binding: FragmentHomeBinding, event: MusicStore.LoadState?) { + binding.homeFab.hide() binding.homePager.visibility = View.INVISIBLE binding.homeLoadingContainer.visibility = View.VISIBLE binding.homeLoadingProgress.visibility = View.VISIBLE diff --git a/app/src/main/java/org/oxycblt/auxio/image/Components.kt b/app/src/main/java/org/oxycblt/auxio/image/Components.kt index cb7d83cc7..e739b3f00 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/Components.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/Components.kt @@ -110,7 +110,7 @@ private constructor( private val genre: Genre, ) : BaseFetcher() { override suspend fun fetch(): FetchResult? { - // Don't sort here to preserve compatibility with previous versions of this image. + // Don't sort here to preserve compatibility with previous versions of this images val albums = genre.songs.groupBy { it.album }.keys val results = albums.mapAtMost(4) { album -> fetchArt(context, album) } return createMosaic(context, results, size) diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt index 03dd92bc8..ff223cf2a 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicStore.kt @@ -25,7 +25,6 @@ import android.provider.OpenableColumns import androidx.core.content.ContextCompat import java.lang.Exception import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay import kotlinx.coroutines.withContext import org.oxycblt.auxio.music.indexer.Indexer import org.oxycblt.auxio.music.indexer.useQuery diff --git a/app/src/main/java/org/oxycblt/auxio/music/indexer/ExoPlayerBackend.kt b/app/src/main/java/org/oxycblt/auxio/music/indexer/ExoPlayerBackend.kt index 4abfcac4e..197998fca 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/indexer/ExoPlayerBackend.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/indexer/ExoPlayerBackend.kt @@ -32,6 +32,7 @@ import java.util.concurrent.Executors import java.util.concurrent.Future import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logW /** @@ -113,9 +114,12 @@ class ExoPlayerBackend(private val inner: MediaStoreBackend) : Indexer.Backend { private val onComplete: (Song) -> Unit, ) : FutureCallback { override fun onSuccess(result: TrackGroupArray) { - val metadata = result[0].getFormat(0).metadata - if (metadata != null) { - completeAudio(audio, metadata) + val metadata = result[0].getFormat(0) + + logD("${metadata.sampleMimeType} ${metadata.averageBitrate} ${metadata.sampleRate}") + + if (metadata.metadata != null) { + completeAudio(audio, metadata.metadata!!) } else { logW("No metadata was found for ${audio.title}") } @@ -131,10 +135,6 @@ class ExoPlayerBackend(private val inner: MediaStoreBackend) : Indexer.Backend { } private fun completeAudio(audio: MediaStoreBackend.Audio, metadata: Metadata) { - if (metadata.length() == 0) { - return - } - // ExoPlayer only exposes ID3v2 and Vorbis metadata, which constitutes the vast majority // of audio formats. Some formats (like FLAC) can contain both ID3v2 and vorbis tags, but // this isn't too big of a deal, as we generally let the "source of truth" for metadata diff --git a/app/src/main/java/org/oxycblt/auxio/music/indexer/Indexer.kt b/app/src/main/java/org/oxycblt/auxio/music/indexer/Indexer.kt index a78e80179..28b532989 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/indexer/Indexer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/indexer/Indexer.kt @@ -54,14 +54,6 @@ object Indexer { else -> Api21MediaStoreBackend() } - // Disabled until direct parsing is fully capable of integration into Auxio's - // architecture. - // val backend = if (settingsManager.useQualityMetadata) { - // ExoPlayerBackend(mediaStoreBackend) - // } else { - // mediaStoreBackend - // } - val songs = buildSongs(context, mediaStoreBackend, callback) if (songs.isEmpty()) { return null @@ -71,6 +63,7 @@ object Indexer { val albums = buildAlbums(songs) val artists = buildArtists(albums) + val genres = buildGenres(songs) // Sanity check: Ensure that all songs are linked up to albums/artists/genres. diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/shot7.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/shot7.png index 616bc683d61903bc8c59d0ec07483f4e1c54b22e..5114bb008c16451c7dbe83082ee4bdd0db3d603e 100644 GIT binary patch delta 5611 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 acN=^4US^VdcN|Y-AQc4-`6^kf@c#odz35i}