-
-
Notifications
You must be signed in to change notification settings - Fork 489
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 controls #1302
Add Playback speed controls #1302
Conversation
Thanks for your pull request(s). Before I review it I'd like to ask you to split all the unit testing changes to a separate PR as it's not simply adding a few tests but adding dependencies etc. with it. We try to focus pull requests to one particular change to make it easier to review, and with this PR I feel like it might take some time to get merged purely because of a secondary change (testing changes). |
This comment has been minimized.
This comment has been minimized.
584e925
to
b3b0a39
Compare
Done, I've rejigged the history of both branches to drop any non-essential commits into their own PRs.
No worries, I'm also aware of the amount of maintainers time required especially with the time commitments from the festive time of the year coming up too. In this case I just got on a bit of a roll and ended up with a much larger PR than originally envisioned.... |
b3b0a39
to
f1e72e0
Compare
f1e72e0
to
a8ad0c9
Compare
a8ad0c9
to
dce56ce
Compare
dce56ce
to
f7e9999
Compare
Adds the various basic mocks required to unit test Playback Controller. At a high level the steps we perform are: - Prep mocks for deps injected by constructor - Prep mocks for Koin, then pass these as singletons - Patch up various calls out to Android SharedPrefs ...etc. This allows us to construct a PlaybackController in a JVM context now. These mechanisms will be useful for later in the patch series too....
Adds setPlaybackSpeed to the view and controller. The controller has associated tests which built on the earlier ones. Unfortunately the view also has logic in it and I've tried to (ab)use mocks to factor out the ExoPlayer factory. However because it's a static final the mock will always defer to the real impl. I could introduce some sort of interface and abstract out the calls to the underlying players using an adapter pattern so we can test this. But alas, the player rewrite will obselete this and I'm 8+ hours into getting tests to work...
Adds a new controller for VideoSpeed, to help encapsulate items following SRP. This also adds a mechanism to track the users most recent speed selection, so switching from videos / to other media and back will restore the user's selection on the next video.
This makes it much easier to compare for equality and has built in indexing making the menu much easier to work with. In comparison using doubles directly would have required us to add a comparison lambda in the view to correctly detect what was selected / determine what is selected.
f7e9999
to
a25c7e2
Compare
app/src/main/java/org/jellyfin/androidtv/preference/UserPreferences.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/ui/playback/PlaybackController.java
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/ui/playback/overlay/action/PlaybackSpeedAction.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/ui/playback/overlay/action/PlaybackSpeedAction.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/ui/playback/overlay/action/PlaybackSpeedAction.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/ui/playback/overlay/action/PlaybackSpeedAction.kt
Outdated
Show resolved
Hide resolved
Wires up the view component for playback speed controls, based on the pattern used in various other action items.
a25c7e2
to
f35ba7d
Compare
This will ignore any values that are clearly incorrect i.e. <0.25. This means the playback controller can still have a sentinel value of -1.0 to ensure the model controlling speed is in-place correctly. Whilst not breaking user playback by default if something goes wrong. As this file directly interfaces with the video manager (which holds surfaces) we can't easily make a test for it, so leave this block untested
d3d0459
to
71047c4
Compare
Inject the interface for shared preferences rather than the concrete type. This avoids Mockk trying to grab the abstract class underneath, which would run the real impl instead. It also brings our DI in this file more in-line with the commonly used pattern
71047c4
to
20415d2
Compare
app/src/main/java/org/jellyfin/androidtv/preference/IUserPreferences.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/preference/UserPreferences.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/ui/playback/VideoSpeedController.kt
Outdated
Show resolved
Hide resolved
- Revert some noisy automatic formatting - Move speed steps out of companion object - Drop supuerfluous interface
app/src/main/java/org/jellyfin/androidtv/preference/UserPreferences.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/preference/UserPreferences.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/di/PreferenceModule.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/ui/playback/PlaybackController.java
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/ui/playback/VideoSpeedController.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/jellyfin/androidtv/ui/playback/VideoSpeedController.kt
Outdated
Show resolved
Hide resolved
- Use Kotlin a kotlin setter directly - Make the variable public - (Small amount of rewiring to make everything work)
Drop PlaybackController test. We can't simply inject by interface as this isn't type safe with how it's currently implemented. Since it's likely PlaybackController is going to undergo a major rework with pending future work, let's simply drop the tests and revert the associated changes.
discussions already resolved
The speed controls are available for live tv playback. Setting the speed to > 1 breaks playback by constantly running out of buffer. Can you patch this? I'm not too familiar with live-tv but it seems likely that even for values < 1 the stream could become unavailable if the client falls too far behind the live edge. If that's likely then it may be better to just disable playback speed adjustment for live tv |
@DavidFair When playing faster speed pass through audio should be disabled as otherwise we get the high pitch audio, |
I'll put a patch in tonight to check if we're playing back live tv and simply reset the speed from the speed controller.
If it doesn't we'll have to leave it as a limitation, where users can choose to play faster with the current caveat that the pitch is wrong. I'll have a look what's available too, but AFAIK Chromium, Firefox and MPV all get around this by implementing a scale filter. So it depends on if ExoPlayer and / or libVLC have the appropriate audio filters available |
@Dnkhatri I can't reproduce this with Exoplayer locally, shifting 1x to 2x maintains the same sang note on my content |
@Dnkhatri It should be there. The only place it is disabled is with live tv |
Changes
Adds Playback speed controls:
Use the same icon / general UX style as Jellyfin-Android's playback button
A playback speed will apply to the current and future videos for the current application launch. I.e. setting speed to 2.00x then playing the next episode will also play at 2.00x
This PR Contains the following:
VideoSpeedController
to keep logic / state nice and encapsulated with the associatedPlaybackSpeedAction
. This should hopefully make it easy to incorporate into The Playback Rewrite #1057See each commit for more detailed descriptions.
This is my first foray into Kotlin, and I haven't done Android dev in 4-5 years. So I'm happy to take any/all criticisms, feedback and change ideas.
Issues
Fixes: #1189
Testing