mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-09 16:11:20 +02:00
WIP
This commit is contained in:
parent
77c787b51f
commit
1ee834d42b
37 changed files with 2322 additions and 18 deletions
|
|
@ -236,7 +236,7 @@ fun PlaybackPage(
|
|||
surfaceType = SURFACE_TYPE_SURFACE_VIEW,
|
||||
modifier = scaledModifier,
|
||||
)
|
||||
if (presentationState.coverSurface) {
|
||||
if (false && presentationState.coverSurface) {
|
||||
Box(
|
||||
Modifier
|
||||
.matchParentSize()
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import androidx.media3.common.TrackSelectionOverride
|
|||
import androidx.media3.common.Tracks
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.DefaultRenderersFactory
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.ItemPlaybackDao
|
||||
import com.github.damontecres.wholphin.data.ItemPlaybackRepository
|
||||
|
|
@ -53,6 +52,7 @@ import com.github.damontecres.wholphin.util.TrackActivityPlaybackListener
|
|||
import com.github.damontecres.wholphin.util.TrackSupport
|
||||
import com.github.damontecres.wholphin.util.checkForSupport
|
||||
import com.github.damontecres.wholphin.util.formatDateTime
|
||||
import com.github.damontecres.wholphin.util.mpv.MpvPlayer
|
||||
import com.github.damontecres.wholphin.util.seasonEpisodePadded
|
||||
import com.github.damontecres.wholphin.util.subtitleMimeTypes
|
||||
import com.github.damontecres.wholphin.util.supportItemKinds
|
||||
|
|
@ -131,13 +131,14 @@ class PlaybackViewModel
|
|||
MediaExtensionStatus.MES_DISABLED -> DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF
|
||||
else -> DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON
|
||||
}
|
||||
ExoPlayer
|
||||
.Builder(context)
|
||||
.setRenderersFactory(
|
||||
DefaultRenderersFactory(context)
|
||||
.setEnableDecoderFallback(true)
|
||||
.setExtensionRendererMode(rendererMode),
|
||||
).build()
|
||||
// ExoPlayer
|
||||
// .Builder(context)
|
||||
// .setRenderersFactory(
|
||||
// DefaultRenderersFactory(context)
|
||||
// .setEnableDecoderFallback(true)
|
||||
// .setExtensionRendererMode(rendererMode),
|
||||
// ).build()
|
||||
MpvPlayer(context)
|
||||
.apply {
|
||||
playWhenReady = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,264 @@
|
|||
package com.github.damontecres.wholphin.util.mpv
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.view.Surface
|
||||
|
||||
// Wrapper for native library
|
||||
|
||||
@Suppress("unused")
|
||||
object MPVLib {
|
||||
init {
|
||||
val libs = arrayOf("mpv", "player")
|
||||
for (lib in libs) {
|
||||
System.loadLibrary(lib)
|
||||
}
|
||||
}
|
||||
|
||||
external fun create(appctx: Context)
|
||||
|
||||
external fun init()
|
||||
|
||||
external fun destroy()
|
||||
|
||||
external fun attachSurface(surface: Surface)
|
||||
|
||||
external fun detachSurface()
|
||||
|
||||
external fun command(cmd: Array<out String>)
|
||||
|
||||
external fun setOptionString(
|
||||
name: String,
|
||||
value: String,
|
||||
): Int
|
||||
|
||||
external fun grabThumbnail(dimension: Int): Bitmap?
|
||||
|
||||
external fun getPropertyInt(property: String): Int?
|
||||
|
||||
external fun setPropertyInt(
|
||||
property: String,
|
||||
value: Int,
|
||||
)
|
||||
|
||||
external fun getPropertyDouble(property: String): Double?
|
||||
|
||||
external fun setPropertyDouble(
|
||||
property: String,
|
||||
value: Double,
|
||||
)
|
||||
|
||||
external fun getPropertyBoolean(property: String): Boolean?
|
||||
|
||||
external fun setPropertyBoolean(
|
||||
property: String,
|
||||
value: Boolean,
|
||||
)
|
||||
|
||||
external fun getPropertyString(property: String): String?
|
||||
|
||||
external fun setPropertyString(
|
||||
property: String,
|
||||
value: String,
|
||||
)
|
||||
|
||||
external fun observeProperty(
|
||||
property: String,
|
||||
format: Int,
|
||||
)
|
||||
|
||||
private val observers = mutableListOf<EventObserver>()
|
||||
|
||||
@JvmStatic
|
||||
fun addObserver(o: EventObserver) {
|
||||
synchronized(observers) {
|
||||
observers.add(o)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun removeObserver(o: EventObserver) {
|
||||
synchronized(observers) {
|
||||
observers.remove(o)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun eventProperty(
|
||||
property: String,
|
||||
value: Long,
|
||||
) {
|
||||
synchronized(observers) {
|
||||
for (o in observers) {
|
||||
o.eventProperty(property, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun eventProperty(
|
||||
property: String,
|
||||
value: Boolean,
|
||||
) {
|
||||
synchronized(observers) {
|
||||
for (o in observers) {
|
||||
o.eventProperty(property, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun eventProperty(
|
||||
property: String,
|
||||
value: Double,
|
||||
) {
|
||||
synchronized(observers) {
|
||||
for (o in observers) {
|
||||
o.eventProperty(property, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun eventProperty(
|
||||
property: String,
|
||||
value: String,
|
||||
) {
|
||||
synchronized(observers) {
|
||||
for (o in observers) {
|
||||
o.eventProperty(property, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun eventProperty(property: String) {
|
||||
synchronized(observers) {
|
||||
for (o in observers) {
|
||||
o.eventProperty(property)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun event(eventId: Int) {
|
||||
synchronized(observers) {
|
||||
for (o in observers) {
|
||||
o.event(eventId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val log_observers = mutableListOf<LogObserver>()
|
||||
|
||||
@JvmStatic
|
||||
fun addLogObserver(o: LogObserver) {
|
||||
synchronized(log_observers) {
|
||||
log_observers.add(o)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun removeLogObserver(o: LogObserver) {
|
||||
synchronized(log_observers) {
|
||||
log_observers.remove(o)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logMessage(
|
||||
prefix: String,
|
||||
level: Int,
|
||||
text: String,
|
||||
) {
|
||||
synchronized(log_observers) {
|
||||
for (o in log_observers) {
|
||||
o.logMessage(prefix, level, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface EventObserver {
|
||||
fun eventProperty(property: String)
|
||||
|
||||
fun eventProperty(
|
||||
property: String,
|
||||
value: Long,
|
||||
)
|
||||
|
||||
fun eventProperty(
|
||||
property: String,
|
||||
value: Boolean,
|
||||
)
|
||||
|
||||
fun eventProperty(
|
||||
property: String,
|
||||
value: String,
|
||||
)
|
||||
|
||||
fun eventProperty(
|
||||
property: String,
|
||||
value: Double,
|
||||
)
|
||||
|
||||
fun event(eventId: Int)
|
||||
}
|
||||
|
||||
interface LogObserver {
|
||||
fun logMessage(
|
||||
prefix: String,
|
||||
level: Int,
|
||||
text: String,
|
||||
)
|
||||
}
|
||||
|
||||
object MpvFormat {
|
||||
const val MPV_FORMAT_NONE: Int = 0
|
||||
const val MPV_FORMAT_STRING: Int = 1
|
||||
const val MPV_FORMAT_OSD_STRING: Int = 2
|
||||
const val MPV_FORMAT_FLAG: Int = 3
|
||||
const val MPV_FORMAT_INT64: Int = 4
|
||||
const val MPV_FORMAT_DOUBLE: Int = 5
|
||||
const val MPV_FORMAT_NODE: Int = 6
|
||||
const val MPV_FORMAT_NODE_ARRAY: Int = 7
|
||||
const val MPV_FORMAT_NODE_MAP: Int = 8
|
||||
const val MPV_FORMAT_BYTE_ARRAY: Int = 9
|
||||
}
|
||||
|
||||
object MpvEvent {
|
||||
const val MPV_EVENT_NONE: Int = 0
|
||||
const val MPV_EVENT_SHUTDOWN: Int = 1
|
||||
const val MPV_EVENT_LOG_MESSAGE: Int = 2
|
||||
const val MPV_EVENT_GET_PROPERTY_REPLY: Int = 3
|
||||
const val MPV_EVENT_SET_PROPERTY_REPLY: Int = 4
|
||||
const val MPV_EVENT_COMMAND_REPLY: Int = 5
|
||||
const val MPV_EVENT_START_FILE: Int = 6
|
||||
const val MPV_EVENT_END_FILE: Int = 7
|
||||
const val MPV_EVENT_FILE_LOADED: Int = 8
|
||||
|
||||
@Deprecated("")
|
||||
const val MPV_EVENT_IDLE: Int = 11
|
||||
|
||||
@Deprecated("")
|
||||
const val MPV_EVENT_TICK: Int = 14
|
||||
const val MPV_EVENT_CLIENT_MESSAGE: Int = 16
|
||||
const val MPV_EVENT_VIDEO_RECONFIG: Int = 17
|
||||
const val MPV_EVENT_AUDIO_RECONFIG: Int = 18
|
||||
const val MPV_EVENT_SEEK: Int = 20
|
||||
const val MPV_EVENT_PLAYBACK_RESTART: Int = 21
|
||||
const val MPV_EVENT_PROPERTY_CHANGE: Int = 22
|
||||
const val MPV_EVENT_QUEUE_OVERFLOW: Int = 24
|
||||
const val MPV_EVENT_HOOK: Int = 25
|
||||
}
|
||||
|
||||
object MpvLogLevel {
|
||||
const val MPV_LOG_LEVEL_NONE: Int = 0
|
||||
const val MPV_LOG_LEVEL_FATAL: Int = 10
|
||||
const val MPV_LOG_LEVEL_ERROR: Int = 20
|
||||
const val MPV_LOG_LEVEL_WARN: Int = 30
|
||||
const val MPV_LOG_LEVEL_INFO: Int = 40
|
||||
const val MPV_LOG_LEVEL_V: Int = 50
|
||||
const val MPV_LOG_LEVEL_DEBUG: Int = 60
|
||||
const val MPV_LOG_LEVEL_TRACE: Int = 70
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
package com.github.damontecres.wholphin.util.mpv
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Looper
|
||||
import android.view.Surface
|
||||
import android.view.SurfaceHolder
|
||||
import android.view.SurfaceView
|
||||
import android.view.TextureView
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.media3.common.AudioAttributes
|
||||
import androidx.media3.common.BasePlayer
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.DeviceInfo
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MediaMetadata
|
||||
import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.PlaybackParameters
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.Timeline
|
||||
import androidx.media3.common.TrackSelectionParameters
|
||||
import androidx.media3.common.Tracks
|
||||
import androidx.media3.common.VideoSize
|
||||
import androidx.media3.common.text.CueGroup
|
||||
import androidx.media3.common.util.Size
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.common.util.Util
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
class MpvPlayer(
|
||||
private val context: Context,
|
||||
) : BasePlayer() {
|
||||
private var surface: Surface? = null
|
||||
private val listeners = mutableListOf<Player.Listener>()
|
||||
private val looper = Util.getCurrentOrMainLooper()
|
||||
private val availableCommands: Player.Commands
|
||||
private lateinit var surfaceSize: Size
|
||||
|
||||
private var mediaItem: MediaItem? = null
|
||||
|
||||
init {
|
||||
MPVLib.create(context)
|
||||
MPVLib.init()
|
||||
MPVLib.setOptionString("hwdec", "mediacodec,mediacodec-copy")
|
||||
MPVLib.setOptionString("gpu-context", "android")
|
||||
MPVLib.setOptionString("opengl-es", "yes")
|
||||
MPVLib.setOptionString("hwdec-codecs", "h264,hevc,mpeg4,mpeg2video,vp8,vp9,av1")
|
||||
val cacheMegs = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) 64 else 32
|
||||
MPVLib.setOptionString("demuxer-max-bytes", "${cacheMegs * 1024 * 1024}")
|
||||
MPVLib.setOptionString("demuxer-max-back-bytes", "${cacheMegs * 1024 * 1024}")
|
||||
|
||||
MPVLib.setOptionString("force-window", "no")
|
||||
// need to idle at least once for playFile() logic to work
|
||||
MPVLib.setOptionString("idle", "once")
|
||||
|
||||
availableCommands =
|
||||
Player.Commands
|
||||
.Builder()
|
||||
.addAll(
|
||||
COMMAND_PLAY_PAUSE,
|
||||
COMMAND_PREPARE,
|
||||
COMMAND_STOP,
|
||||
COMMAND_SET_SPEED_AND_PITCH,
|
||||
COMMAND_SET_SHUFFLE_MODE,
|
||||
COMMAND_SET_REPEAT_MODE,
|
||||
COMMAND_GET_CURRENT_MEDIA_ITEM,
|
||||
COMMAND_GET_TIMELINE,
|
||||
COMMAND_GET_METADATA,
|
||||
// COMMAND_SET_PLAYLIST_METADATA,
|
||||
COMMAND_SET_MEDIA_ITEM,
|
||||
// COMMAND_CHANGE_MEDIA_ITEMS,
|
||||
COMMAND_GET_TRACKS,
|
||||
// COMMAND_GET_AUDIO_ATTRIBUTES,
|
||||
// COMMAND_SET_AUDIO_ATTRIBUTES,
|
||||
// COMMAND_GET_VOLUME,
|
||||
// COMMAND_SET_VOLUME,
|
||||
COMMAND_SET_VIDEO_SURFACE,
|
||||
// COMMAND_GET_TEXT,
|
||||
COMMAND_RELEASE,
|
||||
).build()
|
||||
}
|
||||
|
||||
override fun getApplicationLooper(): Looper = looper
|
||||
|
||||
override fun addListener(listener: Player.Listener) {
|
||||
listeners.add(listener)
|
||||
}
|
||||
|
||||
override fun removeListener(listener: Player.Listener) {
|
||||
listeners.remove(listener)
|
||||
}
|
||||
|
||||
override fun setMediaItems(
|
||||
mediaItems: List<MediaItem>,
|
||||
resetPosition: Boolean,
|
||||
) {
|
||||
mediaItems.firstOrNull()?.let {
|
||||
mediaItem = it
|
||||
}
|
||||
}
|
||||
|
||||
override fun setMediaItems(
|
||||
mediaItems: List<MediaItem>,
|
||||
startIndex: Int,
|
||||
startPositionMs: Long,
|
||||
) {
|
||||
setMediaItems(mediaItems.subList(startIndex, mediaItems.size), false)
|
||||
seekTo(startPositionMs)
|
||||
}
|
||||
|
||||
override fun addMediaItems(
|
||||
index: Int,
|
||||
mediaItems: List<MediaItem>,
|
||||
): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun moveMediaItems(
|
||||
fromIndex: Int,
|
||||
toIndex: Int,
|
||||
newIndex: Int,
|
||||
): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun replaceMediaItems(
|
||||
fromIndex: Int,
|
||||
toIndex: Int,
|
||||
mediaItems: List<MediaItem>,
|
||||
): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun removeMediaItems(
|
||||
fromIndex: Int,
|
||||
toIndex: Int,
|
||||
): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun getAvailableCommands(): Player.Commands = availableCommands
|
||||
|
||||
override fun prepare() {
|
||||
}
|
||||
|
||||
override fun getPlaybackState(): Int {
|
||||
val state = STATE_READY
|
||||
return state
|
||||
}
|
||||
|
||||
override fun getPlaybackSuppressionReason(): Int = Player.PLAYBACK_SUPPRESSION_REASON_NONE
|
||||
|
||||
override fun getPlayerError(): PlaybackException? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun setPlayWhenReady(playWhenReady: Boolean) {
|
||||
if (playWhenReady) {
|
||||
} else {
|
||||
MPVLib.setPropertyBoolean("pause", true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPlayWhenReady(): Boolean {
|
||||
val isPaused = MPVLib.getPropertyBoolean("pause")!!
|
||||
return !isPaused
|
||||
}
|
||||
|
||||
override fun setRepeatMode(repeatMode: Int) {
|
||||
}
|
||||
|
||||
override fun getRepeatMode(): Int = Player.REPEAT_MODE_OFF
|
||||
|
||||
override fun setShuffleModeEnabled(shuffleModeEnabled: Boolean) {
|
||||
}
|
||||
|
||||
override fun getShuffleModeEnabled(): Boolean = false
|
||||
|
||||
override fun isLoading(): Boolean = false
|
||||
|
||||
override fun getSeekBackIncrement(): Long = 10_000
|
||||
|
||||
override fun getSeekForwardIncrement(): Long = 30_000
|
||||
|
||||
override fun getMaxSeekToPreviousPosition(): Long = 10_000
|
||||
|
||||
override fun setPlaybackParameters(playbackParameters: PlaybackParameters) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
override fun getPlaybackParameters(): PlaybackParameters {
|
||||
// TODO
|
||||
return PlaybackParameters.DEFAULT
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
pause()
|
||||
// MPVLib.setPropertyString("vo", "gpu")
|
||||
}
|
||||
|
||||
override fun release() {
|
||||
MPVLib.destroy()
|
||||
}
|
||||
|
||||
override fun getCurrentTracks(): Tracks {
|
||||
// TODO
|
||||
return Tracks.EMPTY
|
||||
}
|
||||
|
||||
override fun getTrackSelectionParameters(): TrackSelectionParameters {
|
||||
// TODO
|
||||
return TrackSelectionParameters.Builder().build()
|
||||
}
|
||||
|
||||
override fun setTrackSelectionParameters(parameters: TrackSelectionParameters) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
override fun getMediaMetadata(): MediaMetadata = mediaItem!!.mediaMetadata
|
||||
|
||||
override fun getPlaylistMetadata(): MediaMetadata = MediaMetadata.EMPTY
|
||||
|
||||
override fun setPlaylistMetadata(mediaMetadata: MediaMetadata): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun getCurrentTimeline(): Timeline {
|
||||
// TODO
|
||||
return Timeline.EMPTY
|
||||
}
|
||||
|
||||
override fun getCurrentPeriodIndex(): Int {
|
||||
// TODO
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun getCurrentMediaItemIndex(): Int = 0
|
||||
|
||||
override fun getDuration(): Long {
|
||||
val duration = MPVLib.getPropertyDouble("duration")!!.milliseconds.inWholeMilliseconds
|
||||
return duration
|
||||
}
|
||||
|
||||
override fun getCurrentPosition(): Long {
|
||||
val position = MPVLib.getPropertyDouble("time-pos/full")?.milliseconds?.inWholeMilliseconds ?: 0
|
||||
return position
|
||||
}
|
||||
|
||||
override fun getBufferedPosition(): Long {
|
||||
// TODO
|
||||
return currentPosition
|
||||
}
|
||||
|
||||
override fun getTotalBufferedDuration(): Long = bufferedPosition
|
||||
|
||||
override fun isPlayingAd(): Boolean = false
|
||||
|
||||
override fun getCurrentAdGroupIndex(): Int = C.INDEX_UNSET
|
||||
|
||||
override fun getCurrentAdIndexInAdGroup(): Int = C.INDEX_UNSET
|
||||
|
||||
override fun getContentPosition(): Long = currentPosition
|
||||
|
||||
override fun getContentBufferedPosition(): Long = bufferedPosition
|
||||
|
||||
override fun getAudioAttributes(): AudioAttributes {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun setVolume(volume: Float) {
|
||||
}
|
||||
|
||||
override fun getVolume(): Float = 1f
|
||||
|
||||
override fun clearVideoSurface(): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun clearVideoSurface(surface: Surface?): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun setVideoSurface(surface: Surface?): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun setVideoSurfaceHolder(surfaceHolder: SurfaceHolder?): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun clearVideoSurfaceHolder(surfaceHolder: SurfaceHolder?): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun setVideoSurfaceView(surfaceView: SurfaceView?) {
|
||||
val surface = surfaceView?.holder?.surface
|
||||
val newSurfaceSize = if (surface == null) 0 else C.LENGTH_UNSET
|
||||
this.surfaceSize = if (surface == null) Size(0, 0) else Size.UNKNOWN
|
||||
if (surface != null) {
|
||||
this.surface = surface
|
||||
MPVLib.attachSurface(surface)
|
||||
MPVLib.setOptionString("force-window", "yes")
|
||||
|
||||
val url = mediaItem!!.localConfiguration?.uri.toString()
|
||||
MPVLib.command(arrayOf("loadfile", url))
|
||||
} else {
|
||||
clearVideoSurfaceView(null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearVideoSurfaceView(surfaceView: SurfaceView?) {
|
||||
MPVLib.detachSurface()
|
||||
MPVLib.setPropertyString("vo", "null")
|
||||
MPVLib.setPropertyString("force-window", "no")
|
||||
mediaItem = null
|
||||
}
|
||||
|
||||
override fun setVideoTextureView(textureView: TextureView?): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun clearVideoTextureView(textureView: TextureView?): Unit = throw UnsupportedOperationException()
|
||||
|
||||
override fun getVideoSize(): VideoSize {
|
||||
val width = MPVLib.getPropertyInt("width")
|
||||
val height = MPVLib.getPropertyInt("height")
|
||||
return if (width != null && height != null) {
|
||||
VideoSize(width, height)
|
||||
} else {
|
||||
VideoSize.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSurfaceSize(): Size {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getCurrentCues(): CueGroup = CueGroup.EMPTY_TIME_ZERO
|
||||
|
||||
override fun getDeviceInfo(): DeviceInfo {
|
||||
// TODO
|
||||
return DeviceInfo.Builder(DeviceInfo.PLAYBACK_TYPE_REMOTE).build()
|
||||
}
|
||||
|
||||
override fun getDeviceVolume(): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isDeviceMuted(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun setDeviceVolume(volume: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun setDeviceVolume(
|
||||
volume: Int,
|
||||
flags: Int,
|
||||
) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun increaseDeviceVolume() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun increaseDeviceVolume(flags: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun decreaseDeviceVolume() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun decreaseDeviceVolume(flags: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun setDeviceMuted(muted: Boolean) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun setDeviceMuted(
|
||||
muted: Boolean,
|
||||
flags: Int,
|
||||
) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun setAudioAttributes(
|
||||
audioAttributes: AudioAttributes,
|
||||
handleAudioFocus: Boolean,
|
||||
) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun seekTo(
|
||||
mediaItemIndex: Int,
|
||||
positionMs: Long,
|
||||
seekCommand: Int,
|
||||
isRepeatingCurrentItem: Boolean,
|
||||
) {
|
||||
if (mediaItemIndex == C.INDEX_UNSET) {
|
||||
return
|
||||
}
|
||||
MPVLib.setPropertyDouble("time-pos", positionMs.toDouble())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue