mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Add support for external player playback (#1256)
## Description Adds a new playback "backend" to play media in another app such as VLC. By default, Wholphin will use the system default app. Typically if you haven't chosen one, a dialog will show to pick which app. You can also set a specific external app to use in Wholphin independent of the system default. Currently, this only support single item playback, ie playing next up episodes is not supported yet. Also since there is no standardized way to send resume position, external subtitle info, etc, Wholphin makes a best effort. VLC, mpv-android, & MX-Player are specifically tested/supported. ### Related issues Closes #85 ### Testing Emulator & nvidia shield w/ VLC, mpv-android, & MX-player ## Screenshots <img width="543" height="407" alt="image" src="https://github.com/user-attachments/assets/ab37d41e-2909-40ed-b537-191ebb54d979" /> ## AI or LLM usage None
This commit is contained in:
parent
5050b087e1
commit
790069d818
16 changed files with 679 additions and 65 deletions
|
|
@ -30,6 +30,7 @@ import androidx.tv.material3.ExperimentalTvMaterial3Api
|
|||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.preferences.AppPreference
|
||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
||||
import com.github.damontecres.wholphin.services.AppUpgradeHandler
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.DatePlayedInvalidationService
|
||||
|
|
@ -70,6 +71,7 @@ import kotlinx.coroutines.flow.firstOrNull
|
|||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.OkHttpClient
|
||||
|
|
@ -151,12 +153,15 @@ class MainActivity : AppCompatActivity() {
|
|||
if (backStackStr != null) {
|
||||
Timber.d("Restoring back stack")
|
||||
var backStack = json.decodeFromString<List<Destination>>(backStackStr)
|
||||
val lastDest = backStack.lastOrNull()
|
||||
if (lastDest is Destination.Playback ||
|
||||
lastDest is Destination.PlaybackList ||
|
||||
lastDest is Destination.Slideshow
|
||||
) {
|
||||
backStack = backStack.toMutableList().apply { removeAt(lastIndex) }
|
||||
if (!savedInstanceState.getBoolean(KEY_EXTERNAL_PLAYER)) {
|
||||
val lastDest = backStack.lastOrNull()
|
||||
if (lastDest is Destination.Playback ||
|
||||
lastDest is Destination.PlaybackList ||
|
||||
lastDest is Destination.Slideshow
|
||||
) {
|
||||
Timber.v("Restoring back stack with playback")
|
||||
backStack = backStack.toMutableList().apply { removeAt(lastIndex) }
|
||||
}
|
||||
}
|
||||
navigationManager.backStack = NavBackStack(*backStack.toTypedArray())
|
||||
} else {
|
||||
|
|
@ -314,6 +319,9 @@ class MainActivity : AppCompatActivity() {
|
|||
Timber.d("onSaveInstanceState")
|
||||
val str = json.encodeToString(navigationManager.backStack.toList())
|
||||
outState.putString(KEY_BACK_STACK, str)
|
||||
val playerBackend =
|
||||
runBlocking { userPreferencesDataStore.data.firstOrNull() }?.playbackPreferences?.playerBackend
|
||||
outState.putBoolean(KEY_EXTERNAL_PLAYER, playerBackend == PlayerBackend.EXTERNAL_PLAYER)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
|
|
@ -390,6 +398,7 @@ class MainActivity : AppCompatActivity() {
|
|||
const val INTENT_SEASON_ID = "seaId"
|
||||
|
||||
private const val KEY_BACK_STACK = "backStack"
|
||||
private const val KEY_EXTERNAL_PLAYER = "extPlayer"
|
||||
|
||||
lateinit var instance: MainActivity
|
||||
private set
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue