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
|
|
@ -2,7 +2,6 @@ package com.github.damontecres.wholphin.services
|
|||
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import dagger.hilt.android.scopes.ActivityRetainedScoped
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -20,13 +19,14 @@ class PlaybackLifecycleObserver
|
|||
private var wasPlaying: Boolean? = null
|
||||
|
||||
override fun onStart(owner: LifecycleOwner) {
|
||||
val lastDest = navigationManager.backStack.lastOrNull()
|
||||
if (lastDest is Destination.Playback ||
|
||||
lastDest is Destination.PlaybackList ||
|
||||
lastDest is Destination.Slideshow
|
||||
) {
|
||||
navigationManager.goBack()
|
||||
}
|
||||
// TODO
|
||||
// val lastDest = navigationManager.backStack.lastOrNull()
|
||||
// if (lastDest is Destination.Playback ||
|
||||
// lastDest is Destination.PlaybackList ||
|
||||
// lastDest is Destination.Slideshow
|
||||
// ) {
|
||||
// navigationManager.goBack()
|
||||
// }
|
||||
wasPlaying = null
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import androidx.annotation.OptIn
|
|||
import androidx.datastore.core.DataStore
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.ExperimentalApi
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.datasource.DefaultDataSource
|
||||
import androidx.media3.exoplayer.DefaultRenderersFactory
|
||||
|
|
@ -126,6 +127,10 @@ class PlayerFactory
|
|||
assHandler?.init(this)
|
||||
}
|
||||
}
|
||||
|
||||
PlayerBackend.EXTERNAL_PLAYER -> {
|
||||
throw IllegalArgumentException("Cannot create a player for external playback")
|
||||
}
|
||||
}
|
||||
currentPlayer = newPlayer
|
||||
return PlayerCreation(newPlayer, assHandler)
|
||||
|
|
@ -151,6 +156,7 @@ class WholphinRenderersFactory(
|
|||
context: Context,
|
||||
private val av1Enabled: Boolean,
|
||||
) : DefaultRenderersFactory(context) {
|
||||
@OptIn(ExperimentalApi::class)
|
||||
override fun buildVideoRenderers(
|
||||
context: Context,
|
||||
extensionRendererMode: Int,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue