feat: match IINA screenshot geometry and controls

This commit is contained in:
2026-10-10 14:04:09 +02:00
parent 462cb52eb2
commit c9b9264109
6 changed files with 186 additions and 43 deletions
+5 -3
View File
@@ -18,7 +18,9 @@ Open a local file with **⌘O**, drop it onto the window, or use Finder's **Open
## Playback UI
The starting layout follows [IINA's video-first window](https://iina.io/img/screenshot.png): dark, edge-to-edge video, a slim titlebar with native traffic lights, and a draggable translucent floating controller. The controller starts centered near the bottom and keeps its relative position when the window changes size.
The layout follows [IINA's video-first window](https://iina.io/img/screenshot.png) and the supplied screenshots: a 32-point frosted titlebar with native traffic lights and file icon, plus a dark frosted 440 × 68-point floating controller. AppKit materials blur the video beneath the chrome; muted icons, an orange volume track, a narrow seek thumb, and zero-padded time labels follow the reference. The controller starts centered with a four-percent bottom inset and keeps its relative position when the window changes size.
Opening video fits the window to its display aspect ratio, including non-square pixels, and constrains subsequent window resizing. Fullscreen retains the normal letterboxed renderer; audio-only playback and close release the aspect constraint. Extreme ratios that cannot fit both the screen and usable controls keep a freely resizable letterboxed window.
- **Space:** play/pause. **←/→:** seek five seconds. The timeline slider seeks on release.
- **↑/↓:** adjust volume by five percent. **M:** mute/unmute, restoring the previous audible level.
@@ -33,7 +35,7 @@ Only implemented actions have controls; there are no placeholder playlist, subti
- `Sources/Core/player.h`: the C interface and authoritative state snapshot. Playback commands enqueue work; poll state for completion. Volume set/get is synchronous and uses a lock-free target gain. Callers own the opaque handle and must stop using it before destruction.
- `Sources/Core/player.cpp`: single demux/decode worker, bounded buffers, timestamps, audio-master synchronization, paused previews, decoder/resampler drain, seeking, errors, and shutdown. A seek stops output and flushes all old timeline state before resuming.
- `Sources/Core/output.hpp` and `Sources/macOS/Output.mm`: native output contract, allocation-free/nonblocking Core Audio callback and bounded audio ring, latency-aware presentation clock, retained frame mailbox, and Metal YUV conversion. The view can outlive the player safely.
- `Sources/App/PlayerApp.swift`: MainActor state polling, file panel/Finder/drop handling, video host, floating controls, visibility, and native window integration.
- `Sources/App/PlayerApp.swift`: MainActor state polling, file panel/Finder/drop handling, video host, AppKit glass and native slider cells, floating controls, visibility, video-fitted sizing, and native window integration.
- `Makefile`: compiler/linker commands and app bundle construction. No generated Xcode project or additional build dependency.
## Runnable check
@@ -42,7 +44,7 @@ Only implemented actions have controls; there are no placeholder playlist, subti
make check
```
Generates short fixtures and exercises the real playback interface and native outputs: audio/video, video-only, audio-only, pause, paused/playing seek, completion, replay, close, HDR rejection, failed-open recovery, and destruction while playing. It initializes the actual Metal shaders and uses an offscreen native window. It requires a working audio device and graphical macOS session, and plays short sine-wave audio. It is a runtime smoke check, not a mocked clock/device test.
Generates short fixtures and exercises the real playback interface and native outputs: audio/video, video-only, audio-only, non-square-pixel display aspect, pause, paused/playing seek, completion, replay, close, HDR rejection, failed-open recovery, and destruction while playing. It initializes the actual Metal shaders and uses an offscreen native window. It requires a working audio device and graphical macOS session, and plays short sine-wave audio. It is a runtime smoke check, not a mocked clock/device test.
`make check-audio` runs just the audio-quality check. A check-only hook captures actual Core Audio callback PCM into preallocated storage and compares every sample against FFmpeg's reference output for PCM/AAC, 44.1/48 kHz, and coarse container timestamps. It checks fractional gain, silent muted startup, smooth live volume changes, and unchanged playback completion. A separate gapped fixture verifies that real timestamp gaps remain silent. Release builds contain no capture hook.