diff --git a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreferencesSerializer.kt b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreferencesSerializer.kt index abcee865..c6dcd8ec 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreferencesSerializer.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/preferences/AppPreferencesSerializer.kt @@ -182,6 +182,8 @@ class AppPreferencesSerializer .apply { enabled = false videoTunnelingEnabled = false + preferAc3Surround = ExperimentalPreference.PreferAc3ForSurround.defaultValue + disableAudioOffload = ExperimentalPreference.DisableAudioOffload.defaultValue }.build() }.build() diff --git a/app/src/main/java/com/github/damontecres/wholphin/preferences/ExperimentalPreference.kt b/app/src/main/java/com/github/damontecres/wholphin/preferences/ExperimentalPreference.kt index 3950d626..e5923659 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/preferences/ExperimentalPreference.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/preferences/ExperimentalPreference.kt @@ -60,6 +60,17 @@ object ExperimentalPreference { } }, ) + + val DisableAudioOffload = + AppSwitchPreference( + title = R.string.disable_audio_offload, + defaultValue = false, + getter = { it.experimentalPreferences.disableAudioOffload }, + setter = { prefs, value -> + prefs.updateExperimentalPreferences { disableAudioOffload = value } + }, + summary = R.string.disable_audio_offload_summary, + ) } val experimentalPreferences = @@ -71,6 +82,7 @@ val experimentalPreferences = listOf( ExperimentalPreference.VideoTunneling, ExperimentalPreference.PreferAc3ForSurround, + ExperimentalPreference.DisableAudioOffload, ), ), ) diff --git a/app/src/main/java/com/github/damontecres/wholphin/services/MusicService.kt b/app/src/main/java/com/github/damontecres/wholphin/services/MusicService.kt index eea66307..38888485 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/services/MusicService.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/services/MusicService.kt @@ -13,6 +13,7 @@ import androidx.media3.session.MediaSession import com.github.damontecres.wholphin.data.ServerRepository import com.github.damontecres.wholphin.data.model.AudioItem import com.github.damontecres.wholphin.data.model.BaseItem +import com.github.damontecres.wholphin.preferences.get import com.github.damontecres.wholphin.services.hilt.DefaultCoroutineScope import com.github.damontecres.wholphin.ui.DefaultItemFields import com.github.damontecres.wholphin.ui.gt @@ -37,6 +38,7 @@ import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext @@ -83,8 +85,15 @@ class MusicService private val audioFormats by lazy { listOf(*supportedAudioCodecs) } val player: Player by lazy { + val disableAudioOffload = + runBlocking { + userPreferencesService + .getCurrent() + .appPreferences.experimentalPreferences + .get { disableAudioOffload } ?: false + } playerFactory - .createAudioPlayer() + .createAudioPlayer(disableAudioOffload = disableAudioOffload) .also { it.addListener(MusicPlayerListener(it, _state)) } diff --git a/app/src/main/java/com/github/damontecres/wholphin/services/PlayerFactory.kt b/app/src/main/java/com/github/damontecres/wholphin/services/PlayerFactory.kt index 24736015..cec0a205 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/services/PlayerFactory.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/services/PlayerFactory.kt @@ -132,9 +132,15 @@ class PlayerFactory extractorsFactory, ) } + val disableAudioOffload = + appPreferences.experimentalPreferences.get { disableAudioOffload } ?: false val tunneling = appPreferences.experimentalPreferences.get { videoTunnelingEnabled } - val trackSelector = createTrackSelector(tunneling) + val trackSelector = + createTrackSelector( + tunneling = tunneling, + disableAudioOffload = disableAudioOffload, + ) ExoPlayer .Builder(context) @@ -164,7 +170,10 @@ class PlayerFactory return PlayerCreation(newPlayer, assHandler) } - fun createAudioPlayer(extensions: MediaExtensionStatus = MediaExtensionStatus.MES_FALLBACK): ExoPlayer { + fun createAudioPlayer( + disableAudioOffload: Boolean, + extensions: MediaExtensionStatus = MediaExtensionStatus.MES_FALLBACK, + ): ExoPlayer { val rendererMode = when (extensions) { MediaExtensionStatus.MES_FALLBACK -> DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON @@ -182,7 +191,7 @@ class PlayerFactory OkHttpDataSource.Factory(authOkHttpClient), extractorsFactory, ) - val trackSelector = createTrackSelector() + val trackSelector = createTrackSelector(disableAudioOffload = disableAudioOffload) return ExoPlayer .Builder(context) .setMediaSourceFactory(mediaSourceFactory) @@ -205,20 +214,28 @@ class PlayerFactory .setConstantBitrateSeekingEnabled(true) .setConstantBitrateSeekingAlwaysEnabled(true) - private fun createTrackSelector(tunneling: Boolean? = null) = - DefaultTrackSelector(context).apply { - setParameters( - buildUponParameters() - .apply { - tunneling?.let { setTunnelingEnabled(tunneling) } - }.setAudioOffloadPreferences( - AudioOffloadPreferences - .Builder() - .setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED) - .build(), - ), - ) - } + private fun createTrackSelector( + tunneling: Boolean? = null, + disableAudioOffload: Boolean = false, + ) = DefaultTrackSelector(context).apply { + val offloadMode = + if (disableAudioOffload) { + AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_DISABLED + } else { + AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED + } + setParameters( + buildUponParameters() + .apply { + tunneling?.let { setTunnelingEnabled(tunneling) } + }.setAudioOffloadPreferences( + AudioOffloadPreferences + .Builder() + .setAudioOffloadMode(offloadMode) + .build(), + ), + ) + } fun createMediaSession(player: Player) = MediaSession diff --git a/app/src/main/proto/WholphinDataStore.proto b/app/src/main/proto/WholphinDataStore.proto index 2db6201b..f190b43b 100644 --- a/app/src/main/proto/WholphinDataStore.proto +++ b/app/src/main/proto/WholphinDataStore.proto @@ -225,6 +225,7 @@ message ExperimentalPreferences { bool enabled = 1; bool video_tunneling_enabled = 2; bool prefer_ac3_surround = 3; + bool disable_audio_offload = 4; } message AppPreferences { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bf37ea15..3b1bd402 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -404,6 +404,8 @@ Will remove PIN [0–9] Image disk cache size (MB) + Disable audio hardware offload + Disabling offloading audio decoding may fix playback freezes on some devices View options Columns Spacing