Keep the programme bar hidden when one programme rolls into the next (0.32.0)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
# Orbit TV 0.32.0 verification
|
||||
|
||||
The programme bar and green channel number no longer appear when one programme rolls into the next. Paul reported the bar popping up unprompted.
|
||||
|
||||
## Changed
|
||||
- At a programme boundary on the same channel, the bar and number stay hidden; the channel's logo shows instead.
|
||||
- They still appear when tuning in or changing channel, and OK still brings up the bar at any time.
|
||||
- Includes 0.31's stream handover, which wasn't installed on its own.
|
||||
|
||||
## Checked
|
||||
- assembleDebug, testDebugUnitTest and lintDebug pass; 138 tests, 0 failures. None of these exercise the rollover on screen.
|
||||
- APK signature verified with apksigner.
|
||||
|
||||
## Not checked
|
||||
- Not yet run on the box. Both this and the 0.31 handover need Paul's on-TV check.
|
||||
- The tuning screen still shows briefly between programmes while the next one opens.
|
||||
@@ -9,8 +9,8 @@ android {
|
||||
applicationId = "tv.orbit.classic"
|
||||
minSdk = 26
|
||||
targetSdk = 36
|
||||
versionCode = 32
|
||||
versionName = "0.31.0-seamless-picture"
|
||||
versionCode = 33
|
||||
versionName = "0.32.0-quiet-rollover"
|
||||
}
|
||||
buildFeatures { compose = true }
|
||||
compileOptions { sourceCompatibility = JavaVersion.VERSION_17; targetCompatibility = JavaVersion.VERSION_17 }
|
||||
|
||||
@@ -41,7 +41,7 @@ internal class HttpsEmbyTransport(internal val deviceId: String = UUID.randomUUI
|
||||
connection.connectTimeout = 10_000
|
||||
connection.readTimeout = request.readTimeoutMs ?: if (request.path == "/Sessions/Logout") 5_000 else 15_000
|
||||
connection.setRequestProperty("Accept", "application/json")
|
||||
connection.setRequestProperty("X-Emby-Authorization", "Emby Client=\"Orbit TV\", Device=\"Orbit TV\", DeviceId=\"$deviceId\", Version=\"0.31.0\"")
|
||||
connection.setRequestProperty("X-Emby-Authorization", "Emby Client=\"Orbit TV\", Device=\"Orbit TV\", DeviceId=\"$deviceId\", Version=\"0.32.0\"")
|
||||
request.token?.let { connection.setRequestProperty("X-Emby-Token", it) }
|
||||
if (request.method == "POST") {
|
||||
val bytes = request.body.orEmpty().toByteArray(Charsets.UTF_8)
|
||||
|
||||
@@ -38,13 +38,13 @@ import kotlinx.coroutines.withContext
|
||||
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
||||
@Composable
|
||||
internal fun EmbyPlaybackDialog(session: EmbySampleSession, plan: EmbyPlaybackPlan, onClose: () -> Unit, scheduled: ScheduledPlayback? = null,
|
||||
onStep: (Int) -> Unit = {}, onLast: () -> Unit = {}, onNumber: (Int) -> Boolean = { false }, subtitlePreference: MutableState<String?>? = null, runningPlayer: ExoPlayer? = null) {
|
||||
onStep: (Int) -> Unit = {}, onLast: () -> Unit = {}, onNumber: (Int) -> Boolean = { false }, subtitlePreference: MutableState<String?>? = null, runningPlayer: ExoPlayer? = null, announce: Boolean = true) {
|
||||
val context = LocalContext.current
|
||||
var failure by remember { mutableStateOf<String?>(null) }
|
||||
var tuningNumberVisible by remember { mutableStateOf(true) }
|
||||
var tuningNumberVisible by remember { mutableStateOf(announce) }
|
||||
var ready by remember { mutableStateOf(false) }
|
||||
var playing by remember { mutableStateOf(false) }
|
||||
var infoVisible by remember { mutableStateOf(true) }
|
||||
var infoVisible by remember { mutableStateOf(announce) }
|
||||
var lastInteraction by remember { mutableLongStateOf(SystemClock.elapsedRealtime()) }
|
||||
fun showInfo() { infoVisible = true; lastInteraction = SystemClock.elapsedRealtime() }
|
||||
var numberEntry by remember { mutableStateOf<ChannelEntry?>(null) }
|
||||
|
||||
@@ -97,6 +97,8 @@ internal fun ScheduledChannelPlayer(session: EmbySampleSession, channel: SampleC
|
||||
LaunchedEffect(channel, clockOffsetMs) { while (true) { now = System.currentTimeMillis() + clockOffsetMs; delay(250) } }
|
||||
val shows = channel.guide(now, 2)
|
||||
val current = shows[0]
|
||||
// The bar and number greet a tune or channel change. One programme rolling into the next stays clean.
|
||||
val announcedChannel = remember { intArrayOf(-1) }
|
||||
val handed = remember {
|
||||
val stream = handoff?.take()
|
||||
if (stream != null && stream.channelNumber == channel.number && stream.startMs == current.startMs && clockOffsetMs == 0L) stream
|
||||
@@ -129,8 +131,10 @@ internal fun ScheduledChannelPlayer(session: EmbySampleSession, channel: SampleC
|
||||
val plan = prepared?.takeIf { it.item.id == current.media.item.id && preparedSlot == current.startMs && problem == null }
|
||||
if (plan != null) {
|
||||
key(current.startMs) {
|
||||
val announce = remember { announcedChannel[0] != channel.number }
|
||||
SideEffect { announcedChannel[0] = channel.number }
|
||||
EmbyPlaybackDialog(session, plan, onClose,
|
||||
scheduled = ScheduledPlayback(channel, current, shows[1], clockOffsetMs), onStep = onStep, onLast = onLast, onNumber = onNumber, subtitlePreference = subtitlePreference, runningPlayer = handed?.takeIf { it.plan === plan }?.claim())
|
||||
scheduled = ScheduledPlayback(channel, current, shows[1], clockOffsetMs), onStep = onStep, onLast = onLast, onNumber = onNumber, subtitlePreference = subtitlePreference, runningPlayer = handed?.takeIf { it.plan === plan }?.claim(), announce = announce)
|
||||
}
|
||||
} else Dialog(onDismissRequest = onClose, properties = DialogProperties(usePlatformDefaultWidth = false,
|
||||
decorFitsSystemWindows = false, securePolicy = SecureFlagPolicy.SecureOn)) {
|
||||
|
||||
@@ -33,7 +33,7 @@ internal class SecureMediaDataSource(private val session: EmbySampleSession) : B
|
||||
next.instanceFollowRedirects = false
|
||||
next.connectTimeout = 10_000
|
||||
next.readTimeout = 20_000
|
||||
next.setRequestProperty("User-Agent", "OrbitTV/0.31.0")
|
||||
next.setRequestProperty("User-Agent", "OrbitTV/0.32.0")
|
||||
next.setRequestProperty("Accept-Encoding", "identity")
|
||||
session.mediaHeaders(address).forEach { (key, value) -> next.setRequestProperty(key, value) }
|
||||
if (dataSpec.position != 0L || dataSpec.length != C.LENGTH_UNSET.toLong()) {
|
||||
|
||||
Reference in New Issue
Block a user