LibreTube/app/src/main/java/com/github/libretube/util/PlayingQueue.kt

205 lines
6.1 KiB
Kotlin
Raw Normal View History

2022-09-19 23:37:55 +05:30
package com.github.libretube.util
2022-11-06 16:20:04 +05:30
import android.util.Log
2022-11-20 21:39:07 +05:30
import com.github.libretube.api.PlaylistsHelper
import com.github.libretube.api.RetrofitInstance
2022-10-23 15:03:35 +05:30
import com.github.libretube.api.obj.StreamItem
2022-10-23 18:39:58 +05:30
import com.github.libretube.extensions.move
2022-10-23 17:09:15 +05:30
import com.github.libretube.extensions.toID
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
2022-10-23 15:03:35 +05:30
2022-09-19 23:37:55 +05:30
object PlayingQueue {
2022-10-23 17:09:15 +05:30
private val queue = mutableListOf<StreamItem>()
private var currentStream: StreamItem? = null
private val scope = CoroutineScope(Dispatchers.IO)
2023-01-13 22:50:00 +05:30
/**
* Listener that gets called when the user selects an item from the queue
*/
2022-11-06 16:20:04 +05:30
private var onQueueTapListener: (StreamItem) -> Unit = {}
2023-01-13 22:50:00 +05:30
/**
* Listener that gets called when the current playing video changes
*/
private val onTrackChangedListeners: MutableList<(StreamItem) -> Unit> = mutableListOf()
2022-11-17 21:15:07 +05:30
var repeatQueue: Boolean = false
2022-10-23 17:09:15 +05:30
2023-01-14 21:29:21 +05:30
fun clear() = queue.clear()
2022-10-23 17:09:15 +05:30
fun add(vararg streamItem: StreamItem) {
for (stream in streamItem) {
if (currentStream?.url?.toID() == stream.url?.toID()) continue
// remove if already present
queue.remove(stream)
queue.add(stream)
2022-10-23 17:09:15 +05:30
}
2022-09-19 23:37:55 +05:30
}
2022-10-23 17:09:15 +05:30
fun addAsNext(streamItem: StreamItem) {
if (currentStream == streamItem) return
if (queue.contains(streamItem)) queue.remove(streamItem)
2022-09-19 23:37:55 +05:30
queue.add(
2022-10-23 17:09:15 +05:30
currentIndex() + 1,
streamItem
2022-09-19 23:37:55 +05:30
)
}
2022-09-19 23:43:25 +05:30
fun getNext(): String? {
2022-11-17 21:15:07 +05:30
try {
return queue[currentIndex() + 1].url?.toID()
2022-09-23 17:42:41 +05:30
} catch (e: Exception) {
2022-11-17 21:15:07 +05:30
Log.e("queue ended", e.toString())
2022-09-20 01:07:30 +05:30
}
2022-11-17 21:15:07 +05:30
if (repeatQueue) return queue.firstOrNull()?.url?.toID()
return null
2022-09-20 01:07:30 +05:30
}
2022-09-20 01:51:30 +05:30
fun getPrev(): String? {
return if (currentIndex() > 0) queue[currentIndex() - 1].url?.toID() else null
2022-09-20 01:07:30 +05:30
}
fun hasPrev(): Boolean {
return currentIndex() > 0
}
fun hasNext(): Boolean {
return currentIndex() + 1 < size()
2022-09-20 01:07:30 +05:30
}
2022-10-23 17:09:15 +05:30
fun updateCurrent(streamItem: StreamItem) {
currentStream = streamItem
2023-01-13 22:50:00 +05:30
onTrackChangedListeners.forEach {
2023-01-13 23:05:38 +05:30
runCatching {
it.invoke(streamItem)
}
2023-01-13 22:50:00 +05:30
}
2023-01-14 21:29:21 +05:30
if (!contains(streamItem)) queue.add(0, streamItem)
2022-09-19 23:43:25 +05:30
}
2022-09-20 01:13:13 +05:30
fun isNotEmpty() = queue.isNotEmpty()
2022-09-23 17:42:41 +05:30
2022-10-23 17:09:15 +05:30
fun isEmpty() = queue.isEmpty()
fun size() = queue.size
2022-09-23 17:42:41 +05:30
2022-10-23 18:49:14 +05:30
fun currentIndex(): Int {
return try {
queue.indexOf(
queue.first { it.url?.toID() == currentStream?.url?.toID() }
)
} catch (e: Exception) {
0
}
}
2022-09-23 17:42:41 +05:30
2023-01-13 22:50:00 +05:30
fun getCurrent(): StreamItem? = currentStream
fun contains(streamItem: StreamItem) = queue.any { it.url?.toID() == streamItem.url?.toID() }
2022-10-23 17:09:15 +05:30
2023-01-04 23:19:06 +05:30
// only returns a copy of the queue, no write access
fun getStreams() = queue.toList()
2022-10-29 02:34:44 +05:30
fun setStreams(streams: List<StreamItem>) {
queue.clear()
queue.addAll(streams)
}
fun remove(index: Int) = queue.removeAt(index)
2022-10-23 18:39:58 +05:30
fun move(from: Int, to: Int) = queue.move(from, to)
private fun fetchMoreFromPlaylist(playlistId: String, nextPage: String?) {
var playlistNextPage: String? = nextPage
scope.launch {
while (playlistNextPage != null) {
RetrofitInstance.authApi.getPlaylistNextPage(
playlistId,
playlistNextPage!!
).apply {
add(
*this.relatedStreams.orEmpty().toTypedArray()
)
playlistNextPage = this.nextpage
}
}
}
}
fun insertPlaylist(playlistId: String, newCurrentStream: StreamItem) {
scope.launch {
try {
val playlist = PlaylistsHelper.getPlaylist(playlistId)
add(*playlist.relatedStreams.orEmpty().toTypedArray())
updateCurrent(newCurrentStream)
2022-11-20 21:39:07 +05:30
if (playlist.nextpage == null) return@launch
fetchMoreFromPlaylist(playlistId, playlist.nextpage)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
2022-11-06 16:20:04 +05:30
private fun fetchMoreFromChannel(channelId: String, nextPage: String?) {
var channelNextPage: String? = nextPage
scope.launch {
while (channelNextPage != null) {
RetrofitInstance.api.getChannelNextPage(channelId, nextPage!!).apply {
add(*relatedStreams.toTypedArray())
channelNextPage = this.nextpage
}
}
}
}
fun insertChannel(channelId: String, newCurrentStream: StreamItem) {
scope.launch {
runCatching {
val channel = RetrofitInstance.api.getChannel(channelId)
add(*channel.relatedStreams.toTypedArray())
updateCurrent(newCurrentStream)
if (channel.nextpage == null) return@launch
fetchMoreFromChannel(channelId, channel.nextpage)
}
}
}
fun insertByVideoId(videoId: String) {
scope.launch {
runCatching {
val streams = RetrofitInstance.api.getStreams(videoId.toID())
add(streams.toStreamItem(videoId))
}
}
}
2022-11-06 16:20:04 +05:30
fun onQueueItemSelected(index: Int) {
try {
val streamItem = queue[index]
updateCurrent(streamItem)
onQueueTapListener.invoke(streamItem)
} catch (e: Exception) {
Log.e("Queue on tap", "lifecycle already ended")
}
}
fun setOnQueueTapListener(listener: (StreamItem) -> Unit) {
onQueueTapListener = listener
}
2023-01-13 22:50:00 +05:30
fun addOnTrackChangedListener(listener: (StreamItem) -> Unit) {
onTrackChangedListeners.add(listener)
}
fun removeOnTrackChangedListener(listener: (StreamItem) -> Unit) {
onTrackChangedListeners.remove(listener)
}
2022-11-17 21:15:07 +05:30
fun resetToDefaults() {
repeatQueue = false
2022-11-06 16:20:04 +05:30
onQueueTapListener = {}
2023-01-13 22:50:00 +05:30
onTrackChangedListeners.clear()
2022-11-06 16:20:04 +05:30
}
2022-09-19 23:37:55 +05:30
}