chore: rename project and app to terebi
This commit is contained in:
@@ -7,10 +7,10 @@ ARCH := $(shell uname -m)
|
||||
CXXFLAGS := -std=c++20 -mmacosx-version-min=15.0 -O2 -g -Wall -Wextra -Wno-unused-parameter $(FF_CFLAGS)
|
||||
FRAMEWORKS := -framework AppKit -framework AudioToolbox -framework CoreAudio -framework Metal -framework MetalKit -framework QuartzCore
|
||||
OBJECTS := .build/player.o .build/Output.o
|
||||
APP := .build/Player.app
|
||||
APP := .build/terebi.app
|
||||
|
||||
.PHONY: all run check check-audio
|
||||
all: $(APP)/Contents/MacOS/Player $(APP)/Contents/Info.plist
|
||||
all: $(APP)/Contents/MacOS/terebi $(APP)/Contents/Info.plist
|
||||
|
||||
.build:
|
||||
mkdir -p $@
|
||||
@@ -21,7 +21,7 @@ all: $(APP)/Contents/MacOS/Player $(APP)/Contents/Info.plist
|
||||
.build/Output.o: Sources/macOS/Output.mm Sources/Core/output.hpp Makefile | .build
|
||||
$(CXX) $(CXXFLAGS) -fobjc-arc -c $< -o $@
|
||||
|
||||
$(APP)/Contents/MacOS/Player: Sources/App/PlayerApp.swift $(OBJECTS) Makefile
|
||||
$(APP)/Contents/MacOS/terebi: Sources/App/TerebiApp.swift $(OBJECTS) Makefile
|
||||
mkdir -p $(APP)/Contents/MacOS
|
||||
$(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O -g -import-objc-header Sources/Core/player_macos.h $< $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -lc++ -o $@
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Player
|
||||
# terebi
|
||||
|
||||
A personal native macOS player whose playback code is small enough to own and modify. FFmpeg reads and decodes media; our C++ worker owns playback. SwiftUI owns the controls, Core Audio owns audio output, and Metal presents video.
|
||||
|
||||
@@ -12,7 +12,7 @@ make
|
||||
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`.
|
||||
The local app is `.build/terebi.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**. Successfully opened files start playback automatically, including when replacing the current file. **⇧⌘W** closes the file; closing the window quits and joins the worker.
|
||||
|
||||
@@ -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, 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.
|
||||
- `Sources/App/TerebiApp.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
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key><string>Player</string>
|
||||
<key>CFBundleIdentifier</key><string>local.personal.player</string>
|
||||
<key>CFBundleName</key><string>Player</string>
|
||||
<key>CFBundleExecutable</key><string>terebi</string>
|
||||
<key>CFBundleIdentifier</key><string>local.personal.terebi</string>
|
||||
<key>CFBundleName</key><string>terebi</string>
|
||||
<key>CFBundlePackageType</key><string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key><string>0.1</string>
|
||||
<key>LSMinimumSystemVersion</key><string>15.0</string>
|
||||
|
||||
@@ -139,7 +139,7 @@ final class PlayerModel: ObservableObject {
|
||||
isSeeking = false
|
||||
seekPending = false
|
||||
window?.representedURL = nil
|
||||
window?.title = "Player"
|
||||
window?.title = "terebi"
|
||||
revealControls()
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ final class PlayerModel: ObservableObject {
|
||||
|
||||
func attachWindow(_ window: NSWindow) {
|
||||
self.window = window
|
||||
window.title = fileName ?? "Player"
|
||||
window.title = fileName ?? "terebi"
|
||||
updateWindowState()
|
||||
fitVideoWindow()
|
||||
}
|
||||
@@ -451,11 +451,11 @@ private struct PlayerContent: View {
|
||||
} else {
|
||||
Image(systemName: "play.rectangle.fill").font(.system(size: 14))
|
||||
}
|
||||
Text(model.fileName ?? "Player")
|
||||
Text(model.fileName ?? "terebi")
|
||||
.font(.system(size: 13, weight: .semibold))
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.help(model.fileName ?? "Player")
|
||||
.help(model.fileName ?? "terebi")
|
||||
Spacer(minLength: 12)
|
||||
iconButton(model.isOnTop ? "pin.fill" : "pin",
|
||||
model.isOnTop ? "Stop Keeping Window on Top" : "Keep Window on Top", action: model.toggleOnTop)
|
||||
@@ -601,7 +601,7 @@ private struct PlayerContent: View {
|
||||
VStack(spacing: 14) {
|
||||
Image(systemName: "play.rectangle").font(.system(size: 56, weight: .ultraLight))
|
||||
.foregroundStyle(.white.opacity(0.65))
|
||||
Text("Player").font(.system(size: 22, weight: .medium))
|
||||
Text("terebi").font(.system(size: 22, weight: .medium))
|
||||
Text("Drop a media file here").font(.callout).foregroundStyle(.secondary)
|
||||
Button("Open File…", action: model.openPanel)
|
||||
.buttonStyle(.bordered).controlSize(.large).disabled(!model.canOpen)
|
||||
@@ -808,12 +808,12 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
@main
|
||||
@MainActor
|
||||
struct PlayerApp: App {
|
||||
struct TerebiApp: App {
|
||||
@NSApplicationDelegateAdaptor(AppDelegate.self) private var delegate
|
||||
@StateObject private var model = PlayerModel.shared
|
||||
|
||||
var body: some Scene {
|
||||
Window("\(model.fileName ?? "Player")", id: "player") {
|
||||
Window("\(model.fileName ?? "terebi")", id: "terebi") {
|
||||
PlayerContent(model: model)
|
||||
}
|
||||
.defaultSize(width: 900, height: 560)
|
||||
Reference in New Issue
Block a user