Skip to content

playback: Fix subtitle visibility leakage and filter missing episodes#496

Merged
RadicalMuffinMan merged 1 commit into
Moonfin-Client:mainfrom
mattsigal:feature/subtitle-visibility-and-missing-episodes-fix
Jun 11, 2026
Merged

playback: Fix subtitle visibility leakage and filter missing episodes#496
RadicalMuffinMan merged 1 commit into
Moonfin-Client:mainfrom
mattsigal:feature/subtitle-visibility-and-missing-episodes-fix

Conversation

@mattsigal

@mattsigal mattsigal commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Pull Request

Summary

This PR resolves two playback issues reported in issue #198:

  1. Subtitle visibility issues where subtitles start invisible on auto-advancing to subsequent episodes due to subtitle visibility state leaking and eager disabling when subtitle selection is null.
  2. The player attempting to play missing/virtual episodes or specials in play queues, causing playback failures or player crashes.

Additionally, it resolves the UI synchronization issue where auto-selected/default subtitles are active during playback, but the subtitle track selector dialog incorrectly highlights "Off" instead of the active track.

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Performance improvement
  • UI/UX update
  • Documentation update
  • Build/CI change
  • Other (describe):

Changes Made

  • Playback Core (packages/playback_core):
    • Modified PlaybackManager to only disable subtitles when the user or server has explicitly set them to -1 (disabled). When null, the backend is allowed to auto-select and display subtitles.
    • Added activeSubtitleTrackIndex getter to PlayerBackend interface.
    • Updated subtitleStreamIndex getter in PlaybackManager to query the player backend for the active native subtitle track and map it back to the Jellyfin streamIndex when _subtitleStreamIndex is null (auto-selected). This ensures the UI subtitle selection highlights the currently active track instead of displaying "Off".
  • MediaKit Player Backend:
    • In MediaKitPlayerBackend, reset the native mpv player's subtitle properties (sid to 'auto', secondary-sid to 'no', sub-visibility to 'yes', sub-ass to 'yes') on starting any new playback. This prevents subtitle disable state from leaking from previous tracks.
    • Implemented activeSubtitleTrackIndex to query _player.state.track.subtitle and resolve the 1-based native track index.
  • Other Player Backends:
    • Overrode activeSubtitleTrackIndex in Media3PlayerBackend, TizenPlayerBackend, and HtmlVideoBackend to return null (not supported/applicable).
  • Client App UI & Queuing:
    • Filtered play queues constructed in ItemDetailScreen (Season, Episode, and Shuffle playback triggers) to exclude missing episodes and virtual placeholder items using isEligibleNextEpisodeCandidate.
    • Filtered adjacent/next-season playback queues in the _nextSeasonItemsProvider in PlaybackModule using isEligibleNextEpisodeCandidate.
  • Unit Tests:
    • Updated outdated migration key checking in audio_migration_test.dart from pref_audio_preference_split_v1 to pref_audio_preference_split_v2 to align with the active implementation and restore 100% test success.

Platform

  • Android
  • iOS
  • macOS
  • Windows
  • Linux
  • All / Shared code

Testing

  • Tested on emulator / simulator
  • Tested on physical device
  • Manual testing completed
  • Not tested (explain why):

Test Steps

  1. Play an episode with subtitles enabled/auto-selected. Let the player auto-advance to the next episode. Verify subtitles are immediately visible on the next track.
  2. Open the Subtitle Track selector dialog on the next episode. Verify the dialog highlights the currently active subtitle track, rather than highlighting "Off".
  3. Go to a season containing missing episodes or virtual specials, start playback of a preceding episode, and let it advance. Verify it skips the missing/virtual episodes and plays the next available episode without errors.
  4. Verify that all 42/42 unit tests pass successfully.

Screenshots (if applicable)

N/A

Checklist

  • Code builds successfully
  • Code follows project style and conventions
  • No unnecessary commented-out code
  • No new warnings introduced

@mattsigal mattsigal marked this pull request as draft June 11, 2026 14:08
@mattsigal mattsigal force-pushed the feature/subtitle-visibility-and-missing-episodes-fix branch from 58bd2ff to 38b97b4 Compare June 11, 2026 14:31
@mattsigal mattsigal marked this pull request as ready for review June 11, 2026 14:32
@RadicalMuffinMan

Copy link
Copy Markdown
Contributor

rebase on main

@mattsigal mattsigal force-pushed the feature/subtitle-visibility-and-missing-episodes-fix branch from 38b97b4 to 1a05cb3 Compare June 11, 2026 22:59

int? get activeSubtitleTrackIndex => null;

Future<int?> getActiveSubtitleTrackIndexAsync() async => null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Future<int?> getActiveSubtitleTrackIndexAsync() async => null;

dead code not used by anything

return null;
}

Future<int?> getSubtitleStreamIndexAsync() async {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

116 - 128 can be deleted. dead code not used by anything

Comment thread lib/playback/media3_player_backend.dart Outdated
@override
int? get activeSubtitleTrackIndex => null;

@override

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@override

dead code not used by anything

Comment thread lib/playback/media3_player_backend.dart Outdated
int? get activeSubtitleTrackIndex => null;

@override
Future<int?> getActiveSubtitleTrackIndexAsync() async => null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Future<int?> getActiveSubtitleTrackIndexAsync() async => null;

dead code not used by anything

Comment thread lib/playback/tizen_player_backend.dart Outdated
@override
int? get activeSubtitleTrackIndex => null;

@override

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@override

dead code not used by anything

@override
int? get activeSubtitleTrackIndex => null;

@override

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@override

dead code not used by anything

int? get activeSubtitleTrackIndex => null;

@override
Future<int?> getActiveSubtitleTrackIndexAsync() async => null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Future<int?> getActiveSubtitleTrackIndexAsync() async => null;

dead code not used by anything

@override
int? get activeSubtitleTrackIndex => null;

@override

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@override

int? get activeSubtitleTrackIndex => null;

@override
Future<int?> getActiveSubtitleTrackIndexAsync() async => null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Future<int?> getActiveSubtitleTrackIndexAsync() async => null;

return null;
}

@override

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1265 - 1288 can be deleted. dead code not used by anything

…ue missing episodes

- Prevent subtitle visibility state leaking between tracks on MediaKit backend.
- Filter out missing/virtual episodes and specials from play queues.
- Asynchronously query native subtitle track to synchronize the UI subtitle track selector when auto-selected.
- Fix broken unit tests from audio pref migrations.
- Change all player backend classes to extend PlayerBackend instead of implements PlayerBackend to allow clean default property inheritance.
- Simplify getActiveSubtitleTrackIndexAsync in MediaKitPlayerBackend to return the activeSubtitleTrackIndex getter directly, removing duplicate native querying block.
- Remove redundant activeSubtitleTrackIndex and getActiveSubtitleTrackIndexAsync overrides in html_video_backend_web, html_video_backend_stub, media3_player_backend, and tizen_player_backend.
- Clean up unused import in tizen_player_backend.
@mattsigal mattsigal force-pushed the feature/subtitle-visibility-and-missing-episodes-fix branch from 1a05cb3 to 67b2c37 Compare June 11, 2026 23:25
@RadicalMuffinMan RadicalMuffinMan merged commit 12571d2 into Moonfin-Client:main Jun 11, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[UI] android tv playback issues

2 participants