feat: support for repeating video in audio mode

This commit is contained in:
Bnyro 2023-10-14 17:59:22 +02:00
parent 2f89bf3756
commit 75c74bcc89
6 changed files with 65 additions and 33 deletions

View File

@ -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!

View File

@ -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
} }
binding.repeat.alpha = if (PlayingQueue.repeatQueue) 1f else 0.5f updateRepeatButton()
}
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(

View File

@ -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)
} }

View File

@ -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 = {}
} }

View 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>

View File

@ -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 &amp; restore</string> <string name="backup_restore">Backup &amp; 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>