mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-28 16:00:31 +05:30
feat: support for repeating video in audio mode
This commit is contained in:
parent
2f89bf3756
commit
75c74bcc89
@ -18,6 +18,7 @@ import androidx.core.net.toUri
|
|||||||
import androidx.media3.common.AudioAttributes
|
import androidx.media3.common.AudioAttributes
|
||||||
import androidx.media3.common.C
|
import androidx.media3.common.C
|
||||||
import androidx.media3.common.PlaybackParameters
|
import androidx.media3.common.PlaybackParameters
|
||||||
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.Tracks
|
import androidx.media3.common.Tracks
|
||||||
import androidx.media3.datasource.DefaultDataSource
|
import androidx.media3.datasource.DefaultDataSource
|
||||||
import androidx.media3.datasource.cronet.CronetDataSource
|
import androidx.media3.datasource.cronet.CronetDataSource
|
||||||
@ -53,6 +54,12 @@ object PlayerHelper {
|
|||||||
const val ROLE_FLAG_AUTO_GEN_SUBTITLE = C.ROLE_FLAG_SUPPLEMENTARY
|
const val ROLE_FLAG_AUTO_GEN_SUBTITLE = C.ROLE_FLAG_SUPPLEMENTARY
|
||||||
const val MINIMUM_BUFFER_DURATION = 1000 * 10 // exo default is 50s
|
const val MINIMUM_BUFFER_DURATION = 1000 * 10 // exo default is 50s
|
||||||
|
|
||||||
|
val repeatModes = listOf(
|
||||||
|
Player.REPEAT_MODE_OFF to R.string.repeat_mode_none,
|
||||||
|
Player.REPEAT_MODE_ONE to R.string.repeat_mode_current,
|
||||||
|
Player.REPEAT_MODE_ALL to R.string.repeat_mode_all
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of all categories that are not disabled by default
|
* A list of all categories that are not disabled by default
|
||||||
* Also update `sponsorblock_settings.xml` when modifying this!
|
* Also update `sponsorblock_settings.xml` when modifying this!
|
||||||
|
@ -5,6 +5,7 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.media3.common.Player
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@ -77,10 +78,15 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.repeat.setOnClickListener {
|
binding.repeat.setOnClickListener {
|
||||||
PlayingQueue.repeatQueue = !PlayingQueue.repeatQueue
|
// select the next available repeat mode
|
||||||
it.alpha = if (PlayingQueue.repeatQueue) 1f else 0.5f
|
PlayingQueue.repeatMode = when (PlayingQueue.repeatMode) {
|
||||||
|
Player.REPEAT_MODE_OFF -> Player.REPEAT_MODE_ONE
|
||||||
|
Player.REPEAT_MODE_ONE -> Player.REPEAT_MODE_ALL
|
||||||
|
else -> Player.REPEAT_MODE_OFF
|
||||||
|
}
|
||||||
|
updateRepeatButton()
|
||||||
}
|
}
|
||||||
binding.repeat.alpha = if (PlayingQueue.repeatQueue) 1f else 0.5f
|
updateRepeatButton()
|
||||||
|
|
||||||
binding.clearQueue.setOnClickListener {
|
binding.clearQueue.setOnClickListener {
|
||||||
val currentIndex = PlayingQueue.currentIndex()
|
val currentIndex = PlayingQueue.currentIndex()
|
||||||
@ -135,6 +141,12 @@ class PlayingQueueSheet : ExpandedBottomSheet() {
|
|||||||
itemTouchHelper.attachToRecyclerView(binding.optionsRecycler)
|
itemTouchHelper.attachToRecyclerView(binding.optionsRecycler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateRepeatButton() {
|
||||||
|
binding.repeat.alpha = if (PlayingQueue.repeatMode == Player.REPEAT_MODE_OFF) 0.5f else 1f
|
||||||
|
val drawableResource = if (PlayingQueue.repeatMode == Player.REPEAT_MODE_ONE) R.drawable.ic_repeat_one else R.drawable.ic_repeat
|
||||||
|
binding.repeat.setImageResource(drawableResource)
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun showSortDialog() {
|
private fun showSortDialog() {
|
||||||
val sortOptions = listOf(
|
val sortOptions = listOf(
|
||||||
|
@ -25,7 +25,6 @@ import androidx.core.view.updateLayoutParams
|
|||||||
import androidx.media3.common.C
|
import androidx.media3.common.C
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import androidx.media3.common.text.Cue
|
import androidx.media3.common.text.Cue
|
||||||
import androidx.media3.common.util.RepeatModeUtil
|
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.ui.AspectRatioFrameLayout
|
import androidx.media3.ui.AspectRatioFrameLayout
|
||||||
import androidx.media3.ui.CaptionStyleCompat
|
import androidx.media3.ui.CaptionStyleCompat
|
||||||
@ -296,10 +295,11 @@ open class CustomExoPlayerView(
|
|||||||
context.getString(R.string.repeat_mode),
|
context.getString(R.string.repeat_mode),
|
||||||
R.drawable.ic_repeat,
|
R.drawable.ic_repeat,
|
||||||
{
|
{
|
||||||
if (player?.repeatMode == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE) {
|
when (PlayingQueue.repeatMode) {
|
||||||
context.getString(R.string.repeat_mode_none)
|
Player.REPEAT_MODE_OFF -> context.getString(R.string.repeat_mode_none)
|
||||||
} else {
|
Player.REPEAT_MODE_ONE -> context.getString(R.string.repeat_mode_current)
|
||||||
context.getString(R.string.repeat_mode_current)
|
Player.REPEAT_MODE_ALL -> context.getString(R.string.repeat_mode_all)
|
||||||
|
else -> throw IllegalArgumentException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
@ -527,27 +527,10 @@ open class CustomExoPlayerView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onRepeatModeClicked() {
|
override fun onRepeatModeClicked() {
|
||||||
val repeatModeNames = listOf(
|
|
||||||
context.getString(R.string.repeat_mode_none),
|
|
||||||
context.getString(R.string.repeat_mode_current),
|
|
||||||
context.getString(R.string.all)
|
|
||||||
)
|
|
||||||
// repeat mode options dialog
|
// repeat mode options dialog
|
||||||
BaseBottomSheet()
|
BaseBottomSheet()
|
||||||
.setSimpleItems(repeatModeNames) { index ->
|
.setSimpleItems(PlayerHelper.repeatModes.map { context.getString(it.second) }) { index ->
|
||||||
PlayingQueue.repeatQueue = when (index) {
|
PlayingQueue.repeatMode = PlayerHelper.repeatModes[index].first
|
||||||
0 -> {
|
|
||||||
player?.repeatMode = Player.REPEAT_MODE_OFF
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
1 -> {
|
|
||||||
player?.repeatMode = Player.REPEAT_MODE_ONE
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.show(supportFragmentManager)
|
.show(supportFragmentManager)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.github.libretube.util
|
package com.github.libretube.util
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.media3.common.Player
|
||||||
import com.github.libretube.api.PlaylistsHelper
|
import com.github.libretube.api.PlaylistsHelper
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.RetrofitInstance
|
||||||
import com.github.libretube.api.obj.StreamItem
|
import com.github.libretube.api.obj.StreamItem
|
||||||
@ -20,7 +21,7 @@ object PlayingQueue {
|
|||||||
*/
|
*/
|
||||||
private var onQueueTapListener: (StreamItem) -> Unit = {}
|
private var onQueueTapListener: (StreamItem) -> Unit = {}
|
||||||
|
|
||||||
var repeatQueue: Boolean = false
|
var repeatMode: Int = Player.REPEAT_MODE_OFF
|
||||||
|
|
||||||
fun clear() = queue.clear()
|
fun clear() = queue.clear()
|
||||||
|
|
||||||
@ -51,12 +52,30 @@ object PlayingQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return the next item, or if repeating enabled, the first one of the queue
|
// return the next item, or if repeating enabled, the first one of the queue
|
||||||
fun getNext(): String? = queue.getOrNull(currentIndex() + 1)?.url?.toID()
|
fun getNext(): String? {
|
||||||
?: queue.firstOrNull()?.url?.toID()?.takeIf { repeatQueue }
|
if (repeatMode != Player.REPEAT_MODE_ONE) {
|
||||||
|
queue.getOrNull(currentIndex() + 1)?.url?.toID()?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (repeatMode) {
|
||||||
|
Player.REPEAT_MODE_ALL -> queue.firstOrNull()?.url?.toID()
|
||||||
|
Player.REPEAT_MODE_ONE -> currentStream?.url?.toID()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return the previous item, or if repeating enabled, the last one of the queue
|
// return the previous item, or if repeating enabled, the last one of the queue
|
||||||
fun getPrev(): String? = queue.getOrNull(currentIndex() - 1)?.url?.toID()
|
fun getPrev(): String? {
|
||||||
?: queue.lastOrNull()?.url?.toID()?.takeIf { repeatQueue }
|
if (repeatMode != Player.REPEAT_MODE_ONE) {
|
||||||
|
queue.getOrNull(currentIndex() - 1)?.url?.toID()?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (repeatMode) {
|
||||||
|
Player.REPEAT_MODE_ALL -> queue.lastOrNull()?.url?.toID()
|
||||||
|
Player.REPEAT_MODE_ONE -> currentStream?.url?.toID()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun hasPrev() = getPrev() != null
|
fun hasPrev() = getPrev() != null
|
||||||
|
|
||||||
@ -214,7 +233,7 @@ object PlayingQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun resetToDefaults() {
|
fun resetToDefaults() {
|
||||||
repeatQueue = false
|
repeatMode = Player.REPEAT_MODE_OFF
|
||||||
onQueueTapListener = {}
|
onQueueTapListener = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
app/src/main/res/drawable/ic_repeat_one.xml
Normal file
10
app/src/main/res/drawable/ic_repeat_one.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M7,7h10v3l4,-4 -4,-4v3L5,5v6h2L7,7zM17,17L7,17v-3l-4,4 4,4v-3h12v-6h-2v4zM13,15L13,9h-1l-2,1v1h1.5v4L13,15z" />
|
||||||
|
</vector>
|
@ -270,6 +270,7 @@
|
|||||||
<string name="resize_mode_zoom">Zoom</string>
|
<string name="resize_mode_zoom">Zoom</string>
|
||||||
<string name="repeat_mode_none">None</string>
|
<string name="repeat_mode_none">None</string>
|
||||||
<string name="repeat_mode_current">Current</string>
|
<string name="repeat_mode_current">Current</string>
|
||||||
|
<string name="repeat_mode_all">Repeat all</string>
|
||||||
<string name="backup_restore">Backup & restore</string>
|
<string name="backup_restore">Backup & restore</string>
|
||||||
<string name="backup">Backup</string>
|
<string name="backup">Backup</string>
|
||||||
<string name="picture_in_picture">Picture-in-Picture</string>
|
<string name="picture_in_picture">Picture-in-Picture</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user