mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-29 14:28:34 +02:00
Fix: Sleep timer for multi-track playback sessions - use duration of all tracks stored in playback session instead of duration from exoplayer #140
This commit is contained in:
parent
d18972e2f3
commit
2dd822e04d
5 changed files with 29 additions and 28 deletions
|
@ -51,8 +51,8 @@ data class LocalLibraryItem(
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
fun updateFromScan(audioTracks:MutableList<AudioTrack>, _localFiles:MutableList<LocalFile>) {
|
fun updateFromScan(audioTracks:MutableList<AudioTrack>, _localFiles:MutableList<LocalFile>) {
|
||||||
media.setAudioTracks(audioTracks)
|
|
||||||
localFiles = _localFiles
|
localFiles = _localFiles
|
||||||
|
media.setAudioTracks(audioTracks)
|
||||||
|
|
||||||
if (coverContentUrl != null) {
|
if (coverContentUrl != null) {
|
||||||
if (localFiles.find { it.contentUrl == coverContentUrl } == null) {
|
if (localFiles.find { it.contentUrl == coverContentUrl } == null) {
|
||||||
|
|
|
@ -57,6 +57,8 @@ class PlaybackSession(
|
||||||
@get:JsonIgnore
|
@get:JsonIgnore
|
||||||
val currentTimeMs get() = (currentTime * 1000L).toLong()
|
val currentTimeMs get() = (currentTime * 1000L).toLong()
|
||||||
@get:JsonIgnore
|
@get:JsonIgnore
|
||||||
|
val totalDurationMs get() = (getTotalDuration() * 1000L).toLong()
|
||||||
|
@get:JsonIgnore
|
||||||
val localLibraryItemId get() = localLibraryItem?.id ?: ""
|
val localLibraryItemId get() = localLibraryItem?.id ?: ""
|
||||||
@get:JsonIgnore
|
@get:JsonIgnore
|
||||||
val localMediaProgressId get() = if (episodeId.isNullOrEmpty()) localLibraryItemId else "$localLibraryItemId-$localEpisodeId"
|
val localMediaProgressId get() = if (episodeId.isNullOrEmpty()) localLibraryItemId else "$localLibraryItemId-$localEpisodeId"
|
||||||
|
|
|
@ -36,7 +36,7 @@ class FolderScanner(var ctx: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var df: DocumentFile? = DocumentFileCompat.fromUri(ctx, Uri.parse(localFolder.contentUrl))
|
val df: DocumentFile? = DocumentFileCompat.fromUri(ctx, Uri.parse(localFolder.contentUrl))
|
||||||
|
|
||||||
if (df == null) {
|
if (df == null) {
|
||||||
Log.e(tag, "Folder Doc File Invalid $localFolder.contentUrl")
|
Log.e(tag, "Folder Doc File Invalid $localFolder.contentUrl")
|
||||||
|
@ -49,7 +49,7 @@ class FolderScanner(var ctx: Context) {
|
||||||
var mediaItemsUpToDate = 0
|
var mediaItemsUpToDate = 0
|
||||||
|
|
||||||
// Search for files in media item folder
|
// Search for files in media item folder
|
||||||
var foldersFound = df.search(false, DocumentFileType.FOLDER)
|
val foldersFound = df.search(false, DocumentFileType.FOLDER)
|
||||||
|
|
||||||
// Match folders found with local library items already saved in db
|
// Match folders found with local library items already saved in db
|
||||||
var existingLocalLibraryItems = DeviceManager.dbManager.getLocalLibraryItemsInFolder(localFolder.id)
|
var existingLocalLibraryItems = DeviceManager.dbManager.getLocalLibraryItemsInFolder(localFolder.id)
|
||||||
|
@ -57,7 +57,7 @@ class FolderScanner(var ctx: Context) {
|
||||||
// Remove existing items no longer there
|
// Remove existing items no longer there
|
||||||
existingLocalLibraryItems = existingLocalLibraryItems.filter { lli ->
|
existingLocalLibraryItems = existingLocalLibraryItems.filter { lli ->
|
||||||
Log.d(tag, "scanForMediaItems Checking Existing LLI ${lli.id}")
|
Log.d(tag, "scanForMediaItems Checking Existing LLI ${lli.id}")
|
||||||
var fileFound = foldersFound.find { f -> lli.id == getLocalLibraryItemId(f.id) }
|
val fileFound = foldersFound.find { f -> lli.id == getLocalLibraryItemId(f.id) }
|
||||||
if (fileFound == null) {
|
if (fileFound == null) {
|
||||||
Log.d(tag, "Existing local library item is no longer in file system ${lli.media.metadata.title}")
|
Log.d(tag, "Existing local library item is no longer in file system ${lli.media.metadata.title}")
|
||||||
DeviceManager.dbManager.removeLocalLibraryItem(lli.id)
|
DeviceManager.dbManager.removeLocalLibraryItem(lli.id)
|
||||||
|
@ -68,9 +68,9 @@ class FolderScanner(var ctx: Context) {
|
||||||
|
|
||||||
foldersFound.forEach { itemFolder ->
|
foldersFound.forEach { itemFolder ->
|
||||||
Log.d(tag, "Iterating over Folder Found ${itemFolder.name} | ${itemFolder.getSimplePath(ctx)} | URI: ${itemFolder.uri}")
|
Log.d(tag, "Iterating over Folder Found ${itemFolder.name} | ${itemFolder.getSimplePath(ctx)} | URI: ${itemFolder.uri}")
|
||||||
var existingItem = existingLocalLibraryItems.find { emi -> emi.id == getLocalLibraryItemId(itemFolder.id) }
|
val existingItem = existingLocalLibraryItems.find { emi -> emi.id == getLocalLibraryItemId(itemFolder.id) }
|
||||||
|
|
||||||
var result = scanLibraryItemFolder(itemFolder, localFolder, existingItem, forceAudioProbe)
|
val result = scanLibraryItemFolder(itemFolder, localFolder, existingItem, forceAudioProbe)
|
||||||
|
|
||||||
if (result == ItemScanResult.REMOVED) mediaItemsRemoved++
|
if (result == ItemScanResult.REMOVED) mediaItemsRemoved++
|
||||||
else if (result == ItemScanResult.UPDATED) mediaItemsUpdated++
|
else if (result == ItemScanResult.UPDATED) mediaItemsUpdated++
|
||||||
|
@ -90,25 +90,23 @@ class FolderScanner(var ctx: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun scanLibraryItemFolder(itemFolder:DocumentFile, localFolder:LocalFolder, existingItem:LocalLibraryItem?, forceAudioProbe:Boolean):ItemScanResult {
|
fun scanLibraryItemFolder(itemFolder:DocumentFile, localFolder:LocalFolder, existingItem:LocalLibraryItem?, forceAudioProbe:Boolean):ItemScanResult {
|
||||||
var itemFolderName = itemFolder.name ?: ""
|
val itemFolderName = itemFolder.name ?: ""
|
||||||
var itemId = getLocalLibraryItemId(itemFolder.id)
|
val itemId = getLocalLibraryItemId(itemFolder.id)
|
||||||
|
|
||||||
var existingLocalFiles = existingItem?.localFiles ?: mutableListOf()
|
val existingLocalFiles = existingItem?.localFiles ?: mutableListOf()
|
||||||
var existingAudioTracks = existingItem?.media?.getAudioTracks() ?: mutableListOf()
|
val existingAudioTracks = existingItem?.media?.getAudioTracks() ?: mutableListOf()
|
||||||
var isNewOrUpdated = existingItem == null
|
var isNewOrUpdated = existingItem == null
|
||||||
|
|
||||||
var audioTracks = mutableListOf<AudioTrack>()
|
val audioTracks = mutableListOf<AudioTrack>()
|
||||||
var localFiles = mutableListOf<LocalFile>()
|
val localFiles = mutableListOf<LocalFile>()
|
||||||
var index = 1
|
var index = 1
|
||||||
var startOffset = 0.0
|
var startOffset = 0.0
|
||||||
var coverContentUrl:String? = null
|
var coverContentUrl:String? = null
|
||||||
var coverAbsolutePath:String? = null
|
var coverAbsolutePath:String? = null
|
||||||
|
|
||||||
// itemFolder.search(false, DocumentFileType.FILE, arrayOf("audio"))
|
val filesInFolder = itemFolder.search(false, DocumentFileType.FILE, arrayOf("audio/*", "image/*", "video/mp4"))
|
||||||
|
|
||||||
var filesInFolder = itemFolder.search(false, DocumentFileType.FILE, arrayOf("audio/*", "image/*", "video/mp4"))
|
val existingLocalFilesRemoved = existingLocalFiles.filter { elf ->
|
||||||
|
|
||||||
var existingLocalFilesRemoved = existingLocalFiles.filter { elf ->
|
|
||||||
filesInFolder.find { fif -> DeviceManager.getBase64Id(fif.id) == elf.id } == null // File was not found in media item folder
|
filesInFolder.find { fif -> DeviceManager.getBase64Id(fif.id) == elf.id } == null // File was not found in media item folder
|
||||||
}
|
}
|
||||||
if (existingLocalFilesRemoved.isNotEmpty()) {
|
if (existingLocalFilesRemoved.isNotEmpty()) {
|
||||||
|
@ -117,14 +115,14 @@ class FolderScanner(var ctx: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
filesInFolder.forEach { file ->
|
filesInFolder.forEach { file ->
|
||||||
var mimeType = file.mimeType ?: ""
|
val mimeType = file.mimeType ?: ""
|
||||||
var filename = file.name ?: ""
|
val filename = file.name ?: ""
|
||||||
var isAudio = mimeType.startsWith("audio") || mimeType == "video/mp4"
|
val isAudio = mimeType.startsWith("audio") || mimeType == "video/mp4"
|
||||||
Log.d(tag, "Found $mimeType file $filename in folder $itemFolderName")
|
Log.d(tag, "Found $mimeType file $filename in folder $itemFolderName")
|
||||||
|
|
||||||
var localFileId = DeviceManager.getBase64Id(file.id)
|
val localFileId = DeviceManager.getBase64Id(file.id)
|
||||||
|
|
||||||
var localFile = LocalFile(localFileId,filename,file.uri.toString(),file.getBasePath(ctx), file.getAbsolutePath(ctx),file.getSimplePath(ctx),mimeType,file.length())
|
val localFile = LocalFile(localFileId,filename,file.uri.toString(),file.getBasePath(ctx), file.getAbsolutePath(ctx),file.getSimplePath(ctx),mimeType,file.length())
|
||||||
localFiles.add(localFile)
|
localFiles.add(localFile)
|
||||||
|
|
||||||
Log.d(tag, "File attributes Id:${localFileId}|ContentUrl:${localFile.contentUrl}|isDownloadsDocument:${file.isDownloadsDocument}")
|
Log.d(tag, "File attributes Id:${localFileId}|ContentUrl:${localFile.contentUrl}|isDownloadsDocument:${file.isDownloadsDocument}")
|
||||||
|
@ -132,7 +130,7 @@ class FolderScanner(var ctx: Context) {
|
||||||
if (isAudio) {
|
if (isAudio) {
|
||||||
var audioTrackToAdd:AudioTrack? = null
|
var audioTrackToAdd:AudioTrack? = null
|
||||||
|
|
||||||
var existingAudioTrack = existingAudioTracks.find { eat -> eat.localFileId == localFileId }
|
val existingAudioTrack = existingAudioTracks.find { eat -> eat.localFileId == localFileId }
|
||||||
if (existingAudioTrack != null) { // Update existing audio track
|
if (existingAudioTrack != null) { // Update existing audio track
|
||||||
if (existingAudioTrack.index != index) {
|
if (existingAudioTrack.index != index) {
|
||||||
Log.d(tag, "scanLibraryItemFolder Updating Audio track index from ${existingAudioTrack.index} to $index")
|
Log.d(tag, "scanLibraryItemFolder Updating Audio track index from ${existingAudioTrack.index} to $index")
|
||||||
|
@ -150,7 +148,7 @@ class FolderScanner(var ctx: Context) {
|
||||||
Log.d(tag, "scanLibraryItemFolder Scanning Audio File Path ${localFile.absolutePath} | ForceAudioProbe=${forceAudioProbe}")
|
Log.d(tag, "scanLibraryItemFolder Scanning Audio File Path ${localFile.absolutePath} | ForceAudioProbe=${forceAudioProbe}")
|
||||||
|
|
||||||
// TODO: Make asynchronous
|
// TODO: Make asynchronous
|
||||||
var audioProbeResult = probeAudioFile(localFile.absolutePath)
|
val audioProbeResult = probeAudioFile(localFile.absolutePath)
|
||||||
|
|
||||||
if (existingAudioTrack != null) {
|
if (existingAudioTrack != null) {
|
||||||
// Update audio probe data on existing audio track
|
// Update audio probe data on existing audio track
|
||||||
|
@ -172,7 +170,7 @@ class FolderScanner(var ctx: Context) {
|
||||||
index++
|
index++
|
||||||
audioTracks.add(audioTrackToAdd)
|
audioTracks.add(audioTrackToAdd)
|
||||||
} else {
|
} else {
|
||||||
var existingLocalFile = existingLocalFiles.find { elf -> elf.id == localFileId }
|
val existingLocalFile = existingLocalFiles.find { elf -> elf.id == localFileId }
|
||||||
|
|
||||||
if (existingLocalFile == null) {
|
if (existingLocalFile == null) {
|
||||||
Log.d(tag, "scanLibraryItemFolder new local file found ${localFile.absolutePath}")
|
Log.d(tag, "scanLibraryItemFolder new local file found ${localFile.absolutePath}")
|
||||||
|
@ -209,8 +207,8 @@ class FolderScanner(var ctx: Context) {
|
||||||
return ItemScanResult.UPDATED
|
return ItemScanResult.UPDATED
|
||||||
} else if (audioTracks.isNotEmpty()) {
|
} else if (audioTracks.isNotEmpty()) {
|
||||||
Log.d(tag, "Found local media item named $itemFolderName with ${audioTracks.size} tracks and ${localFiles.size} local files")
|
Log.d(tag, "Found local media item named $itemFolderName with ${audioTracks.size} tracks and ${localFiles.size} local files")
|
||||||
var localMediaItem = LocalMediaItem(itemId, itemFolderName, localFolder.mediaType, localFolder.id, itemFolder.uri.toString(), itemFolder.getSimplePath(ctx), itemFolder.getBasePath(ctx), itemFolder.getAbsolutePath(ctx),audioTracks,localFiles,coverContentUrl,coverAbsolutePath)
|
val localMediaItem = LocalMediaItem(itemId, itemFolderName, localFolder.mediaType, localFolder.id, itemFolder.uri.toString(), itemFolder.getSimplePath(ctx), itemFolder.getBasePath(ctx), itemFolder.getAbsolutePath(ctx),audioTracks,localFiles,coverContentUrl,coverAbsolutePath)
|
||||||
var localLibraryItem = localMediaItem.getLocalLibraryItem()
|
val localLibraryItem = localMediaItem.getLocalLibraryItem()
|
||||||
DeviceManager.dbManager.saveLocalLibraryItem(localLibraryItem)
|
DeviceManager.dbManager.saveLocalLibraryItem(localLibraryItem)
|
||||||
return ItemScanResult.ADDED
|
return ItemScanResult.ADDED
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -454,7 +454,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDuration() : Long {
|
fun getDuration() : Long {
|
||||||
return currentPlayer.duration
|
return currentPlaybackSession?.totalDurationMs ?: 0L
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentBookTitle() : String? {
|
fun getCurrentBookTitle() : String? {
|
||||||
|
|
|
@ -13,8 +13,9 @@
|
||||||
<p class="text-sm text-gray-400">by {{ author }}</p>
|
<p class="text-sm text-gray-400">by {{ author }}</p>
|
||||||
<p v-if="numTracks" class="text-gray-300 text-sm my-1">
|
<p v-if="numTracks" class="text-gray-300 text-sm my-1">
|
||||||
{{ $elapsedPretty(duration) }}
|
{{ $elapsedPretty(duration) }}
|
||||||
<span class="px-4">{{ $bytesPretty(size) }}</span>
|
<span v-if="!isLocal" class="px-4">{{ $bytesPretty(size) }}</span>
|
||||||
</p>
|
</p>
|
||||||
|
<p v-if="numTracks" class="text-gray-300 text-sm my-1">{{ numTracks }} Tracks</p>
|
||||||
|
|
||||||
<div v-if="!isPodcast && progressPercent > 0" class="px-4 py-2 bg-primary text-sm font-semibold rounded-md text-gray-200 mt-4 relative" :class="resettingProgress ? 'opacity-25' : ''">
|
<div v-if="!isPodcast && progressPercent > 0" class="px-4 py-2 bg-primary text-sm font-semibold rounded-md text-gray-200 mt-4 relative" :class="resettingProgress ? 'opacity-25' : ''">
|
||||||
<p class="leading-6">Your Progress: {{ Math.round(progressPercent * 100) }}%</p>
|
<p class="leading-6">Your Progress: {{ Math.round(progressPercent * 100) }}%</p>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue