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

feat: Chapter additions #466

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c665c39
Add chapter markers and "skip chapter" on long press
Natanel-Shitrit Aug 12, 2023
d5802fd
Fix linting problems
Natanel-Shitrit Aug 12, 2023
d72bdc7
Add preferences options
Natanel-Shitrit Aug 12, 2023
3a64a38
Drop chapter support for ExoPlayer
Natanel-Shitrit Aug 12, 2023
9b725d1
Fix linting
Natanel-Shitrit Aug 12, 2023
bec7937
Remove Trailing spaces
Natanel-Shitrit Aug 12, 2023
e35e40f
Remove TODO from marker color
Natanel-Shitrit Aug 12, 2023
6249897
Move code to function
Natanel-Shitrit Aug 12, 2023
956a941
Optimize imports
Natanel-Shitrit Aug 17, 2023
84d0c72
Fix crash on episode skip
Natanel-Shitrit Jan 11, 2024
424038f
Disable player control view animation
Natanel-Shitrit Jan 18, 2024
8378501
Avoid crash when there are no chapters for media item
Natanel-Shitrit Jan 18, 2024
08aa37a
Skip to next episode when skipping last chapter
Natanel-Shitrit Jan 18, 2024
0d2d69a
Load chapters from Jellyfin API instead of MPV Player
Natanel-Shitrit Jan 24, 2024
43cf2ca
Remove chapter gesture
Natanel-Shitrit Jan 24, 2024
1c9137e
Fix build
Natanel-Shitrit Jan 24, 2024
2d3fc59
Fix linting
Natanel-Shitrit Jan 24, 2024
ff01630
Fix linting
Natanel-Shitrit Jan 24, 2024
b6f6363
Support chapters with offline media
Natanel-Shitrit Jan 25, 2024
b3e00fb
Remove debug print
Natanel-Shitrit Jan 25, 2024
79e7ab0
Add chapter skipping
Natanel-Shitrit Jan 28, 2024
d3eb04a
Merge branch 'main' into feature/chapter-selector
Natanel-Shitrit Feb 9, 2024
c9e038e
Remove trailing spaces
Natanel-Shitrit Feb 9, 2024
eb4c921
fix(chapters): display correct chapter while seeking
jarnedemeulemeester Feb 13, 2024
2a74b6e
refactor: faster and cleaner `getCurrentChapterIndex`
jarnedemeulemeester Feb 13, 2024
c6a7c41
refactor: seek to start of current chapter if player position is more…
jarnedemeulemeester Feb 13, 2024
9699b34
refactor: change "Matroska chapters" to just "Chapters"
jarnedemeulemeester Feb 13, 2024
1d175f1
Bump database version
Natanel-Shitrit Feb 16, 2024
1ce2a4a
Add auto-migration for database version bump
Natanel-Shitrit Feb 16, 2024
c683d7a
Save database schema
Natanel-Shitrit Feb 16, 2024
7ebdfb7
chore: clean up
jarnedemeulemeester Feb 17, 2024
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
19 changes: 18 additions & 1 deletion app/phone/src/main/java/dev/jdtech/jellyfin/PlayerActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Rect
import android.media.AudioManager
import android.os.Build
Expand All @@ -29,6 +30,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.media3.common.C
import androidx.media3.ui.DefaultTimeBar
import androidx.media3.ui.PlayerControlView
import androidx.media3.ui.PlayerView
import androidx.navigation.navArgs
import dagger.hilt.android.AndroidEntryPoint
Expand Down Expand Up @@ -144,6 +146,18 @@ class PlayerActivity : BasePlayerActivity() {
it.currentTrickPlay = currentTrickPlay
}

// Chapters
if (appPreferences.showChapterMarkers && currentChapters != null) {
currentChapters?.let { chapters ->
val playerControlView = findViewById<PlayerControlView>(R.id.exo_controller)
val numOfChapters = chapters.size
playerControlView.setExtraAdGroupMarkers(
LongArray(numOfChapters) { index -> chapters[index].startPosition },
BooleanArray(numOfChapters) { false },
)
}
}

// File Loaded
if (fileLoaded) {
audioButton.isEnabled = true
Expand Down Expand Up @@ -239,9 +253,12 @@ class PlayerActivity : BasePlayerActivity() {
pictureInPicture()
}

// Set marker color
val timeBar = binding.playerView.findViewById<DefaultTimeBar>(R.id.exo_progress)
timeBar.setAdMarkerColor(Color.WHITE)

if (appPreferences.playerTrickPlay) {
val imagePreview = binding.playerView.findViewById<ImageView>(R.id.image_preview)
val timeBar = binding.playerView.findViewById<DefaultTimeBar>(R.id.exo_progress)
previewScrubListener = PreviewScrubListener(
imagePreview,
timeBar,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import dev.jdtech.jellyfin.AppPreferences
import dev.jdtech.jellyfin.Constants
import dev.jdtech.jellyfin.PlayerActivity
import dev.jdtech.jellyfin.isControlsLocked
import dev.jdtech.jellyfin.models.PlayerChapter
import dev.jdtech.jellyfin.mpv.MPVPlayer
import timber.log.Timber
import kotlin.math.abs
Expand Down Expand Up @@ -74,21 +75,19 @@ class PlayerGestureHelper(
return true
}

@SuppressLint("SetTextI18n")
override fun onLongPress(e: MotionEvent) {
// Disables long press gesture if view is locked
if (isControlsLocked) return

// Stop long press gesture when more than 1 pointer
if (currentNumberOfPointers > 1) return

playerView.player?.let {
if (it.isPlaying) {
lastPlaybackSpeed = it.playbackParameters.speed
it.setPlaybackSpeed(playbackSpeedIncrease)
activity.binding.gestureSpeedText.text = playbackSpeedIncrease.toString() + "x"
activity.binding.gestureSpeedLayout.visibility = View.VISIBLE
}
// This is a temporary solution for chapter skipping.
// TODO: Remove this after implementing #636
if (appPreferences.playerGesturesChapterSkip) {
handleChapterSkip(e)
} else {
enableSpeedIncrease()
}
}

Expand Down Expand Up @@ -123,6 +122,55 @@ class PlayerGestureHelper(
},
)

@SuppressLint("SetTextI18n")
private fun enableSpeedIncrease() {
playerView.player?.let {
if (it.isPlaying) {
lastPlaybackSpeed = it.playbackParameters.speed
it.setPlaybackSpeed(playbackSpeedIncrease)
activity.binding.gestureSpeedText.text = playbackSpeedIncrease.toString() + "x"
activity.binding.gestureSpeedLayout.visibility = View.VISIBLE
}
}
}

private fun handleChapterSkip(e: MotionEvent) {
if (isControlsLocked) {
return
}

val viewWidth = playerView.measuredWidth
val areaWidth = viewWidth / 5 // Divide the view into 5 parts: 2:1:2

// Define the areas and their boundaries
val leftmostAreaStart = 0
val middleAreaStart = areaWidth * 2
val rightmostAreaStart = middleAreaStart + areaWidth

when (e.x.toInt()) {
in leftmostAreaStart until middleAreaStart -> {
activity.viewModel.seekToPreviousChapter()?.let { chapter ->
displayChapter(chapter)
}
}
in rightmostAreaStart until viewWidth -> {
if (activity.viewModel.isLastChapter() == true) {
playerView.player?.seekToNextMediaItem()
return
}
activity.viewModel.seekToNextChapter()?.let { chapter ->
displayChapter(chapter)
}
}
else -> return
}
}

private fun displayChapter(chapter: PlayerChapter) {
activity.binding.progressScrubberLayout.visibility = View.VISIBLE
activity.binding.progressScrubberText.text = chapter.name ?: ""
}

private fun fastForward() {
val currentPosition = playerView.player?.currentPosition ?: 0
val fastForwardPosition = currentPosition + appPreferences.playerSeekForwardIncrement
Expand Down
10 changes: 6 additions & 4 deletions app/phone/src/main/res/layout/exo_player_view.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/exo_controller">

<androidx.media3.ui.AspectRatioFrameLayout
android:id="@id/exo_content_frame"
Expand Down Expand Up @@ -82,9 +83,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />

<View
android:id="@id/exo_controller_placeholder"
<androidx.media3.ui.PlayerControlView
android:id="@id/exo_controller"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
app:animation_enabled="false"/>

</merge>
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ val dummyEpisode = FindroidEpisode(
seasonId = UUID.randomUUID(),
communityRating = 9.2f,
images = FindroidImages(),
chapters = null,
)

val dummyEpisodes = listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ val dummyMovie = FindroidMovie(
endDate = null,
trailer = "https://www.youtube.com/watch?v=puKWa8hrvA8",
images = FindroidImages(),
chapters = null,
)

val dummyMovies = listOf(
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,10 @@
<string name="player_gestures_vb">Volume and brightness gestures</string>
<string name="player_gestures_zoom">Zoom gesture</string>
<string name="player_gestures_seek">Seek gesture</string>
<string name="player_gestures_chapter_skip">Chapter gesture</string>
<string name="player_gestures_vb_summary">Swipe up and down on the right side of the screen to change the volume and on the left side to change the brightness</string>
<string name="player_gestures_zoom_summary">Pinch to fill the screen with the video</string>
<string name="player_gestures_chapter_skip_summary">Long press on Left / Right side to skip chapters (overrides 2x speed gesture)</string>
<string name="player_gestures_seek_summary">Swipe horizontally to seek forwards or backwards</string>
<string name="player_brightness_remember">Remember brightness level</string>
<string name="player_start_maximized">Start maximized</string>
Expand Down Expand Up @@ -145,6 +147,8 @@
<string name="pref_player_intro_skipper_summary">Requires ConfusedPolarBear\'s Intro Skipper plugin to be installed on the server</string>
<string name="pref_player_trick_play">Trick Play</string>
<string name="pref_player_trick_play_summary">Requires nicknsy\'s Jellyscrub plugin to be installed on the server</string>
<string name="pref_player_chapter_markers">Chapter markers</string>
<string name="pref_player_chapter_markers_summary">Display chapter markers on the timebar</string>
<string name="addresses">Addresses</string>
<string name="add_address">Add address</string>
<string name="add_server_address">Add server address</string>
Expand Down
13 changes: 13 additions & 0 deletions core/src/main/res/xml/fragment_settings_player.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
app:key="pref_player_gestures_seek"
app:summary="@string/player_gestures_seek_summary"
app:title="@string/player_gestures_seek" />
<SwitchPreferenceCompat
app:defaultValue="true"
app:dependency="pref_player_gestures"
app:key="pref_player_gestures_chapter_skip"
app:summary="@string/player_gestures_chapter_skip_summary"
app:title="@string/player_gestures_chapter_skip" />
<SwitchPreferenceCompat
app:dependency="pref_player_gestures_vb"
app:key="pref_player_brightness_remember"
Expand Down Expand Up @@ -97,6 +103,13 @@
app:title="@string/pref_player_trick_play"
app:widgetLayout="@layout/preference_material3_switch" />

<SwitchPreferenceCompat
app:defaultValue="true"
app:key="pref_player_chapter_markers"
app:summary="@string/pref_player_chapter_markers_summary"
app:title="@string/pref_player_chapter_markers"
app:widgetLayout="@layout/preference_material3_switch" />

<PreferenceCategory app:title="@string/picture_in_picture">
<SwitchPreferenceCompat
app:key="pref_player_picture_in_picture_gesture"
Expand Down
Loading