funkwhale-app-android/app/src/main/java/audio/funkwhale/ffa/playback/QueueManager.kt

202 lines
5.0 KiB
Kotlin
Raw Normal View History

package audio.funkwhale.ffa.playback
2019-08-19 16:50:33 +02:00
import android.content.Context
import android.net.Uri
import audio.funkwhale.ffa.model.QueueCache
import audio.funkwhale.ffa.model.Track
2021-09-09 09:56:15 +02:00
import audio.funkwhale.ffa.utils.Command
import audio.funkwhale.ffa.utils.CommandBus
import audio.funkwhale.ffa.utils.Event
import audio.funkwhale.ffa.utils.EventBus
import audio.funkwhale.ffa.utils.FFACache
import audio.funkwhale.ffa.utils.log
import audio.funkwhale.ffa.utils.mustNormalizeUrl
2019-08-19 16:50:33 +02:00
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.android.exoplayer2.source.ConcatenatingMediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.gson.Gson
import org.koin.java.KoinJavaComponent.inject
class QueueManager(val context: Context) {
private val cacheDataSourceFactoryProvider: CacheDataSourceFactoryProvider by inject(
CacheDataSourceFactoryProvider::class.java
)
2021-07-30 10:57:49 +02:00
var metadata: MutableList<Track> = mutableListOf()
val dataSources = ConcatenatingMediaSource()
var current = -1
2019-08-19 16:50:33 +02:00
2020-06-10 16:25:20 +02:00
init {
FFACache.getLine(context, "queue")?.let { json ->
gsonDeserializerOf(QueueCache::class.java).deserialize(json.reader())?.let { cache ->
2019-08-19 16:50:33 +02:00
metadata = cache.data.toMutableList()
val factory = cacheDataSourceFactoryProvider.create(context)
2019-08-19 16:50:33 +02:00
2021-09-09 09:56:15 +02:00
dataSources.addMediaSources(
metadata.map { track ->
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
2019-08-19 16:50:33 +02:00
2021-09-09 09:56:15 +02:00
ProgressiveMediaSource.Factory(factory).setTag(track.title)
.createMediaSource(Uri.parse(url))
}
)
2019-08-19 16:50:33 +02:00
}
}
FFACache.getLine(context, "current")?.let {
current = it.toInt()
2019-08-19 16:50:33 +02:00
}
}
private fun persist() {
FFACache.set(
2019-08-19 16:50:33 +02:00
context,
"queue",
Gson().toJson(QueueCache(metadata)).toString()
2019-08-19 16:50:33 +02:00
)
}
fun replace(tracks: List<Track>) {
2021-08-13 14:54:42 +02:00
tracks.map { it.formatted }.log("Replacing queue with ${tracks.size} tracks")
val factory = cacheDataSourceFactoryProvider.create(context)
2019-08-19 16:50:33 +02:00
val sources = tracks.map { track ->
2019-10-22 21:56:33 +02:00
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
2019-08-19 16:50:33 +02:00
ProgressiveMediaSource.Factory(factory).setTag(track.title).createMediaSource(Uri.parse(url))
}
metadata = tracks.toMutableList()
dataSources.clear()
dataSources.addMediaSources(sources)
2019-08-19 16:50:33 +02:00
persist()
EventBus.send(Event.QueueChanged)
}
fun append(tracks: List<Track>) {
2021-08-13 14:54:42 +02:00
tracks.map { it.formatted }.log("Appending ${tracks.size} tracks")
val factory = cacheDataSourceFactoryProvider.create(context)
val missingTracks = tracks.filter { metadata.indexOf(it) == -1 }
2019-08-19 16:50:33 +02:00
val sources = missingTracks.map { track ->
2019-10-22 21:56:33 +02:00
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
2019-08-19 16:50:33 +02:00
ProgressiveMediaSource.Factory(factory).createMediaSource(Uri.parse(url))
}
metadata.addAll(tracks)
dataSources.addMediaSources(sources)
2019-08-19 16:50:33 +02:00
persist()
EventBus.send(Event.QueueChanged)
}
fun insertNext(track: Track) {
2021-08-13 15:04:15 +02:00
track.formatted.log("Next track")
val factory = cacheDataSourceFactoryProvider.create(context)
2019-10-22 21:56:33 +02:00
val url = mustNormalizeUrl(track.bestUpload()?.listen_url ?: "")
2019-08-19 16:50:33 +02:00
if (metadata.indexOf(track) == -1) {
ProgressiveMediaSource.Factory(factory).createMediaSource(Uri.parse(url)).let {
dataSources.addMediaSource(current + 1, it)
2019-08-19 16:50:33 +02:00
metadata.add(current + 1, track)
}
} else {
move(metadata.indexOf(track), current + 1)
}
persist()
EventBus.send(Event.QueueChanged)
}
fun remove(track: Track) {
2021-08-13 14:54:42 +02:00
track.formatted.log("Removing track")
2019-08-19 16:50:33 +02:00
metadata.indexOf(track).let {
if (it < 0) {
return
}
dataSources.removeMediaSource(it)
2019-08-19 16:50:33 +02:00
metadata.removeAt(it)
if (it == current) {
CommandBus.send(Command.NextTrack)
}
if (it < current) {
current--
}
}
if (metadata.isEmpty()) {
current = -1
2019-08-19 16:50:33 +02:00
}
persist()
EventBus.send(Event.QueueChanged)
}
fun move(oldPosition: Int, newPosition: Int) {
dataSources.moveMediaSource(oldPosition, newPosition)
2019-08-19 16:50:33 +02:00
metadata.add(newPosition, metadata.removeAt(oldPosition))
persist()
}
fun get() = metadata.mapIndexed { index, track ->
track.current = index == current
track
}
fun get(index: Int): Track = metadata[index]
fun current(): Track? {
if (current == -1) {
return metadata.getOrNull(0)
}
return metadata.getOrNull(current)
}
2019-10-30 22:06:57 +01:00
fun clear() {
metadata = mutableListOf()
dataSources.clear()
2019-10-30 22:06:57 +01:00
current = -1
persist()
2019-10-30 22:06:57 +01:00
}
fun shuffle() {
if (metadata.size < 2) return
if (current == -1) {
replace(metadata.shuffled())
} else {
move(current, 0)
current = 0
val shuffled =
metadata
.drop(1)
.shuffled()
while (metadata.size > 1) {
dataSources.removeMediaSource(metadata.size - 1)
metadata.removeAt(metadata.size - 1)
}
append(shuffled)
}
persist()
EventBus.send(Event.QueueChanged)
}
2021-07-02 13:55:49 +02:00
}