Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add playback speed menu to ExoPlayer #392

Merged
merged 3 commits into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions app/src/main/java/org/jellyfin/mobile/player/PlaybackMenus.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ class PlaybackMenus(
private val lockScreenButton: View by playerControlsBinding::lockScreenButton
private val audioStreamsButton: View by playerControlsBinding::audioStreamsButton
private val subtitlesButton: ImageButton by playerControlsBinding::subtitlesButton
private val speedButton: View by playerControlsBinding::speedButton
private val infoButton: View by playerControlsBinding::infoButton
private val playbackInfo: TextView by playerBinding::playbackInfo
private val audioStreamsMenu: PopupMenu = createAudioStreamsMenu()
private val subtitlesMenu: PopupMenu = createSubtitlesMenu()
private val speedMenu: PopupMenu = createSpeedMenu()

private var subtitleCount = 0
private var subtitlesOn = false
Expand Down Expand Up @@ -63,6 +65,10 @@ class PlaybackMenus(
}
}
}
speedButton.setOnClickListener {
fragment.suppressControllerAutoHide(true)
speedMenu.show()
}
infoButton.setOnClickListener {
playbackInfo.isVisible = !playbackInfo.isVisible
}
Expand Down Expand Up @@ -147,6 +153,25 @@ class PlaybackMenus(
setOnDismissListener(this@PlaybackMenus)
}

private fun createSpeedMenu() = PopupMenu(context, speedButton).apply {
for (step in 2..8) {
val newSpeed = step * 0.25f
menu.add(SPEED_MENU_GROUP, step, Menu.NONE, "${newSpeed}x").isChecked = newSpeed == 1f
}
menu.setGroupCheckable(SPEED_MENU_GROUP, true, true)
setOnMenuItemClickListener { clickedItem: MenuItem ->
fragment.onSpeedSelected(clickedItem.itemId * 0.25f).also { success ->
if (success) {
menu.forEach { item ->
item.isChecked = false
}
clickedItem.isChecked = true
}
}
}
setOnDismissListener(this@PlaybackMenus)
}

private fun buildMenuItems(menu: Menu, groupId: Int, mediaStreams: List<MediaStream>, selectedStream: MediaStream?, showNone: Boolean = false) {
menu.clear()
val itemNone = if (showNone) menu.add(groupId, -1, Menu.NONE, fragment.getString(R.string.menu_item_none)) else null
Expand Down Expand Up @@ -180,5 +205,6 @@ class PlaybackMenus(
companion object {
private const val SUBTITLES_MENU_GROUP = 0
private const val AUDIO_MENU_GROUP = 1
private const val SPEED_MENU_GROUP = 2
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,13 @@ class PlayerFragment : Fragment() {
return viewModel.mediaQueueManager.toggleSubtitles()
}

/**
* @return true if the playback speed was changed
*/
fun onSpeedSelected(speed: Float): Boolean {
return viewModel.setPlaybackSpeed(speed)
}

fun onSkipToPrevious() {
viewModel.skipToPrevious()
}
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/java/org/jellyfin/mobile/player/PlayerViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,22 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application),
}
}

/**
* Set the playback speed to [speed]
*
* @return true if the speed was changed
*/
fun setPlaybackSpeed(speed: Float): Boolean {
val player = playerOrNull ?: return false

val parameters = player.playbackParameters
if (parameters.speed != speed) {
player.setPlaybackParameters(parameters.withSpeed(speed))
return true
}
return false
}

fun stop() {
pause()
reportPlaybackStop()
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_slow_motion_video_white_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#ffffff"
android:pathData="M13.05,9.79L10,7.5v9l3.05,-2.29L16,12zM13.05,9.79L10,7.5v9l3.05,-2.29L16,12zM13.05,9.79L10,7.5v9l3.05,-2.29L16,12zM11,4.07L11,2.05c-2.01,0.2 -3.84,1 -5.32,2.21L7.1,5.69c1.11,-0.86 2.44,-1.44 3.9,-1.62zM5.69,7.1L4.26,5.68C3.05,7.16 2.25,8.99 2.05,11h2.02c0.18,-1.46 0.76,-2.79 1.62,-3.9zM4.07,13L2.05,13c0.2,2.01 1,3.84 2.21,5.32l1.43,-1.43c-0.86,-1.1 -1.44,-2.43 -1.62,-3.89zM5.68,19.74C7.16,20.95 9,21.75 11,21.95v-2.02c-1.46,-0.18 -2.79,-0.76 -3.9,-1.62l-1.42,1.43zM22,12c0,5.16 -3.92,9.42 -8.95,9.95v-2.02C16.97,19.41 20,16.05 20,12s-3.03,-7.41 -6.95,-7.93L13.05,2.05C18.08,2.58 22,6.84 22,12z" />
</vector>
13 changes: 12 additions & 1 deletion app/src/main/res/layout/exo_player_control_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/audio_streams_button" />

<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/speed_button"
android:layout_width="@dimen/exo_bottom_controls_size"
android:layout_height="@dimen/exo_bottom_controls_size"
android:layout_marginBottom="@dimen/exo_bottom_controls_margin"
android:background="@drawable/ripple_background_circular"
android:padding="@dimen/exo_bottom_controls_padding"
android:src="@drawable/ic_slow_motion_video_white_24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/subtitles_button" />

<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/info_button"
android:layout_width="@dimen/exo_bottom_controls_size"
Expand All @@ -164,7 +175,7 @@
android:padding="@dimen/exo_bottom_controls_padding"
android:src="@drawable/ic_info_white_24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/subtitles_button" />
app:layout_constraintStart_toEndOf="@id/speed_button" />

<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/fullscreen_switcher"
Expand Down