Add playback speed control to the player (#46)
* add playback speed control to MPV player * add playback speed control to exoplayer * remove unnecessary method * remove unused import * use gauge icon from lucide * use gauge icon from lucide * fix the gauge icon
This commit is contained in:
parent
e991fab24e
commit
11ff3b4e16
5 changed files with 92 additions and 0 deletions
|
@ -16,6 +16,7 @@ import com.google.android.exoplayer2.trackselection.MappingTrackSelector
|
||||||
import com.google.android.exoplayer2.ui.TrackSelectionDialogBuilder
|
import com.google.android.exoplayer2.ui.TrackSelectionDialogBuilder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.databinding.ActivityPlayerBinding
|
import dev.jdtech.jellyfin.databinding.ActivityPlayerBinding
|
||||||
|
import dev.jdtech.jellyfin.dialogs.SpeedSelectionDialogFragment
|
||||||
import dev.jdtech.jellyfin.dialogs.TrackSelectionDialogFragment
|
import dev.jdtech.jellyfin.dialogs.TrackSelectionDialogFragment
|
||||||
import dev.jdtech.jellyfin.mpv.MPVPlayer
|
import dev.jdtech.jellyfin.mpv.MPVPlayer
|
||||||
import dev.jdtech.jellyfin.mpv.TrackType
|
import dev.jdtech.jellyfin.mpv.TrackType
|
||||||
|
@ -65,6 +66,7 @@ class PlayerActivity : AppCompatActivity() {
|
||||||
|
|
||||||
val audioButton = binding.playerView.findViewById<ImageButton>(R.id.btn_audio_track)
|
val audioButton = binding.playerView.findViewById<ImageButton>(R.id.btn_audio_track)
|
||||||
val subtitleButton = binding.playerView.findViewById<ImageButton>(R.id.btn_subtitle)
|
val subtitleButton = binding.playerView.findViewById<ImageButton>(R.id.btn_subtitle)
|
||||||
|
val speedButton = binding.playerView.findViewById<ImageButton>(R.id.btn_speed)
|
||||||
|
|
||||||
audioButton.isEnabled = false
|
audioButton.isEnabled = false
|
||||||
audioButton.imageAlpha = 75
|
audioButton.imageAlpha = 75
|
||||||
|
@ -72,6 +74,9 @@ class PlayerActivity : AppCompatActivity() {
|
||||||
subtitleButton.isEnabled = false
|
subtitleButton.isEnabled = false
|
||||||
subtitleButton.imageAlpha = 75
|
subtitleButton.imageAlpha = 75
|
||||||
|
|
||||||
|
speedButton.isEnabled = false
|
||||||
|
speedButton.imageAlpha = 75
|
||||||
|
|
||||||
audioButton.setOnClickListener {
|
audioButton.setOnClickListener {
|
||||||
when (viewModel.player) {
|
when (viewModel.player) {
|
||||||
is MPVPlayer -> {
|
is MPVPlayer -> {
|
||||||
|
@ -134,12 +139,21 @@ class PlayerActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
speedButton.setOnClickListener {
|
||||||
|
SpeedSelectionDialogFragment(viewModel).show(
|
||||||
|
supportFragmentManager,
|
||||||
|
"speedselectiondialog"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.fileLoaded.observe(this, {
|
viewModel.fileLoaded.observe(this, {
|
||||||
if (it) {
|
if (it) {
|
||||||
audioButton.isEnabled = true
|
audioButton.isEnabled = true
|
||||||
audioButton.imageAlpha = 255
|
audioButton.imageAlpha = 255
|
||||||
subtitleButton.isEnabled = true
|
subtitleButton.isEnabled = true
|
||||||
subtitleButton.imageAlpha = 255
|
subtitleButton.imageAlpha = 255
|
||||||
|
speedButton.isEnabled = true
|
||||||
|
speedButton.imageAlpha = 255
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package dev.jdtech.jellyfin.dialogs
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
|
||||||
|
import java.lang.IllegalStateException
|
||||||
|
|
||||||
|
class SpeedSelectionDialogFragment(
|
||||||
|
private val viewModel: PlayerActivityViewModel
|
||||||
|
) : DialogFragment() {
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
val speedTexts = listOf("0.5x", "0.75x", "1x", "1.25x", "1.5x", "1.75x", "2x")
|
||||||
|
val speedNumbers = listOf(0.5f, 0.75f, 1f, 1.25f, 1.5f, 1.75f, 2f)
|
||||||
|
|
||||||
|
|
||||||
|
return activity?.let { activity ->
|
||||||
|
val builder = MaterialAlertDialogBuilder(activity)
|
||||||
|
builder.setTitle("Select playback speed")
|
||||||
|
.setSingleChoiceItems(
|
||||||
|
speedTexts.toTypedArray(),
|
||||||
|
speedNumbers.indexOf(viewModel.playbackSpeed)
|
||||||
|
) { dialog, which ->
|
||||||
|
viewModel.selectSpeed(
|
||||||
|
speedNumbers[which]
|
||||||
|
)
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
builder.create()
|
||||||
|
} ?: throw IllegalStateException("Activity cannot be null")
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,8 @@ constructor(
|
||||||
private var currentWindow = 0
|
private var currentWindow = 0
|
||||||
private var playbackPosition: Long = 0
|
private var playbackPosition: Long = 0
|
||||||
|
|
||||||
|
var playbackSpeed: Float = 1f
|
||||||
|
|
||||||
private val sp = PreferenceManager.getDefaultSharedPreferences(application)
|
private val sp = PreferenceManager.getDefaultSharedPreferences(application)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -225,4 +227,9 @@ constructor(
|
||||||
player.selectTrack(trackType, isExternal = false, index = track.ffIndex)
|
player.selectTrack(trackType, isExternal = false, index = track.ffIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun selectSpeed(speed: Float) {
|
||||||
|
player.setPlaybackSpeed(speed)
|
||||||
|
playbackSpeed = speed
|
||||||
|
}
|
||||||
}
|
}
|
22
app/src/main/res/drawable/ic_gauge.xml
Normal file
22
app/src/main/res/drawable/ic_gauge.xml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M12 15l3.5-3.5"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="2"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="@color/white"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M20.3 18c.4-1 .7-2.2.7-3.4C21 9.8 17 6 12 6s-9 3.8-9 8.6c0 1.2.3 2.4.7 3.4"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="2"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="@color/white"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
|
||||||
|
</vector>
|
|
@ -55,6 +55,20 @@
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btn_speed"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:background="@drawable/transparent_circle_background"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:src="@drawable/ic_gauge"
|
||||||
|
app:tint="@color/white" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="0dp" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/btn_audio_track"
|
android:id="@+id/btn_audio_track"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
Loading…
Reference in a new issue