mirror of
https://github.com/narrrl/proton-stream.git
synced 2026-11-07 09:22:10 +01:00
feat(android,player): the read-ahead on the seek bar
pstr_mpv observes demuxer-cache-time and hands it over with the rest of the state, and the seek bar shades from the start to where the demuxer has read, lighter than the played part. A jump that lands in the shaded run costs no fetch, as on the desktop.
This commit is contained in:
1 parent
0bc7cba428
commit
cfd654b267
4 files changed
+29
-5
No files matched your search
@@ -75,6 +75,8 @@ data class MpvPlaybackState(
|
||||
val cachePercent: Double = 0.0,
|
||||
/** A seek has been issued but playback has not resumed at the new position. */
|
||||
val seeking: Boolean = false,
|
||||
/** How far the demuxer has read ahead, in seconds into the file. */
|
||||
val cachedUntil: Double = 0.0,
|
||||
) {
|
||||
/** Whether the picture is stopped for a reason the viewer did not choose. */
|
||||
val stalled: Boolean get() = (buffering || seeking) && !paused && !ended
|
||||
@@ -313,6 +315,7 @@ class NativeMpvHost private constructor(private val nativeHandle: Long) : Libmpv
|
||||
buffering = values[BUFFERING] != 0.0,
|
||||
cachePercent = values[CACHE_PERCENT],
|
||||
seeking = values[SEEKING] != 0.0,
|
||||
cachedUntil = values[CACHED_UNTIL],
|
||||
)
|
||||
mutableState.value = next
|
||||
// The listeners drive the media session and the player UI,
|
||||
@@ -431,7 +434,7 @@ class NativeMpvHost private constructor(private val nativeHandle: Long) : Libmpv
|
||||
|
||||
companion object {
|
||||
/** Fields `nativeState` fills, in the order `pstr_mpv.cpp` writes them. */
|
||||
private const val FIELDS = 13
|
||||
private const val FIELDS = 14
|
||||
private const val GENERATION = 6
|
||||
private const val WIDTH = 7
|
||||
private const val HEIGHT = 8
|
||||
@@ -439,6 +442,7 @@ class NativeMpvHost private constructor(private val nativeHandle: Long) : Libmpv
|
||||
private const val BUFFERING = 10
|
||||
private const val CACHE_PERCENT = 11
|
||||
private const val SEEKING = 12
|
||||
private const val CACHED_UNTIL = 13
|
||||
|
||||
init {
|
||||
System.loadLibrary("pstr_android")
|
||||
|
||||
@@ -640,7 +640,12 @@ private fun PlayerControls(
|
||||
scrubbing = null
|
||||
},
|
||||
valueRange = 0f..duration,
|
||||
track = { AccentTrack(it) },
|
||||
track = {
|
||||
AccentTrack(
|
||||
it,
|
||||
buffered = if (state.duration > 0) (state.cachedUntil / state.duration).toFloat() else 0f,
|
||||
)
|
||||
},
|
||||
)
|
||||
ChapterMarks(chapters, state.duration, Modifier.matchParentSize())
|
||||
}
|
||||
|
||||
@@ -168,11 +168,21 @@ internal fun AccentProgress(
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
internal fun AccentTrack(state: SliderState, modifier: Modifier = Modifier) {
|
||||
internal fun AccentTrack(state: SliderState, modifier: Modifier = Modifier, buffered: Float = 0f) {
|
||||
val brush = accentBrush()
|
||||
Canvas(modifier.fillMaxWidth().height(TRACK_HEIGHT.dp)) {
|
||||
val radius = CornerRadius(size.height / 2)
|
||||
drawRoundRect(color = Color.White.copy(alpha = 0.30f), cornerRadius = radius)
|
||||
// What is already read ahead, lighter than the rest and under the
|
||||
// played part: a jump that lands in it costs no fetch.
|
||||
val ahead = size.width * buffered.coerceIn(0f, 1f)
|
||||
if (ahead >= size.height) {
|
||||
drawRoundRect(
|
||||
color = Color.White.copy(alpha = 0.55f),
|
||||
size = Size(ahead, size.height),
|
||||
cornerRadius = radius,
|
||||
)
|
||||
}
|
||||
val done = size.width * state.coercedValueAsFraction
|
||||
if (done >= size.height) {
|
||||
drawRoundRect(brush = brush, size = Size(done, size.height), cornerRadius = radius)
|
||||
|
||||
Reference in new issue
Block a user