mirror of
https://github.com/dirtydishes/dreamio.git
synced 2026-06-06 13:37:24 +00:00
218 lines
9.4 KiB
HTML
218 lines
9.4 KiB
HTML
<!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>
|