This took me quite a while to figure out, but I rewrote the iOS sleep timer again to address issues with multi-track books. Fixes#351.
The iOS sleep timer now:
Uses a Timer for countdown-based sleep timers
Uses a TimeObserver for a scheduled chapter end time
This seems to strike the balance of accuracy, reliability, and code readability. I have tested this PR with:
Single-track books
Multi-track books
Podcasts
For each media type, I have verified:
How the timer reacts to play/pause
How the timer reacts to changes in playback speed
How the timer reacts to seeking
How the timer handles seeking past the end time (in case of a chapter end timer)
Why rewrite the sleep timer again? While the previous strategy worked, it involved recalculating the stop time each time seeking and playback rate changes occurred. Not to mention the edge cases with a chapter sleep time.
In theory, the previous strategy should work, but the way the player reinitialized when tracks are changed out during seeks with multi-file books caused the stop time to be recalculated wrong depending on the order of operations. I tried a number of different strategies to debug it, and race conditions would continue to come up, due to the fact that pause/stopping audio causes the playback rate to change on iOS. This would force the stop time to be recalculated, which would be occurring while the seek was happening. There is probably a way to solve for it, but I opted to simplify the logic.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
## 📋 Pull Request Information
**Original PR:** https://github.com/advplyr/audiobookshelf-app/pull/359
**Author:** [@ronaldheft](https://github.com/ronaldheft)
**Created:** 9/3/2022
**Status:** ✅ Merged
**Merged:** 9/3/2022
**Merged by:** [@advplyr](https://github.com/advplyr)
**Base:** `master` ← **Head:** `bug-ios-sleep-timer`
---
### 📝 Commits (7)
- [`586405f`](https://github.com/advplyr/audiobookshelf-app/commit/586405f9de3c77de0e10ee8885d66e0539f3b99d) Rewrite sleep timer
- [`dc8852e`](https://github.com/advplyr/audiobookshelf-app/commit/dc8852eb0dd885905175ab16ee943d4c23310548) Guard against seeking during initialization
- [`c14f6ec`](https://github.com/advplyr/audiobookshelf-app/commit/c14f6ec4c24f11843195ce4f07f5771a53035646) Rewrite sleep timer logic again
- [`c8ff5a7`](https://github.com/advplyr/audiobookshelf-app/commit/c8ff5a7817e32377cfdfb54674dda1af4347a0f9) Handle multi-track files for sleep timer
- [`836ffdd`](https://github.com/advplyr/audiobookshelf-app/commit/836ffddd4fb81f0b5a115f483c13aa47dc43e008) Fix race condition with chapter sleep timer
- [`fb8e640`](https://github.com/advplyr/audiobookshelf-app/commit/fb8e6408bbde945f414a4caf5dc3fbfbb19f70e2) Fix memory leak
- [`b697dea`](https://github.com/advplyr/audiobookshelf-app/commit/b697deac1cfaafd98826a2cec5e4aca21cc4f7a2) Fix cluegy way chapter sleep timer was being reset after skipping past
### 📊 Changes
**6 files changed** (+256 additions, -231 deletions)
<details>
<summary>View changed files</summary>
📝 `ios/App/App.xcodeproj/project.pbxproj` (+4 -0)
📝 `ios/App/App/plugins/AbsAudioPlayer.swift` (+9 -10)
📝 `ios/App/Shared/models/server/AudioTrack.swift` (+7 -0)
📝 `ios/App/Shared/player/AudioPlayer.swift` (+68 -180)
➕ `ios/App/Shared/player/AudioPlayerSleepTimer.swift` (+156 -0)
📝 `ios/App/Shared/player/PlayerHandler.swift` (+12 -41)
</details>
### 📄 Description
This took me quite a while to figure out, but I rewrote the iOS sleep timer again to address issues with multi-track books. Fixes #351.
The iOS sleep timer now:
* Uses a `Timer` for countdown-based sleep timers
* Uses a `TimeObserver` for a scheduled chapter end time
This seems to strike the balance of accuracy, reliability, and code readability. I have tested this PR with:
* Single-track books
* Multi-track books
* Podcasts
For each media type, I have verified:
* How the timer reacts to play/pause
* How the timer reacts to changes in playback speed
* How the timer reacts to seeking
* How the timer handles seeking past the end time (in case of a chapter end timer)
Why rewrite the sleep timer again? While the previous strategy worked, it involved recalculating the stop time each time seeking and playback rate changes occurred. Not to mention the edge cases with a chapter sleep time.
In theory, the previous strategy should work, but the way the player reinitialized when tracks are changed out during seeks with multi-file books caused the stop time to be recalculated wrong depending on the order of operations. I tried a number of different strategies to debug it, and race conditions would continue to come up, due to the fact that pause/stopping audio causes the playback rate to change on iOS. This would force the stop time to be recalculated, which would be occurring while the seek was happening. There is probably a way to solve for it, but I opted to simplify the logic.
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/advplyr/audiobookshelf-app/pull/359
Author: @ronaldheft
Created: 9/3/2022
Status: ✅ Merged
Merged: 9/3/2022
Merged by: @advplyr
Base:
master← Head:bug-ios-sleep-timer📝 Commits (7)
586405fRewrite sleep timerdc8852eGuard against seeking during initializationc14f6ecRewrite sleep timer logic againc8ff5a7Handle multi-track files for sleep timer836ffddFix race condition with chapter sleep timerfb8e640Fix memory leakb697deaFix cluegy way chapter sleep timer was being reset after skipping past📊 Changes
6 files changed (+256 additions, -231 deletions)
View changed files
📝
ios/App/App.xcodeproj/project.pbxproj(+4 -0)📝
ios/App/App/plugins/AbsAudioPlayer.swift(+9 -10)📝
ios/App/Shared/models/server/AudioTrack.swift(+7 -0)📝
ios/App/Shared/player/AudioPlayer.swift(+68 -180)➕
ios/App/Shared/player/AudioPlayerSleepTimer.swift(+156 -0)📝
ios/App/Shared/player/PlayerHandler.swift(+12 -41)📄 Description
This took me quite a while to figure out, but I rewrote the iOS sleep timer again to address issues with multi-track books. Fixes #351.
The iOS sleep timer now:
Timerfor countdown-based sleep timersTimeObserverfor a scheduled chapter end timeThis seems to strike the balance of accuracy, reliability, and code readability. I have tested this PR with:
For each media type, I have verified:
Why rewrite the sleep timer again? While the previous strategy worked, it involved recalculating the stop time each time seeking and playback rate changes occurred. Not to mention the edge cases with a chapter sleep time.
In theory, the previous strategy should work, but the way the player reinitialized when tracks are changed out during seeks with multi-file books caused the stop time to be recalculated wrong depending on the order of operations. I tried a number of different strategies to debug it, and race conditions would continue to come up, due to the fact that pause/stopping audio causes the playback rate to change on iOS. This would force the stop time to be recalculated, which would be occurring while the seek was happening. There is probably a way to solve for it, but I opted to simplify the logic.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.