Commit graph

62 commits

Author SHA1 Message Date
Ray
20fe5e2626
Move MPV init & destroy to looper thread (#534)
## 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.
2025-12-22 10:40:42 -05:00
Ray
13d70e7623
Rework internals of ApiRequestPager (#518)
## 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
2025-12-20 14:39:48 -05:00
Ray
8b40e89b8a
Update MPV playback threading model (#481)
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
2025-12-17 18:24:25 -05:00
Ray
8479d8621d
Bump dependency versions, notably media3 (#496)
## Description
Bumps dependency versions, notably media3/ExoPlayer to `1.9.0`

### Related issues

Fixes #108
Fixes #355
Fixes #479
2025-12-17 17:00:15 -05:00
damontecres
ab8bbf2bd7
MPV: Adjust subtitle delay/offset (#470)
**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 


![subtitle_delay](https://github.com/user-attachments/assets/824e3a28-650a-4619-9535-b67addaabf1e)
2025-12-15 10:06:36 -05:00
damontecres
9e7742034a
Update style for ktlint 1.8 (#390)
Updated `ktlint`, so lots of code style changes, no user facing changes
2025-12-06 18:11:07 -05:00
damontecres
ac10517028
Add setting for subtitle outline size (#375)
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

![outline
Large](https://github.com/user-attachments/assets/dfef74a5-a4d4-49db-a8d2-231e46ab151e)

Dev note: the ExoPlayer implementation is bad code, don't write code
like this. It works though
2025-12-05 16:55:46 -05:00
damontecres
a294661520
Support custom mpv.conf (#327)
Part of #235 
Closes #305

Adds a preference for specifying a custom `mpv.conf`

Also adds a preference to toggle between `vo=gpu` and `vo=gpu-next`, see
https://github.com/mpv-player/mpv/wiki/GPU-Next-vs-GPU

There are some caveats:
* Multi-line text entry via a remote is rough
* [Track selection
options](https://mpv.io/manual/stable/#track-selection) may not work as
expected because Wholphin manages this itself
* Bad settings will crash the app hard

Dev note: This rewrites the text field inputs to use the [state based
implementations](https://developer.android.com/develop/ui/compose/text/migrate-state-based)
2025-12-04 13:21:40 -05:00
damontecres
bddf51e076
Fix some threading issues (#364)
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
2025-12-02 19:17:28 -05:00
damontecres
56bf3cb7a0
Optimizes recommended content & image caching (#359)
## 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
2025-12-02 16:00:21 -05:00
damontecres
10233eb459
Support VC-1 direct play if device supports it (#362)
Adds VC-1 to ExoPlayer direct play profile, if the device supports it.

Also proposed to add this to the official app in
https://github.com/jellyfin/jellyfin-androidtv/pull/5208
2025-12-02 10:56:39 -05:00
damontecres
eca3268a7d
Add setting to increase logging verbosity (#354)
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.
2025-11-30 17:27:41 -05:00
damontecres
5b96be6662
Updates to details pages including videos' stream details display (#279)
## 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
2025-11-24 15:35:55 -05:00
damontecres
20ab146c97
Update device profile for Jellyfin 10.11 (#293)
## 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
2025-11-21 20:16:49 -05:00
damontecres
45567bf4eb
Variety of UI changes for grids, home page order, & tv guide (#272)
## 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 #249 
Closes #271
2025-11-20 17:00:11 -05:00
damontecres
6be2662d4e
Add experimental MPV player backend (#161)
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
2025-11-16 18:46:25 -05:00
damontecres
b7cb6efc4f
Dev: Move services into their own package (#214)
Moves service classes into their own files and package for easier
organization and discovery

No user facing changes in the PR
2025-11-13 19:39:37 -05:00
damontecres
fe29b0cd88
Show local & remote trailers for TV Shows (#212)
Shows local & remote trailers for TV Shows similar to how its shown for
Movies

Closes #141
2025-11-13 18:31:23 -05:00
Jakub Syty
f61e819a98
Add FLAG_ACTIVITY_NEW_TASK to fix updates for some older devices (#211)
Without this the installation intent is crashing with an error on my
Xiaomi Mi Box S (Android 8.1)
2025-11-13 17:27:20 -05:00
damontecres
19b712d54b
More favorite tabs & add people to favorites (#210)
Adds Video, Playlists, & People tabs to the favorites page

Also adds ability to add people to favorites via context menu or on
their page

Closes #199
2025-11-13 16:12:42 -05:00
damontecres
5061277fd1
Keep activity tracking alive even after errors (#209)
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
2025-11-13 11:36:57 -05:00
damontecres
58395e9adf
Refactoring switching server or user (#205)
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
2025-11-12 17:44:16 -05:00
damontecres
2e3e4e3f5f
Add long clicking context menus everywhere (#202)
Adds long click context menus to just about every card throughout the
app. Previously only a few pages had this.

Closes #196
2025-11-12 15:36:36 -05:00
damontecres
5e2c75bb70
Log while navigating around the app (#195)
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
2025-11-11 20:10:16 -05:00
Damontecres
d6c9b236ef
Fix reversed logic 2025-11-10 18:45:31 -05:00
damontecres
fbf77b9376
Better playback lifecycle handling (#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
2025-11-10 17:55:58 -05:00
damontecres
98fc996bd5
Load movie & tv recommendations asynchronously (#183)
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
2025-11-09 17:40:47 -05:00
damontecres
0fb1a69556
Fix only loading 100 episode in a season (#187)
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.
2025-11-09 17:40:13 -05:00
damontecres
5720603447
Add ability to style subtitles (#177)
Adds settings for styling text subtitles such as srt/subrip

## Issues
Closes #11
2025-11-08 19:54:51 -05:00
damontecres
5d085a3ab4
Show update download progress (#165)
Shows a simple dialog while the app update is downloading to show
progress
2025-11-06 18:15:25 -05:00
damontecres
77c787b51f
Add settings to show the current time (#155)
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.
2025-11-04 15:27:38 -05:00
damontecres
40a8249469
Support basic adding to playlists (#157)
Closes #143 

Adds option in the "More" menu to add the item to a playlist. Can also
create a playlist if needed.
2025-11-04 15:27:26 -05:00
damontecres
2840fa3f2a
Extract strings into resources (#151)
Move all strings into resource files to make future translating easier

No user facing changes in this PR
2025-11-03 15:38:12 -05:00
damontecres
08577b8a31
Play theme song for movies (#149)
Closes #133 
Fixes #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.
2025-11-03 11:50:47 -05:00
damontecres
9f3691fd1b
Optional to automatically go to new page on focus instead of clicking (#127)
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.
2025-10-31 15:09:13 -04:00
damontecres
1508fa1ea3
Show file details in overview dialog (#126)
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.
2025-10-31 12:27:30 -04:00
damontecres
982506555f
Add page to details about people (#119)
Adds a page to show details about people (actors, directors, etc) when
clicking on the person card

<img width="1280" height="771" alt="wholphin_person"
src="https://github.com/user-attachments/assets/ceba6c77-2943-4faf-a2c2-81471fb3acff"
/>
2025-10-30 19:24:36 -04:00
damontecres
3f7c2ac730
UI Updates & Fixes (#114)
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
2025-10-30 13:41:46 -04:00
damontecres
f76556f90e
Fix network on main exception trying to play theme songs (#111)
Fetch the theme song info on the IO thread

This would throw an exception on some devices, but it would be caught
without affecting the app, other than just not playing theme music.
2025-10-29 20:07:00 -04:00
damontecres
cbcae526b4
Don't report playback started until it actually starts (#107)
Wait until playback actually beings before reporting status to the
server. And also ensure progress isn't reported until after reporting
start.
2025-10-29 13:15:17 -04:00
damontecres
1db48334ab
Sort & format subtitle download options (#88)
Sorts the subtitle download options by community rating and downloads.

Also abbreviates the download count if it's large (eg 5133->5.1k).
2025-10-28 13:07:30 -04:00
damontecres
af0e853c21
Don't send crash reports as json (#84)
This is a workaround for jellyfin/jellyfin-web#7267 to ensure the client
logs are not valid JSON and can be rendered on the `10.11.x` web UI.

Related to #82
2025-10-27 21:22:44 -04:00
damontecres
f1f6b729aa
Fix several UI focus issues (#81)
Remembers the page position & focused item on both Movie & Series detail
pages

Only loads similar movies & series once so that if you click on one and
go back, it doesn't refresh the entire list

Remember the tab on the Favorite page (if remember tabs is enabled in
settings)
2025-10-27 20:44:04 -04:00
damontecres
89b9364807
Dependency updates & removing unused code (#70)
Just bumping dependencies and deleting some unused code. No user facing
changes
2025-10-26 18:17:47 -04:00
damontecres
143fc03d9b
Add long click to home page (#66)
Add a popup when long clicking items on the home page

Also fixes a bug where the latest Recorded TV row would show non-Live TV
items if nothing has ever been recorded.
2025-10-26 08:50:24 -04:00
damontecres
2667090485
Send crash reports to the server (#65)
Adds ability to send app crash reports to the last connected server. The
app prompts you before sending. There is an advanced settings to disable
this as well.

Additionally, there is an advanced settings button to send the app logs
to the current server.

The resulting reports can be found on the server's web UI under
Dashboard->Logs

If sharing the logs, make sure there's no private information present!
2025-10-26 07:35:42 -04:00
damontecres
05f3811149
Add Live TV & DVR Support (#49)
Closes #1 

Adds support for Live TV & DVR functionality.

TODO:
- [x] EPG / TV Guide
- [x] View DVR schedule
- [x] Play live TV channel
- [x] Record program
- [x] Record Series
- [x] Cancel recordings
- [x] Access previously recorded content
2025-10-23 22:46:16 -04:00
damontecres
27d0a17a00
Support remote media control commands (#58)
Adds support for remote media controls (play, pause, etc) and displaying
messages.
2025-10-22 21:04:25 -04:00
damontecres
b5771db54e
Save remembered tabs per user (#57)
If the remember tab setting is enabled, tabs will be remembered per user
profile now
2025-10-22 19:24:17 -04:00
damontecres
77aaa87126
More bug fixes (#45)
Fixes:
* Issue from #39 where pressing back from playback went back two screens
instead of one
* Sometimes having to click on a server twice to switch to it
* Update UI when marking a single season as watched
* Fix needing to press back twice to hide skip segment buttons
* Fix skip intro/outro behaviors being swapped
* Always attempt to save playback progress when stopping playback
2025-10-19 22:35:47 -04:00