#!/usr/bin/env bash # slab-video [--playlist] [more.mov …] — open videos in slab's # minimal player. Without --playlist, appends absolute paths to # $SLAB_HOME/state/open-video and raises one chromeless AVKit panel per movie; # a second open panel grids the wall automatically. With --playlist, writes one # atomic ordered queue request and raises one panel with the queue listed # beside the picture (click a row to jump; left/right also change tracks; it # advances on its own). Re-asking for an open source brings its window forward # and restarts playback. Single-video panels watch the file and reload on # rewrite. # # slab-video --close-all close every open panel # slab-video --tile re-grid the open panels # # See slab/menubar-swift/Sources/SlabMenubar/VideoViewer.swift. set -euo pipefail SLAB_HOME="${SLAB_HOME:-$HOME/.local/share/slab}" REQUEST="$SLAB_HOME/state/open-video" PLAYLIST_REQUESTS="$SLAB_HOME/state/open-video-playlists" mkdir -p "$SLAB_HOME/state" "$PLAYLIST_REQUESTS" case "${1:-}" in --close-all) touch "$SLAB_HOME/state/close-video"; exit 0 ;; --tile) touch "$SLAB_HOME/state/tile-video"; exit 0 ;; esac playlist=false if [ "${1:-}" = "--playlist" ]; then playlist=true shift fi if [ $# -eq 0 ]; then echo "usage: slab-video [--playlist] [more.mov …] | --close-all | --tile" >&2 exit 1 fi # Which Claude session asked? Walk up the process tree to the claude pid # (same loop as claude-prompt-log.sh) and match it against the live # active-prompts markers — the viewer chip then wears that session's # sticky emoji. Empty when not launched from a Claude session. session_id="" claude_pid=$$ for _ in 1 2 3 4 5 6 7 8; do parent=$(ps -o ppid= -p "$claude_pid" 2>/dev/null | tr -d ' ') [ -z "$parent" ] || [ "$parent" = "1" ] && break comm=$(ps -o comm= -p "$parent" 2>/dev/null | tr -d ' ') claude_pid=$parent case "$comm" in *claude*) break ;; esac done if command -v jq >/dev/null 2>&1; then for marker in "$SLAB_HOME"/state/active-prompts/*; do [ -f "$marker" ] || continue if [ "$(jq -r '.claude_pid // 0' "$marker" 2>/dev/null)" = "$claude_pid" ]; then session_id=$(jq -r '.session_id // ""' "$marker" 2>/dev/null) break fi done fi for f in "$@"; do if [ ! -f "$f" ]; then echo "slab-video: no such file: $f" >&2 exit 1 fi done if [ "$playlist" = true ]; then request_tmp=$(mktemp "$PLAYLIST_REQUESTS/.playlist.XXXXXX") trap 'rm -f "$request_tmp"' EXIT for f in "$@"; do abs="$(cd "$(dirname "$f")" && pwd)/$(basename "$f")" printf '%s\t%s\n' "$abs" "$session_id" >> "$request_tmp" done request_final="$PLAYLIST_REQUESTS/$(date +%s)-$$.playlist" mv "$request_tmp" "$request_final" trap - EXIT exit 0 fi for f in "$@"; do # realpath isn't guaranteed on stock macOS bash paths — resolve by hand. abs="$(cd "$(dirname "$f")" && pwd)/$(basename "$f")" printf '%s\t%s\n' "$abs" "$session_id" >> "$REQUEST" done