Compare commits
5 Commits
a14c7c7a3f
...
0ae0d644a9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ae0d644a9 | ||
|
|
ce2832a584 | ||
|
|
b6b902ad4a | ||
|
|
3da3b187ec | ||
|
|
86ea73bfbd |
53
README.md
53
README.md
@@ -296,7 +296,7 @@ to change.
|
|||||||
| `window_control({action, value?})` | Electron window: maximize, minimize, restore, close, fullscreen, kiosk, devtools, reload. |
|
| `window_control({action, value?})` | Electron window: maximize, minimize, restore, close, fullscreen, kiosk, devtools, reload. |
|
||||||
| `set_wallpaper({path?, url?, url_external?, display?, api_key?, account_id?})` | Sets desktop wallpaper. Accepts a local `path` or downloads from `url` (cached to `~/Library/Caches/OSIT/wallpaper/`). `url_external` sets a separate image on the projector/second display. `display`: `'all'` (default) \| `'primary'` \| `'external'`. macOS only in production; Linux returns a dev-mode preview payload without applying. |
|
| `set_wallpaper({path?, url?, url_external?, display?, api_key?, account_id?})` | Sets desktop wallpaper. Accepts a local `path` or downloads from `url` (cached to `~/Library/Caches/OSIT/wallpaper/`). `url_external` sets a separate image on the projector/second display. `display`: `'all'` (default) \| `'primary'` \| `'external'`. macOS only in production; Linux returns a dev-mode preview payload without applying. |
|
||||||
| `power_control({action})` | Shutdown, reboot, or sleep. macOS + Linux. Requires sudo for shutdown/reboot. |
|
| `power_control({action})` | Shutdown, reboot, or sleep. macOS + Linux. Requires sudo for shutdown/reboot. |
|
||||||
| `set_display_layout({mode, configStr?})` | Mirror/extend displays via bundled `displayplacer` binary. macOS only. Auto-detects connected displays via `displayplacer list` when no `configStr` is given — no manual config needed. `configStr` is an optional manual override (the full `displayplacer` config string) stored in `event_device.data_json` if per-device tuning is needed. |
|
| `set_display_layout({mode, configStr?})` | Mirror/extend displays. macOS only. **Primary path:** bundled `display_control` binary (native CoreGraphics, no Homebrew). **Fallback:** `displayplacer` — used when `display_control` binary is absent, or when a `configStr` override is set. `configStr` is an optional manual override (full `displayplacer` config string) stored in `event_device.data_json` for per-device tuning. Build `display_control` once via `scripts/build-display-control.sh` on a Mac and commit `resources/bin/display_control`. |
|
||||||
| `manage_recording({action, options?})` | Screen recording via bundled `aperture` binary. macOS only. |
|
| `manage_recording({action, options?})` | Screen recording via bundled `aperture` binary. macOS only. |
|
||||||
| `update_app(args)` | **Stub.** Downloads update package but does not install. Not functional. |
|
| `update_app(args)` | **Stub.** Downloads update package but does not install. Not functional. |
|
||||||
| `list_tools()` | Returns a self-describing manifest of all available bridge functions. |
|
| `list_tools()` | Returns a self-describing manifest of all available bridge functions. |
|
||||||
@@ -352,6 +352,57 @@ See `documentation/PROJECT__AE_Events_Launcher_Native_integration.md` Section 8
|
|||||||
- **Handlers:** OS-level logic in `src/main/shell_handlers.ts`, `src/main/file_handlers.ts`, and `src/main/system_handlers.ts`.
|
- **Handlers:** OS-level logic in `src/main/shell_handlers.ts`, `src/main/file_handlers.ts`, and `src/main/system_handlers.ts`.
|
||||||
- **Types:** Shared TypeScript interfaces in `src/shared/types.ts`.
|
- **Types:** Shared TypeScript interfaces in `src/shared/types.ts`.
|
||||||
|
|
||||||
|
### One-Time: Build the `display_control` Binary (macOS)
|
||||||
|
|
||||||
|
The `display_control` binary provides native CoreGraphics display mirror/extend without any Homebrew dependency. It must be compiled on a Mac (Xcode CLT required) and committed to the repo so it is bundled into every packaged app. Produces a universal binary (x86_64 + arm64) that runs on both Intel and Apple Silicon Macs.
|
||||||
|
|
||||||
|
Rebuild only if `scripts/display_control.m` changes.
|
||||||
|
|
||||||
|
#### Option A — From the Linux workstation (preferred)
|
||||||
|
|
||||||
|
Laptop 01 (`192.168.32.101`) is the designated build Mac — Xcode CLT is installed there.
|
||||||
|
The remote build script copies the source over SSH, compiles on that Mac, and pulls the binary back.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From the repo root on the workstation:
|
||||||
|
./scripts/remote-build-display-control.sh
|
||||||
|
|
||||||
|
# Override the build Mac IP if needed:
|
||||||
|
./scripts/remote-build-display-control.sh 192.168.32.102
|
||||||
|
```
|
||||||
|
|
||||||
|
The script prints `file resources/bin/display_control` at the end. Confirm both arches appear:
|
||||||
|
```
|
||||||
|
resources/bin/display_control: Mach-O universal binary with 2 architectures: [x86_64] [arm64]
|
||||||
|
```
|
||||||
|
|
||||||
|
Then commit:
|
||||||
|
```bash
|
||||||
|
git add resources/bin/display_control
|
||||||
|
git commit -m "build: update display_control binary (universal)"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option B — Directly on a Mac
|
||||||
|
|
||||||
|
If you have repo access on the Mac itself (Xcode CLT required — `xcode-select --install`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/build-display-control.sh
|
||||||
|
# Expected last output line: x86_64 arm64
|
||||||
|
|
||||||
|
# Test with a second display connected:
|
||||||
|
./resources/bin/display_control status
|
||||||
|
./resources/bin/display_control extend
|
||||||
|
./resources/bin/display_control mirror
|
||||||
|
|
||||||
|
git add resources/bin/display_control
|
||||||
|
git commit -m "build: update display_control binary (universal)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Once committed, `brew install displayplacer` is no longer required on any venue Mac. The `displayplacer` fallback remains in the handler only for `configStr` per-device overrides.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Build Requirements (System Dependencies)
|
### Build Requirements (System Dependencies)
|
||||||
|
|
||||||
`bsdtar` (libarchive) must be present on the build host. It is used by the `postinstall` patch
|
`bsdtar` (libarchive) must be present on the build host. It is used by the `postinstall` patch
|
||||||
|
|||||||
BIN
resources/bin/display_control
Executable file
BIN
resources/bin/display_control
Executable file
Binary file not shown.
@@ -24,13 +24,26 @@ fi
|
|||||||
|
|
||||||
mkdir -p "$OUT_DIR"
|
mkdir -p "$OUT_DIR"
|
||||||
|
|
||||||
echo "Building display_control..."
|
TMP_X86="$OUT_DIR/display_control_x86_64"
|
||||||
clang -framework Cocoa -framework Carbon \
|
TMP_ARM="$OUT_DIR/display_control_arm64"
|
||||||
-o "$OUT_BIN" "$SRC"
|
|
||||||
|
echo "Building display_control (x86_64)..."
|
||||||
|
clang -arch x86_64 -framework Cocoa -framework Carbon \
|
||||||
|
-o "$TMP_X86" "$SRC"
|
||||||
|
|
||||||
|
echo "Building display_control (arm64)..."
|
||||||
|
clang -arch arm64 -framework Cocoa -framework Carbon \
|
||||||
|
-o "$TMP_ARM" "$SRC"
|
||||||
|
|
||||||
|
echo "Linking universal binary..."
|
||||||
|
lipo -create -output "$OUT_BIN" "$TMP_X86" "$TMP_ARM"
|
||||||
|
rm "$TMP_X86" "$TMP_ARM"
|
||||||
|
|
||||||
chmod +x "$OUT_BIN"
|
chmod +x "$OUT_BIN"
|
||||||
|
|
||||||
echo "Built: $OUT_BIN"
|
echo ""
|
||||||
|
echo "Built universal binary: $OUT_BIN"
|
||||||
|
lipo -archs "$OUT_BIN"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Test it:"
|
echo "Test it:"
|
||||||
echo " $OUT_BIN status"
|
echo " $OUT_BIN status"
|
||||||
|
|||||||
94
scripts/remote-build-display-control.sh
Executable file
94
scripts/remote-build-display-control.sh
Executable file
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# scripts/remote-build-display-control.sh
|
||||||
|
# Build the display_control universal binary on a remote Mac via SSH,
|
||||||
|
# then pull the result back to resources/bin/display_control.
|
||||||
|
#
|
||||||
|
# Use this from the Linux workstation when you don't have a Mac locally.
|
||||||
|
# The target Mac must have Xcode Command Line Tools installed.
|
||||||
|
#
|
||||||
|
# USAGE:
|
||||||
|
# ./scripts/remote-build-display-control.sh # uses default Mac (laptop 01)
|
||||||
|
# ./scripts/remote-build-display-control.sh 192.168.32.102
|
||||||
|
#
|
||||||
|
# The default IP is laptop 01 — the designated build Mac.
|
||||||
|
# Change DEFAULT_IP below if Xcode moves to a different laptop.
|
||||||
|
#
|
||||||
|
# SSH key must already be installed on the target:
|
||||||
|
# ssh-copy-id "speaker ready"@192.168.32.101
|
||||||
|
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
SRC="$SCRIPT_DIR/display_control.m"
|
||||||
|
OUT_BIN="$REPO_ROOT/resources/bin/display_control"
|
||||||
|
|
||||||
|
SSH_USER="speaker ready"
|
||||||
|
DEFAULT_IP="192.168.32.101"
|
||||||
|
IP="${1:-$DEFAULT_IP}"
|
||||||
|
|
||||||
|
REMOTE_TMP="/tmp/ae_display_control_build"
|
||||||
|
|
||||||
|
echo "═══════════════════════════════════════════════"
|
||||||
|
echo " Remote build: display_control"
|
||||||
|
echo " Build Mac: $SSH_USER @ $IP"
|
||||||
|
echo "═══════════════════════════════════════════════"
|
||||||
|
|
||||||
|
# ── Step 1: Copy source to remote ────────────────────────────────────────────
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 1/4 — Copying source to $IP..."
|
||||||
|
ssh "$SSH_USER@$IP" "mkdir -p $REMOTE_TMP"
|
||||||
|
ssh "$SSH_USER@$IP" "cat > $REMOTE_TMP/display_control.m" < "$SRC"
|
||||||
|
|
||||||
|
# ── Step 2: Build universal binary on remote ──────────────────────────────────
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 2/4 — Building on $IP..."
|
||||||
|
ssh "$SSH_USER@$IP" bash << 'ENDSSH'
|
||||||
|
set -e
|
||||||
|
REMOTE_TMP="/tmp/ae_display_control_build"
|
||||||
|
SRC="$REMOTE_TMP/display_control.m"
|
||||||
|
TMP_X86="$REMOTE_TMP/display_control_x86_64"
|
||||||
|
TMP_ARM="$REMOTE_TMP/display_control_arm64"
|
||||||
|
OUT="$REMOTE_TMP/display_control"
|
||||||
|
|
||||||
|
echo " Compiling x86_64..."
|
||||||
|
clang -arch x86_64 -framework Cocoa -framework Carbon -o "$TMP_X86" "$SRC"
|
||||||
|
|
||||||
|
echo " Compiling arm64..."
|
||||||
|
clang -arch arm64 -framework Cocoa -framework Carbon -o "$TMP_ARM" "$SRC"
|
||||||
|
|
||||||
|
echo " Linking universal binary..."
|
||||||
|
lipo -create -output "$OUT" "$TMP_X86" "$TMP_ARM"
|
||||||
|
rm "$TMP_X86" "$TMP_ARM"
|
||||||
|
chmod +x "$OUT"
|
||||||
|
|
||||||
|
echo " Archs: $(lipo -archs "$OUT")"
|
||||||
|
ENDSSH
|
||||||
|
|
||||||
|
# ── Step 3: Pull binary back ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 3/4 — Pulling binary to resources/bin/..."
|
||||||
|
mkdir -p "$(dirname "$OUT_BIN")"
|
||||||
|
ssh "$SSH_USER@$IP" "cat $REMOTE_TMP/display_control" > "$OUT_BIN"
|
||||||
|
chmod +x "$OUT_BIN"
|
||||||
|
|
||||||
|
# ── Step 4: Clean up remote ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 4/4 — Cleaning up remote..."
|
||||||
|
ssh "$SSH_USER@$IP" "rm -rf $REMOTE_TMP"
|
||||||
|
|
||||||
|
# ── Done ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "═══════════════════════════════════════════════"
|
||||||
|
echo " Built: $OUT_BIN"
|
||||||
|
file "$OUT_BIN"
|
||||||
|
echo ""
|
||||||
|
echo " If both archs shown above, you're good:"
|
||||||
|
echo " git add resources/bin/display_control"
|
||||||
|
echo " git commit -m \"build: update display_control binary (universal)\""
|
||||||
|
echo "═══════════════════════════════════════════════"
|
||||||
@@ -335,8 +335,10 @@ export function registerSystemHandlers() {
|
|||||||
: path.join(__dirname, '../../resources/bin/display_control');
|
: path.join(__dirname, '../../resources/bin/display_control');
|
||||||
|
|
||||||
if (fs.existsSync(dc_bin) && !configStr) {
|
if (fs.existsSync(dc_bin) && !configStr) {
|
||||||
const dc_cmd = mode === 'mirror' ? 'mirror' : 'extend';
|
if (mode !== 'mirror' && mode !== 'extend') {
|
||||||
return await runExec(`"${dc_bin}" ${dc_cmd}`);
|
return { success: false, error: `Unsupported display mode: ${mode}` };
|
||||||
|
}
|
||||||
|
return await runExec(`"${dc_bin}" ${mode}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: displayplacer — required when display_control binary is not built yet,
|
// Fallback: displayplacer — required when display_control binary is not built yet,
|
||||||
|
|||||||
Reference in New Issue
Block a user