summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-10-14 08:38:27 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-10-14 08:38:27 +0000
commitb7c22e660c929bbd5640c57d87201c19c13c8e19 (patch)
tree922386abb844bf6bf37c26b52e55072cc5574000
parentb1d8647f5dc655faffd8b95a7a96b78c83eeffea (diff)
Keep the kind the server sent
Defaulted to advertising so a server that predates kinds still parses, and because that is what such a server meant by every break it sent.
-rw-r--r--.coverage-baseline2
-rw-r--r--app/src/main/java/org/terst/listen/server/ServerSkips.kt1
-rw-r--r--app/src/main/java/org/terst/listen/server/SkipServer.kt1
-rw-r--r--app/src/test/java/org/terst/listen/server/ServerSkipsTest.kt23
-rw-r--r--app/src/test/java/org/terst/listen/server/SkipServerTest.kt32
5 files changed, 58 insertions, 1 deletions
diff --git a/.coverage-baseline b/.coverage-baseline
index f3739dd..76690f3 100644
--- a/.coverage-baseline
+++ b/.coverage-baseline
@@ -1 +1 @@
-93.70
+93.75
diff --git a/app/src/main/java/org/terst/listen/server/ServerSkips.kt b/app/src/main/java/org/terst/listen/server/ServerSkips.kt
index ed70d07..aec261b 100644
--- a/app/src/main/java/org/terst/listen/server/ServerSkips.kt
+++ b/app/src/main/java/org/terst/listen/server/ServerSkips.kt
@@ -83,6 +83,7 @@ class ServerSkips(
candidateId = "server-$index",
startMs = range.startMs,
endMs = range.endMs,
+ kind = range.kind,
)
)
}
diff --git a/app/src/main/java/org/terst/listen/server/SkipServer.kt b/app/src/main/java/org/terst/listen/server/SkipServer.kt
index 2e013de..a1d3ccc 100644
--- a/app/src/main/java/org/terst/listen/server/SkipServer.kt
+++ b/app/src/main/java/org/terst/listen/server/SkipServer.kt
@@ -29,6 +29,7 @@ interface SkipTransport {
data class ServerBreak(
@SerialName("startMs") val startMs: Long = 0,
@SerialName("endMs") val endMs: Long = 0,
+ val kind: String = "ad",
)
/** What the server knows about one episode. */
diff --git a/app/src/test/java/org/terst/listen/server/ServerSkipsTest.kt b/app/src/test/java/org/terst/listen/server/ServerSkipsTest.kt
index 11bba35..ae933dc 100644
--- a/app/src/test/java/org/terst/listen/server/ServerSkipsTest.kt
+++ b/app/src/test/java/org/terst/listen/server/ServerSkipsTest.kt
@@ -229,4 +229,27 @@ class ServerSkipsTest {
assertTrue(midrolls.rangeRows.none { it.episodeId == "e1" })
}
+
+ /**
+ * The kind from the server is what the furniture setting acts on, and it has to reach
+ * the stored entity so playback can read it.
+ */
+ @Test
+ fun `carries the kind through to the stored entity`() = runTest {
+ val midrolls = FakeMidrollDao()
+
+ subject(StubTransport(null), midrolls = midrolls).record(
+ episode,
+ ServerEpisode(
+ ready = true, audioUrl = "x", durationMs = null, introMs = null, outroMs = null,
+ detected = true,
+ breaks = listOf(ServerBreak(0, 60_000, "intro"), ServerBreak(100_000, 120_000, "cue")),
+ ),
+ )
+
+ val ranges = midrolls.rangeRows.filter { it.episodeId == "e1" }.sortedBy { it.startMs }
+ assertEquals(2, ranges.size)
+ assertEquals("intro", ranges[0].kind)
+ assertEquals("cue", ranges[1].kind)
+ }
}
diff --git a/app/src/test/java/org/terst/listen/server/SkipServerTest.kt b/app/src/test/java/org/terst/listen/server/SkipServerTest.kt
index 320306a..4c48600 100644
--- a/app/src/test/java/org/terst/listen/server/SkipServerTest.kt
+++ b/app/src/test/java/org/terst/listen/server/SkipServerTest.kt
@@ -270,4 +270,36 @@ class SkipServerTest {
assertEquals(1, got?.breaks?.size)
assertEquals(7000L, got?.breaks?.single()?.startMs)
}
+
+ /**
+ * The kind is what the furniture setting acts on. A break that arrives without one has to
+ * read as advertising, because advertising is what gets skipped unconditionally -- which is
+ * also what an older server, which does not send a kind at all, used to mean.
+ */
+ @Test
+ fun `reads the kind of each break`() = runTest {
+ val transport = FakeTransport().apply {
+ response = """
+ {"status":"ready","audioUrl":"/audio/abc","detected":true,
+ "breaks":[{"startMs":0,"endMs":98000,"kind":"intro"},
+ {"startMs":900000,"endMs":1020000,"kind":"cue"}]}
+ """.trimIndent()
+ }
+
+ val got = server(transport).episode("https://f", "g1", "", "")
+
+ assertEquals("intro", got?.breaks?.get(0)?.kind)
+ assertEquals("cue", got?.breaks?.get(1)?.kind)
+ }
+
+ @Test
+ fun `a break with no kind is treated as advertising`() = runTest {
+ val transport = FakeTransport().apply {
+ response = """{"status":"ready","audioUrl":"/audio/abc","breaks":[{"startMs":0,"endMs":98000}]}"""
+ }
+
+ val got = server(transport).episode("https://f", "g1", "", "")
+
+ assertEquals("ad", got?.breaks?.single()?.kind)
+ }
}