summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/src/main/java/org/terst/listen/playback/AdJump.kt17
-rw-r--r--app/src/main/java/org/terst/listen/playback/NotificationControls.kt7
-rw-r--r--app/src/main/java/org/terst/listen/playback/PlaybackService.kt10
-rw-r--r--app/src/main/java/org/terst/listen/playback/SeekAmounts.kt24
-rw-r--r--app/src/main/java/org/terst/listen/ui/Transport.kt8
-rw-r--r--app/src/test/java/org/terst/listen/playback/AdJumpTest.kt4
-rw-r--r--app/src/test/java/org/terst/listen/playback/SeekAmountsTest.kt37
7 files changed, 85 insertions, 22 deletions
diff --git a/app/src/main/java/org/terst/listen/playback/AdJump.kt b/app/src/main/java/org/terst/listen/playback/AdJump.kt
index 99622c1..baf09ed 100644
--- a/app/src/main/java/org/terst/listen/playback/AdJump.kt
+++ b/app/src/main/java/org/terst/listen/playback/AdJump.kt
@@ -7,19 +7,18 @@ import org.terst.listen.data.EpisodeMidrollEntity
* How far "this is an ad" jumps.
*
* The press means "get me past this advertisement", so the jump is the best estimate available
- * at that moment rather than a constant. If detection already found a break here, its end is a
- * measured answer and is used. Otherwise the default stands in.
+ * at that moment: if detection already found a break here, its end is a measured answer and is
+ * used.
*
- * The size of that default is the trade between too small -- several presses to clear one pod --
- * and too large, which lands him in the programme and makes him correct constantly. Advertising
- * is sold in roughly 15-second units grouped into pods, and he presses partway through one, so
- * the typical *remaining* duration is what this estimates. Erring small is deliberate: a second
- * press costs one tap and improves the label, while over-shooting costs him content.
+ * With nothing measured it falls back to the forward button's own amount, and deliberately
+ * introduces no timing of its own. Skipping forward is already what the listener does to an
+ * advertisement; this button does the same distance and additionally says why. One number to
+ * know, and pressing again goes the same distance again -- which also extends the label.
*/
object AdJump {
- /** Three 15-second units. See the class comment for why it is not larger. */
- const val DEFAULT_JUMP_MS = 45_000L
+ /** The forward button's amount. Not a constant of this feature's own; see [SeekAmounts]. */
+ const val DEFAULT_JUMP_MS = SeekAmounts.FORWARD_MS
fun targetFor(
ranges: List<EpisodeMidrollEntity>,
diff --git a/app/src/main/java/org/terst/listen/playback/NotificationControls.kt b/app/src/main/java/org/terst/listen/playback/NotificationControls.kt
index 21f3959..1dba3df 100644
--- a/app/src/main/java/org/terst/listen/playback/NotificationControls.kt
+++ b/app/src/main/java/org/terst/listen/playback/NotificationControls.kt
@@ -41,17 +41,18 @@ object NotificationControls {
* Media3 ships numbered icons for 5, 10, 15 and 30 seconds only.
*
* Back is 15, so it gets the numbered icon. Forward is 25 and there is no 25 icon, so it
- * gets the plain arrow rather than one captioned with a number the button doesn't do.
+ * gets the plain arrow rather than one captioned with a number the button doesn't do. The
+ * captions come from [SeekAmounts] for the same reason.
*/
fun mediaButtonPreferences(): List<CommandButton> = listOf(
CommandButton.Builder()
- .setDisplayName("Back 15 seconds")
+ .setDisplayName(SeekAmounts.backLabel)
.setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_back_15)
.setSessionCommand(seekBackCommand)
.setSlots(CommandButton.SLOT_BACK)
.build(),
CommandButton.Builder()
- .setDisplayName("Forward 25 seconds")
+ .setDisplayName(SeekAmounts.forwardLabel)
.setIconResId(androidx.media3.session.R.drawable.media3_icon_skip_forward)
.setSessionCommand(seekForwardCommand)
.setSlots(CommandButton.SLOT_FORWARD)
diff --git a/app/src/main/java/org/terst/listen/playback/PlaybackService.kt b/app/src/main/java/org/terst/listen/playback/PlaybackService.kt
index 3a2543b..7af4e0a 100644
--- a/app/src/main/java/org/terst/listen/playback/PlaybackService.kt
+++ b/app/src/main/java/org/terst/listen/playback/PlaybackService.kt
@@ -66,10 +66,10 @@ class PlaybackService : MediaLibraryService() {
/* handleAudioFocus = */ true,
)
.setHandleAudioBecomingNoisy(true)
- // These drive the notification, lock screen, Bluetooth remote and car controls.
- // Asymmetric on purpose: back catches a missed sentence, forward steps over an ad.
- .setSeekBackIncrementMs(SEEK_BACK_MS)
- .setSeekForwardIncrementMs(SEEK_FORWARD_MS)
+ // These drive the notification, lock screen, Bluetooth remote and car controls --
+ // and, through SeekAmounts, the in-app transport and the button captions too.
+ .setSeekBackIncrementMs(SeekAmounts.BACK_MS)
+ .setSeekForwardIncrementMs(SeekAmounts.FORWARD_MS)
.build()
player = exo
@@ -345,8 +345,6 @@ class PlaybackService : MediaLibraryService() {
private companion object {
const val TAG = "ListenPlayback"
const val POSITION_TICK_MS = 2_000L
- const val SEEK_BACK_MS = 15_000L
- const val SEEK_FORWARD_MS = 25_000L
}
}
diff --git a/app/src/main/java/org/terst/listen/playback/SeekAmounts.kt b/app/src/main/java/org/terst/listen/playback/SeekAmounts.kt
new file mode 100644
index 0000000..a02a56b
--- /dev/null
+++ b/app/src/main/java/org/terst/listen/playback/SeekAmounts.kt
@@ -0,0 +1,24 @@
+package org.terst.listen.playback
+
+/**
+ * How far a skip goes. One definition, because there were three.
+ *
+ * The player's increments, the episode screen's transport buttons and the notification button's
+ * caption each carried their own copy of 15 and 25 seconds, and the "this is an ad" jump nearly
+ * became a fourth with a different number again. A listener has one idea of how far a skip goes;
+ * every control that skips uses this.
+ *
+ * Asymmetric on purpose: back catches a missed sentence, forward steps over an advertisement.
+ */
+object SeekAmounts {
+
+ const val BACK_MS = 15_000L
+ const val FORWARD_MS = 25_000L
+
+ /**
+ * Captions, derived rather than written out, so a caption cannot name a number the button
+ * does not do.
+ */
+ val backLabel: String = "Back ${BACK_MS / 1_000} seconds"
+ val forwardLabel: String = "Forward ${FORWARD_MS / 1_000} seconds"
+}
diff --git a/app/src/main/java/org/terst/listen/ui/Transport.kt b/app/src/main/java/org/terst/listen/ui/Transport.kt
index 80c1018..506770d 100644
--- a/app/src/main/java/org/terst/listen/ui/Transport.kt
+++ b/app/src/main/java/org/terst/listen/ui/Transport.kt
@@ -1,10 +1,14 @@
package org.terst.listen.ui
+import org.terst.listen.playback.SeekAmounts
+
/** The episode screen's transport arithmetic, kept out of the composable so it can be tested. */
object Transport {
- const val BACK_MS = 15_000L
- const val FORWARD_MS = 25_000L
+ // The player's own increments, not a second opinion about them: the screen's buttons and
+ // the notification's have to move the playhead by the same amount.
+ const val BACK_MS = SeekAmounts.BACK_MS
+ const val FORWARD_MS = SeekAmounts.FORWARD_MS
/** Where a skip lands, kept inside the episode. */
fun stepped(positionMs: Long, deltaMs: Long, durationMs: Long?): Long {
diff --git a/app/src/test/java/org/terst/listen/playback/AdJumpTest.kt b/app/src/test/java/org/terst/listen/playback/AdJumpTest.kt
index 3421aa2..d2b3138 100644
--- a/app/src/test/java/org/terst/listen/playback/AdJumpTest.kt
+++ b/app/src/test/java/org/terst/listen/playback/AdJumpTest.kt
@@ -87,7 +87,7 @@ class AdJumpTest {
}
@Test
- fun `the default is a plausible remaining advertisement, in whole ad units`() {
- assertEquals(0L, AdJump.DEFAULT_JUMP_MS % 15_000L)
+ fun `the default jump is the forward button's amount, not a number of its own`() {
+ assertEquals(SeekAmounts.FORWARD_MS, AdJump.DEFAULT_JUMP_MS)
}
}
diff --git a/app/src/test/java/org/terst/listen/playback/SeekAmountsTest.kt b/app/src/test/java/org/terst/listen/playback/SeekAmountsTest.kt
new file mode 100644
index 0000000..8d0865c
--- /dev/null
+++ b/app/src/test/java/org/terst/listen/playback/SeekAmountsTest.kt
@@ -0,0 +1,37 @@
+package org.terst.listen.playback
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+/**
+ * One definition of how far a skip goes.
+ *
+ * These were duplicated in three places -- the player's increments, the episode screen's
+ * transport, and the notification button's caption -- and a fourth nearly appeared.
+ */
+class SeekAmountsTest {
+
+ @Test
+ fun `the amounts are what they have always been`() {
+ assertEquals(15_000L, SeekAmounts.BACK_MS)
+ assertEquals(25_000L, SeekAmounts.FORWARD_MS)
+ }
+
+ @Test
+ fun `the episode screen skips by the same amounts as the player`() {
+ assertEquals(SeekAmounts.BACK_MS, org.terst.listen.ui.Transport.BACK_MS)
+ assertEquals(SeekAmounts.FORWARD_MS, org.terst.listen.ui.Transport.FORWARD_MS)
+ }
+
+ @Test
+ fun `a notification caption states the amount it actually seeks`() {
+ assertEquals("Back 15 seconds", SeekAmounts.backLabel)
+ assertEquals("Forward 25 seconds", SeekAmounts.forwardLabel)
+ }
+
+ @Test
+ fun `back is shorter than forward -- back catches a missed sentence, forward steps over an ad`() {
+ assertTrue(SeekAmounts.BACK_MS < SeekAmounts.FORWARD_MS)
+ }
+}