Add rewind on pause - #492
Closed
skorokithakis wants to merge 5 commits into
Closed
Conversation
Moves the position back when a book is continued, proportionally to how long that book was paused: amount * min(pause, 300s) / 300s. A momentary pause moves almost nothing, a pause of five minutes or more moves the full amount. The setting lives in Settings -> Playback -> Seek settings (on by default, 30s, 1-60s) and is part of the settings backup. It reuses the dormant RewindOnPauseTime domain class and drops the unused SeekTimeOption enum. The last active time is stored per book, so pausing book A and listening to book B does not reset A. A book with no stored time gets the full rewind. The map keeps the 100 newest books. The rewind is applied in one place, a forwarding player around the ExoPlayer that the media session is built on, so the seek happens before the audio starts and every source behaves the same: the app, the notification, media buttons, Android Auto, the widget, and the sleep timer. It fires only on a real playWhenReady false -> true change, so a repeated play command cannot rewind. The automatic resume after a short audio focus loss has no play command, so it is covered separately by the playback suppression reason; a buffering stall is excluded there.
The proportional part alone means a short pause moves the position almost not at all, which is not useful: after any interruption you want a little context back. Every resume now rewinds at least 5 seconds, and the proportional amount applies above that floor. The amount can therefore no longer be set below 10 seconds, because 5 and less would be inert. The manual rewind and forward intervals keep their own range.
The 5 seconds is a starting point, not a floor that swallows short pauses: a 10 second pause with a 30 second amount now rewinds about 6 seconds instead of 5. Both ends are unchanged, a momentary pause gives 5 seconds and a pause of five minutes gives exactly the amount that is set.
The timeline holds one media item per chapter, and PlaybackNavigationService.onPositionDiscontinuity treats a backward seek into a different media item as a discontinuity. With a partly downloaded book, a rewind that walks into a missing chapter becomes a jump to the start of a much earlier chapter, or a stall when no chapter is available to skip to. Clamp the rewind at position 0 of the current chapter so the discontinuity handler exits at its currentIndex != previousIndex guard and the interaction cannot happen.
Contributor
Author
|
I've tested this on my phone and it works great, with #493 as well. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I have an issue where, if I haven't listened to a book I a while, I forget my place. I implemented a feature to set an interval to rewind by, eg 60 seconds.
When you pause a book, I store the time of the pause. When you unpause, the book rewinds a specific amount, up to the full 60 seconds (or whatever you set) , depending on how long the pause was. A short pause rewinds 5 seconds, a 5-minute (or longer) pause rewinds the full duration.
I hope that's useful.
LLM details follow:
Moves the position back when a book is continued, based on how long that book was paused:
So any resume gives you a little context back, and a pause of five minutes or more rewinds the full amount that is set. With the default 30s amount: a momentary pause rewinds 5s, a 10 second pause about 5.8s, a 150 second pause 17.5s, and five minutes or more the full 30s.
The rewind never crosses into the previous chapter. If the position is closer to the chapter start than the rewind amount, it stops at the start of the current chapter.
The setting
"Rewind on pause" in Settings -> Playback -> Seek settings: a toggle and an amount (10-60s, presets 10/15/30/60), on by default with 30s. It is part of the settings backup, and the amount is clamped to its range both on read and on import, so an edited backup cannot produce a strange rewind. The amount cannot go below 10 seconds, because the rewind always starts at 5 seconds and a smaller maximum would be inert. The manual rewind and forward intervals keep their own 1-60 range.
This puts the dormant
RewindOnPauseTimedomain class to use and removes theSeekTimeOptionenum, which nothing else referenced.Per book, not global
The last active time is stored per book (a
bookId -> epoch millismap, capped at the 100 newest books). Pausing book A and starting book B must not reset A's clock: the rewind models how much of that book the listener forgot. A book with no stored time gets the full rewind, because "no record" means the listener probably forgot more, not less.One choke point
The rewind is applied by a thin
ForwardingPlayeraround theExoPlayerthat theMediaLibrarySessionis built on. The seek therefore happens before the audio starts, so there is no audible jump, and every source behaves the same: the app, the notification, media buttons, Android Auto, the widget, the sleep timer, a book switch, and a resume after the process was killed.Two details in there:
playWhenReadyfalse -> true change, so a repeated play command during a session cannot rewind.Notes for review
PlaybackNavigationService.onPositionDiscontinuitytreats a backward seek into a different media item as a discontinuity. On a partly downloaded book, a rewind that walks into a missing chapter becomes a jump to the start of a much earlier chapter, or a stall when there is no available chapter to skip to. Clamping inside the current chapter keeps that handler on itscurrentIndex != previousIndexguard, so the interaction cannot arise. It also means the rewind needs no chapter durations at all.Tests
Unit tests for the interpolated amount, the seek target (including the clamp at the start of the chapter), the preference storage and its cap, the handler (book switch, suppression resume, the
playWhenReadygate), the shared slider range, the settings backup, and the view model../gradlew lintKotlin testpasses.