mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 07:29:14 +01:00
playback: show notification progress for unknown-length streams
Media3 marks a progressive stream live when the data source reports no length and the extractor no duration, and a live item makes the media session publish PLAYBACK_POSITION_UNKNOWN, so the notification progress never advances even though the item carries the library duration. The app only declares a stream length for a transcode of a track that has one in a length-estimable format (`declaredStreamLength`), so a chunked response stays live for an Opus/Ogg/Vorbis transcode (a length estimate breaks the end-seek they rely on), for a transcode of a track whose library duration is missing, and for a direct play the server does not give a Content-Length. The now playing screen shows progress in all of those because it falls back to the metadata duration; the notification had nothing to advance. Wrap the ExoPlayer in a ForwardingPlayer that reports an item with a declared duration as finite. The session then publishes the real position and the metadata duration, so the notification shows progress for every unknown-length stream, not just Opus. The stream is still not seekable; only the reported liveness changes.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package com.subtracks.playback
|
||||
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.media3.common.ForwardingPlayer
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
|
||||
/**
|
||||
* Reports a track whose duration is known from its metadata as finite rather than live.
|
||||
*
|
||||
* Media3 marks a progressive stream live when the data source reports no length and the extractor
|
||||
* no duration. The app declares a length only for a transcode of a track that has one in a
|
||||
* length-estimable format, so a chunked response stays live for an Opus/Ogg/Vorbis transcode, for
|
||||
* a transcode of a track whose library duration is missing, and for a direct play the server does
|
||||
* not give a Content-Length. A live item makes the media session publish no playback position, so
|
||||
* the notification loses its progress even though the item carries a real duration. The stream is
|
||||
* still not seekable; this only restores the position the session reports.
|
||||
*/
|
||||
@OptIn(UnstableApi::class)
|
||||
internal class KnownDurationPlayer(
|
||||
player: Player,
|
||||
) : ForwardingPlayer(player) {
|
||||
override fun isCurrentMediaItemLive(): Boolean = if (declaredDurationMs() != null) false else super.isCurrentMediaItemLive()
|
||||
|
||||
private fun declaredDurationMs(): Long? =
|
||||
currentMediaItem
|
||||
?.mediaMetadata
|
||||
?.durationMs
|
||||
?.takeIf { it > 0 }
|
||||
}
|
||||
@@ -130,6 +130,7 @@ class PlaybackService : MediaSessionService() {
|
||||
}
|
||||
},
|
||||
)
|
||||
val player = KnownDurationPlayer(exoPlayer)
|
||||
val loader =
|
||||
CoverArtBitmapLoader(
|
||||
applicationContext,
|
||||
@@ -139,7 +140,7 @@ class PlaybackService : MediaSessionService() {
|
||||
artworkLoader = loader
|
||||
session =
|
||||
MediaSession
|
||||
.Builder(this, exoPlayer)
|
||||
.Builder(this, player)
|
||||
.setSessionActivity(
|
||||
PendingIntent.getActivity(
|
||||
this,
|
||||
|
||||
Reference in New Issue
Block a user