add readonly List implementation of playlist
This commit is contained in:
parent
a2e8f6c4ad
commit
32075dec73
|
@ -31,6 +31,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import net.newpipe.newplayer.utils.PlayList
|
||||||
import kotlin.Exception
|
import kotlin.Exception
|
||||||
|
|
||||||
enum class PlayMode {
|
enum class PlayMode {
|
||||||
|
@ -57,6 +58,8 @@ interface NewPlayer {
|
||||||
var playBackMode: PlayMode
|
var playBackMode: PlayMode
|
||||||
var playMode: PlayMode?
|
var playMode: PlayMode?
|
||||||
|
|
||||||
|
var playlist: PlayList
|
||||||
|
|
||||||
// calbacks
|
// calbacks
|
||||||
|
|
||||||
interface Listener {
|
interface Listener {
|
||||||
|
@ -140,9 +143,10 @@ class NewPlayerImpl(
|
||||||
override val duration: Long
|
override val duration: Long
|
||||||
get() = internalPlayer.duration
|
get() = internalPlayer.duration
|
||||||
|
|
||||||
|
override var playlist = PlayList(internalPlayer)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
internalPlayer.addListener(object: Player.Listener {
|
internalPlayer.addListener(object : Player.Listener {
|
||||||
override fun onPlayerError(error: PlaybackException) {
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
launchJobAndCollectError {
|
launchJobAndCollectError {
|
||||||
val item = internalPlayer.currentMediaItem?.mediaId
|
val item = internalPlayer.currentMediaItem?.mediaId
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
/* NewPlayer
|
||||||
|
*
|
||||||
|
* @author Christian Schabesberger
|
||||||
|
*
|
||||||
|
* Copyright (C) NewPipe e.V. 2024 <code(at)newpipe-ev.de>
|
||||||
|
*
|
||||||
|
* NewPlayer is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* NewPlayer is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.newpipe.newplayer.utils
|
||||||
|
|
||||||
|
import androidx.media3.common.Player
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: This is cool, but it might still contains all raceconditions since two actors are mutating the
|
||||||
|
// same time.
|
||||||
|
// Be aware when using this list and this iterator: There can alwas be out of bounds exceptions
|
||||||
|
// even if the size in a previous query said otherwise, since between the size query and
|
||||||
|
// a get element query the count of elements might have been changed by exoplayer itself
|
||||||
|
// due to this reason some functions force the user to handle elements out of bounds exceptions.
|
||||||
|
|
||||||
|
|
||||||
|
class PlayListIterator(
|
||||||
|
val exoPlayer: Player,
|
||||||
|
val fromIndex: Int,
|
||||||
|
val toIndex: Int
|
||||||
|
) : ListIterator<String> {
|
||||||
|
|
||||||
|
var index = fromIndex
|
||||||
|
|
||||||
|
override fun hasNext() =
|
||||||
|
index < minOf(exoPlayer.mediaItemCount, toIndex)
|
||||||
|
|
||||||
|
override fun hasPrevious() = fromIndex < index
|
||||||
|
|
||||||
|
@Throws(IndexOutOfBoundsException::class)
|
||||||
|
override fun next(): String {
|
||||||
|
if (exoPlayer.mediaItemCount <= index)
|
||||||
|
throw NoSuchElementException("No Stream with index $index in the playlist")
|
||||||
|
val item = exoPlayer.getMediaItemAt(index).mediaId
|
||||||
|
index++
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IndexOutOfBoundsException::class)
|
||||||
|
override fun nextIndex() =
|
||||||
|
if (exoPlayer.mediaItemCount <= index)
|
||||||
|
exoPlayer.mediaItemCount - fromIndex
|
||||||
|
else
|
||||||
|
(index + 1) - fromIndex
|
||||||
|
|
||||||
|
@Throws(IndexOutOfBoundsException::class)
|
||||||
|
override fun previous(): String {
|
||||||
|
if (index <= fromIndex)
|
||||||
|
throw NoSuchElementException("No Stream with index ${index - 1} in the playlist")
|
||||||
|
index--
|
||||||
|
val item = exoPlayer.getMediaItemAt(index).mediaId
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun previousIndex() =
|
||||||
|
if (index <= fromIndex)
|
||||||
|
0
|
||||||
|
else
|
||||||
|
(index - 1) - fromIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlayList(val exoPlayer: Player, val fromIndex: Int = 0, val toIndex: Int = Int.MAX_VALUE) :
|
||||||
|
List<String> {
|
||||||
|
|
||||||
|
override val size: Int
|
||||||
|
get() = minOf(exoPlayer.mediaItemCount, toIndex) - fromIndex
|
||||||
|
|
||||||
|
override fun contains(element: String): Boolean {
|
||||||
|
for (i in fromIndex..minOf(exoPlayer.mediaItemCount, toIndex)) {
|
||||||
|
try {
|
||||||
|
if (exoPlayer.getMediaItemAt(i).mediaId == element)
|
||||||
|
return true
|
||||||
|
} catch (e: IndexOutOfBoundsException) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun containsAll(elements: Collection<String>): Boolean {
|
||||||
|
for (element in elements) {
|
||||||
|
if (!this.contains(element)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IndexOutOfBoundsException::class)
|
||||||
|
override fun get(index: Int) =
|
||||||
|
if (index < fromIndex || toIndex < index)
|
||||||
|
throw IndexOutOfBoundsException("Accessed playlist item outside of permitted Playlist ListWindow: $index")
|
||||||
|
else
|
||||||
|
exoPlayer.getMediaItemAt(index).mediaId
|
||||||
|
|
||||||
|
override fun isEmpty() = exoPlayer.mediaItemCount == 0 || fromIndex == toIndex
|
||||||
|
|
||||||
|
override fun iterator() = PlayListIterator(exoPlayer, fromIndex, toIndex)
|
||||||
|
|
||||||
|
override fun listIterator() = PlayListIterator(exoPlayer, fromIndex, toIndex)
|
||||||
|
|
||||||
|
override fun listIterator(index: Int) = PlayListIterator(exoPlayer, index, toIndex)
|
||||||
|
|
||||||
|
override fun subList(fromIndex: Int, toIndex: Int): List<String> =
|
||||||
|
PlayList(
|
||||||
|
exoPlayer,
|
||||||
|
fromIndex = this.fromIndex + fromIndex,
|
||||||
|
toIndex = this.fromIndex + toIndex
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun lastIndexOf(element: String): Int {
|
||||||
|
for (i in minOf(toIndex, exoPlayer.mediaItemCount) downTo fromIndex) {
|
||||||
|
try {
|
||||||
|
if (exoPlayer.getMediaItemAt(i).mediaId == element) {
|
||||||
|
return i - fromIndex
|
||||||
|
}
|
||||||
|
} catch (e: IndexOutOfBoundsException) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun indexOf(element: String): Int {
|
||||||
|
for (i in fromIndex.. minOf(toIndex, exoPlayer.mediaItemCount)) {
|
||||||
|
try {
|
||||||
|
if (exoPlayer.getMediaItemAt(i).mediaId == element) {
|
||||||
|
return i - fromIndex
|
||||||
|
}
|
||||||
|
} catch (e: IndexOutOfBoundsException) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue