commit 36354807aa0334316f804194a44cc40440eeb36e Author: 28allday Date: Sat Mar 28 12:24:08 2026 +0000 Initial commit: DaVinci Resolve installer for openSUSE Tumbleweed Co-Authored-By: Claude Opus 4.6 (1M context) diff --git a/install-resolve-tw.sh b/install-resolve-tw.sh new file mode 100755 index 0000000..984a705 --- /dev/null +++ b/install-resolve-tw.sh @@ -0,0 +1,192 @@ +#!/usr/bin/env bash +# openSUSE Tumbleweed — DaVinci Resolve + gdk-pixbuf (Fedora) + GLib + OpenCL + APR +# Folds in the working recipe discussed by Mark Himsley and others. +# Works for Resolve 19/20 (free or Studio). +[ -n "${BASH_VERSION:-}" ] || exec /usr/bin/env bash "$0" "$@" +set -euo pipefail +export PATH="$PATH:/sbin:/usr/sbin" +[[ "${DEBUG:-0}" == "1" ]] && set -x + +say() { echo -e "\033[1;32m==>\033[0m $*"; } +warn() { echo -e "\033[1;33m[!]\033[0m $*"; } +err() { echo -e "\033[1;31m[ERROR]\033[0m $*"; } +have() { command -v "$1" >/dev/null 2>&1; } +pkg_install() { sudo zypper -n in --no-recommends "$@" || true; } + +TARGET_USER="${SUDO_USER:-$USER}" +TARGET_HOME="$(getent passwd "$TARGET_USER" | cut -d: -f6)" +USR_APP_DIR="$TARGET_HOME/.local/share/applications" +WORKDIR="" +XHOST_ADDED="" + +cleanup() { + [[ -n "$WORKDIR" && -d "$WORKDIR" ]] && rm -rf "$WORKDIR" + [[ -n "$XHOST_ADDED" ]] && xhost -SI:localuser:root >/dev/null 2>&1 || true +} +trap cleanup EXIT + +pick_latest() { + local z r + z=$(ls -t "$TARGET_HOME"/Downloads/DaVinci_Resolve*_Linux.zip 2>/dev/null | head -n1 || true) + r=$(ls -t "$TARGET_HOME"/Downloads/DaVinci_Resolve*_Linux.run 2>/dev/null | head -n1 || true) + [[ -n "$z" ]] && { echo "$z"; return; } + [[ -n "$r" ]] && { echo "$r"; return; } + echo "" +} + +# -------- inputs ---------- +SRC="${1:-}" +[[ -z "$SRC" ]] && SRC="$(pick_latest)" +[[ -n "$SRC" ]] || { err "Give a path to DaVinci Resolve Linux .zip or .run (or put it in ~/Downloads)."; exit 1; } +[[ -e "$SRC" ]] || { err "File not found: $SRC"; exit 1; } + +# -------- deps ---------- +say "Installing runtime tools + common libs…" +sudo zypper -n ref || true +RUNTIME_PKGS=( + unzip xhost curl rpm cpio + xwayland desktop-file-utils xdg-utils + libOpenCL1 libjpeg62 libX11-xcb1 libxcb-xinerama0 libxkbcommon-x11-0 libxcb-keysyms1 + libxcb-icccm4 libxcb-cursor0 libxcb-xfixes0 libxcb-randr0 libxcb-shape0 + libglib-2_0-0 libgobject-2_0-0 libgmodule-2_0-0 libgio-2_0-0 libgthread-2_0-0 + libapr1-0 libapr-util1-0 # APR libs Resolve sometimes needs on TW +) +pkg_install "${RUNTIME_PKGS[@]}" + +# Ensure gthread exists (blackmagic GUI installer needs it) +if ! ldconfig -p 2>/dev/null | grep -q 'libgthread-2\.0\.so\.0'; then + pkg_install libgthread-2_0-0 +fi + +# -------- prepare installer -------- +RUN_PATH="" +if [[ "$SRC" == *.run ]]; then + RUN_PATH="$(readlink -f "$SRC")" +elif [[ "$SRC" == *.zip ]]; then + say "Validating ZIP…" + unzip -tqq "$SRC" >/dev/null 2>&1 || { err "ZIP CRC failed. Re-download from Blackmagic."; exit 1; } + BASE="${XDG_CACHE_HOME:-$TARGET_HOME/.cache}/resolve-installer" + mkdir -p "$BASE" + WORKDIR="$(mktemp -d -p "$BASE")" + say "Extracting…" + unzip -q "$SRC" -d "$WORKDIR" + RUN_PATH="$(find "$WORKDIR" -maxdepth 3 -type f -name 'DaVinci_Resolve*_Linux.run' | head -n1 || true)" + [[ -n "$RUN_PATH" && -f "$RUN_PATH" ]] || { err "Could not find DaVinci_Resolve*_Linux.run inside ZIP."; exit 1; } +else + err "Unsupported file type: $SRC" +fi +say "Using installer: $RUN_PATH" + +# -------- run installer -------- +say "Running Blackmagic installer (user)…" +chmod +x "$RUN_PATH" || true +set +e +env QT_QPA_PLATFORM=xcb SKIP_PACKAGE_CHECK=1 "$RUN_PATH" +RC_USER=$? +set -e +say "User-run exit code: $RC_USER" + +if [[ ! -x /opt/resolve/bin/resolve ]]; then + if [[ -n "${DISPLAY:-}" ]] && have xhost; then + xhost +SI:localuser:root >/dev/null 2>&1 && XHOST_ADDED=1 || true + fi + say "Running Blackmagic installer (sudo fallback)…" + set +e + sudo -E env DISPLAY="${DISPLAY:-:0}" XAUTHORITY="${XAUTHORITY:-$HOME/.Xauthority}" \ + XDG_RUNTIME_DIR="/run/user/$(id -u "$TARGET_USER")" \ + QT_QPA_PLATFORM=xcb SKIP_PACKAGE_CHECK=1 "$RUN_PATH" + RC_SUDO=$? + set -e + say "Sudo-run exit code: $RC_SUDO" +fi + +[[ -d /opt/resolve/libs ]] || { err "/opt/resolve not present; installer likely cancelled."; exit 1; } + +# -------- TW fix: fetch Fedora gdk-pixbuf2 and copy into /opt/resolve/libs -------- +say "Applying gdk-pixbuf + GLib + OpenCL + APR tweaks for Tumbleweed…" +tmp="$(mktemp -d)" +rpmfile="$tmp/gdk.rpm" +fetch_ok="" + +# Try stable archived Fedora builds first (x86_64) +for url in \ + "https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/38/Everything/x86_64/os/Packages/g/gdk-pixbuf2-2.42.10-2.fc38.x86_64.rpm" \ + "https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/40/Everything/x86_64/os/Packages/g/gdk-pixbuf2-2.42.10-8.fc40.x86_64.rpm" \ +; do + if curl -fsSL -o "$rpmfile" "$url"; then fetch_ok="1"; break; fi +done + +# Last resort: scrape Rawhide index for the latest gdk-pixbuf2 x86_64 rpm +if [[ -z "$fetch_ok" ]]; then + idx="https://dl.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/Packages/g/" + html="$(curl -fsSL "$idx" || true)" + cand="$(printf "%s" "$html" | grep -o 'gdk-pixbuf2-[^\" ]*\.x86_64\.rpm' | head -n1 || true)" + if [[ -n "$cand" ]]; then + curl -fsSL -o "$rpmfile" "${idx}${cand}" && fetch_ok="1" + fi +fi + +if [[ -n "$fetch_ok" ]]; then + say "Extracting Fedora gdk-pixbuf2 into /opt/resolve/libs…" + ( cd "$tmp" && rpm2cpio "$rpmfile" | cpio -idmv >/dev/null 2>&1 ) + if [[ -d "$tmp/usr/lib64" ]]; then + sudo cp -vr "$tmp/usr/lib64/"* /opt/resolve/libs/ || true + else + warn "No usr/lib64 in RPM payload — skipping copy." + fi +else + warn "Could not fetch a Fedora gdk-pixbuf2 RPM (all URLs failed)." +fi +rm -rf "$tmp" + +# Symlink system OpenCL into Resolve dir +ocl="$(ldconfig -p 2>/dev/null | awk '/libOpenCL\.so\.1/{print $4; exit}')" +[[ -z "${ocl:-}" && -e /usr/lib64/ocl-icd/libOpenCL.so.1.0.0 ]] && ocl=/usr/lib64/ocl-icd/libOpenCL.so.1.0.0 +[[ -n "${ocl:-}" ]] && sudo ln -sf "$ocl" /opt/resolve/libs/libOpenCL.so.1 || warn "libOpenCL.so.1 not found." + +# Copy system GLib into Resolve’s lib folder (overwrites bundled copies) +if ls /lib64/libglib-2.0.* >/dev/null 2>&1; then + sudo rm -f /opt/resolve/libs/libglib-2.0.so* || true + sudo cp -va /lib64/libglib-2.0.* /opt/resolve/libs/ +elif ls /usr/lib64/libglib-2.0.* >/dev/null 2>&1; then + sudo rm -f /opt/resolve/libs/libglib-2.0.so* || true + sudo cp -va /usr/lib64/libglib-2.0.* /opt/resolve/libs/ +fi + +# Optional: libtiff5 shim (TW ships libtiff6) +if ! ldconfig -p | grep -q 'libtiff\.so\.5'; then + [[ -e /usr/lib64/libtiff.so.6 && ! -e /opt/resolve/libs/libtiff.so.5 ]] && \ + sudo ln -s /usr/lib64/libtiff.so.6 /opt/resolve/libs/libtiff.so.5 || true +fi + +# -------- wrapper -------- +say "Creating /usr/local/bin/resolve wrapper…" +sudo tee /usr/local/bin/resolve >/dev/null <<'EOF' +#!/usr/bin/env bash +# Force X11/XWayland + NVIDIA GLVND +export QT_QPA_PLATFORM=xcb +export __GLX_VENDOR_LIBRARY_NAME=nvidia +export QT_XCB_GL_INTEGRATION=none +export QT_OPENGL=desktop +# Prefer the libs we just placed in /opt/resolve/libs +export LD_LIBRARY_PATH="/opt/resolve/libs:/opt/resolve/bin:${LD_LIBRARY_PATH:-}" +exec /opt/resolve/bin/resolve "$@" +EOF +sudo chmod +x /usr/local/bin/resolve + +# -------- desktop entries -------- +say "Patching desktop entries to use wrapper…" +mkdir -p "$USR_APP_DIR" +for f in /usr/share/applications/davinci-resolve.desktop \ + /usr/share/applications/com.blackmagicdesign.resolve.desktop; do + if [[ -f "$f" ]]; then + install -m 0644 "$f" "$USR_APP_DIR/" + tgt="$USR_APP_DIR/$(basename "$f")" + sed -i 's|^Exec=.*|Exec=/usr/local/bin/resolve %u|g' "$tgt" + sed -i 's|^TryExec=.*|TryExec=/usr/local/bin/resolve|g' "$tgt" || true + sed -i 's|^Path=.*|Path=/opt/resolve/|g' "$tgt" || true + fi +done +command -v update-desktop-database >/dev/null 2>&1 && update-desktop-database "$USR_APP_DIR" || true + +say "Done. Launch with: resolve"