mirror of
https://github.com/dirtydishes/dreamio.git
synced 2026-06-06 13:37:24 +00:00
fix native playback cocoa pods build
This commit is contained in:
parent
6e220e6df9
commit
511224bcd4
9 changed files with 386 additions and 5 deletions
218
docs/turns/2026-05-25-guard-native-playback-availability.html
Normal file
218
docs/turns/2026-05-25-guard-native-playback-availability.html
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Guard Native Playback Availability</title>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--ink: oklch(23% 0.024 282);
|
||||
--muted: oklch(48% 0.03 282);
|
||||
--paper: oklch(98% 0.007 285);
|
||||
--panel: oklch(95% 0.012 285);
|
||||
--line: oklch(84% 0.026 285);
|
||||
--accent: oklch(56% 0.16 292);
|
||||
--warn: oklch(62% 0.14 58);
|
||||
--good: oklch(54% 0.13 160);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--paper);
|
||||
color: var(--ink);
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
line-height: 1.55;
|
||||
}
|
||||
main {
|
||||
max-width: 1040px;
|
||||
margin: 0 auto;
|
||||
padding: 56px 28px 72px;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 34px;
|
||||
}
|
||||
h1 {
|
||||
max-width: 820px;
|
||||
margin: 0 0 16px;
|
||||
font-size: clamp(2rem, 4vw, 3.8rem);
|
||||
line-height: 1;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
h2 {
|
||||
margin: 34px 0 10px;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
p {
|
||||
max-width: 74ch;
|
||||
}
|
||||
ul {
|
||||
max-width: 78ch;
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
code {
|
||||
font-family: "SFMono-Regular", Consolas, monospace;
|
||||
font-size: 0.95em;
|
||||
background: var(--panel);
|
||||
padding: 0.08rem 0.28rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
pre {
|
||||
max-width: 100%;
|
||||
overflow: auto;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: oklch(99% 0.004 285);
|
||||
padding: 16px;
|
||||
font-family: "SFMono-Regular", Consolas, monospace;
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.summary {
|
||||
max-width: 76ch;
|
||||
color: var(--muted);
|
||||
font-size: 1.08rem;
|
||||
}
|
||||
.meta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
.pill {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 999px;
|
||||
padding: 5px 10px;
|
||||
color: var(--muted);
|
||||
background: oklch(96% 0.01 285);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.callout {
|
||||
max-width: 78ch;
|
||||
border: 1px solid oklch(78% 0.08 58);
|
||||
background: oklch(95% 0.035 68);
|
||||
border-radius: 8px;
|
||||
padding: 14px 16px;
|
||||
}
|
||||
.ok {
|
||||
border-color: oklch(78% 0.08 160);
|
||||
background: oklch(95% 0.032 160);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<header>
|
||||
<h1>Guard Native Playback Availability</h1>
|
||||
<p class="summary">Dreamio now checks whether the MobileVLCKit-backed native player is actually linked before presenting the full-screen native player. Raw project builds stay buildable, but they now show a setup alert instead of opening a black player that can only fail.</p>
|
||||
<div class="meta">
|
||||
<span class="pill">Beads: dreamio-2k5</span>
|
||||
<span class="pill">Native playback</span>
|
||||
<span class="pill">CocoaPods setup</span>
|
||||
<span class="pill">2026-05-25</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<h2>Summary</h2>
|
||||
<p>Fixed the unavailable native playback build path by exposing a build-time availability check on <code>VLCNativePlaybackBackend</code> and using it before Dreamio presents native playback. CocoaPods was installed through Homebrew, <code>pod install</code> was run, and the generated workspace now links MobileVLCKit.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Changes Made</h2>
|
||||
<ul>
|
||||
<li>Added <code>VLCNativePlaybackBackend.isAvailable</code>, backed by the same <code>canImport(MobileVLCKit)</code> compile condition as the real VLC implementation.</li>
|
||||
<li>Updated <code>DreamioWebViewController</code> to check native backend availability before resolving and presenting the native player.</li>
|
||||
<li>Added an actionable setup alert for builds that do not link <code>MobileVLCKit</code>.</li>
|
||||
<li>Updated the README to explain that the exact unavailable-build message means the binary was built without the CocoaPods workspace.</li>
|
||||
<li>Installed CocoaPods 1.16.2 with Homebrew and ran <code>pod install</code>, generating <code>Dreamio.xcworkspace</code> and <code>Podfile.lock</code> with MobileVLCKit 3.7.3.</li>
|
||||
<li>Disabled Xcode user script sandboxing for the project so CocoaPods can embed MobileVLCKit during the framework copy phase.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Context</h2>
|
||||
<p>The repository has a <code>Podfile</code> declaring <code>MobileVLCKit</code>, but this checkout did not have a generated <code>Pods/</code> directory or <code>Dreamio.xcworkspace</code>. In that state, Swift takes the fallback compile path where <code>canImport(MobileVLCKit)</code> is false. Before this change, Dreamio could still present the native player, which then displayed the generic fallback error.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Important Implementation Details</h2>
|
||||
<ul>
|
||||
<li>The fallback backend remains intact so opening <code>Dreamio.xcodeproj</code> directly still compiles.</li>
|
||||
<li>The guard runs before stream resolution, avoiding unnecessary resolver network work when native playback cannot succeed in the current build.</li>
|
||||
<li>The duplicate playback key is cleared when the guard blocks playback, so the user can retry after rebuilding the app correctly.</li>
|
||||
<li>The generated workspace references <code>Dreamio.xcodeproj</code> and <code>Pods/Pods.xcodeproj</code>. The <code>Pods/</code> directory remains ignored, while <code>Podfile.lock</code> and workspace metadata are tracked.</li>
|
||||
<li><code>ENABLE_USER_SCRIPT_SANDBOXING</code> is set to <code>NO</code> because the CocoaPods embed frameworks script uses <code>rsync</code> to copy the MobileVLCKit framework into the app bundle.</li>
|
||||
<li>No public app-facing API changed.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Relevant Diff Snippets</h2>
|
||||
<p><code>@pierre/diffs</code> is installed as a library dependency, but its package does not expose a runnable CLI in this checkout, and <code>npx @pierre/diffs --help</code> failed with "could not determine executable to run." The plain diff below is the fallback snippet for the core behavior change.</p>
|
||||
<pre><code>diff --git a/Dreamio/DreamioWebViewController.swift b/Dreamio/DreamioWebViewController.swift
|
||||
@@ -368,6 +368,12 @@ final class DreamioWebViewController: UIViewController {
|
||||
@MainActor
|
||||
private func resolveAndPresentNativePlayback(_ request: NativePlaybackRequest) async {
|
||||
+ guard VLCNativePlaybackBackend.isAvailable else {
|
||||
+ lastNativePlaybackURL = nil
|
||||
+ showNativePlaybackUnavailableAlert()
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
do {
|
||||
let resolved = try await streamResolver.resolve(request: request)
|
||||
|
||||
diff --git a/Dreamio/VLCNativePlaybackBackend.swift b/Dreamio/VLCNativePlaybackBackend.swift
|
||||
@@ -5,6 +5,14 @@ import MobileVLCKit
|
||||
#endif
|
||||
|
||||
final class VLCNativePlaybackBackend: NSObject, NativePlaybackBackend {
|
||||
+ static var isAvailable: Bool {
|
||||
+#if canImport(MobileVLCKit)
|
||||
+ true
|
||||
+#else
|
||||
+ false
|
||||
+#endif
|
||||
+ }
|
||||
+
|
||||
let view = UIView()
|
||||
var onReady: (() -> Void)?
|
||||
var onFailure: ((Error) -> Void)?</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Expected Impact for End-Users</h2>
|
||||
<p>Users who accidentally run a raw <code>.xcodeproj</code> build will see a clear CocoaPods setup message instead of a black native player with an unavailable-build failure. Users who build from <code>Dreamio.xcworkspace</code> with <code>MobileVLCKit</code> linked should continue into VLC-backed direct-file playback.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Validation</h2>
|
||||
<ul>
|
||||
<li>Ran <code>swiftc Dreamio/StreamCandidate.swift Dreamio/StreamResolver.swift Tests/StreamResolverTests.swift -o /tmp/dreamio-stream-tests && /tmp/dreamio-stream-tests</code>: passed.</li>
|
||||
<li>Ran <code>swiftc -typecheck Dreamio/StreamCandidate.swift Dreamio/StreamResolver.swift</code>: passed.</li>
|
||||
<li>Ran <code>git diff --check</code>: passed.</li>
|
||||
<li>Ran <code>HOMEBREW_NO_AUTO_UPDATE=1 brew install cocoapods</code>: passed, installing CocoaPods 1.16.2.</li>
|
||||
<li>Ran <code>pod --version && pod install</code>: passed, installing MobileVLCKit 3.7.3 and generating the workspace.</li>
|
||||
<li>Ran <code>DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcodebuild -workspace Dreamio.xcworkspace -scheme Dreamio -configuration Debug -sdk iphonesimulator build</code>: passed.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Issues, Limitations, and Mitigations</h2>
|
||||
<div class="callout">The simulator workspace build passes. Real-device playback validation is still required for the actual VLC-backed stream behavior.</div>
|
||||
<ul>
|
||||
<li>The global <code>xcode-select</code> value still points at Command Line Tools because changing it requires sudo. Command-line builds can use <code>DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer</code>.</li>
|
||||
<li>The <code>Pods/</code> directory is intentionally ignored by git, so another checkout should run <code>pod install</code> after pulling.</li>
|
||||
<li>The native player still depends on MobileVLCKit behavior once the workspace build is available.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Follow-up Work</h2>
|
||||
<ul>
|
||||
<li>On device, select a direct MKV, AVI, or WebM stream and confirm the VLC-backed player starts.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue