- Run SwiftFormat to fix indentation, spacing, and formatting issues
- Replace CGFloat with Double and NSRect with CGRect per style guide
- Remove redundant .center alignment specifications
- Remove unnecessary @available checks for satisfied deployment targets
- Fix closure brace indentation for consistency
- Disable closure_end_indentation rule to resolve SwiftFormat conflict
All linting checks now pass with zero errors and warnings.
Implemented automatic retry logic with exponential backoff (2, 4, 6 seconds) when file loading fails in AVPlayerBackend. Retries up to 3 times before showing error to user. Retry state is properly reset on successful loads. This matches the retry implementation added to MPVBackend in commit b6df73f9.
This commit enables proper Now Playing Info Center integration on iOS, allowing video playback information to appear in Control Center and Lock Screen with working remote controls.
Key changes:
- Activate audio session on app launch with setCategory(.playback, mode: .moviePlayback) and setActive(true)
- Set up remote commands on first play() call instead of during app initialization to avoid claiming Now Playing slot prematurely
- Remove removeTarget(nil) calls that were claiming Now Playing without content
- Enable remote commands (play, pause, toggle, seek) explicitly and add proper target handlers
- Use backend.isPlaying instead of PlayerModel.isPlaying to avoid race conditions
- Include playback rate (1.0 for playing, 0.0 for paused) in Now Playing info
- Update Now Playing info on main queue for thread safety
- Update Now Playing when switching between backends
- Remove audio session deactivation from pause() and stop() methods
Note: This fix works for AVPlayer backend. MPV backend has fundamental incompatibility with iOS Now Playing system.
Remove incorrect safe area insets from offsetY calculation that was
causing unequal black bars (smaller top, larger bottom). Now properly
centers video with equal padding like AVPlayer backend.
Refactored glUpdate to use requestRedraw method for better control. Added needsRedraw flag to prevent redundant display calls. Enabled asynchronous drawing on VideoLayer for improved performance. Modified displayLinkCallback to only report swap without triggering display to avoid flooding the main thread.
Added guard check to return early if currentTime is nil in getTimeUpdates. Simplified optional unwrapping by using the guarded currentTime value throughout the method.
Added comprehensive nil checks for stream resolution values across PlayerBackend, QualityProfile, and PlayerQueue to prevent crashes when streams have missing resolution metadata. Also added backend nil checks in PlayerQueue.
Implemented automatic retry logic with exponential backoff (2, 4, 6 seconds) when file loading fails in MPVBackend. Retries up to 3 times before showing error to user. Retry state is properly reset on successful loads.
Refactor orientation logic when entering fullscreen to better handle
button-initiated vs gesture-initiated transitions:
- Consolidate orientation determination into a single expression that
considers whether fullscreen was initiated by button or gesture
- When initiated by button, always use rotateToLandscapeOnEnterFullScreen
preference
- When initiated by gesture, respect current device orientation if already
in landscape, otherwise use preference
- Apply .landscape lock only for button-initiated transitions, .all for
gesture-initiated (when not orientation locked)
This provides more intuitive behavior where button taps rotate to preferred
orientation, while gestures respect current device orientation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add logging for video and audio asset URLs during stream filtering to help debug stream selection issues.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add proper validation and fallback logic for audio track selection in MPV backend:
- Validate audio track index is within bounds before switching
- Handle streams without separate audio tracks (single asset streams)
- Reset selectedAudioTrackIndex if out of bounds
- Add fallback path for streams without audioTracks array
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- fix subtitle disabling not working
- make subtitle adding/removing async
- make subtitle menu non blocking
Signed-off-by: Toni Förster <toni.foerster@gmail.com>
Currently, we have a hard-coded list of resolutions. Since Invidious reports the actual resolution of a stream and does not hard-code them to a fixed value anymore, resolutions that are not in the list won’t be handled, and the stream cannot be played back.
Instead of hard-coding even more resolutions (and inadvertently might not cover all), we revert the list back to a finite set of resolutions, the users can select from. All other resolutions are handled dynamically and compared to the existing set of defined resolutions when selecting the best stream for playback.
Signed-off-by: Toni Förster <toni.foerster@gmail.com>
- use displays refresh rate
- execute needs drawing with higher priority
- run create() with higher priority
- determine the number of threads used for rendering
- enable VSYNC and change video-sync to display-resample
- iOS/tvOS: set new display refresh rate on change
- run setSize with higher priority
- add more options to MPVClient
- get refresh rate updates
- sync refresh rate to fps
- update CADisplayLink to current refresh rate
- update refresh rate on macOS
- Add experimental feature to sync display with content fps
Signed-off-by: Toni Förster <toni.foerster@gmail.com>
- iPad: rotate to device orientation on startup
- fixed controls in portrait fullscreen
- iOS: don’t call setNeedsDrawing multiple times
- On iOS we call set needs drawing only once.
- Added cooldown time to MPV.Client setNeedsDrawing to avoid multiple successive calls
- make fullscreen animation smoother
- dragGesture now calls toggleFullScreenAction
- fix tvOS and macOS build
Signed-off-by: Toni Förster <toni.foerster@gmail.com>
Currently when returning from background, the app is fullscreen but the video is in portrait mode.
Now when entering background we leave fullscreen and enter it again the the app is in foreground.
Signed-off-by: Toni Förster <toni.foerster@gmail.com>
- MP4 contains av1 encoded video which is not hardware accelerated.
- MP4 format removed from AVPlayer
Signed-off-by: Toni Förster <toni.foerster@gmail.com>
- Don’t use System Controls with AVPlayer by default
- Changed default order of the formats
- no default AVPlayer profiles except for tvOS
- new constants isIOS, isTvOS, isMacOS
- ArtWork for nowPlaying is .medium on iPhone .maxres on all other platforms
- changes to the player bar defaults
Signed-off-by: Toni Förster <toni.foerster@gmail.com>