diff --git a/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt b/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt
index 93fd4c72..a85a84a2 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt
@@ -103,6 +103,8 @@ data class DeviceSettings(
var autoSleepTimer: Boolean,
var autoSleepTimerStartTime: String,
var autoSleepTimerEndTime: String,
+ var autoSleepTimerAutoRewind: Boolean,
+ var autoSleepTimerAutoRewindTime: Long, //Time in milliseconds
var sleepTimerLength: Long, // Time in milliseconds
var disableSleepTimerFadeOut: Boolean,
var disableSleepTimerResetFeedback: Boolean
@@ -123,6 +125,8 @@ data class DeviceSettings(
autoSleepTimerStartTime = "22:00",
autoSleepTimerEndTime = "06:00",
sleepTimerLength = 900000L, // 15 minutes
+ autoSleepTimerAutoRewind = false,
+ autoSleepTimerAutoRewindTime = 300000L, // 5 minutes
disableSleepTimerFadeOut = false,
disableSleepTimerResetFeedback = false
)
@@ -142,6 +146,7 @@ data class DeviceSettings(
@get:JsonIgnore
val autoSleepTimerEndMinute get() = autoSleepTimerEndTime.split(":")[1].toInt()
+
@JsonIgnore
fun getShakeThresholdGravity() : Float { // Used in ShakeDetector
return if (shakeSensitivity == ShakeSensitivitySetting.VERY_HIGH) 1.2f
diff --git a/android/app/src/main/java/com/audiobookshelf/app/device/DeviceManager.kt b/android/app/src/main/java/com/audiobookshelf/app/device/DeviceManager.kt
index 57245e19..77391ae2 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/device/DeviceManager.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/device/DeviceManager.kt
@@ -39,6 +39,10 @@ object DeviceManager {
if (deviceData.deviceSettings?.shakeSensitivity == null) {
deviceData.deviceSettings?.shakeSensitivity = ShakeSensitivitySetting.MEDIUM
}
+ // Initialize auto sleep timer auto rewind added in v0.9.64
+ if (deviceData.deviceSettings?.autoSleepTimerAutoRewindTime == null) {
+ deviceData.deviceSettings?.autoSleepTimerAutoRewindTime = 300000L // 5 minutes
+ }
}
fun getBase64Id(id:String):String {
diff --git a/android/app/src/main/java/com/audiobookshelf/app/managers/SleepTimerManager.kt b/android/app/src/main/java/com/audiobookshelf/app/managers/SleepTimerManager.kt
index 47c3113c..1d13eb30 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/managers/SleepTimerManager.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/managers/SleepTimerManager.kt
@@ -1,6 +1,7 @@
package com.audiobookshelf.app.managers
import android.content.Context
+import android.media.metrics.PlaybackSession
import android.os.*
import android.util.Log
import com.audiobookshelf.app.device.DeviceManager
@@ -21,6 +22,8 @@ class SleepTimerManager constructor(private val playerNotificationService: Playe
private var sleepTimerElapsed:Long = 0L
private var sleepTimerFinishedAt:Long = 0L
private var isAutoSleepTimer:Boolean = false // When timer was auto-set
+ private var isFirstAutoSleepTimer: Boolean = true
+ private var sleepTimerSessionId:String = ""
private fun getCurrentTime():Long {
return playerNotificationService.getCurrentTime()
@@ -123,7 +126,8 @@ class SleepTimerManager constructor(private val playerNotificationService: Playe
return true
}
- fun setManualSleepTimer(time: Long, isChapterTime:Boolean):Boolean {
+ fun setManualSleepTimer(playbackSessionId:String, time: Long, isChapterTime:Boolean):Boolean {
+ sleepTimerSessionId = playbackSessionId
isAutoSleepTimer = false
return setSleepTimer(time, isChapterTime)
}
@@ -133,7 +137,6 @@ class SleepTimerManager constructor(private val playerNotificationService: Playe
sleepTimerTask = null
sleepTimerEndTime = 0
sleepTimerRunning = false
- isAutoSleepTimer = false
playerNotificationService.unregisterSensor()
setVolume(1f)
@@ -227,6 +230,17 @@ class SleepTimerManager constructor(private val playerNotificationService: Playe
return
}
+ // Automatically Rewind in the book if settings is enabled
+ if (isAutoSleepTimer) {
+ DeviceManager.deviceData.deviceSettings?.let { deviceSettings ->
+ if (deviceSettings.autoSleepTimerAutoRewind && !isFirstAutoSleepTimer) {
+ Log.i(tag, "Auto sleep timer auto rewind seeking back ${deviceSettings.autoSleepTimerAutoRewindTime}ms")
+ playerNotificationService.seekBackward(deviceSettings.autoSleepTimerAutoRewindTime)
+ }
+ isFirstAutoSleepTimer = false
+ }
+ }
+
// Set sleep timer
// When sleepTimerLength is 0 then use end of chapter/track time
if (sleepTimerLength == 0L) {
@@ -343,6 +357,13 @@ class SleepTimerManager constructor(private val playerNotificationService: Playe
if (currentCalendar.after(startCalendar) && currentCalendar.before(endCalendar)) {
Log.i(tag, "Current hour $currentHour is between ${deviceSettings.autoSleepTimerStartTime} and ${deviceSettings.autoSleepTimerEndTime} - starting sleep timer")
+ // Automatically Rewind in the book if settings is enabled
+ if (deviceSettings.autoSleepTimerAutoRewind && !isFirstAutoSleepTimer) {
+ Log.i(tag, "Auto sleep timer auto rewind seeking back ${deviceSettings.autoSleepTimerAutoRewindTime}ms")
+ playerNotificationService.seekBackward(deviceSettings.autoSleepTimerAutoRewindTime)
+ }
+ isFirstAutoSleepTimer = false
+
// Set sleep timer
// When sleepTimerLength is 0 then use end of chapter/track time
if (deviceSettings.sleepTimerLength == 0L) {
@@ -358,13 +379,23 @@ class SleepTimerManager constructor(private val playerNotificationService: Playe
setSleepTimer(deviceSettings.sleepTimerLength, false)
}
} else {
+ isFirstAutoSleepTimer = true
Log.d(tag, "Current hour $currentHour is NOT between ${deviceSettings.autoSleepTimerStartTime} and ${deviceSettings.autoSleepTimerEndTime}")
}
}
}
- fun handleMediaPlayEvent() {
- checkShouldResetSleepTimer()
+ fun handleMediaPlayEvent(playbackSessionId:String) {
+ // Check if the playback session has changed
+ // If it hasn't changed OR the sleep timer is running then check reset the timer
+ // e.g. You set a manual sleep timer for 10 mins, then decide to change books, the sleep timer will stay on and reset to 10 mins
+ if (sleepTimerSessionId == playbackSessionId || sleepTimerRunning) {
+ checkShouldResetSleepTimer()
+ } else {
+ isFirstAutoSleepTimer = true
+ }
+ sleepTimerSessionId = playbackSessionId
+
checkAutoSleepTimer()
}
}
diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerListener.kt b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerListener.kt
index d7d42f7a..e4ae9c47 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerListener.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerListener.kt
@@ -92,12 +92,15 @@ class PlayerListener(var playerNotificationService:PlayerNotificationService) :
// Start/stop progress sync interval
if (isPlaying) {
- // Handles auto-starting sleep timer and resetting sleep timer
- playerNotificationService.sleepTimerManager.handleMediaPlayEvent()
-
- player.volume = 1F // Volume on sleep timer might have decreased this
val playbackSession: PlaybackSession? = playerNotificationService.mediaProgressSyncer.currentPlaybackSession ?: playerNotificationService.currentPlaybackSession
- playbackSession?.let { playerNotificationService.mediaProgressSyncer.play(it) }
+ playbackSession?.let {
+ // Handles auto-starting sleep timer and resetting sleep timer
+ playerNotificationService.sleepTimerManager.handleMediaPlayEvent(it.id)
+
+ player.volume = 1F // Volume on sleep timer might have decreased this
+
+ playerNotificationService.mediaProgressSyncer.play(it)
+ }
} else {
playerNotificationService.mediaProgressSyncer.pause {
Log.d(tag, "Media Progress Syncer paused and synced")
diff --git a/android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt b/android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt
index a19d2227..a3b6a6e1 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt
@@ -341,7 +341,8 @@ class AbsAudioPlayer : Plugin() {
val isChapterTime:Boolean = call.getBoolean("isChapterTime", false) == true
Handler(Looper.getMainLooper()).post {
- val success:Boolean = playerNotificationService.sleepTimerManager.setManualSleepTimer(time, isChapterTime)
+ val playbackSession: PlaybackSession? = playerNotificationService.mediaProgressSyncer.currentPlaybackSession ?: playerNotificationService.currentPlaybackSession
+ val success:Boolean = playerNotificationService.sleepTimerManager.setManualSleepTimer(playbackSession?.id ?: "", time, isChapterTime)
val ret = JSObject()
ret.put("success", success)
call.resolve(ret)
diff --git a/components/modals/AutoSleepTimerRewindLengthModal.vue b/components/modals/AutoSleepTimerRewindLengthModal.vue
new file mode 100644
index 00000000..2f13df25
--- /dev/null
+++ b/components/modals/AutoSleepTimerRewindLengthModal.vue
@@ -0,0 +1,95 @@
+
+ Auto Rewind Time {{ manualTimeoutMin }} min
+
+
+
Auto Sleep Timer Auto Rewind
+ +Auto Rewind Time
+