CXX := xcrun clang++ SWIFT := xcrun swiftc FFMPEG := libavformat libavcodec libavutil libswresample libswscale ARCH := $(shell uname -m) DEPENDENCY_ROOT := $(abspath .build/dependencies/$(ARCH)) NATIVE_STAMP := $(DEPENDENCY_ROOT)/native.stamp HELPER_STAMP := $(DEPENDENCY_ROOT)/helpers.stamp FF_CFLAGS = $(shell PKG_CONFIG_LIBDIR="$(DEPENDENCY_ROOT)/ffmpeg/lib/pkgconfig" pkg-config --cflags $(FFMPEG)) FF_LIBS = $(shell PKG_CONFIG_LIBDIR="$(DEPENDENCY_ROOT)/ffmpeg/lib/pkgconfig" pkg-config --libs $(FFMPEG)) BUILD_DIR ?= .build DEBUG_FLAGS ?= -g PREFIX ?= $(HOME)/.local APPDIR ?= $(HOME)/Applications CXXFLAGS = -std=c++20 -mmacosx-version-min=15.0 -O2 $(DEBUG_FLAGS) -Wall -Wextra -Wno-unused-parameter $(FF_CFLAGS) FRAMEWORKS := -framework AppKit -framework AudioToolbox -framework CoreAudio -framework Metal -framework MetalKit -framework QuartzCore -framework MediaPlayer OBJECTS := $(BUILD_DIR)/player.o $(BUILD_DIR)/progress_reporter.o $(BUILD_DIR)/Output.o $(BUILD_DIR)/cast_media.o SWIFT_SOURCES := Sources/App/TerebiApp.swift Sources/App/PlayerActions.swift Sources/App/CompactWindow.swift Sources/App/YouTubeResolver.swift Sources/App/PlaybackProgress.swift Sources/App/PlaybackQueue.swift Sources/App/SystemPlaybackControls.swift Sources/App/AutomaticQuality.swift Sources/App/ResolvedSource.swift Sources/App/ExternalSubtitles.swift Sources/App/CastSession.swift Sources/App/CastMediaServer.swift Sources/App/CastControls.swift RUNTIME_SOURCE := Sources/Launcher/FFmpegRuntime.swift CLI_SOURCES := Sources/CLI/TerebiCLI.swift Sources/CLI/PlayerCommand.swift Sources/App/YouTubeResolver.swift Sources/App/ResolvedSource.swift $(RUNTIME_SOURCE) SWIFT_SOURCES += Sources/App/StreamResolver.swift SWIFT_SOURCES += Sources/App/MiruroMetadata.swift SWIFT_SOURCES += Sources/App/MiruroTransport.swift Sources/App/MiruroEmbed.swift Sources/App/ZokoResolver.swift CLI_SOURCES += Sources/App/StreamResolver.swift CLI_SOURCES += Sources/CLI/SourceCheck.swift Sources/App/ZokoResolver.swift Sources/App/MiruroTransport.swift Sources/App/MiruroEmbed.swift SWIFT_SOURCES += Sources/App/StreamQueue.swift SWIFT_SOURCES += Sources/App/SponsorBlock.swift CLI_SOURCES += Sources/App/StreamQueue.swift CONFIG_BUILD := .build/configuration CONFIG_BIN := $(shell xcrun swift build --scratch-path $(CONFIG_BUILD) -c release --show-bin-path) CONFIG_LIBRARY := $(CONFIG_BIN)/libTerebiConfiguration.a CONFIG_FLAGS := -I $(CONFIG_BIN) -I $(CONFIG_BIN)/Modules $(CONFIG_LIBRARY) APP := $(BUILD_DIR)/terebi.app PLAYER := $(APP)/Contents/Frameworks/libterebi-player.dylib BOOTSTRAP := $(APP)/Contents/MacOS/terebi CLI := $(APP)/Contents/MacOS/terebi-cli BUNDLE_STAMP := $(BUILD_DIR)/bundle.stamp SIGNING_IDENTITY ?= - DECODE_FIXTURES := $(addprefix $(BUILD_DIR)/fixtures/decode-,h264.mp4 hevc.mp4 vp9.mp4 av1.mp4 h264-10.mp4 mpeg4.mp4) .PHONY: all release install check-dependencies run check check-seek-queue check-video-decoding check-config check-fixtures check-audio check-window check-youtube check-quality check-adaptive check-network check-progress check-reporting check-cli check-runtime check-media check-startup check-bundle check-subtitles check-resolved check-cast check-queue all: $(BUILD_DIR)/terebi $(NATIVE_STAMP): Scripts/dependencies.py Dependencies.lock.json python3 Scripts/dependencies.py --root "$(DEPENDENCY_ROOT)" --arch "$(ARCH)" --part native $(HELPER_STAMP): Scripts/dependencies.py Dependencies.lock.json python3 Scripts/dependencies.py --root "$(DEPENDENCY_ROOT)" --arch "$(ARCH)" --part helpers check-dependencies: $(NATIVE_STAMP) @PKG_CONFIG_LIBDIR="$(DEPENDENCY_ROOT)/ffmpeg/lib/pkgconfig" pkg-config --exists $(FFMPEG) || { printf '%s\n' 'Error: bundled FFmpeg development libraries are unavailable. Remove .build/dependencies and rebuild terebi.' >&2; exit 1; } release: $(MAKE) BUILD_DIR=.build/release DEBUG_FLAGS= all install: release mkdir -p "$(APPDIR)" "$(PREFIX)/bin" rm -f "$(PREFIX)/lib/terebi/terebi" rm -rf "$(PREFIX)/lib/terebi/terebi.app" "$(APPDIR)/terebi.app" "$(APPDIR)/Terebi.app" cp -R ".build/release/terebi.app" "$(APPDIR)/Terebi.app" ln -sfn "$$(cd "$(APPDIR)" && pwd)/Terebi.app/Contents/MacOS/terebi-cli" "$(PREFIX)/bin/terebi" /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f "$(APPDIR)/Terebi.app" mdimport "$(APPDIR)/Terebi.app" $(BUILD_DIR): mkdir -p "$@" Package.resolved: Package.swift xcrun swift package --scratch-path $(CONFIG_BUILD) resolve $(CONFIG_LIBRARY): Package.swift Package.resolved $(wildcard Sources/Configuration/*.swift) xcrun swift build --scratch-path $(CONFIG_BUILD) -c release --product TerebiConfiguration $(APP)/Contents/Resources/TOMLDecoder-LICENSE.txt: $(CONFIG_LIBRARY) mkdir -p "$(APP)/Contents/Resources" cp -f "$(CONFIG_BUILD)/checkouts/TOMLDecoder/LICENSE.md" "$@" $(BUILD_DIR)/player.o: Sources/Core/player.cpp Sources/Core/player.h Sources/Core/player_macos.h Sources/Core/output.hpp Sources/Core/video_decoder.hpp Sources/Core/network_input.hpp Sources/Core/network_policy.hpp Sources/Core/progress_reporter.hpp Makefile $(NATIVE_STAMP) | $(BUILD_DIR) check-dependencies $(CXX) $(CXXFLAGS) -c $< -o $@ $(BUILD_DIR)/progress_reporter.o: Sources/Core/progress_reporter.cpp Sources/Core/progress_reporter.hpp Sources/Core/network_policy.hpp Sources/Core/player.h Makefile $(NATIVE_STAMP) | $(BUILD_DIR) $(CXX) $(CXXFLAGS) -c $< -o $@ $(BUILD_DIR)/cast_media.o: Sources/Core/cast_media.cpp Sources/Core/cast_media.h Sources/Core/video_decoder.hpp Sources/Core/network_policy.hpp Sources/Core/network_input.hpp Makefile $(NATIVE_STAMP) | $(BUILD_DIR) check-dependencies $(CXX) $(CXXFLAGS) -c $< -o $@ $(BUILD_DIR)/Output.o: Sources/macOS/Output.mm Sources/Core/output.hpp Makefile $(NATIVE_STAMP) | $(BUILD_DIR) check-dependencies $(CXX) $(CXXFLAGS) -fobjc-arc -c $< -o $@ $(PLAYER): $(SWIFT_SOURCES) $(OBJECTS) $(CONFIG_LIBRARY) Makefile | check-dependencies mkdir -p "$(APP)/Contents/Frameworks" rm -f "$(APP)/Contents/MacOS/terebi-player" $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -emit-library -O $(DEBUG_FLAGS) -import-objc-header Sources/Core/player_macos.h $(SWIFT_SOURCES) $(CONFIG_FLAGS) $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -lc++ -Xlinker -install_name -Xlinker @rpath/libterebi-player.dylib -o $@ $(BOOTSTRAP): Sources/App/Bootstrap.swift $(RUNTIME_SOURCE) Makefile | check-dependencies mkdir -p "$(APP)/Contents/MacOS" $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Sources/App/Bootstrap.swift $(RUNTIME_SOURCE) -framework AppKit -o $@ $(APP)/Contents/Info.plist: Resources/Info.plist mkdir -p "$(APP)/Contents" cp "$<" "$@" $(CLI): $(CLI_SOURCES) $(CONFIG_LIBRARY) Makefile mkdir -p "$(APP)/Contents/MacOS" $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) $(CLI_SOURCES) $(CONFIG_FLAGS) -framework AppKit -o $@ $(BUNDLE_STAMP): $(PLAYER) $(BOOTSTRAP) $(CLI) $(APP)/Contents/Info.plist $(APP)/Contents/Resources/TOMLDecoder-LICENSE.txt $(NATIVE_STAMP) $(HELPER_STAMP) Scripts/bundle.py python3 Scripts/bundle.py --app "$(APP)" --dependencies "$(DEPENDENCY_ROOT)" --signing-identity "$(SIGNING_IDENTITY)" touch "$@" $(BUILD_DIR)/terebi: $(BUNDLE_STAMP) ln -sfn "terebi.app/Contents/MacOS/terebi-cli" "$@" run: all open "$(APP)" $(BUILD_DIR)/playback-check: Checks/playback.mm $(OBJECTS) Makefile | check-dependencies $(CXX) $(CXXFLAGS) -fobjc-arc $< $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -o $@ $(BUILD_DIR)/video-decoding-check: Checks/video-decoding.mm Sources/Core/player.cpp Sources/Core/player.h Sources/Core/player_macos.h Sources/Core/output.hpp Sources/Core/video_decoder.hpp Sources/Core/network_input.hpp Sources/Core/network_policy.hpp Sources/Core/progress_reporter.hpp $(filter-out $(BUILD_DIR)/player.o,$(OBJECTS)) Makefile | check-dependencies $(CXX) $(CXXFLAGS) -fobjc-arc $< $(filter-out $(BUILD_DIR)/player.o,$(OBJECTS)) $(FF_LIBS) $(FRAMEWORKS) -o $@ $(BUILD_DIR)/video-decoding-software-check: Checks/video-decoding.mm Sources/Core/player.cpp Sources/Core/player.h Sources/Core/player_macos.h Sources/Core/output.hpp Sources/Core/video_decoder.hpp Sources/Core/network_input.hpp Sources/Core/network_policy.hpp Sources/Core/progress_reporter.hpp $(filter-out $(BUILD_DIR)/player.o,$(OBJECTS)) Makefile | check-dependencies $(CXX) $(CXXFLAGS) -DTEREBI_SOFTWARE_DECODE -fobjc-arc $< $(filter-out $(BUILD_DIR)/player.o,$(OBJECTS)) $(FF_LIBS) $(FRAMEWORKS) -o $@ $(BUILD_DIR)/cast-media-software-check: Checks/cast-media.cpp Sources/Core/cast_media.cpp Sources/Core/cast_media.h Sources/Core/video_decoder.hpp Sources/Core/network_policy.hpp Sources/Core/network_input.hpp Makefile | check-dependencies $(CXX) $(CXXFLAGS) -ISources/Core -DCAST_MEDIA_CHECK -DTEREBI_SOFTWARE_DECODE Checks/cast-media.cpp Sources/Core/cast_media.cpp $(FF_LIBS) -o $@ check-video-decoding: $(BUILD_DIR)/video-decoding-check $(BUILD_DIR)/cast-media-check $(DECODE_FIXTURES) $(BUILD_DIR)/fixtures/decode-preroll.ts $(BUILD_DIR)/video-decoding-check --metal $(DECODE_FIXTURES) $(BUILD_DIR)/video-decoding-check --preroll $(BUILD_DIR)/fixtures/decode-preroll.ts for fixture in $(DECODE_FIXTURES); do $(BUILD_DIR)/cast-media-check --decode-work "$$fixture" || exit; done $(DECODE_FIXTURES): Makefile | check-dependencies mkdir -p $(BUILD_DIR)/fixtures ffmpeg -hide_banner -loglevel error -y -f lavfi -i testsrc2=size=1280x720:rate=30:duration=12 -vf setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709 -an -threads 2 $(DECODE_ENCODER) $@ $(BUILD_DIR)/fixtures/decode-h264.mp4: DECODE_ENCODER = -c:v libx264 -preset ultrafast -bf 2 -g 60 $(BUILD_DIR)/fixtures/decode-hevc.mp4: DECODE_ENCODER = -c:v libx265 -preset ultrafast -x265-params log-level=error:pools=2 -g 60 $(BUILD_DIR)/fixtures/decode-vp9.mp4: DECODE_ENCODER = -c:v libvpx-vp9 -deadline realtime -cpu-used 8 -row-mt 1 -g 60 $(BUILD_DIR)/fixtures/decode-av1.mp4: DECODE_ENCODER = -c:v libsvtav1 -preset 12 -svtav1-params lp=2 -g 60 $(BUILD_DIR)/fixtures/decode-h264-10.mp4: DECODE_ENCODER = -c:v libx264 -preset ultrafast -pix_fmt yuv420p10le -bf 2 -g 60 $(BUILD_DIR)/fixtures/decode-mpeg4.mp4: DECODE_ENCODER = -c:v mpeg4 -bf 2 -g 60 $(BUILD_DIR)/fixtures/decode-preroll.ts: $(BUILD_DIR)/fixtures/decode-h264.mp4 Makefile ffmpeg -hide_banner -loglevel error -y -i $< -map 0:v:0 -c copy -mpegts_copyts 1 -muxdelay 0 -avoid_negative_ts disabled $@ $(BUILD_DIR)/seek-queue-check: Checks/seek-queue.cpp Sources/Core/player.cpp Sources/Core/player.h Sources/Core/player_macos.h Sources/Core/output.hpp Sources/Core/video_decoder.hpp Sources/Core/network_input.hpp Sources/Core/network_policy.hpp Sources/Core/progress_reporter.hpp $(filter-out $(BUILD_DIR)/player.o,$(OBJECTS)) Makefile | check-dependencies $(CXX) $(CXXFLAGS) $< $(filter-out $(BUILD_DIR)/player.o,$(OBJECTS)) $(FF_LIBS) $(FRAMEWORKS) -o $@ check-seek-queue: $(BUILD_DIR)/seek-queue-check $(BUILD_DIR)/seek-queue-check $(BUILD_DIR)/local-seek-check: Checks/local-seek.mm Sources/Core/player.cpp Sources/Core/player.h Sources/Core/player_macos.h Sources/Core/output.hpp Sources/Core/video_decoder.hpp Sources/Core/network_input.hpp Sources/Core/network_policy.hpp Sources/Core/progress_reporter.hpp $(filter-out $(BUILD_DIR)/player.o,$(OBJECTS)) Makefile | check-dependencies $(CXX) $(CXXFLAGS) $< $(filter-out $(BUILD_DIR)/player.o,$(OBJECTS)) $(FF_LIBS) $(FRAMEWORKS) -o $@ $(BUILD_DIR)/fixtures/local-seek.mp4: Makefile | check-dependencies mkdir -p $(BUILD_DIR)/fixtures ffmpeg -hide_banner -loglevel error -y -f lavfi -i testsrc2=size=1920x1080:rate=30:duration=12 -f lavfi -i sine=frequency=440:sample_rate=48000:duration=12 -c:v libx264 -preset ultrafast -threads 2 -bf 2 -g 300 -keyint_min 300 -sc_threshold 0 -c:a aac $@ .PHONY: check-local-seek check-local-seek: $(BUILD_DIR)/local-seek-check $(BUILD_DIR)/fixtures/local-seek.mp4 $(DECODE_FIXTURES) $(BUILD_DIR)/local-seek-check $(BUILD_DIR)/fixtures/local-seek.mp4 $(DECODE_FIXTURES) check: check-stream check: check-sponsorblock check: check-dependencies $(BUILD_DIR)/playback-check check-seek-queue check-local-seek check-video-decoding check-fixtures check-audio check-window check-config check-youtube check-quality check-adaptive check-network check-progress check-reporting check-cli check-runtime check-media check-startup check-bundle check-subtitles check-resolved check-cast check-queue $(BUILD_DIR)/playback-check $(BUILD_DIR)/fixtures check-fixtures: | check-dependencies mkdir -p $(BUILD_DIR)/fixtures ffmpeg -hide_banner -loglevel error -y -f lavfi -i testsrc2=size=320x180:rate=24 -f lavfi -i sine=frequency=440:sample_rate=44100 -t 4 -c:v mpeg4 -bf 2 -c:a aac $(BUILD_DIR)/fixtures/av.mp4 ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/av.mp4 -an -c:v copy $(BUILD_DIR)/fixtures/video.mp4 ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/av.mp4 -an -vf setsar=3/2 -c:v mpeg4 $(BUILD_DIR)/fixtures/anamorphic.mp4 ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/av.mp4 -vn -c:a pcm_s16le $(BUILD_DIR)/fixtures/audio.wav # Literal frame PTS: 0,.1,.2,.3,.4,.65,.9,1.15,1.4,1.5,1.6,1.7; reordered B-frames across short GOPs. ffmpeg -hide_banner -loglevel error -y -f lavfi -i testsrc2=size=320x180:rate=10:duration=1.2 -f lavfi -i sine=frequency=440:sample_rate=44100:duration=2 -vf "settb=1/1000,setpts='if(lt(N,5),N*100,if(lt(N,9),400+(N-4)*250,1400+(N-8)*100))'" -fps_mode vfr -enc_time_base:v 1:1000 -c:v mpeg4 -g 4 -bf 2 -video_track_timescale 1000 -c:a aac $(BUILD_DIR)/fixtures/frame-step.mp4 ffmpeg -hide_banner -loglevel error -y -f lavfi -i testsrc2=size=160x90:rate=12 -t 1 -vf 'format=yuv420p10le,setparams=color_primaries=bt2020:color_trc=smpte2084:colorspace=bt2020nc' -c:v ffv1 $(BUILD_DIR)/fixtures/hdr.mkv ffmpeg -hide_banner -loglevel error -y -f lavfi -i testsrc2=size=320x180:rate=24 -f lavfi -i sine=frequency=440:sample_rate=44100 -t 120 -c:v mpeg4 -q:v 2 -g 24 -bf 2 -c:a aac -movflags +faststart $(BUILD_DIR)/fixtures/cache.mp4 $(BUILD_DIR)/Output-check.o: Sources/macOS/Output.mm Sources/Core/output.hpp Makefile $(NATIVE_STAMP) | $(BUILD_DIR) check-dependencies $(CXX) $(CXXFLAGS) -fobjc-arc -DPLAYER_AUDIO_CHECK -c $< -o $@ $(BUILD_DIR)/audio-continuity-check: Checks/audio-continuity.cpp $(BUILD_DIR)/player.o $(BUILD_DIR)/progress_reporter.o $(BUILD_DIR)/Output-check.o Makefile | check-dependencies $(CXX) $(CXXFLAGS) $< $(BUILD_DIR)/player.o $(BUILD_DIR)/progress_reporter.o $(BUILD_DIR)/Output-check.o $(FF_LIBS) $(FRAMEWORKS) -o $@ check-audio: $(BUILD_DIR)/audio-continuity-check mkdir -p $(BUILD_DIR)/fixtures ffmpeg -hide_banner -loglevel error -y -f lavfi -i sine=frequency=440:sample_rate=44100 -t 2 -c:a pcm_s16le $(BUILD_DIR)/fixtures/tone441.wav ffmpeg -hide_banner -loglevel error -y -f lavfi -i sine=frequency=440:sample_rate=48000 -t 2 -c:a pcm_s16le $(BUILD_DIR)/fixtures/tone480.wav ffmpeg -hide_banner -loglevel error -y -f lavfi -i testsrc2=size=160x90:rate=24:duration=2 -i $(BUILD_DIR)/fixtures/tone480.wav -c:v mpeg4 -g 48 -bf 2 -c:a copy $(BUILD_DIR)/fixtures/tone-step.mov ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/tone441.wav -c:a copy $(BUILD_DIR)/fixtures/tone441.mka ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/tone441.wav -c:a aac $(BUILD_DIR)/fixtures/tone-aac.m4a ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/tone480.wav -af "asetnsamples=n=1024:p=0,asetpts='round(PTS*TB*1000)/1000/TB'" -c:a aac -f mpegts $(BUILD_DIR)/fixtures/tone-jitter.ts ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/tone441.wav -af "asetpts='PTS+gte(T,1)*0.25/TB'" -c:a pcm_s16le $(BUILD_DIR)/fixtures/tone-gap.mka ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/tone441.wav -ar 48000 -ac 2 -f f32le $(BUILD_DIR)/fixtures/tone441.wav.f32 ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/tone480.wav -ar 48000 -ac 2 -f f32le $(BUILD_DIR)/fixtures/tone480.wav.f32 ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/tone441.mka -ar 48000 -ac 2 -f f32le $(BUILD_DIR)/fixtures/tone441.mka.f32 ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/tone-aac.m4a -ar 48000 -ac 2 -f f32le $(BUILD_DIR)/fixtures/tone-aac.m4a.f32 ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/tone-jitter.ts -ar 48000 -ac 2 -f f32le $(BUILD_DIR)/fixtures/tone-jitter.ts.f32 $(BUILD_DIR)/audio-continuity-check $(BUILD_DIR)/fixtures $(BUILD_DIR)/compact-window-check: Checks/compact-window.swift Sources/App/CompactWindow.swift Makefile | $(BUILD_DIR) check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/compact-window.swift Sources/App/CompactWindow.swift -framework AppKit -o $@ check-window: $(BUILD_DIR)/compact-window-check $(BUILD_DIR)/compact-window-check $(BUILD_DIR)/configuration-check: Checks/configuration.swift $(CONFIG_LIBRARY) Makefile | $(BUILD_DIR) $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) $< $(CONFIG_FLAGS) -o $@ check-config: $(BUILD_DIR)/configuration-check $(BUILD_DIR)/configuration-check $(BUILD_DIR)/youtube-resolver-check: Checks/youtube-resolver.swift Sources/App/YouTubeResolver.swift Makefile | $(BUILD_DIR) check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/youtube-resolver.swift Sources/App/YouTubeResolver.swift -framework Foundation -o $@ check-youtube: $(BUILD_DIR)/youtube-resolver-check $(BUNDLE_STAMP) $(BUILD_DIR)/youtube-resolver-check "$(abspath $(APP))" $(BUILD_DIR)/sponsorblock-check: Checks/sponsor-block.swift Sources/App/SponsorBlock.swift Makefile | $(BUILD_DIR) $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) $< Sources/App/SponsorBlock.swift -framework Foundation -o $@ .PHONY: check-sponsorblock check-sponsorblock: $(BUILD_DIR)/sponsorblock-check $(BUILD_DIR)/sponsorblock-check $(BUILD_DIR)/stream-resolver-check: Checks/stream-resolver.swift Sources/App/StreamResolver.swift Sources/App/YouTubeResolver.swift Sources/App/ResolvedSource.swift Makefile | $(BUILD_DIR) $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/stream-resolver.swift Sources/App/StreamResolver.swift Sources/App/YouTubeResolver.swift Sources/App/ResolvedSource.swift -framework Foundation -o $@ .PHONY: check-stream check-stream: $(BUILD_DIR)/stream-resolver-check $(BUILD_DIR)/stream-resolver-check $(BUILD_DIR)/miruro-metadata-check: Checks/miruro-metadata.swift Sources/App/MiruroMetadata.swift Sources/App/ResolvedSource.swift Sources/App/StreamResolver.swift Sources/App/YouTubeResolver.swift Makefile | $(BUILD_DIR) $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/miruro-metadata.swift Sources/App/MiruroMetadata.swift Sources/App/ResolvedSource.swift Sources/App/StreamResolver.swift Sources/App/YouTubeResolver.swift -framework Foundation -o $@ .PHONY: check-miruro-metadata check: check-miruro-metadata check-miruro-metadata: $(BUILD_DIR)/miruro-metadata-check $(BUILD_DIR)/miruro-metadata-check $(BUILD_DIR)/automatic-quality-check: Checks/automatic-quality.swift Sources/App/AutomaticQuality.swift Makefile | $(BUILD_DIR) check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/automatic-quality.swift Sources/App/AutomaticQuality.swift -framework Foundation -o $@ check-quality: $(BUILD_DIR)/automatic-quality-check $(BUILD_DIR)/automatic-quality-check $(BUILD_DIR)/playback-queue-check: Checks/playback-queue.swift Sources/App/PlaybackQueue.swift Makefile | $(BUILD_DIR) $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/playback-queue.swift Sources/App/PlaybackQueue.swift -framework Foundation -o $@ check-queue: $(BUILD_DIR)/playback-queue-check $(BUILD_DIR)/playback-queue-check $(BUILD_DIR)/automatic-quality-playback-check: Checks/automatic-quality-playback.swift $(SWIFT_SOURCES) $(OBJECTS) $(CONFIG_LIBRARY) Makefile | check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -DPLAYER_CHECK -O $(DEBUG_FLAGS) -import-objc-header Sources/Core/player_macos.h $< $(SWIFT_SOURCES) $(CONFIG_FLAGS) $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -lc++ -o $@ check-adaptive: $(BUILD_DIR)/automatic-quality-playback-check $(BUNDLE_STAMP) mkdir -p $(BUILD_DIR)/fixtures ffmpeg -hide_banner -loglevel error -y -f lavfi -i color=c=blue:size=1920x1080:rate=24 -f lavfi -i sine=frequency=440:sample_rate=44100 -t 120 -c:v mpeg4 -g 24 -bf 2 -c:a aac -movflags +faststart $(BUILD_DIR)/fixtures/quality-1080.mp4 ffmpeg -hide_banner -loglevel error -y -f lavfi -i color=c=green:size=1280x720:rate=24 -f lavfi -i sine=frequency=440:sample_rate=44100 -t 120 -c:v mpeg4 -g 24 -bf 2 -c:a aac -movflags +faststart $(BUILD_DIR)/fixtures/quality-720.mp4 python3 Checks/automatic-quality.py $(BUILD_DIR)/automatic-quality-playback-check $(BUILD_DIR)/fixtures "$(APP)" $(BUILD_DIR)/network-playback-check: Checks/network-playback.mm $(OBJECTS) Makefile | check-dependencies $(CXX) $(CXXFLAGS) -fobjc-arc $< $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -o $@ $(BUILD_DIR)/playback-benchmark: Checks/playback-benchmark.mm $(OBJECTS) Makefile | check-dependencies $(CXX) $(CXXFLAGS) -fobjc-arc $< $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -o $@ .PHONY: benchmark-playback benchmark-playback: $(BUILD_DIR)/playback-benchmark $(BUILD_DIR)/cast-media-check python3 Checks/playback-benchmark.py $(BUILD_DIR)/playback-benchmark $(BUILD_DIR)/cast-media-check $(BUILD_DIR)/fixtures/playback-benchmark check-network: $(BUILD_DIR)/network-playback-check check-fixtures ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/frame-step.mp4 -an -c:v copy $(BUILD_DIR)/fixtures/frame-step-video.mp4 ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/frame-step.mp4 -vn -c:a copy $(BUILD_DIR)/fixtures/frame-step-audio.m4a ffmpeg -hide_banner -loglevel error -y -f lavfi -i testsrc2=size=320x180:rate=24 -f lavfi -i sine=frequency=440:sample_rate=44100 -t 30 -c:v mpeg4 -q:v 2 -bf 2 -c:a aac -movflags +faststart $(BUILD_DIR)/fixtures/streaming.mp4 ffmpeg -hide_banner -loglevel error -y -i $(BUILD_DIR)/fixtures/av.mp4 -c:v libx264 -g 24 -keyint_min 24 -sc_threshold 0 -c:a aac -hls_time 1 -hls_playlist_type vod -hls_segment_filename $(BUILD_DIR)/fixtures/network-vod-%d.ts $(BUILD_DIR)/fixtures/network-vod.m3u8 python3 Checks/streaming.py $(BUILD_DIR)/network-playback-check $(BUILD_DIR)/fixtures $(BUILD_DIR)/playback-progress-check: Checks/playback-progress.swift Sources/App/PlaybackProgress.swift Makefile | $(BUILD_DIR) check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/playback-progress.swift Sources/App/PlaybackProgress.swift -framework Foundation -o $@ check-progress: $(BUILD_DIR)/playback-progress-check $(BUILD_DIR)/playback-progress-check $(BUILD_DIR)/progress-reporting-check: Checks/progress-reporting.mm Sources/Core/progress_reporter.cpp Sources/Core/progress_reporter.hpp Sources/Core/network_policy.hpp Sources/Core/player.h Makefile | $(BUILD_DIR) $(CXX) $(CXXFLAGS) -fobjc-arc Checks/progress-reporting.mm Sources/Core/progress_reporter.cpp -framework Foundation -o $@ check-reporting: $(BUILD_DIR)/progress-reporting-check $(BUILD_DIR)/progress-reporting-check $(BUILD_DIR)/player-command-check: Checks/player-command.swift Sources/CLI/PlayerCommand.swift Sources/App/YouTubeResolver.swift Sources/App/ResolvedSource.swift Sources/App/StreamResolver.swift Sources/App/StreamQueue.swift Makefile | $(BUILD_DIR) check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/player-command.swift Sources/CLI/PlayerCommand.swift Sources/App/YouTubeResolver.swift Sources/App/ResolvedSource.swift Sources/App/StreamResolver.swift Sources/App/StreamQueue.swift -framework Foundation -o $@ check-cli: $(BUILD_DIR)/player-command-check $(BUILD_DIR)/player-command-check # Source checking shares only Swift resolver/transport code, never native player objects. SOURCE_CHECK_SOURCES := $(filter-out Sources/CLI/TerebiCLI.swift $(RUNTIME_SOURCE),$(CLI_SOURCES)) $(BUILD_DIR)/source-check-check: Checks/source-check.swift $(SOURCE_CHECK_SOURCES) Makefile | $(BUILD_DIR) $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) $< $(SOURCE_CHECK_SOURCES) -framework Foundation -o $@ .PHONY: check-source check-source-live check: check-source check-source: $(BUILD_DIR)/source-check-check $(CLI) $(BUILD_DIR)/source-check-check python3 Checks/source-check.py "$(CLI)" check-source-live: $(CLI) python3 Checks/source-check.py "$(CLI)" --live $(BUILD_DIR)/external-subtitles-check: Checks/external-subtitles.swift Sources/App/ExternalSubtitles.swift Makefile | $(BUILD_DIR) $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/external-subtitles.swift Sources/App/ExternalSubtitles.swift -framework Foundation -o $@ check-subtitles: $(BUILD_DIR)/external-subtitles-check $(BUILD_DIR)/external-subtitles-check $(BUILD_DIR)/resolved-playback-check: Checks/resolved-playback.swift $(SWIFT_SOURCES) $(OBJECTS) $(CONFIG_LIBRARY) Makefile | check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -DPLAYER_CHECK -O $(DEBUG_FLAGS) -import-objc-header Sources/Core/player_macos.h $< $(SWIFT_SOURCES) $(CONFIG_FLAGS) $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -lc++ -o $@ check-resolved: $(BUILD_DIR)/resolved-playback-check check-fixtures python3 Checks/resolved-playback.py $(BUILD_DIR)/resolved-playback-check $(BUILD_DIR)/fixtures $(BUILD_DIR)/ffmpeg-runtime-check: Checks/ffmpeg-runtime.swift $(RUNTIME_SOURCE) Makefile | $(BUILD_DIR) $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) Checks/ffmpeg-runtime.swift $(RUNTIME_SOURCE) -framework Foundation -o $@ check-runtime: $(BUILD_DIR)/ffmpeg-runtime-check $(BUNDLE_STAMP) $(BUILD_DIR)/ffmpeg-runtime-check "$(APP)" $(BUILD_DIR)/system-playback-check: Checks/system-playback.swift Checks/playback-power.swift $(SWIFT_SOURCES) $(OBJECTS) $(CONFIG_LIBRARY) Makefile | check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -DPLAYER_CHECK -O $(DEBUG_FLAGS) -import-objc-header Sources/Core/player_macos.h Checks/system-playback.swift Checks/playback-power.swift $(SWIFT_SOURCES) $(CONFIG_FLAGS) $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -lc++ -o $@ check-media: $(BUILD_DIR)/system-playback-check check-fixtures $(BUILD_DIR)/system-playback-check $(BUILD_DIR)/fixtures $(BUILD_DIR)/cast-session-check: Checks/cast-session.swift Sources/App/CastSession.swift Makefile | $(BUILD_DIR) $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -DCAST_SESSION_CHECKS -O $(DEBUG_FLAGS) Checks/cast-session.swift Sources/App/CastSession.swift -framework Foundation -framework Network -framework Security -o $@ $(BUILD_DIR)/cast_media-check.o: Sources/Core/cast_media.cpp Sources/Core/cast_media.h Sources/Core/video_decoder.hpp Sources/Core/network_policy.hpp Sources/Core/network_input.hpp Makefile $(NATIVE_STAMP) | $(BUILD_DIR) check-dependencies $(CXX) $(CXXFLAGS) -DCAST_MEDIA_CHECK -c $< -o $@ $(BUILD_DIR)/cast-media-check: Checks/cast-media.cpp $(BUILD_DIR)/cast_media-check.o Makefile | check-dependencies $(CXX) $(CXXFLAGS) -ISources/Core -DCAST_MEDIA_CHECK $< $(BUILD_DIR)/cast_media-check.o $(FF_LIBS) -o $@ $(BUILD_DIR)/cast-playback-check: Checks/cast-playback.swift Checks/playback-power.swift $(SWIFT_SOURCES) $(OBJECTS) $(CONFIG_LIBRARY) Makefile | check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -DPLAYER_CHECK -O $(DEBUG_FLAGS) -import-objc-header Sources/Core/player_macos.h $< Checks/playback-power.swift $(SWIFT_SOURCES) $(CONFIG_FLAGS) $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -lc++ -o $@ check-cast: $(BUILD_DIR)/cast-session-check $(BUILD_DIR)/cast-media-check $(BUILD_DIR)/cast-playback-check check-fixtures $(BUILD_DIR)/cast-session-check $(BUILD_DIR)/cast-media-check --live $(BUILD_DIR)/cast-media-check --remux-work $(BUILD_DIR)/cast-media-check --codec-work $(BUILD_DIR)/cast-session-check --playback $(BUILD_DIR)/cast-playback-check $(BUILD_DIR)/fixtures/cache.mp4 $(BUILD_DIR)/app-startup-check.dylib: Checks/app-startup.swift $(SWIFT_SOURCES) $(OBJECTS) $(CONFIG_LIBRARY) Makefile | check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -emit-library -DPLAYER_CHECK -O $(DEBUG_FLAGS) -import-objc-header Sources/Core/player_macos.h Checks/app-startup.swift $(SWIFT_SOURCES) $(CONFIG_FLAGS) $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -lc++ -o $@ check-startup: all $(BUILD_DIR)/app-startup-check.dylib check-fixtures python3 Checks/app-startup.py "$(APP)" "$(BUILD_DIR)/app-startup-check.dylib" "$(BUILD_DIR)/fixtures" "$(DEPENDENCY_ROOT)" check-bundle: all check-fixtures python3 Checks/bundle.py "$(APP)" "$(BUILD_DIR)/fixtures" "$(DEPENDENCY_ROOT)" ZOKO_CHECK_SOURCES := Sources/App/ZokoResolver.swift Sources/App/StreamResolver.swift Sources/App/YouTubeResolver.swift Sources/App/ResolvedSource.swift Sources/App/MiruroTransport.swift Sources/App/MiruroEmbed.swift Sources/App/ExternalSubtitles.swift Sources/App/PlaybackProgress.swift $(BUILD_DIR)/zoko-check: Checks/zoko.swift $(ZOKO_CHECK_SOURCES) $(OBJECTS) Makefile | check-dependencies $(SWIFT) -target $(ARCH)-apple-macosx15.0 -swift-version 6 -parse-as-library -O $(DEBUG_FLAGS) -import-objc-header Sources/Core/player.h $< $(ZOKO_CHECK_SOURCES) $(OBJECTS) $(FF_LIBS) $(FRAMEWORKS) -lc++ -o $@ .PHONY: check-zoko check-zoko-live check: check-zoko check-zoko: $(BUILD_DIR)/zoko-check $(BUILD_DIR)/zoko-check check-zoko-live: $(BUILD_DIR)/zoko-check $(BUILD_DIR)/zoko-check --live