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:
NIK679 2021-10-20 23:46:43 +05:30 committed by GitHub
parent e991fab24e
commit 11ff3b4e16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 0 deletions

View file

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

View file

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

View file

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

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

View file

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