From 33858bd8cee7eba1b68e5053b2ada81eb5e72e0c Mon Sep 17 00:00:00 2001 From: hl-valdemar Date: Sat, 10 Oct 2026 19:04:31 +0200 Subject: [PATCH] fix: center controller content and autoplay opened files --- README.md | 6 +++--- Sources/App/PlayerApp.swift | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fd07ca5..4a11f0f 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ make run The local app is `.build/Player.app`. It links the installed FFmpeg libraries; it is not a standalone distributable bundle. After upgrading FFmpeg, rebuild with `make -B`. -Open a local file with **⌘O**, drop it onto the window, or use Finder's **Open With**. Files open paused. **⇧⌘W** closes the file; closing the window quits and joins the worker. +Open a local file with **⌘O**, drop it onto the window, or use Finder's **Open With**. Successfully opened files start playback automatically, including when replacing the current file. **⇧⌘W** closes the file; closing the window quits and joins the worker. ## Playback UI -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. +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. Shared vertical padding and an optical offset for symbol/slider insets balance the controller's visible top and bottom margins in both play and pause states. 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. @@ -49,7 +49,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. `seek_pending` is set synchronously when a seek or frame step is accepted and clears when all queued seeks/steps on that timeline finish. `player_step_frame` accepts only `-1` or `+1`, requires ready video, and publishes the selected frame's timestamp as `position`. 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, exact frame stepping, 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, AppKit glass and native slider cells, floating controls, visibility, video-fitted sizing, and native window integration. +- `Sources/App/PlayerApp.swift`: MainActor state polling, file panel/Finder/drop handling, autoplay, video host, AppKit glass and native slider cells, floating controls, visibility, video-fitted sizing, and native window integration. The shared `PlayerModel.open` path enqueues play after an accepted open, on the new file's command timeline; the C interface still opens paused for callers that need explicit playback control. - `Makefile`: compiler/linker commands and app bundle construction. No generated Xcode project or additional build dependency. ## Runnable check diff --git a/Sources/App/PlayerApp.swift b/Sources/App/PlayerApp.swift index 9363609..811bc40 100644 --- a/Sources/App/PlayerApp.swift +++ b/Sources/App/PlayerApp.swift @@ -95,12 +95,11 @@ final class PlayerModel: ObservableObject { commandError = "Could not queue the file to open. Please try again." return } - // Open is always paused; never queue play against the previous file. pendingRevision = revision fileName = url.lastPathComponent fileIcon = NSWorkspace.shared.icon(forFile: url.path) needsVideoFit = true - commandError = nil + commandError = player_play(handle) ? nil : "Could not queue playback. Please try again." isSeeking = false seekPending = false seekPosition = 0 @@ -528,7 +527,6 @@ private struct PlayerContent: View { .frame(width: 106, alignment: .trailing) } .padding(.horizontal, 16) - .padding(.top, 14) HStack(spacing: 10) { Text(time(model.seekPosition)).frame(minWidth: 32, alignment: .trailing) @@ -553,8 +551,10 @@ private struct PlayerContent: View { } .font(.system(size: 11).monospacedDigit()) .padding(.horizontal, 16) - .padding(.bottom, 8) } + .padding(.vertical, 11) + // Optical centering accounts for symbol insets and the native seek thumb. + .offset(y: -1.5) .foregroundStyle(.white.opacity(0.6)) .onHover(perform: model.setControlsHovered) }