From 5e0f778daf7844d5e335c6253b5fcd340ff323de Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Mon, 26 Sep 2022 13:47:03 -0600 Subject: [PATCH] image: unify cover settings Unify the "Show Covers" and "Ignore MediaStore Covers" settings under an new "Album covers" setting. This will make it easier to extend to new forms of album cover collection. --- CHANGELOG.md | 4 +- app/build.gradle | 1 - .../java/org/oxycblt/auxio/IntegerTable.kt | 15 +++++-- .../java/org/oxycblt/auxio/image/CoverMode.kt | 45 +++++++++++++++++++ .../auxio/image/extractor/BaseFetcher.kt | 17 +++---- .../auxio/image/extractor/Components.kt | 6 +-- .../org/oxycblt/auxio/playback/ActionMode.kt | 14 +++--- .../playback/system/MediaSessionComponent.kt | 3 +- .../org/oxycblt/auxio/settings/Settings.kt | 32 +++++++++---- ...sListFragment.kt => PreferenceFragment.kt} | 5 +-- .../oxycblt/auxio/widgets/WidgetComponent.kt | 3 +- app/src/main/res/layout/fragment_settings.xml | 2 +- app/src/main/res/values/settings.xml | 27 ++++++++--- app/src/main/res/values/strings.xml | 8 ++-- app/src/main/res/xml/prefs_main.xml | 18 +++----- 15 files changed, 136 insertions(+), 64 deletions(-) create mode 100644 app/src/main/java/org/oxycblt/auxio/image/CoverMode.kt rename app/src/main/java/org/oxycblt/auxio/settings/prefs/{SettingsListFragment.kt => PreferenceFragment.kt} (97%) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9ba4c489..074f01388 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,9 @@ audio focus was lost #### What's Changed - Ignore MediaStore tags is now on by default -- Removed the "Play from genre" option in the library/detail playback mode settings +- Removed the "Play from genre" option in the library/detail playback mode settings+ +- "Use alternate notification action" is now "Custom notification action" +- "Show covers" and "Ignore MediaStore covers" have been unified into "Album covers" #### Dev/Meta - Completed migration to reactive playback system diff --git a/app/build.gradle b/app/build.gradle index 09e3c64dc..28ae802c2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,7 +3,6 @@ plugins { id "kotlin-android" id "androidx.navigation.safeargs.kotlin" id "com.diffplug.spotless" - id "kotlin-kapt" id "kotlin-parcelize" } diff --git a/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt b/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt index 1b75b2f1b..8879c4558 100644 --- a/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt +++ b/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt @@ -144,11 +144,20 @@ object IntegerTable { const val REPLAY_GAIN_MODE_DYNAMIC = 0xA113 /** ActionMode.Next */ - const val BAR_ACTION_NEXT = 0xA119 + const val ACTION_MODE_NEXT = 0xA119 /** ActionMode.Repeat */ - const val BAR_ACTION_REPEAT = 0xA11A + const val ACTION_MODE_REPEAT = 0xA11A /** ActionMode.Shuffle */ - const val BAR_ACTION_SHUFFLE = 0xA11B + const val ACTION_MODE_SHUFFLE = 0xA11B + + /** CoverMode.Off */ + const val COVER_MODE_OFF = 0xA11C + + /** CoverMode.MediaStore */ + const val COVER_MODE_MEDIA_STORE = 0xA11D + + /** CoverMode.Quality */ + const val COVER_MODE_QUALITY = 0xA11E } diff --git a/app/src/main/java/org/oxycblt/auxio/image/CoverMode.kt b/app/src/main/java/org/oxycblt/auxio/image/CoverMode.kt new file mode 100644 index 000000000..f8ffc0cf1 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/image/CoverMode.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 Auxio Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.image + +import org.oxycblt.auxio.IntegerTable + +/** + * Represents the options available for album cover loading. + * @author OxygenCobalt + */ +enum class CoverMode { + OFF, + MEDIA_STORE, + QUALITY; + + val intCode: Int get() = when (this) { + OFF -> IntegerTable.COVER_MODE_OFF + MEDIA_STORE -> IntegerTable.COVER_MODE_MEDIA_STORE + QUALITY -> IntegerTable.COVER_MODE_QUALITY + } + + companion object { + fun fromIntCode(intCode: Int) = when (intCode) { + IntegerTable.COVER_MODE_OFF -> OFF + IntegerTable.COVER_MODE_MEDIA_STORE -> MEDIA_STORE + IntegerTable.COVER_MODE_QUALITY -> QUALITY + else -> null + } + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/BaseFetcher.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/BaseFetcher.kt index 921b11820..6a69ac978 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/BaseFetcher.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/BaseFetcher.kt @@ -41,6 +41,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import okio.buffer import okio.source +import org.oxycblt.auxio.image.CoverMode import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.util.logD @@ -57,21 +58,17 @@ import android.util.Size as AndroidSize */ abstract class BaseFetcher : Fetcher { /** - * Fetch the artwork of an [album]. This call respects user configuration and has proper + * Fetch the [album] cover. This call respects user configuration and has proper * redundancy in the case that metadata fails to load. */ - protected suspend fun fetchArt(context: Context, album: Album): InputStream? { + protected suspend fun fetchCover(context: Context, album: Album): InputStream? { val settings = Settings(context) - if (!settings.showCovers) { - return null - } - return try { - if (settings.useQualityCovers) { - fetchQualityCovers(context, album) - } else { - fetchMediaStoreCovers(context, album) + when (settings.coverMode) { + CoverMode.OFF -> null + CoverMode.MEDIA_STORE -> fetchMediaStoreCovers(context, album) + CoverMode.QUALITY -> fetchQualityCovers(context, album) } } catch (e: Exception) { logW("Unable to extract album cover due to an error: $e") diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt index 91f0c7c37..2201eb9d1 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt @@ -56,7 +56,7 @@ class MusicKeyer : Keyer { class AlbumCoverFetcher private constructor(private val context: Context, private val album: Album) : BaseFetcher() { override suspend fun fetch(): FetchResult? = - fetchArt(context, album)?.let { stream -> + fetchCover(context, album)?.let { stream -> SourceResult( source = ImageSource(stream.source().buffer(), context), mimeType = null, @@ -87,7 +87,7 @@ private constructor( ) : BaseFetcher() { override suspend fun fetch(): FetchResult? { val albums = Sort(Sort.Mode.ByName, true).albums(artist.albums) - val results = albums.mapAtMost(4) { album -> fetchArt(context, album) } + val results = albums.mapAtMost(4) { album -> fetchCover(context, album) } return createMosaic(context, results, size) } @@ -108,7 +108,7 @@ private constructor( private val genre: Genre ) : BaseFetcher() { override suspend fun fetch(): FetchResult? { - val results = genre.albums.mapAtMost(4) { fetchArt(context, it) } + val results = genre.albums.mapAtMost(4) { fetchCover(context, it) } return createMosaic(context, results, size) } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/ActionMode.kt b/app/src/main/java/org/oxycblt/auxio/playback/ActionMode.kt index 6c9f2eb92..6bceaacb1 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/ActionMode.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/ActionMode.kt @@ -19,7 +19,7 @@ package org.oxycblt.auxio.playback import org.oxycblt.auxio.IntegerTable -/** Represents the action that should be shown on the playback bar. */ +/** Represents custom actions available in certain areas of the playback UI. */ enum class ActionMode { NEXT, REPEAT, @@ -27,18 +27,18 @@ enum class ActionMode { val intCode: Int get() = when (this) { - NEXT -> IntegerTable.BAR_ACTION_NEXT - REPEAT -> IntegerTable.BAR_ACTION_REPEAT - SHUFFLE -> IntegerTable.BAR_ACTION_SHUFFLE + NEXT -> IntegerTable.ACTION_MODE_NEXT + REPEAT -> IntegerTable.ACTION_MODE_REPEAT + SHUFFLE -> IntegerTable.ACTION_MODE_SHUFFLE } companion object { /** Convert an int [code] into an instance, or null if it isn't valid. */ fun fromIntCode(code: Int) = when (code) { - IntegerTable.BAR_ACTION_NEXT -> NEXT - IntegerTable.BAR_ACTION_REPEAT -> REPEAT - IntegerTable.BAR_ACTION_SHUFFLE -> SHUFFLE + IntegerTable.ACTION_MODE_NEXT -> NEXT + IntegerTable.ACTION_MODE_REPEAT -> REPEAT + IntegerTable.ACTION_MODE_SHUFFLE -> SHUFFLE else -> null } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt index 650bf9ab3..a5371f8fb 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/MediaSessionComponent.kt @@ -252,8 +252,7 @@ class MediaSessionComponent(private val context: Context, private val callback: override fun onSettingChanged(key: String) { when (key) { - context.getString(R.string.set_key_show_covers), - context.getString(R.string.set_key_quality_covers) -> + context.getString(R.string.set_key_cover_mode) -> updateMediaMetadata(playbackManager.song, playbackManager.parent) context.getString(R.string.set_key_notif_action) -> invalidateSecondaryAction() } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt b/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt index b546d37cc..9ec104e64 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt @@ -27,6 +27,7 @@ import androidx.preference.PreferenceManager import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.R import org.oxycblt.auxio.home.tabs.Tab +import org.oxycblt.auxio.image.CoverMode import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.storage.Directory @@ -80,6 +81,22 @@ class Settings(private val context: Context, private val callback: Callback? = n } } + if (inner.contains(OldKeys.KEY_SHOW_COVERS) || inner.contains(OldKeys.KEY_QUALITY_COVERS)) { + logD("Migrating cover settings") + + val mode = when { + !inner.getBoolean(OldKeys.KEY_SHOW_COVERS, true) -> CoverMode.OFF + !inner.getBoolean(OldKeys.KEY_QUALITY_COVERS, true) -> CoverMode.MEDIA_STORE + else -> CoverMode.QUALITY + } + + inner.edit { + putInt(context.getString(R.string.set_key_cover_mode), mode.intCode) + remove(OldKeys.KEY_SHOW_COVERS) + remove(OldKeys.KEY_QUALITY_COVERS) + } + } + if (inner.contains(OldKeys.KEY_ALT_NOTIF_ACTION)) { logD("Migrating ${OldKeys.KEY_ALT_NOTIF_ACTION}") @@ -187,13 +204,9 @@ class Settings(private val context: Context, private val callback: Callback? = n } } - /** Whether to load embedded covers */ - val showCovers: Boolean - get() = inner.getBoolean(context.getString(R.string.set_key_show_covers), true) - - /** Whether to ignore MediaStore covers */ - val useQualityCovers: Boolean - get() = inner.getBoolean(context.getString(R.string.set_key_quality_covers), false) + /** The strategy used when loading images. */ + val coverMode: CoverMode + get() = CoverMode.fromIntCode(inner.getInt(context.getString(R.string.set_key_cover_mode), Int.MIN_VALUE)) ?: CoverMode.MEDIA_STORE /** Whether to round additional UI elements (including album covers) */ val roundMode: Boolean @@ -208,8 +221,7 @@ class Settings(private val context: Context, private val callback: Callback? = n ?: ActionMode.NEXT /** - * Whether to display the RepeatMode or the shuffle status on the notification. False if repeat, - * true if shuffle. + * The custom action to display in the notification. */ val notifAction: ActionMode get() = ActionMode.fromIntCode(inner.getInt(context.getString(R.string.set_key_notif_action), Int.MIN_VALUE)) ?: ActionMode.REPEAT @@ -458,6 +470,8 @@ class Settings(private val context: Context, private val callback: Callback? = n private object OldKeys { const val KEY_ACCENT3 = "auxio_accent" const val KEY_ALT_NOTIF_ACTION = "KEY_ALT_NOTIF_ACTION" + const val KEY_SHOW_COVERS = "KEY_SHOW_COVERS" + const val KEY_QUALITY_COVERS = "KEY_QUALITY_COVERS" const val KEY_LIB_PLAYBACK_MODE = "KEY_SONG_PLAY_MODE2" const val KEY_DETAIL_PLAYBACK_MODE = "auxio_detail_song_play_mode" } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/prefs/SettingsListFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/prefs/PreferenceFragment.kt similarity index 97% rename from app/src/main/java/org/oxycblt/auxio/settings/prefs/SettingsListFragment.kt rename to app/src/main/java/org/oxycblt/auxio/settings/prefs/PreferenceFragment.kt index af4181792..06ab07128 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/prefs/SettingsListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/prefs/PreferenceFragment.kt @@ -47,7 +47,7 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat * @author OxygenCobalt */ @Suppress("UNUSED") -class SettingsListFragment : PreferenceFragmentCompat() { +class PreferenceFragment : PreferenceFragmentCompat() { private val playbackModel: PlaybackViewModel by androidActivityViewModels() private val musicModel: MusicViewModel by activityViewModels() private val navModel: NavigationViewModel by activityViewModels() @@ -171,8 +171,7 @@ class SettingsListFragment : PreferenceFragmentCompat() { true } } - context.getString(R.string.set_key_show_covers), - context.getString(R.string.set_key_quality_covers) -> { + context.getString(R.string.set_key_cover_mode) -> { preference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, _ -> Coil.imageLoader(context).memoryCache?.clear() diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt index 730ddb8c1..1a3e74481 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetComponent.kt @@ -146,8 +146,7 @@ class WidgetComponent(private val context: Context) : override fun onShuffledChanged(isShuffled: Boolean) = update() override fun onRepeatChanged(repeatMode: RepeatMode) = update() override fun onSettingChanged(key: String) { - if (key == context.getString(R.string.set_key_show_covers) || - key == context.getString(R.string.set_key_quality_covers) || + if (key == context.getString(R.string.set_key_cover_mode) || key == context.getString(R.string.set_key_round_mode) ) { update() diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 6c4ad78a1..7ce79e13d 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -26,7 +26,7 @@ auxio_accent2 auxio_lib_tabs - KEY_SHOW_COVERS - KEY_QUALITY_COVERS + auxio_cover_mode auxio_round_covers auxio_bar_action auxio_notif_action @@ -63,6 +62,18 @@ @integer/theme_dark + + @string/set_cover_mode_off + @string/set_cover_mode_media_store + @string/set_cover_mode_quality + + + + @integer/cover_mode_off + @integer/cover_mode_media_store + @integer/cover_mode_quality + + @string/set_bar_action_next @string/set_bar_action_repeat @@ -127,10 +138,6 @@ 1 2 - 0xA119 - 0xA11A - 0xA11B - -2147483648 0xA109 0xA10A @@ -139,4 +146,12 @@ 0xA111 0xA112 0xA113 + + 0xA119 + 0xA11A + 0xA11B + + 0xA11C + 0xA11D + 0xA11E \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3cc5d0bf8..fe5fa8360 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -170,10 +170,10 @@ Display Library tabs Change visibility and order of library tabs - Show album covers - Turn off to save memory usage - Ignore MediaStore covers - Increases album cover quality, but results in longer loading times and higher memory usage + Album covers + Off + Fast + High quality Round mode Enable rounded corners on additional UI elements (Requires album covers to be rounded) Custom playback bar action diff --git a/app/src/main/res/xml/prefs_main.xml b/app/src/main/res/xml/prefs_main.xml index 858569d0a..aff0caadc 100644 --- a/app/src/main/res/xml/prefs_main.xml +++ b/app/src/main/res/xml/prefs_main.xml @@ -31,18 +31,12 @@ app:summary="@string/set_lib_tabs_desc" app:title="@string/set_lib_tabs" /> - - - +