mirror of
https://github.com/sudoxnym/audiobookshelf-atv.git
synced 2026-04-14 19:46:30 +00:00
Android cleaning up and refactoring
This commit is contained in:
parent
4b834cb5c1
commit
cc744bb975
14 changed files with 107 additions and 689 deletions
|
|
@ -4,13 +4,7 @@ import android.app.DownloadManager
|
|||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.util.Log
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.anggrayudi.storage.SimpleStorage
|
||||
import com.anggrayudi.storage.callback.FileCallback
|
||||
import com.anggrayudi.storage.file.*
|
||||
import com.anggrayudi.storage.media.FileDescription
|
||||
import com.audiobookshelf.app.data.LibraryItem
|
||||
import com.audiobookshelf.app.data.LocalFolder
|
||||
import com.audiobookshelf.app.device.DeviceManager
|
||||
|
|
@ -28,7 +22,6 @@ import kotlinx.coroutines.GlobalScope
|
|||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
package com.audiobookshelf.app
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.support.v4.media.MediaBrowserCompat
|
||||
import android.support.v4.media.MediaDescriptionCompat
|
||||
import android.support.v4.media.MediaMetadataCompat
|
||||
import com.getcapacitor.JSObject
|
||||
|
||||
|
|
@ -70,10 +67,6 @@ class Audiobook {
|
|||
return Uri.parse("$serverUrl${book.cover}?token=$token&ts=${book.lastUpdate}")
|
||||
}
|
||||
|
||||
fun getDurationLong():Long {
|
||||
return duration.toLong() * 1000L
|
||||
}
|
||||
|
||||
fun toMediaMetadata():MediaMetadataCompat {
|
||||
return MediaMetadataCompat.Builder().apply {
|
||||
putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, id)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.os.Looper
|
|||
import android.support.v4.media.MediaMetadataCompat
|
||||
|
||||
import android.util.Log
|
||||
import com.audiobookshelf.app.device.DeviceManager
|
||||
import com.getcapacitor.JSObject
|
||||
import okhttp3.*
|
||||
import org.json.JSONArray
|
||||
|
|
@ -16,58 +17,23 @@ import java.io.IOException
|
|||
class AudiobookManager {
|
||||
var tag = "AudiobookManager"
|
||||
|
||||
interface OnStreamData {
|
||||
fun onStreamReady(asd:AudiobookStreamData)
|
||||
}
|
||||
|
||||
var hasLoaded = false
|
||||
var isLoading = false
|
||||
var ctx: Context
|
||||
var serverUrl = ""
|
||||
var token = ""
|
||||
private var client:OkHttpClient
|
||||
|
||||
var localMediaManager:LocalMediaManager
|
||||
|
||||
var audiobooks:MutableList<Audiobook> = mutableListOf()
|
||||
var audiobooksInProgress:MutableList<Audiobook> = mutableListOf()
|
||||
|
||||
var storageSharedPreferences: SharedPreferences? = null
|
||||
|
||||
constructor(_ctx:Context, _client:OkHttpClient) {
|
||||
ctx = _ctx
|
||||
client = _client
|
||||
|
||||
localMediaManager = LocalMediaManager(ctx)
|
||||
}
|
||||
|
||||
fun init() {
|
||||
storageSharedPreferences = ctx.getSharedPreferences("CapacitorStorage", Activity.MODE_PRIVATE)
|
||||
serverUrl = storageSharedPreferences?.getString("serverUrl", "").toString()
|
||||
Log.d(tag, "SHARED PREF SERVERURL $serverUrl")
|
||||
token = storageSharedPreferences?.getString("token", "").toString()
|
||||
Log.d(tag, "SHARED PREF TOKEN $token")
|
||||
}
|
||||
|
||||
fun getPlaybackRate() : Float {
|
||||
if (storageSharedPreferences != null) {
|
||||
var userSettings = storageSharedPreferences?.getString("userSettings", "").toString()
|
||||
if (userSettings != "") {
|
||||
var json = JSObject(userSettings)
|
||||
var playbackRate = json.getString("playbackRate", "1")
|
||||
if (playbackRate != null) {
|
||||
return playbackRate.toFloat()
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1f
|
||||
}
|
||||
|
||||
fun loadCategories(cb: (() -> Unit)) {
|
||||
Log.d(tag, "LOAD Categories $serverUrl | $token")
|
||||
var url = "$serverUrl/api/libraries/main/categories"
|
||||
var url = "${DeviceManager.serverAddress}/api/libraries/main/categories"
|
||||
val request = Request.Builder()
|
||||
.url(url).addHeader("Authorization", "Bearer $token")
|
||||
.url(url).addHeader("Authorization", "Bearer ${DeviceManager.token}")
|
||||
.build()
|
||||
|
||||
client.newCall(request).enqueue(object : Callback {
|
||||
|
|
@ -101,7 +67,7 @@ class AudiobookManager {
|
|||
Log.d(tag, "Shelf category ab id $y = ${abobj.toString()}")
|
||||
var abjsobj = JSObject(abobj.toString())
|
||||
abjsobj.put("isDownloaded", false)
|
||||
var audiobook = Audiobook(abjsobj, serverUrl, token)
|
||||
var audiobook = Audiobook(abjsobj, DeviceManager.serverAddress, DeviceManager.token)
|
||||
if (audiobook.isMissing || audiobook.isInvalid || audiobook.numTracks <= 0) {
|
||||
Log.d(tag, "Not an audiobook or invalid/missing")
|
||||
} else {
|
||||
|
|
@ -121,13 +87,12 @@ class AudiobookManager {
|
|||
}
|
||||
|
||||
fun loadAudiobooks(cb: (() -> Unit)) {
|
||||
Log.d(tag, "Load Audiobooks: $serverUrl | $token")
|
||||
if (serverUrl == "" || token == "") {
|
||||
if (DeviceManager.serverAddress == "" || DeviceManager.token == "") {
|
||||
Log.d(tag, "Load Audiobooks: No Server or Token set")
|
||||
cb()
|
||||
return
|
||||
} else if (!serverUrl.startsWith("http")) {
|
||||
Log.e(tag, "Load Audiobooks: Invalid server url $serverUrl")
|
||||
} else if (!DeviceManager.serverAddress.startsWith("http")) {
|
||||
Log.e(tag, "Load Audiobooks: Invalid server url ${DeviceManager.serverAddress}")
|
||||
cb()
|
||||
return
|
||||
}
|
||||
|
|
@ -135,9 +100,9 @@ class AudiobookManager {
|
|||
// First load currently reading
|
||||
loadCategories() {
|
||||
// Then load all
|
||||
var url = "$serverUrl/api/libraries/main/books/all?sort=book.title"
|
||||
var url = "${DeviceManager.serverAddress}/api/libraries/main/books/all?sort=book.title"
|
||||
val request = Request.Builder()
|
||||
.url(url).addHeader("Authorization", "Bearer $token")
|
||||
.url(url).addHeader("Authorization", "Bearer ${DeviceManager.token}")
|
||||
.build()
|
||||
|
||||
client.newCall(request).enqueue(object : Callback {
|
||||
|
|
@ -161,7 +126,7 @@ class AudiobookManager {
|
|||
var jsobj = JSObject(abobj.toString())
|
||||
|
||||
jsobj.put("isDownloaded", false)
|
||||
var audiobook = Audiobook(jsobj, serverUrl, token)
|
||||
var audiobook = Audiobook(jsobj, DeviceManager.serverAddress, DeviceManager.token)
|
||||
|
||||
if (audiobook.isMissing || audiobook.isInvalid) {
|
||||
Log.d(tag, "Audiobook ${audiobook.book.title} is missing or invalid")
|
||||
|
|
@ -187,100 +152,6 @@ class AudiobookManager {
|
|||
fun load() {
|
||||
isLoading = true
|
||||
hasLoaded = true
|
||||
|
||||
localMediaManager.loadLocalAudio()
|
||||
}
|
||||
|
||||
fun openStream(audiobook:Audiobook, streamListener:OnStreamData) {
|
||||
var url = "$serverUrl/api/books/${audiobook.id}/stream"
|
||||
val request = Request.Builder()
|
||||
.url(url).addHeader("Authorization", "Bearer $token")
|
||||
.build()
|
||||
|
||||
client.newCall(request).enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
response.use {
|
||||
if (!response.isSuccessful) throw IOException("Unexpected code $response")
|
||||
|
||||
var playbackRate = getPlaybackRate()
|
||||
|
||||
var bodyString = response.body!!.string()
|
||||
var stream = JSObject(bodyString)
|
||||
var streamId = stream.getString("streamId", "").toString()
|
||||
var startTime = stream.getDouble("startTime")
|
||||
var streamUrl = stream.getString("streamUrl", "").toString()
|
||||
|
||||
var startTimeLong = (startTime * 1000).toLong()
|
||||
|
||||
var abStreamDataObj = JSObject()
|
||||
abStreamDataObj.put("id", streamId)
|
||||
abStreamDataObj.put("audiobookId", audiobook.id)
|
||||
abStreamDataObj.put("playlistUrl", "$serverUrl$streamUrl")
|
||||
abStreamDataObj.put("title", audiobook.book.title)
|
||||
abStreamDataObj.put("author", audiobook.book.authorFL)
|
||||
abStreamDataObj.put("token", token)
|
||||
abStreamDataObj.put("cover", audiobook.getCover())
|
||||
abStreamDataObj.put("duration", audiobook.getDurationLong())
|
||||
abStreamDataObj.put("startTime", startTimeLong)
|
||||
abStreamDataObj.put("playbackSpeed", playbackRate)
|
||||
abStreamDataObj.put("playWhenReady", true)
|
||||
abStreamDataObj.put("isLocal", false)
|
||||
|
||||
var audiobookStreamData = AudiobookStreamData(abStreamDataObj)
|
||||
|
||||
Handler(Looper.getMainLooper()).post() {
|
||||
Log.d(tag, "Stream Ready on Main Looper")
|
||||
streamListener.onStreamReady(audiobookStreamData)
|
||||
}
|
||||
|
||||
Log.d(tag, "Init Player Stream")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun initDownloadPlay(audiobook:Audiobook):AudiobookStreamData {
|
||||
var playbackRate = getPlaybackRate()
|
||||
|
||||
var abStreamDataObj = JSObject()
|
||||
abStreamDataObj.put("id", "download")
|
||||
abStreamDataObj.put("audiobookId", audiobook.id)
|
||||
abStreamDataObj.put("contentUrl", audiobook.contentUrl)
|
||||
abStreamDataObj.put("title", audiobook.book.title)
|
||||
abStreamDataObj.put("author", audiobook.book.authorFL)
|
||||
abStreamDataObj.put("token", null)
|
||||
abStreamDataObj.put("cover", audiobook.getCover())
|
||||
abStreamDataObj.put("duration", audiobook.getDurationLong())
|
||||
abStreamDataObj.put("startTime", 0)
|
||||
abStreamDataObj.put("playbackSpeed", playbackRate)
|
||||
abStreamDataObj.put("playWhenReady", true)
|
||||
abStreamDataObj.put("isLocal", true)
|
||||
|
||||
var audiobookStreamData = AudiobookStreamData(abStreamDataObj)
|
||||
return audiobookStreamData
|
||||
}
|
||||
|
||||
fun initLocalPlay(local: LocalMediaManager.LocalAudio):AudiobookStreamData {
|
||||
var abStreamDataObj = JSObject()
|
||||
abStreamDataObj.put("id", "local")
|
||||
abStreamDataObj.put("audiobookId", local.id)
|
||||
abStreamDataObj.put("contentUrl", local.uri.toString())
|
||||
abStreamDataObj.put("title", local.name)
|
||||
abStreamDataObj.put("author", "")
|
||||
abStreamDataObj.put("token", null)
|
||||
abStreamDataObj.put("cover", local.coverUri)
|
||||
abStreamDataObj.put("duration", local.duration)
|
||||
abStreamDataObj.put("startTime", 0)
|
||||
abStreamDataObj.put("playbackSpeed", 1)
|
||||
abStreamDataObj.put("playWhenReady", true)
|
||||
abStreamDataObj.put("isLocal", true)
|
||||
|
||||
var audiobookStreamData = AudiobookStreamData(abStreamDataObj)
|
||||
return audiobookStreamData
|
||||
}
|
||||
|
||||
private fun levenshtein(lhs : CharSequence, rhs : CharSequence) : Int {
|
||||
|
|
@ -333,20 +204,14 @@ class AudiobookManager {
|
|||
}
|
||||
|
||||
fun getFirstAudiobook():Audiobook? {
|
||||
if (audiobooks.isEmpty()) return null
|
||||
return audiobooks[0]
|
||||
}
|
||||
|
||||
fun getFirstLocal(): LocalMediaManager.LocalAudio? {
|
||||
if (localMediaManager.localAudioFiles.isEmpty()) return null
|
||||
return localMediaManager.localAudioFiles[0]
|
||||
return null
|
||||
}
|
||||
|
||||
// Used for media browser loadChildren, fallback to using the samples if no audiobooks are there
|
||||
fun getAudiobooksMediaMetadata() : List<MediaMetadataCompat> {
|
||||
var mediaMetadata:MutableList<MediaMetadataCompat> = mutableListOf()
|
||||
if (audiobooks.isEmpty()) {
|
||||
localMediaManager.localAudioFiles.forEach { mediaMetadata.add(it.toMediaMetadata()) }
|
||||
|
||||
} else {
|
||||
audiobooks.forEach { mediaMetadata.add(it.toMediaMetadata()) }
|
||||
}
|
||||
|
|
@ -356,7 +221,7 @@ class AudiobookManager {
|
|||
fun getDownloadedAudiobooksMediaMetadata() : List<MediaMetadataCompat> {
|
||||
var mediaMetadata:MutableList<MediaMetadataCompat> = mutableListOf()
|
||||
if (audiobooks.isEmpty()) {
|
||||
localMediaManager.localAudioFiles.forEach { mediaMetadata.add(it.toMediaMetadata()) }
|
||||
|
||||
} else {
|
||||
audiobooks.forEach { if (it.isDownloaded) { mediaMetadata.add(it.toMediaMetadata()) } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,176 +0,0 @@
|
|||
package com.audiobookshelf.app
|
||||
|
||||
import android.net.Uri
|
||||
import android.support.v4.media.MediaMetadataCompat
|
||||
import android.util.Log
|
||||
import com.getcapacitor.JSObject
|
||||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.MediaMetadata
|
||||
import com.google.android.exoplayer2.util.MimeTypes
|
||||
import java.lang.Exception
|
||||
|
||||
class AudiobookStreamData {
|
||||
var id:String = "unset"
|
||||
var audiobookId:String = ""
|
||||
var token:String = ""
|
||||
var playlistUrl:String = ""
|
||||
var title:String = "No Title"
|
||||
var author:String = "Unknown"
|
||||
var series:String = ""
|
||||
var cover:String = ""
|
||||
var playWhenReady:Boolean = false
|
||||
var startTime:Long = 0
|
||||
var playbackSpeed:Float = 1f
|
||||
var duration:Long = 0
|
||||
var tracks:MutableList<String> = mutableListOf()
|
||||
|
||||
var isLocal:Boolean = false
|
||||
var contentUrl:String = ""
|
||||
|
||||
var hasPlayerLoaded:Boolean = false
|
||||
|
||||
var playlistUri:Uri = Uri.EMPTY
|
||||
var coverUri:Uri = Uri.EMPTY
|
||||
var contentUri:Uri = Uri.EMPTY // For Local only
|
||||
|
||||
constructor(jsondata:JSObject) {
|
||||
id = jsondata.getString("id", "unset").toString()
|
||||
audiobookId = jsondata.getString("audiobookId", "").toString()
|
||||
title = jsondata.getString("title", "No Title").toString()
|
||||
token = jsondata.getString("token", "").toString()
|
||||
author = jsondata.getString("author", "Unknown").toString()
|
||||
series = jsondata.getString("series", "").toString()
|
||||
cover = jsondata.getString("cover", "").toString()
|
||||
playlistUrl = jsondata.getString("playlistUrl", "").toString()
|
||||
playWhenReady = jsondata.getBoolean("playWhenReady", false) == true
|
||||
|
||||
if (jsondata.has("startTime")) {
|
||||
startTime = jsondata.getString("startTime", "0")!!.toLong()
|
||||
}
|
||||
|
||||
if (jsondata.has("duration")) {
|
||||
duration = jsondata.getString("duration", "0")!!.toLong()
|
||||
}
|
||||
|
||||
if (jsondata.has("playbackSpeed")) {
|
||||
playbackSpeed = jsondata.getDouble("playbackSpeed")!!.toFloat()
|
||||
}
|
||||
|
||||
|
||||
// Local data
|
||||
isLocal = jsondata.getBoolean("isLocal", false) == true
|
||||
contentUrl = jsondata.getString("contentUrl", "").toString()
|
||||
|
||||
if (playlistUrl != "") {
|
||||
playlistUri = Uri.parse(playlistUrl)
|
||||
}
|
||||
if (cover != "" && cover != null) {
|
||||
coverUri = Uri.parse(cover)
|
||||
} else {
|
||||
coverUri = Uri.parse("android.resource://com.audiobookshelf.app/" + R.drawable.icon)
|
||||
cover = coverUri.toString()
|
||||
}
|
||||
|
||||
if (contentUrl != "") {
|
||||
contentUri = Uri.parse(contentUrl)
|
||||
}
|
||||
|
||||
// Tracks for cast
|
||||
try {
|
||||
var tracksTest = jsondata.getJSONArray("tracks")
|
||||
Log.d("AudiobookStreamData", "Load tracks from json array ${tracksTest.length()}")
|
||||
for (i in 0 until tracksTest.length()) {
|
||||
var track = tracksTest.get(i)
|
||||
Log.d("AudiobookStreamData", "Extracting track $track")
|
||||
tracks.add(track as String)
|
||||
}
|
||||
} catch(e:Exception) {
|
||||
Log.d("AudiobookStreamData", "No tracks found $e")
|
||||
}
|
||||
}
|
||||
|
||||
fun clearCover() {
|
||||
coverUri = Uri.EMPTY
|
||||
cover = ""
|
||||
}
|
||||
|
||||
fun getMediaMetadataCompat():MediaMetadataCompat {
|
||||
var metadataBuilder = MediaMetadataCompat.Builder()
|
||||
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
|
||||
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, title)
|
||||
.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, author)
|
||||
.putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, author)
|
||||
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, author)
|
||||
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, series)
|
||||
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, id)
|
||||
|
||||
// if (cover != "") {
|
||||
// metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, cover)
|
||||
// metadataBuilder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, cover)
|
||||
// }
|
||||
return metadataBuilder.build()
|
||||
}
|
||||
|
||||
fun getMediaMetadata():MediaMetadata {
|
||||
var metadataBuilder = MediaMetadata.Builder()
|
||||
.setTitle(title)
|
||||
.setDisplayTitle(title)
|
||||
.setArtist(author)
|
||||
.setAlbumArtist(author)
|
||||
.setSubtitle(author)
|
||||
|
||||
// if (coverUri != Uri.EMPTY) {
|
||||
// metadataBuilder.setArtworkUri(coverUri)
|
||||
// }
|
||||
if (playlistUri != Uri.EMPTY) {
|
||||
metadataBuilder.setMediaUri(playlistUri)
|
||||
}
|
||||
if (contentUri != Uri.EMPTY) {
|
||||
metadataBuilder.setMediaUri(contentUri)
|
||||
}
|
||||
return metadataBuilder.build()
|
||||
}
|
||||
|
||||
fun getMimeType():String {
|
||||
return if (isLocal) {
|
||||
MimeTypes.BASE_TYPE_AUDIO
|
||||
} else {
|
||||
MimeTypes.APPLICATION_M3U8
|
||||
}
|
||||
}
|
||||
|
||||
fun getMediaUri():Uri {
|
||||
return if (isLocal) {
|
||||
contentUri
|
||||
} else {
|
||||
Uri.parse("$playlistUrl?token=$token")
|
||||
}
|
||||
}
|
||||
|
||||
fun getCastQueue():ArrayList<MediaItem> {
|
||||
var mediaQueue: java.util.ArrayList<MediaItem> = java.util.ArrayList<MediaItem>()
|
||||
|
||||
for (i in 0 until tracks.size) {
|
||||
var track = tracks[i]
|
||||
var metadataBuilder = MediaMetadata.Builder()
|
||||
.setTitle(title)
|
||||
.setDisplayTitle(title)
|
||||
.setArtist(author)
|
||||
.setAlbumArtist(author)
|
||||
.setSubtitle(author)
|
||||
.setTrackNumber(i + 1)
|
||||
|
||||
if (coverUri != Uri.EMPTY) {
|
||||
metadataBuilder.setArtworkUri(coverUri)
|
||||
}
|
||||
|
||||
var mimeType = MimeTypes.BASE_TYPE_AUDIO
|
||||
|
||||
var mediaMetadata = metadataBuilder.build()
|
||||
var mediaItem = MediaItem.Builder().setUri(Uri.parse(track)).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
|
||||
mediaQueue.add(mediaItem)
|
||||
}
|
||||
|
||||
return mediaQueue
|
||||
}
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
package com.audiobookshelf.app
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ContentResolver
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.AssetFileDescriptor
|
||||
import android.database.Cursor
|
||||
import android.media.MediaPlayer
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.MediaStore
|
||||
import android.support.v4.media.MediaMetadataCompat
|
||||
import android.util.Log
|
||||
import androidx.annotation.AnyRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toFile
|
||||
import androidx.core.net.toUri
|
||||
import com.bumptech.glide.Glide
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
class LocalMediaManager {
|
||||
private var ctx: Context
|
||||
val tag = "LocalAudioManager"
|
||||
|
||||
constructor(ctx: Context) {
|
||||
this.ctx = ctx
|
||||
}
|
||||
|
||||
data class LocalAudio(val uri: Uri,
|
||||
val id: String,
|
||||
val name: String,
|
||||
val duration: Int,
|
||||
val size: Int,
|
||||
val coverUri: Uri?
|
||||
) {
|
||||
|
||||
fun toMediaMetadata(): MediaMetadataCompat {
|
||||
return MediaMetadataCompat.Builder().apply {
|
||||
putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, id)
|
||||
putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, name)
|
||||
putString(MediaMetadataCompat.METADATA_KEY_TITLE, name)
|
||||
|
||||
if (coverUri != null) {
|
||||
putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, coverUri.toString())
|
||||
}
|
||||
}.build()
|
||||
}
|
||||
}
|
||||
val localAudioFiles = mutableListOf<LocalAudio>()
|
||||
|
||||
/**
|
||||
* get uri to drawable or any other resource type if u wish
|
||||
* @param context - context
|
||||
* @param drawableId - drawable res id
|
||||
* @return - uri
|
||||
*/
|
||||
fun getUriToDrawable(context: Context,
|
||||
@AnyRes drawableId: Int): Uri {
|
||||
return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
|
||||
+ "://" + context.resources.getResourcePackageName(drawableId)
|
||||
+ '/' + context.resources.getResourceTypeName(drawableId)
|
||||
+ '/' + context.resources.getResourceEntryName(drawableId))
|
||||
}
|
||||
|
||||
fun loadLocalAudio() {
|
||||
localAudioFiles.clear()
|
||||
|
||||
localAudioFiles += LocalAudio(Uri.parse("asset:///public/samples/Anthem/AnthemSample.m4b"), "anthem_sample", "Anthem", 60000, 10000, getUriToDrawable(ctx, R.drawable.exo_icon_localaudio))
|
||||
localAudioFiles += LocalAudio(Uri.parse("asset:///public/samples/Legend of Sleepy Hollow/LegendOfSleepyHollowSample.m4b"), "sleepy_hollow", "Legend of Sleepy Hollow", 60000, 10000, getUriToDrawable(ctx, R.drawable.exo_icon_localaudio))
|
||||
|
||||
// TODO: No longer reading in local audio files - just use samples
|
||||
// if (ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
// Log.e(tag, "Permission not granted to read from external storage")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// val collection =
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
// MediaStore.Audio.Media.getContentUri(
|
||||
// MediaStore.VOLUME_EXTERNAL
|
||||
// )
|
||||
// } else {
|
||||
// MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
|
||||
// }
|
||||
//
|
||||
// val proj = arrayOf(MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.DURATION, MediaStore.Audio.Media.SIZE)
|
||||
// val audioCursor: Cursor? = ctx.contentResolver.query(collection, proj, null, null, null)
|
||||
//
|
||||
// audioCursor?.use { cursor ->
|
||||
// // Cache column indices.
|
||||
// val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)
|
||||
// val nameColumn =
|
||||
// cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)
|
||||
// val durationColumn =
|
||||
// cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION)
|
||||
// val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE)
|
||||
//
|
||||
// while (cursor.moveToNext()) {
|
||||
// // Get values of columns for a given video.
|
||||
// val id = cursor.getLong(idColumn)
|
||||
// val name = cursor.getString(nameColumn)
|
||||
// val duration = cursor.getInt(durationColumn)
|
||||
// val size = cursor.getInt(sizeColumn)
|
||||
//
|
||||
// val contentUri: Uri = ContentUris.withAppendedId(
|
||||
// MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||
// id
|
||||
// )
|
||||
// Log.d(tag, "Found local audio file $name")
|
||||
// localAudioFiles += LocalAudio(contentUri, id.toString(), name, duration, size, null)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Log.d(tag, "${localAudioFiles.size} Local Audio Files found")
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ import androidx.core.app.ActivityCompat
|
|||
import com.anggrayudi.storage.SimpleStorage
|
||||
import com.anggrayudi.storage.SimpleStorageHelper
|
||||
import com.audiobookshelf.app.data.DbManager
|
||||
import com.audiobookshelf.app.player.PlayerNotificationService
|
||||
import com.getcapacitor.BridgeActivity
|
||||
import io.paperdb.Paper
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
package com.audiobookshelf.app
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.audiobookshelf.app.data.PlaybackSession
|
||||
import com.audiobookshelf.app.device.DeviceManager
|
||||
import com.audiobookshelf.app.player.CastManager
|
||||
import com.audiobookshelf.app.player.PlayerNotificationService
|
||||
import com.audiobookshelf.app.server.ApiHandler
|
||||
import com.capacitorjs.plugins.app.AppPlugin
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.getcapacitor.*
|
||||
import com.getcapacitor.annotation.CapacitorPlugin
|
||||
|
|
@ -100,46 +99,6 @@ class MyNativeAudio : Plugin() {
|
|||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
fun getLibraryItems(call: PluginCall) {
|
||||
var libraryId = call.getString("libraryId", "").toString()
|
||||
apiHandler.getLibraryItems(libraryId) {
|
||||
val mapper = jacksonObjectMapper()
|
||||
var jsobj = JSObject()
|
||||
var libarray = JSArray()
|
||||
it.map {
|
||||
libarray.put(JSObject(mapper.writeValueAsString(it)))
|
||||
}
|
||||
jsobj.put("value", libarray)
|
||||
call.resolve(jsobj)
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
fun initPlayer(call: PluginCall) {
|
||||
if (!PlayerNotificationService.isStarted) {
|
||||
Log.w(tag, "Starting foreground service --")
|
||||
Intent(mainActivity, PlayerNotificationService::class.java).also { intent ->
|
||||
ContextCompat.startForegroundService(mainActivity, intent)
|
||||
}
|
||||
}
|
||||
var jsobj = JSObject()
|
||||
|
||||
var audiobookStreamData:AudiobookStreamData = AudiobookStreamData(call.data)
|
||||
if (audiobookStreamData.playlistUrl == "" && audiobookStreamData.contentUrl == "") {
|
||||
Log.e(tag, "Invalid URL for init audio player")
|
||||
|
||||
jsobj.put("success", false)
|
||||
return call.resolve(jsobj)
|
||||
}
|
||||
|
||||
Handler(Looper.getMainLooper()).post() {
|
||||
playerNotificationService.initPlayer(audiobookStreamData)
|
||||
jsobj.put("success", true)
|
||||
call.resolve(jsobj)
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
fun getCurrentTime(call: PluginCall) {
|
||||
Handler(Looper.getMainLooper()).post() {
|
||||
|
|
@ -152,28 +111,6 @@ class MyNativeAudio : Plugin() {
|
|||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
fun getStreamSyncData(call: PluginCall) {
|
||||
Handler(Looper.getMainLooper()).post() {
|
||||
var isPlaying = playerNotificationService.getPlayStatus()
|
||||
var lastPauseTime = playerNotificationService.getTheLastPauseTime()
|
||||
Log.d(tag, "Get Last Pause Time $lastPauseTime")
|
||||
var currentTime = playerNotificationService.getCurrentTime()
|
||||
//if (!isPlaying) currentTime -= playerNotificationService.calcPauseSeekBackTime()
|
||||
var id = playerNotificationService.getCurrentAudiobookId()
|
||||
Log.d(tag, "Get Current id $id")
|
||||
var duration = playerNotificationService.getDuration()
|
||||
Log.d(tag, "Get duration $duration")
|
||||
val ret = JSObject()
|
||||
ret.put("lastPauseTime", lastPauseTime)
|
||||
ret.put("currentTime", currentTime)
|
||||
ret.put("isPlaying", isPlaying)
|
||||
ret.put("id", id)
|
||||
ret.put("duration", duration)
|
||||
call.resolve(ret)
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
fun pausePlayer(call: PluginCall) {
|
||||
Handler(Looper.getMainLooper()).post() {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
package com.audiobookshelf.app
|
||||
package com.audiobookshelf.app.player
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.support.v4.media.session.MediaControllerCompat
|
||||
import android.util.Log
|
||||
import com.audiobookshelf.app.R
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
package com.audiobookshelf.app
|
||||
package com.audiobookshelf.app.player
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import com.audiobookshelf.app.device.DeviceManager
|
||||
import com.getcapacitor.JSObject
|
||||
import okhttp3.*
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
|
|
@ -45,9 +46,9 @@ class AudiobookProgressSyncer constructor(playerNotificationService:PlayerNotifi
|
|||
|
||||
webviewOpenOnStart = playerNotificationService.getIsWebviewOpen()
|
||||
listeningBookTitle = playerNotificationService.getCurrentBookTitle()
|
||||
listeningBookIsLocal = playerNotificationService.getCurrentBookIsLocal()
|
||||
listeningBookId = playerNotificationService.getCurrentBookId()
|
||||
listeningStreamId = playerNotificationService.getCurrentStreamId()
|
||||
listeningBookIsLocal = false
|
||||
listeningBookId = "empty"
|
||||
listeningStreamId = "empty"
|
||||
|
||||
lastPlaybackTime = playerNotificationService.getCurrentTime()
|
||||
lastUpdateTime = System.currentTimeMillis() / 1000L
|
||||
|
|
@ -117,7 +118,8 @@ class AudiobookProgressSyncer constructor(playerNotificationService:PlayerNotifi
|
|||
|
||||
// Send sync data only for local books
|
||||
var syncData: JSObject = JSObject()
|
||||
var duration = playerNotificationService.getAudiobookDuration() / 1000
|
||||
// var duration = playerNotificationService.getAudiobookDuration() / 1000
|
||||
var duration = 1000
|
||||
var currentTime = playerNotificationService.getCurrentTime() / 1000
|
||||
syncData.put("totalDuration", duration)
|
||||
syncData.put("currentTime", currentTime)
|
||||
|
|
@ -132,8 +134,8 @@ class AudiobookProgressSyncer constructor(playerNotificationService:PlayerNotifi
|
|||
}
|
||||
|
||||
fun sendLocalSyncData(payload:JSObject, cb: (() -> Unit)) {
|
||||
var serverUrl = playerNotificationService.getServerUrl()
|
||||
var token = playerNotificationService.getUserToken()
|
||||
var serverUrl = DeviceManager.serverAddress
|
||||
var token = DeviceManager.token
|
||||
|
||||
if (serverUrl == "" || token == "") {
|
||||
return
|
||||
|
|
@ -145,8 +147,8 @@ class AudiobookProgressSyncer constructor(playerNotificationService:PlayerNotifi
|
|||
}
|
||||
|
||||
fun sendStreamSyncData(payload:JSObject, cb: (() -> Unit)) {
|
||||
var serverUrl = playerNotificationService.getServerUrl()
|
||||
var token = playerNotificationService.getUserToken()
|
||||
var serverUrl = DeviceManager.serverAddress
|
||||
var token = DeviceManager.token
|
||||
|
||||
if (serverUrl == "" || token == "") {
|
||||
return
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.audiobookshelf.app
|
||||
package com.audiobookshelf.app.player
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
|
|
@ -6,6 +6,8 @@ import android.net.Uri
|
|||
import android.support.v4.media.MediaMetadataCompat
|
||||
import android.util.Log
|
||||
import androidx.annotation.AnyRes
|
||||
import com.audiobookshelf.app.Audiobook
|
||||
import com.audiobookshelf.app.R
|
||||
|
||||
|
||||
class BrowseTree(
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.audiobookshelf.app
|
||||
package com.audiobookshelf.app.player
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
|
|
@ -22,7 +22,7 @@ class CastManager constructor(playerNotificationService:PlayerNotificationServic
|
|||
private val tag = "SleepTimerManager"
|
||||
private val playerNotificationService:PlayerNotificationService = playerNotificationService
|
||||
|
||||
private var newConnectionListener:SessionListener? = null
|
||||
private var newConnectionListener: SessionListener? = null
|
||||
private var mainActivity:Activity? = null
|
||||
|
||||
private fun switchToPlayer(useCastPlayer:Boolean) {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.audiobookshelf.app
|
||||
package com.audiobookshelf.app.player
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.*
|
||||
|
|
@ -19,12 +19,10 @@ import android.util.Log
|
|||
import android.view.KeyEvent
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.media.MediaBrowserServiceCompat
|
||||
import androidx.media.utils.MediaConstants
|
||||
import com.anggrayudi.storage.file.isExternalStorageDocument
|
||||
import com.audiobookshelf.app.data.DbManager
|
||||
import com.audiobookshelf.app.data.LocalMediaItem
|
||||
import com.audiobookshelf.app.Audiobook
|
||||
import com.audiobookshelf.app.AudiobookManager
|
||||
import com.audiobookshelf.app.data.PlaybackSession
|
||||
import com.getcapacitor.Bridge
|
||||
import com.getcapacitor.JSObject
|
||||
|
|
@ -38,11 +36,7 @@ import com.google.android.exoplayer2.source.ProgressiveMediaSource
|
|||
import com.google.android.exoplayer2.source.hls.HlsMediaSource
|
||||
import com.google.android.exoplayer2.ui.PlayerNotificationManager
|
||||
import com.google.android.exoplayer2.upstream.*
|
||||
import com.google.android.gms.cast.*
|
||||
import com.google.android.gms.cast.framework.*
|
||||
import kotlinx.coroutines.*
|
||||
import okhttp3.OkHttpClient
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
import kotlin.concurrent.schedule
|
||||
|
||||
|
|
@ -74,7 +68,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
private lateinit var playerNotificationManager: PlayerNotificationManager
|
||||
private lateinit var mediaSession: MediaSessionCompat
|
||||
private lateinit var transportControls:MediaControllerCompat.TransportControls
|
||||
private lateinit var audiobookManager:AudiobookManager
|
||||
private lateinit var audiobookManager: AudiobookManager
|
||||
|
||||
lateinit var mPlayer: SimpleExoPlayer
|
||||
lateinit var currentPlayer:Player
|
||||
|
|
@ -88,7 +82,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
private var channelId = "audiobookshelf_channel"
|
||||
private var channelName = "Audiobookshelf Channel"
|
||||
|
||||
private var currentAudiobookStreamData:AudiobookStreamData? = null
|
||||
private var currentPlaybackSession:PlaybackSession? = null
|
||||
|
||||
private var mediaButtonClickCount: Int = 0
|
||||
|
|
@ -162,54 +155,17 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
return channelId
|
||||
}
|
||||
|
||||
private fun playLocal(local: LocalMediaManager.LocalAudio, playWhenReady: Boolean) {
|
||||
var asd = audiobookManager.initLocalPlay(local)
|
||||
asd.playWhenReady = playWhenReady
|
||||
initPlayer(asd)
|
||||
}
|
||||
|
||||
private fun playFirstLocal(playWhenReady: Boolean) {
|
||||
var localAudio = audiobookManager.getFirstLocal()
|
||||
if (localAudio != null) {
|
||||
playLocal(localAudio, playWhenReady)
|
||||
}
|
||||
}
|
||||
|
||||
private fun playAudiobookFromMediaBrowser(audiobook: Audiobook, playWhenReady: Boolean) {
|
||||
if (!audiobook.isDownloaded) {
|
||||
var streamListener = object : AudiobookManager.OnStreamData {
|
||||
override fun onStreamReady(asd: AudiobookStreamData) {
|
||||
Log.d(tag, "Stream Ready ${asd.playlistUrl}")
|
||||
asd.playWhenReady = playWhenReady
|
||||
initPlayer(asd)
|
||||
}
|
||||
}
|
||||
audiobookManager.openStream(audiobook, streamListener)
|
||||
} else {
|
||||
var asd = audiobookManager.initDownloadPlay(audiobook)
|
||||
asd.playWhenReady = playWhenReady
|
||||
initPlayer(asd)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun playFirstAudiobook(playWhenReady: Boolean) {
|
||||
var firstAudiobook = audiobookManager.getFirstAudiobook()
|
||||
if (firstAudiobook != null) {
|
||||
playAudiobookFromMediaBrowser(firstAudiobook, playWhenReady)
|
||||
} else {
|
||||
playFirstLocal(playWhenReady)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun openFromMediaId(mediaId: String, playWhenReady: Boolean) {
|
||||
var audiobook = audiobookManager.audiobooks.find { it.id == mediaId }
|
||||
if (audiobook == null) {
|
||||
var localAudio = audiobookManager.localMediaManager.localAudioFiles.find { it.id == mediaId }
|
||||
if (localAudio != null) {
|
||||
playLocal(localAudio, playWhenReady)
|
||||
return
|
||||
}
|
||||
|
||||
Log.e(tag, "Audiobook NOT FOUND")
|
||||
return
|
||||
}
|
||||
|
|
@ -295,7 +251,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
|
||||
// Initialize audiobook manager
|
||||
audiobookManager = AudiobookManager(ctx, client)
|
||||
audiobookManager.init()
|
||||
|
||||
channelId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createNotificationChannel(channelId, channelName)
|
||||
|
|
@ -719,68 +674,68 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
currentPlayer.setPlaybackSpeed(1f) // TODO: Playback speed should come from settings
|
||||
currentPlayer.prepare()
|
||||
}
|
||||
|
||||
fun initPlayer(audiobookStreamData: AudiobookStreamData) {
|
||||
currentAudiobookStreamData = audiobookStreamData
|
||||
|
||||
Log.d(tag, "Init Player Audiobook ${currentAudiobookStreamData!!.playlistUrl} | ${currentAudiobookStreamData!!.title} | ${currentAudiobookStreamData!!.author}")
|
||||
|
||||
if (mPlayer.isPlaying) {
|
||||
Log.d(tag, "Init Player audiobook already playing")
|
||||
}
|
||||
|
||||
// Issue with onenote plus crashing when using local cover art. https://github.com/advplyr/audiobookshelf-app/issues/35
|
||||
// Same issue with sony xperia https://github.com/advplyr/audiobookshelf-app/issues/94
|
||||
if (currentAudiobookStreamData?.coverUri != null && currentAudiobookStreamData?.isLocal == true) {
|
||||
var deviceName = Build.DEVICE
|
||||
var deviceMan = Build.MANUFACTURER
|
||||
var deviceModel = Build.MODEL
|
||||
Log.d(tag, "Checking device $deviceName | Model $deviceModel | Manufacturer $deviceMan")
|
||||
if (deviceMan.lowercase(Locale.getDefault()).contains("oneplus") || deviceName.lowercase(Locale.getDefault()).contains("oneplus")) {
|
||||
Log.d(tag, "Detected OnePlus device - removing local cover")
|
||||
currentAudiobookStreamData?.clearCover()
|
||||
} else if (deviceName.lowercase(Locale.getDefault()).contains("xperia") || deviceModel.lowercase(Locale.getDefault()).contains("xperia")) {
|
||||
Log.d(tag, "Detected Sony Xperia device - removing local cover")
|
||||
currentAudiobookStreamData?.clearCover()
|
||||
}
|
||||
}
|
||||
|
||||
var metadata = currentAudiobookStreamData!!.getMediaMetadataCompat()
|
||||
mediaSession.setMetadata(metadata)
|
||||
|
||||
var mediaUri:Uri = currentAudiobookStreamData!!.getMediaUri()
|
||||
var mimeType:String = currentAudiobookStreamData!!.getMimeType()
|
||||
|
||||
var mediaMetadata = currentAudiobookStreamData!!.getMediaMetadata()
|
||||
var mediaItem = MediaItem.Builder().setUri(mediaUri).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
|
||||
|
||||
if (mPlayer == currentPlayer) {
|
||||
var mediaSource:MediaSource
|
||||
|
||||
if (currentAudiobookStreamData!!.isLocal) {
|
||||
Log.d(tag, "Playing Local File")
|
||||
var dataSourceFactory = DefaultDataSourceFactory(ctx, channelId)
|
||||
mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
||||
} else {
|
||||
Log.d(tag, "Playing HLS File")
|
||||
var dataSourceFactory = DefaultHttpDataSource.Factory()
|
||||
dataSourceFactory.setUserAgent(channelId)
|
||||
dataSourceFactory.setDefaultRequestProperties(hashMapOf("Authorization" to "Bearer ${currentAudiobookStreamData!!.token}"))
|
||||
mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
||||
}
|
||||
mPlayer.setMediaSource(mediaSource, currentAudiobookStreamData!!.startTime)
|
||||
} else if (castPlayer != null) {
|
||||
var mediaQueue = currentAudiobookStreamData!!.getCastQueue()
|
||||
// TODO: Start position will need to be adjusted if using multi-track queue
|
||||
castPlayer?.setMediaItems(mediaQueue, 0, 0)
|
||||
}
|
||||
|
||||
currentPlayer.prepare()
|
||||
currentPlayer.playWhenReady = currentAudiobookStreamData!!.playWhenReady
|
||||
currentPlayer.setPlaybackSpeed(audiobookStreamData.playbackSpeed)
|
||||
|
||||
lastPauseTime = 0
|
||||
}
|
||||
//
|
||||
// fun initPlayer(audiobookStreamData: AudiobookStreamData) {
|
||||
// currentAudiobookStreamData = audiobookStreamData
|
||||
//
|
||||
// Log.d(tag, "Init Player Audiobook ${currentAudiobookStreamData!!.playlistUrl} | ${currentAudiobookStreamData!!.title} | ${currentAudiobookStreamData!!.author}")
|
||||
//
|
||||
// if (mPlayer.isPlaying) {
|
||||
// Log.d(tag, "Init Player audiobook already playing")
|
||||
// }
|
||||
//
|
||||
// // Issue with onenote plus crashing when using local cover art. https://github.com/advplyr/audiobookshelf-app/issues/35
|
||||
// // Same issue with sony xperia https://github.com/advplyr/audiobookshelf-app/issues/94
|
||||
// if (currentAudiobookStreamData?.coverUri != null && currentAudiobookStreamData?.isLocal == true) {
|
||||
// var deviceName = Build.DEVICE
|
||||
// var deviceMan = Build.MANUFACTURER
|
||||
// var deviceModel = Build.MODEL
|
||||
// Log.d(tag, "Checking device $deviceName | Model $deviceModel | Manufacturer $deviceMan")
|
||||
// if (deviceMan.lowercase(Locale.getDefault()).contains("oneplus") || deviceName.lowercase(Locale.getDefault()).contains("oneplus")) {
|
||||
// Log.d(tag, "Detected OnePlus device - removing local cover")
|
||||
// currentAudiobookStreamData?.clearCover()
|
||||
// } else if (deviceName.lowercase(Locale.getDefault()).contains("xperia") || deviceModel.lowercase(Locale.getDefault()).contains("xperia")) {
|
||||
// Log.d(tag, "Detected Sony Xperia device - removing local cover")
|
||||
// currentAudiobookStreamData?.clearCover()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var metadata = currentAudiobookStreamData!!.getMediaMetadataCompat()
|
||||
// mediaSession.setMetadata(metadata)
|
||||
//
|
||||
// var mediaUri:Uri = currentAudiobookStreamData!!.getMediaUri()
|
||||
// var mimeType:String = currentAudiobookStreamData!!.getMimeType()
|
||||
//
|
||||
// var mediaMetadata = currentAudiobookStreamData!!.getMediaMetadata()
|
||||
// var mediaItem = MediaItem.Builder().setUri(mediaUri).setMediaMetadata(mediaMetadata).setMimeType(mimeType).build()
|
||||
//
|
||||
// if (mPlayer == currentPlayer) {
|
||||
// var mediaSource:MediaSource
|
||||
//
|
||||
// if (currentAudiobookStreamData!!.isLocal) {
|
||||
// Log.d(tag, "Playing Local File")
|
||||
// var dataSourceFactory = DefaultDataSourceFactory(ctx, channelId)
|
||||
// mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
||||
// } else {
|
||||
// Log.d(tag, "Playing HLS File")
|
||||
// var dataSourceFactory = DefaultHttpDataSource.Factory()
|
||||
// dataSourceFactory.setUserAgent(channelId)
|
||||
// dataSourceFactory.setDefaultRequestProperties(hashMapOf("Authorization" to "Bearer ${currentAudiobookStreamData!!.token}"))
|
||||
// mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
||||
// }
|
||||
// mPlayer.setMediaSource(mediaSource, currentAudiobookStreamData!!.startTime)
|
||||
// } else if (castPlayer != null) {
|
||||
// var mediaQueue = currentAudiobookStreamData!!.getCastQueue()
|
||||
// // TODO: Start position will need to be adjusted if using multi-track queue
|
||||
// castPlayer?.setMediaItems(mediaQueue, 0, 0)
|
||||
// }
|
||||
//
|
||||
// currentPlayer.prepare()
|
||||
// currentPlayer.playWhenReady = currentAudiobookStreamData!!.playWhenReady
|
||||
// currentPlayer.setPlaybackSpeed(audiobookStreamData.playbackSpeed)
|
||||
//
|
||||
// lastPauseTime = 0
|
||||
// }
|
||||
|
||||
fun switchToPlayer(useCastPlayer: Boolean) {
|
||||
currentPlayer = if (useCastPlayer) {
|
||||
|
|
@ -792,9 +747,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
mediaSessionConnector.setPlayer(mPlayer)
|
||||
mPlayer
|
||||
}
|
||||
if (currentAudiobookStreamData != null) {
|
||||
if (currentPlaybackSession != null) {
|
||||
Log.d(tag, "switchToPlayer: Initing current ab stream data")
|
||||
initPlayer(currentAudiobookStreamData!!)
|
||||
preparePlayer(currentPlaybackSession!!, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -827,33 +782,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
}
|
||||
|
||||
fun getCurrentBookTitle() : String? {
|
||||
return currentAudiobookStreamData?.title
|
||||
}
|
||||
|
||||
fun getCurrentBookIsLocal() : Boolean {
|
||||
return currentAudiobookStreamData?.isLocal == true
|
||||
}
|
||||
|
||||
fun getCurrentBookId() : String? {
|
||||
return currentAudiobookStreamData?.audiobookId
|
||||
}
|
||||
|
||||
fun getCurrentStreamId() : String? {
|
||||
return currentAudiobookStreamData?.id
|
||||
}
|
||||
|
||||
// The duration stored on the audiobook
|
||||
fun getAudiobookDuration() : Long {
|
||||
if (currentAudiobookStreamData == null) return 0L
|
||||
return currentAudiobookStreamData!!.duration
|
||||
}
|
||||
|
||||
fun getServerUrl(): String {
|
||||
return audiobookManager.serverUrl
|
||||
}
|
||||
|
||||
fun getUserToken() : String {
|
||||
return audiobookManager.token
|
||||
return currentPlaybackSession?.displayTitle
|
||||
}
|
||||
|
||||
fun calcPauseSeekBackTime() : Long {
|
||||
|
|
@ -869,14 +798,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
|
|||
return seekback
|
||||
}
|
||||
|
||||
fun getPlayStatus() : Boolean {
|
||||
return mPlayer.isPlaying
|
||||
}
|
||||
|
||||
fun getCurrentAudiobookId() : String {
|
||||
return currentAudiobookStreamData?.id.toString()
|
||||
}
|
||||
|
||||
fun play() {
|
||||
if (currentPlayer.isPlaying) {
|
||||
Log.d(tag, "Already playing")
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
package com.audiobookshelf.app
|
||||
package com.audiobookshelf.app.player
|
||||
|
||||
import android.hardware.Sensor
|
||||
import android.hardware.SensorEvent
|
||||
import android.hardware.SensorEventListener
|
||||
import android.hardware.SensorManager
|
||||
import java.lang.Math.sqrt
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class ShakeDetector : SensorEventListener {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.audiobookshelf.app
|
||||
package com.audiobookshelf.app.player
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
Loading…
Reference in a new issue