Add song cache settings

This commit is contained in:
vfsfitvnm
2022-06-12 14:40:41 +02:00
parent 05afb475d4
commit 625fbb0247
5 changed files with 87 additions and 24 deletions

View File

@@ -42,6 +42,7 @@ import it.vfsfitvnm.vimusic.ui.components.rememberBottomSheetState
import it.vfsfitvnm.vimusic.ui.components.rememberMenuState import it.vfsfitvnm.vimusic.ui.components.rememberMenuState
import it.vfsfitvnm.vimusic.ui.screens.HomeScreen import it.vfsfitvnm.vimusic.ui.screens.HomeScreen
import it.vfsfitvnm.vimusic.ui.screens.IntentUriScreen import it.vfsfitvnm.vimusic.ui.screens.IntentUriScreen
import it.vfsfitvnm.vimusic.ui.screens.settings.OtherScreen
import it.vfsfitvnm.vimusic.ui.styling.* import it.vfsfitvnm.vimusic.ui.styling.*
import it.vfsfitvnm.vimusic.ui.views.PlayerView import it.vfsfitvnm.vimusic.ui.views.PlayerView
import it.vfsfitvnm.vimusic.utils.* import it.vfsfitvnm.vimusic.utils.*

View File

@@ -1,7 +1,6 @@
package it.vfsfitvnm.vimusic package it.vfsfitvnm.vimusic
import android.app.Application import android.app.Application
import android.content.Context
import coil.ImageLoader import coil.ImageLoader
import coil.ImageLoaderFactory import coil.ImageLoaderFactory
import coil.disk.DiskCache import coil.disk.DiskCache
@@ -15,18 +14,14 @@ class MainApplication : Application(), ImageLoaderFactory {
} }
override fun newImageLoader(): ImageLoader { override fun newImageLoader(): ImageLoader {
return defaultCoilImageLoader(preferences.coilDiskCacheMaxSizeBytes) return ImageLoader.Builder(this)
.crossfade(true)
.diskCache(
DiskCache.Builder()
.directory(filesDir.resolve("coil"))
.maxSizeBytes(preferences.coilDiskCacheMaxSizeBytes)
.build()
)
.build()
} }
} }
fun Context.defaultCoilImageLoader(diskCacheMaxSize: Long): ImageLoader {
return ImageLoader.Builder(this)
.crossfade(true)
.diskCache(
DiskCache.Builder()
.directory(filesDir.resolve("coil"))
.maxSizeBytes(diskCacheMaxSize)
.build()
)
.build()
}

View File

@@ -18,6 +18,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.IconCompat import androidx.core.graphics.drawable.IconCompat
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.os.bundleOf
import androidx.media3.common.* import androidx.media3.common.*
import androidx.media3.common.util.Util import androidx.media3.common.util.Util
import androidx.media3.database.StandaloneDatabaseProvider import androidx.media3.database.StandaloneDatabaseProvider
@@ -25,7 +26,7 @@ import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DefaultHttpDataSource import androidx.media3.datasource.DefaultHttpDataSource
import androidx.media3.datasource.ResolvingDataSource import androidx.media3.datasource.ResolvingDataSource
import androidx.media3.datasource.cache.CacheDataSource import androidx.media3.datasource.cache.CacheDataSource
import androidx.media3.datasource.cache.NoOpCacheEvictor import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
import androidx.media3.datasource.cache.SimpleCache import androidx.media3.datasource.cache.SimpleCache
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.analytics.AnalyticsListener import androidx.media3.exoplayer.analytics.AnalyticsListener
@@ -36,11 +37,10 @@ import androidx.media3.session.*
import androidx.media3.session.MediaNotification.ActionFactory import androidx.media3.session.MediaNotification.ActionFactory
import coil.ImageLoader import coil.ImageLoader
import coil.request.ImageRequest import coil.request.ImageRequest
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import it.vfsfitvnm.vimusic.Database import it.vfsfitvnm.vimusic.*
import it.vfsfitvnm.vimusic.MainActivity
import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.internal
import it.vfsfitvnm.vimusic.models.QueuedMediaItem import it.vfsfitvnm.vimusic.models.QueuedMediaItem
import it.vfsfitvnm.vimusic.utils.* import it.vfsfitvnm.vimusic.utils.*
import it.vfsfitvnm.youtubemusic.Outcome import it.vfsfitvnm.youtubemusic.Outcome
@@ -52,6 +52,8 @@ val StartRadioCommand = SessionCommand("StartRadioCommand", Bundle.EMPTY)
val StartArtistRadioCommand = SessionCommand("StartArtistRadioCommand", Bundle.EMPTY) val StartArtistRadioCommand = SessionCommand("StartArtistRadioCommand", Bundle.EMPTY)
val StopRadioCommand = SessionCommand("StopRadioCommand", Bundle.EMPTY) val StopRadioCommand = SessionCommand("StopRadioCommand", Bundle.EMPTY)
val GetCacheSizeCommand = SessionCommand("GetCacheSizeCommand", Bundle.EMPTY)
@ExperimentalAnimationApi @ExperimentalAnimationApi
@ExperimentalFoundationApi @ExperimentalFoundationApi
class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller, class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
@@ -83,7 +85,8 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
createNotificationChannel() createNotificationChannel()
setMediaNotificationProvider(this) setMediaNotificationProvider(this)
cache = SimpleCache(cacheDir, NoOpCacheEvictor(), StandaloneDatabaseProvider(this)) val cacheEvictor = LeastRecentlyUsedCacheEvictor(preferences.exoPlayerDiskCacheMaxSizeBytes)
cache = SimpleCache(cacheDir, cacheEvictor, StandaloneDatabaseProvider(this))
val player = ExoPlayer.Builder(this) val player = ExoPlayer.Builder(this)
.setHandleAudioBecomingNoisy(true) .setHandleAudioBecomingNoisy(true)
@@ -176,6 +179,7 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
.add(StartRadioCommand) .add(StartRadioCommand)
.add(StartArtistRadioCommand) .add(StartArtistRadioCommand)
.add(StopRadioCommand) .add(StopRadioCommand)
.add(GetCacheSizeCommand)
.build() .build()
val playerCommands = Player.Commands.Builder().addAllCommands().build() val playerCommands = Player.Commands.Builder().addAllCommands().build()
return MediaSession.ConnectionResult.accept(sessionCommands, playerCommands) return MediaSession.ConnectionResult.accept(sessionCommands, playerCommands)
@@ -206,6 +210,9 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
} }
} }
StopRadioCommand -> radio = null StopRadioCommand -> radio = null
GetCacheSizeCommand -> {
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS, bundleOf("cacheSize" to cache.cacheSpace)))
}
} }
return super.onCustomCommand(session, controller, customCommand, args) return super.onCustomCommand(session, controller, customCommand, args)

View File

@@ -1,5 +1,6 @@
package it.vfsfitvnm.vimusic.ui.screens.settings package it.vfsfitvnm.vimusic.ui.screens.settings
import android.os.Bundle
import android.text.format.Formatter import android.text.format.Formatter
import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.* import androidx.compose.foundation.*
@@ -16,15 +17,18 @@ import coil.Coil
import coil.annotation.ExperimentalCoilApi import coil.annotation.ExperimentalCoilApi
import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.services.GetCacheSizeCommand
import it.vfsfitvnm.vimusic.ui.components.SeekBar import it.vfsfitvnm.vimusic.ui.components.SeekBar
import it.vfsfitvnm.vimusic.ui.components.TopAppBar import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.screens.* import it.vfsfitvnm.vimusic.ui.screens.*
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
import it.vfsfitvnm.vimusic.ui.styling.LocalTypography import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
import it.vfsfitvnm.vimusic.utils.LocalPreferences import it.vfsfitvnm.vimusic.utils.LocalPreferences
import it.vfsfitvnm.vimusic.utils.LocalYoutubePlayer
import it.vfsfitvnm.vimusic.utils.secondary import it.vfsfitvnm.vimusic.utils.secondary
import it.vfsfitvnm.vimusic.utils.semiBold import it.vfsfitvnm.vimusic.utils.semiBold
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.guava.await
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@OptIn(ExperimentalCoilApi::class) @OptIn(ExperimentalCoilApi::class)
@@ -54,10 +58,9 @@ fun OtherScreen() {
val colorPalette = LocalColorPalette.current val colorPalette = LocalColorPalette.current
val typography = LocalTypography.current val typography = LocalTypography.current
val preferences = LocalPreferences.current val preferences = LocalPreferences.current
val mediaController = LocalYoutubePlayer.current?.mediaController
var coilDiskCache by remember { val coilDiskCache = Coil.imageLoader(context).diskCache
mutableStateOf(Coil.imageLoader(context).diskCache)
}
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
@@ -94,7 +97,6 @@ fun OtherScreen() {
) )
} }
coilDiskCache?.let { diskCache -> coilDiskCache?.let { diskCache ->
var diskCacheSize by remember(diskCache) { var diskCacheSize by remember(diskCache) {
mutableStateOf(diskCache.size) mutableStateOf(diskCache.size)
@@ -133,7 +135,6 @@ fun OtherScreen() {
}, },
onDrag = { delta -> onDrag = { delta ->
scrubbingDiskCacheMaxSize = scrubbingDiskCacheMaxSize?.plus(delta)?.coerceIn(250L * 1024 * 1024, 2048L * 1024 * 1024) scrubbingDiskCacheMaxSize = scrubbingDiskCacheMaxSize?.plus(delta)?.coerceIn(250L * 1024 * 1024, 2048L * 1024 * 1024)
println("new = $scrubbingDiskCacheMaxSize")
}, },
onDragEnd = { onDragEnd = {
preferences.coilDiskCacheMaxSizeBytes = scrubbingDiskCacheMaxSize ?: preferences.coilDiskCacheMaxSizeBytes preferences.coilDiskCacheMaxSizeBytes = scrubbingDiskCacheMaxSize ?: preferences.coilDiskCacheMaxSizeBytes
@@ -164,6 +165,64 @@ fun OtherScreen() {
} }
) )
} }
mediaController?.let { mediaController ->
val diskCacheSize by produceState(initialValue = 0L) {
value = mediaController.sendCustomCommand(GetCacheSizeCommand, Bundle.EMPTY).await().extras.getLong("cacheSize")
}
var scrubbingDiskCacheMaxSize by remember {
mutableStateOf<Long?>(null)
}
SettingsEntryGroupText(
title = "SONG CACHE",
)
Column(
modifier = Modifier
.padding(start = 24.dp)
.padding(horizontal = 32.dp, vertical = 16.dp)
.fillMaxWidth()
) {
BasicText(
text = "Max size",
style = typography.xs.semiBold,
)
BasicText(
text = Formatter.formatShortFileSize(context, scrubbingDiskCacheMaxSize ?: preferences.exoPlayerDiskCacheMaxSizeBytes),
style = typography.xs.semiBold.secondary
)
SeekBar(
value = (scrubbingDiskCacheMaxSize ?: preferences.exoPlayerDiskCacheMaxSizeBytes).coerceIn(250L * 1024 * 1024, 4096L * 1024 * 1024),
minimumValue = 250L * 1024 * 1024,
maximumValue = 4096L * 1024 * 1024,
onDragStart = {
scrubbingDiskCacheMaxSize = it
},
onDrag = { delta ->
scrubbingDiskCacheMaxSize = scrubbingDiskCacheMaxSize?.plus(delta)?.coerceIn(250L * 1024 * 1024, 4096L * 1024 * 1024)
},
onDragEnd = {
preferences.exoPlayerDiskCacheMaxSizeBytes = scrubbingDiskCacheMaxSize ?: preferences.exoPlayerDiskCacheMaxSizeBytes
scrubbingDiskCacheMaxSize = null
},
color = colorPalette.text,
backgroundColor = colorPalette.textDisabled,
shape = RoundedCornerShape(8.dp),
modifier = Modifier
.padding(top = 8.dp)
.fillMaxWidth()
)
}
DisabledSettingsEntry(
title = "Space used",
text = "${Formatter.formatShortFileSize(context, diskCacheSize)} (${diskCacheSize * 100 / preferences.exoPlayerDiskCacheMaxSizeBytes.coerceAtLeast(1)}%)",
)
}
} }
} }
} }

View File

@@ -23,6 +23,7 @@ class Preferences(holder: SharedPreferences) : SharedPreferences by holder {
var homePageSongCollection by preference("homePageSongCollection", SongCollection.MostPlayed) var homePageSongCollection by preference("homePageSongCollection", SongCollection.MostPlayed)
var thumbnailRoundness by preference("thumbnailRoundness", ThumbnailRoundness.Light) var thumbnailRoundness by preference("thumbnailRoundness", ThumbnailRoundness.Light)
var coilDiskCacheMaxSizeBytes by preference("coilDiskCacheMaxSizeBytes", 512L * 1024 * 1024) var coilDiskCacheMaxSizeBytes by preference("coilDiskCacheMaxSizeBytes", 512L * 1024 * 1024)
var exoPlayerDiskCacheMaxSizeBytes by preference("exoPlayerDiskCacheMaxSizeBytes", 512L * 1024 * 1024)
var displayLikeButtonInNotification by preference("displayLikeButtonInNotification", false) var displayLikeButtonInNotification by preference("displayLikeButtonInNotification", false)
var persistentQueue by preference("persistentQueue", false) var persistentQueue by preference("persistentQueue", false)
} }