## Description
Ensure that MPV is always destroyed before being initialized again.
Also, now creating a new player is only done when switching backends
which means faster, more efficient playing the next up.
### Related issues
Fixes#766
## Description
Adds the [`dav1d` decoder
module](https://github.com/androidx/media/tree/release/libraries/decoder_av1)
for ExoPlayer as an option. It can be enabled in advanced settings.
Performance will vary between devices.
### Related issues
Closes#103
### Dev notes
As with the ffmpeg module, this one is not required to build the entire
app so it's easier for developers to get started.
This also introduces a customized `DefaultRenderersFactory` for
ExoPlayer, but its largely copied from the super class's implementation.
## Description
This PR add the ability to integrate with a [Jellyseerr/Seerr
server](https://github.com/seerr-team/seerr).
### Features
- Login to the Seerr server using API Key, Jellyfin credentials, or
local Seerr credentials
- Separate Seerr logins per user profile
- Search Seerr from the search page
- Discover media from Seerr on the nav drawer `Discover` page
- Also from movie, series, or person pages
- Seamless integration with existing media, i.e. selecting media found
from Seerr that already exists on the Jellyfin server, will go directly
to the regular media page
- Mostly consistent UI between Jellyfin media & Seerr media
- Submit requests to Seerr
- Cancel submitted requests
### Screenshots

### Related issues
Closes#54
## Acknowledgements
The `app/src/main/seerr/seerr-api.yml` file is copied & modified from
https://github.com/seerr-team/seerr/blob/develop/seerr-api.yml. I hope
to try to upstream some of the changes in the future.
## Description
A few devices, like the Nvidia Shield Pro 2019, are able to correctly
handle Dolby Vision Profile 7. However, when a Full Enhancement Layer
(FEL) is present, these devices effectively ignore the enhancement layer
and only apply the RPU metadata.
Due to this behavior, device capabilities are reported as not supporting
`DOVIWithEL`, which causes the Jellyfin server to strip the DV layer
entirely with a remux.
This commit adds an option to force direct play of Dolby Vision Profile
7 content, preventing the server from stripping the Dolby Vision layer
and allowing compatible devices to handle playback as intended.
### Related issues
Fixes https://github.com/damontecres/Wholphin/issues/449
### Screenshots
<img width="1280" height="720" alt="dovi7"
src="https://github.com/user-attachments/assets/849e9897-93b6-419f-a1fb-7f361f9c88dd"
/>
### AI/LLM usage
None
Co-authored-by: Ray <154766448+damontecres@users.noreply.github.com>
## Description
Check if playback is for a remote source and, if so, play that remote
URL directly. Works for both ExoPlayer & MPV.
Also adds support for direct playback for DASH in ExoPlayer.
### Related issues
Closes#471Closes#666
## Description
Fixes duplicate play/pause commands from a remote button press and
`MediaSession`.
This ended up being a bit complicated because Wholphin overrides the
default play/pause behavior for the skip back setting and to show the
controller on pause. This means using a forwarding player which meant
implementing more functionality into `MpvPlayer`.
### Related issues
Fixes#653
## Description
When switching resolution (and possibly refresh rate less frequently),
the initial surface is not always valid. This means, the MPV playback
treated it as detaching the surface and would never update.
This PR instead subscribes to the `SurfaceHolder`'s callbacks which will
provide a new, valid surface once the switch is ready. Then the surface
is attached and queued commands execute to start playback.
Also temporarily disables content scale options for MPV since the
compose implementation conflicts with MPV rendering.
### Related issues
Fixes#626
## Description
This is an embarrassing bug... In #619, a change was made to avoid a
race condition and wait for the video output surface to be ready by
re-enqueuing commands. Except I missed cancelling executing the current
command.
This meant the command would both be executed and queued again. So, if
attaching the video surface takes a while, such as needing to wait for a
refresh rate change, _a lot_ of commands could have been added to the
queue and trigger a constant start-stop playback loop.
I think technically it would eventually resolve itself, but can take a
while.
### Related issues
Should fix#626
## Description
Fixes a race condition where `libmpv` is beginning playback before it
has been attached to the output video surface.
The solution is for the handler to re-enqueue commands if MPV is either
not initialized or not attached yet. Once `libmpv` is ready, the
commands will be processed.
### Related issues
Should fix#576
## Description
No user facing changes in this PR
This is a continuation of #481 to move initializing and tearing down
`libmpv` onto the looper thread to prevent main thread blocking.
~The only function left that runs on the main thread is
`setVideoSurfaceView`. Since this has to directly interact with the UI,
I need to read the docs and ExoPlayer code a bit more to see how this
can safely done multi-threaded.~ It is safe/correct to attach on another
thread.
## Description
Changes how `init()` works for `ApiRequestPager` so that it 1) always
forces updating the total count if needed and 2) propagates errors
during the initial fetch up to the original caller
This means if an error occurs during the initialization of the pager
data, it won't be quietly logged and ignored. Instead, ViewModel code
will catch it and display an error in the UI.
### Related issues
Should fix#492
There's no user facing changes in this PR
This PR updates `MpvPlayer` to use a threading model more similar to
[ExoPlayer's
model](https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlayer#threading-model).
There's now a dedicated thread looper message queue between the UI
interactions on the main thread and calls to `libmpv`. This is necessary
because previously, the main thread would make the calls into `libmpv`.
`libmpv` uses internal mutex locking for some operations which meant
that the main thread would be blocked momentarily.
Now, the UI issues a command (eg seek to X position) and the command is
added to the thread looper queue and processed on that separate thread.
This uses the standard Android Handler/Looper mechanisms.
Related to #235
**This is for MPV playback backend only!** Since this only works in MPV
for now, the option is not shown if using ExoPlayer.
Adds a setting (the gear icon during playback) to adjust the subtitle
delay.
A negative delay shows subtitles sooner. A positive delay shows them
later. For example, if a subtitle is supposed to show between
1000ms-2000ms, a negative 250ms delay will show it at 750ms-1750ms
instead.
The delay is persisted between plays of the same media & subtitle track.
Ref: #12

Adds a settings allowing for adjusting the thickness of unstyled
subtitle outlines, if outline is enabled.
This is applied for both ExoPlayer & MPV
Closes#179

Dev note: the ExoPlayer implementation is bad code, don't write code
like this. It works though
Fixes thread used by changes from #359
Also create the device direct play profile lazily-ish off of the main
thread because this can take some time to create.
Should help address some of the "too much work" reported in #363, and
also fixes the network-on-main exception in the logs on #363
## Details
This PR contains a number of optimizations
### Images
Updates to request images with maximum sizes
The max sizes are estimates on the maximum number of pixels that will be
actually displayed. This means the server is downscaling large images
which means 1) better quality downscaling and 2) smaller images sent
over the network and cached
This should mean slightly better quality images and more images that can
be cached locally
### Paging
Reduces network calls when fetching paginated data, ie grid pages and
some rows. This PR combines the total record count & first page queries
which slightly reduces total time to load paginated data.
Additionally, on movies/tv show recommended pages, the rows now only
fetch a limited number of items (same as number on home page). While
they previously fetched using pagination, there is an overhead required
to paginate requests, so this is slightly faster.
### Async recommended fetching
On movies/tv show recommended pages, the rows are now fetched completely
separately from each other. Previously, the rows were requested
separtely, but each was only added to the UI in order as each completed.
Now they will add as the data arrived.
Note: Top unwatched TV shows is still very slow on `10.11.x`, see #204
### Image cache
The local, on-disk image cache size is increased from 100mb to 200mb.
Combined with the smaller images, this covers about 1500-2000 poster
images, but will vary by server.
The cache size is now also configurable in advanced settings from 25mb
to 1000mb. Additionally, you can see how much of both the disk and
memory caches are in use.
## Issues
Closes#330
Related to #120
Adds a toggle to increase the verbosity of the app logs for
release/production builds
Most users won't need to use this, but it can be helpful when [gathering
app
logs](https://github.com/damontecres/Wholphin/wiki/Gathering-app-logs)
to report an issue.
## Details
This PR updates the detail pages for Movies & TV Shows.
- Increase backdrop image size & brightness (now matches home page)
- Increase max width for titles
- Decrease max width for detail text
- Switch to using a customized display labels for video, audio, &
subtitle streams
Additional change for movie pages:
- Don't dim movie details text
- Move video stream details below play buttons
- Move first row up higher
### Labels
Instead of using the server provided `DisplayTitle`, create display
labels in-app. In general, this shortens the text without losing
significant detail. It is similar to the official app.
Some of the changes:
- Don't show "SDR", only "HDR"
- Simplify audio channel info, eg "Surround 5.1" => "5.1"
- Show chosen subtitle language
- Show chosen subtitle codec
- Show "(+#)" if there are additional audio or subtitle tracks
- Use gray background slightly tinted by the theme color
## Issues
Closes#239
## Details
This PR updates the device profile used by ExoPlayer. It should more
accurately report support for HDR formats.
## Acknowledgements
This PR contains a commit (cd6351912af72d274b0baf50af4d777b986f0f46)
that has code copied and slightly modified from
https://github.com/jellyfin/jellyfin-androidtv `v0.19.4`.
Major acknowledgement & credit to the Jellyfin Android TV developers for
this code!
## Issues
Related to #15
## Details
This PR ended up being larger than I meant. It contains some UI changes
and code organization.
## TV & DVR
- Uses the "Recordings" library position to order "Recently added in
Recordings" instead of Live TV position
- The times at the top of the TV guide are more distinguishable from
each other
- Removes the duplicate title on the Live TV->Recordings tab
## Other libraries
- Bare-bone support for "Music Video" libraries. Full support for "Music
Video" is work-in-progress in #267, but the libraries should be
browseable now.
- Bare-bone support for "Other" (aka Mixed Movies & TV Shows) libraries.
Note: this type of library is considered [broken and
deprecated](https://jellyfin.org/docs/general/server/media/mixed-movies-and-shows),
so this won't be expanded any further
## Grids
Updates various grid types to use poster vs wide cards. For example,
Favorite TV Episodes will use episode images in a wide card now.
## Issues
Closes#249Closes#271
Experimental MPV player backend
Related to #14, #22, & #85
You can switch to MPV in advanced settings and toggle using hardware
decoding or not.
This uses code and buildscripts from
https://github.com/mpv-android/mpv-android, plus other third party
libraries to build MPV
Previously if the activity tracker got an error from the server during
one of the reports, the timer thread would stop and no further reports
would be sent.
This PR fixes that so it will continue to attempt to send reports since
if playback is continuing without error, the report error is likely
transient. For example, I observed the server returning an error during
its DB optimization scheduled task.
I think this will fix#208
Now when initiating a user or server switch, you can't back out of it
and must select a user/server. This will be useful when PIN code are
implemented down the road.
The app will now disconnect the web socket when backgrounded.
Also lots of internal refactoring
Just adds some logging while navigating around the app. If an error or
crash occurs and users want to share their logs, this information is
useful to know what page.
Logs are never sent without explicit user content and they are only
shared with the Jellyfin server the app is currently connected to. [See
here for more
details](https://github.com/damontecres/Wholphin/wiki/Gathering-app-logs#privacy)
Also stops theme music when the app is paused similar to #191
Refactors lifecycle event observers
When the app is "paused", aka not actively focused, but still visible
(such as when opening Android TV OS menu), playback will pause.
When the app is "stopped", aka not visible (such as pressing Home
button), playback will stop, report playback progress, and return to the
previous screen.
I think this will fix#181, but I don't have a controller to test with
Previously all of the rows on the recommended tab for Movies & TV Shows
were loaded sequentially before any results were shown. This is not a
great experience because some of the queries (eg top rated unwatched)
can take a while sometimes.
This PR starts displaying content once the first 1 or 2 rows is loaded
and then shows placeholders while the rest are querying.
Finally the row queries are now mostly independent so if one errors out,
the rest of the rows will still be displayed.
Closes#180
Fixes#184
Data was being fetched, but the UI wasn't being properly notified to
display the data.
This PR also adjusts so that "focused episode header" still takes up the
space even if the focused episode hasn't fully loaded yet. This prevents
the UI from jumping up and down.
Also #42 is _not_ fixed by this PR because it is a different issue.
Closes#154
Adds a settings to show the current time in the upper right corner.
If enabled, it will also show the end time for the playback on the
overlay.
Closes#133Fixes#142
Theme songs will play for both TV shows and movies, if available. Also,
if there are multiple theme songs, one will be picked randomly instead
of always playing the first.
Additionally, the music now waits to start until the UI has loaded.
Closes#95
Adds a setting (defaults to enabled) to automatically go to a page when
the navigation drawer item is focused after a brief delay.
Basically, if you open the left nav drawer, and scroll down to "Movies"
after a brief delay (600ms), the app will switch to the Movies page
without having to click.
It can be disabled in advanced settings.
When clicking the overview for an item, the dialog now shows details
about each file/media source including video, audio, & subtitle
information.
It only shows the full file path if the user is an administrator.
Fixes#113
- Ensures all audio and subtitle options are shown during playback
- Fix home rows not being at top when going back
- Show error message when background home page refresh fails
Also shows more details for login failures and adds a link to the debug
page (with log info) after multiple login failure attempts. Hopefully
this can help diagnose #112 and #18