Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,26 @@ jobs:
libgl-dev \
python3

- name: Compile EverLive Userspace Engine (GCC)
run: |
make -C tools/opengc573-userd -j"$(nproc)"
make -C tools/opengc570d-userd CC=gcc -j"$(nproc)"
make -C tools/opengc573-userd clean
make -C tools/opengc570d-userd clean
- name: Compile everything (GCC)
run: make -j"$(nproc)"

- name: Compile EverLive Userspace Engine (Clang)
run: |
make -C tools/opengc573-userd CC=clang -j"$(nproc)"
make -C tools/opengc570d-userd CC=clang -j"$(nproc)"
- name: Unit tests (GCC)
run: make -C tests clean test

- name: Frame generation cadence self-test
run: |
make -C tools/opengc573-userd selftest
run: make -C tools/opengc573-userd framegen-selftest

- name: OpenGC570D EDID & config unit tests
- name: Compile everything (Clang)
run: |
make -C tools/opengc570d-userd selftest
make clean
make CC=clang -j"$(nproc)"
make CC=clang -C tests clean test

- name: Sanitizer run
run: make -C tests asan

- name: Clean
run: make clean

- name: Verify Python syntax
run: |
Expand All @@ -66,3 +67,4 @@ jobs:
bash -n tools/opengc573-userd/vfio_pci_bind.sh
bash -n tools/opengc570d-userd/gc570d-vfio-bind.sh
bash -n tools/opengc570d-userd/gc570d-sleep.sh
bash -n tools/libeverlive-core/everlive-service.sh
13 changes: 12 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
*.ko
*.mod.c
*.o
*.d
*.symvers
*.order
*.cmd
Expand Down Expand Up @@ -42,7 +43,17 @@ tools/opengc570d-userd/libgc570d-v4l2.so
# Test binaries
tests/test_edid
tests/test_config
tools/opengc573-userd/gc573_framegen_selftest
tests/test_card_registry
tests/test_frame_convert
tests/test_ctl_proto
tests/test_json_rpc
tests/test_framegen

# libeverlive-core build outputs
tools/libeverlive-core/*.a
tools/libeverlive-core/*.so*
tools/libeverlive-core/everlive-ctl
tools/libeverlive-core/**/*.d

# Raw uncompressed video dumps
20261010_131220.mp4
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

---

## [Unreleased]

### Added
- **Shared `libeverlive-core`:** card registry and subsystem-aware autodiscovery, YUY2 frame conversion, jsmn-backed JSON-RPC helpers, control-socket path resolution, and the `everlive-ctl` CLI.
- **Unified control plane for the GC570D:** the DUO daemon now serves the same newline-delimited JSON-RPC 2.0 protocol on `everlive.sock` (status, LED, audio, OSD, aspect/scale, input switching, HPD, EDID policy) alongside the legacy `gc570d-ctl` socket.

### Changed
- **GC573 layout:** sources moved to `tools/opengc573-userd/src/`; the build links `libeverlive_core.a` and only applies SDL/FFmpeg/PipeWire flags to the translation units that need them.
- **Build and install:** a top-level `Makefile` orchestrates the core and both engines; `build.sh`, `install.sh`, and `uninstall.sh` now install and remove `everlive-ctl`, the core library and headers, and the universal `everlive.service` unit.
- **Launchers:** `play.sh` and `everlive-service.sh` share `everlive-ctl detect` instead of duplicating PCI ID logic.

### Fixed
- The GC573 engine no longer claims a GC570D that shares PCI ID `1461:0054`; discovery is subsystem-aware and fails safe when the subsystem ID is unreadable.
- `everlive-ctl` connects to the live `everlive.sock` instead of the stale `everlive-experimental.sock` path.

### Tests
- Unified `tests/` suite linking the core archive, `test_json_rpc` (renamed from `test_ipc_json`), the framegen cadence test, `make -C tests asan`, and `run_tests.sh --asan`.

## [1.5.0] - 2026-11-10

### Added
Expand Down
46 changes: 46 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# EverLive — top-level orchestration.
# Build order: libeverlive-core, then both engines, then tests.

CORE_DIR := tools/libeverlive-core
GC573_DIR := tools/opengc573-userd
GC570D_DIR := tools/opengc570d-userd
TESTS_DIR := tests

.PHONY: all core gc573 gc570d test check asan clean install uninstall

all: core gc573 gc570d

core:
+$(MAKE) -C $(CORE_DIR)

gc573: core
+$(MAKE) -C $(GC573_DIR)

gc570d: core
+$(MAKE) -C $(GC570D_DIR)

test: all
+$(MAKE) -C $(TESTS_DIR) test

check: test

asan: all
+$(MAKE) -C $(TESTS_DIR) asan

clean:
+$(MAKE) -C $(CORE_DIR) clean
+$(MAKE) -C $(GC573_DIR) clean
+$(MAKE) -C $(GC570D_DIR) clean
+$(MAKE) -C $(TESTS_DIR) clean

install: all
+$(MAKE) -C $(CORE_DIR) install
+$(MAKE) -C $(GC573_DIR) install
+$(MAKE) -C $(GC570D_DIR) install

uninstall:
+$(MAKE) -C $(CORE_DIR) uninstall
+$(MAKE) -C $(GC573_DIR) uninstall
+$(MAKE) -C $(GC570D_DIR) uninstall
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,21 @@ sudo ./install.sh --no-loopback

`--skip-loopback` is an alias, and `sudo ./install.sh --help` lists all options. Without `v4l2loopback`, `/dev/video10` is unavailable — capture the game window via PipeWire instead (see [Streaming & Recording with OBS](#-streaming--recording-with-obs)). Re-running the installer without the flag re-enables the Virtual Camera.

### Building and testing from source
```bash
make -j"$(nproc)" # libeverlive-core + both engines
make -C tests test # 7 unit-test suites
make -C tests asan # sanitizer run
```

`./build.sh` is a thin wrapper around the same top-level `make`.

### What the installer does:
1. Installs the build/runtime dependencies: SDL2, FFmpeg development libraries (`libavcodec`/`libswresample`/`libavutil`), `libcap` (`setcap`), PipeWire/WirePlumber, `xcb-util-cursor`, PySide6, standard build tools, optional `lsfg-vk` frame generation layer (skip with `--no-framegen`), and `v4l2loopback` where packaged (skip with `--no-loopback`).
2. Configures udev rules (`/etc/udev/rules.d/70-everlive.rules`) and early-boot VFIO autobind (`/etc/modules-load.d/everlive-vfio.conf` + `/etc/modprobe.d/everlive-vfio.conf`) granting your local user read/write access to the card's VFIO group and binding `vfio-pci`.
3. Sets `/etc/security/limits.d/99-everlive-memlock.conf` and adds `cap_ipc_lock` capabilities so unprivileged users can pin DMA buffers required for native 4K and dual-HDMI capture.
4. Blacklists the legacy out-of-tree `open_gc573` module (`/etc/modprobe.d/blacklist-everlive-legacy.conf`) so it cannot race with `vfio-pci` at boot.
5. Compiles userspace engines: `opengc573-userd` (`gc573_user_streamer`, `everlive_userd`, `gc573_user_probe`, `gc573_user_diag`) and `opengc570d-userd` (`opengc570d-userd`, `gc570d-ctl`, `libgc570d-v4l2.so`).
5. Compiles the shared core and userspace engines through the top-level `Makefile`: `libeverlive-core` (`everlive-ctl`, `libeverlive_core.so`), `opengc573-userd` (`gc573_user_streamer`, `everlive_userd`, `gc573_user_probe`, `gc573_user_diag`) and `opengc570d-userd` (`opengc570d-userd`, `gc570d-ctl`, `libgc570d-v4l2.so`). The core library, its headers, `everlive-ctl`, `everlive-service`, and the universal `everlive.service` unit are installed system-wide.
6. Configures an isolated PipeWire audio sink (`50-everlive-capture.conf`) providing the dedicated `"EverLive Capture Audio"` source for OBS.
7. Configures the Virtual Camera: `/etc/modprobe.d/everlive-v4l2loopback.conf` (`video_nr=10,11 card_label="EverLive Capture,EverLive Capture HDMI 2" exclusive_caps=0`) and loads the module at boot via `/etc/modules-load.d/`.
8. Installs the desktop application launcher and icon.
Expand Down Expand Up @@ -361,6 +370,7 @@ Writing clean-room Linux drivers for proprietary capture hardware requires havin
| Component | Path | License | Notes |
|:---|:---|:---:|:---|
| **Userspace Driver & Streamer** | `tools/opengc573-userd/` | **GPL-2.0-only** | Userspace VFIO implementation. Copyright © 2026 Everlite. |
| **Shared Core Library** | `tools/libeverlive-core/` | **GPL-2.0-only** | Card registry and autodiscovery, YUY2 frame conversion, jsmn-backed JSON-RPC helpers, control-socket resolution, `everlive-ctl`, and the `everlive.service` unit. Copyright © 2026 Everlite. |
| **Live Gamer DUO Engine** | `tools/opengc570d-userd/` | **GPL-2.0-only** | Derived from [`neoyagami/OpenGC570D`](https://github.com/neoyagami/OpenGC570D) with userspace VFIO-PCI + PipeWire port by [@PolygonPrincess](https://github.com/PolygonPrincess). Upstream base `4673bb9`, splitter PR #6 `484aa8d`, userspace import `afbb06e`. EverLive integration and frontend © 2026 Everlite & PolygonPrincess. |
| **EverLive Console Hub** | `tools/everlive/`, `play.sh`, `install.sh` | **GPL-2.0-only** | Python/Qt hub and launcher scripts. Copyright © 2026 Everlite. |
| **Legacy Kernel Module** | `legacy/open_gc573-kernel/` | **GPL-2.0-only** | Historical kernel module based on work by ostrich, extended by Everlite. |
Expand Down
27 changes: 14 additions & 13 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GC573_DIR="${SCRIPT_DIR}/tools/opengc573-userd"
GC570D_DIR="${SCRIPT_DIR}/tools/opengc570d-userd"

echo "[*] Baue EverLive GC573 Userspace VFIO Engine (gc573_user_streamer & everlive_userd)..."
make -C "${GC573_DIR}" clean >/dev/null 2>&1 || true
make -C "${GC573_DIR}" -j"$(nproc)"
echo "[*] Building EverLive core library (libeverlive-core & everlive-ctl)..."
echo "[*] Building GC573 (Live Gamer 4K) userspace VFIO engine..."
echo "[*] Building GC570D (Live Gamer DUO) userspace engine..."
make -C "${SCRIPT_DIR}" -j"$(nproc)"

echo "[*] Baue EverLive GC570D (Live Gamer DUO) Userspace Engine..."
make -C "${GC570D_DIR}" clean >/dev/null 2>&1 || true
make -C "${GC570D_DIR}" -j"$(nproc)"
echo "[+] EverLive Userspace Engines built successfully!"

echo "[+] EverLive Userspace Engines erfolgreich gebaut!"

# Optional: Baue Legacy Direct-Renderer falls Quellcode vorhanden
# Optional: build the legacy direct renderer if its source is present
if [ -f "${SCRIPT_DIR}/tools/everlive/everlive_display.c" ]; then
echo "[*] Baue Legacy Direct-Renderer (everlive_display)..."
gcc -O3 -march=native -o "${SCRIPT_DIR}/tools/everlive/everlive_display" "${SCRIPT_DIR}/tools/everlive/everlive_display.c" $(sdl2-config --cflags --libs 2>/dev/null || true) -lGL -lm -lX11 -lpthread 2>/dev/null || true
echo "[*] Building legacy direct renderer (everlive_display)..."
SDL_FLAGS="$(pkg-config --cflags --libs sdl2 2>/dev/null || sdl2-config --cflags --libs 2>/dev/null || true)"
if [ -n "${SDL_FLAGS}" ]; then
gcc -O3 -o "${SCRIPT_DIR}/tools/everlive/everlive_display" \
"${SCRIPT_DIR}/tools/everlive/everlive_display.c" ${SDL_FLAGS} \
-lGL -lm -lX11 -lpthread
chmod 0755 "${SCRIPT_DIR}/tools/everlive/everlive_display" 2>/dev/null || true
fi
fi
29 changes: 21 additions & 8 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CORE_DIR="${SCRIPT_DIR}/tools/libeverlive-core"
USERD_DIR="${SCRIPT_DIR}/tools/opengc573-userd"
GC570D_DIR="${SCRIPT_DIR}/tools/opengc570d-userd"
VIEWER_DIR="${SCRIPT_DIR}/tools/everlive"
Expand Down Expand Up @@ -395,20 +396,32 @@ detect_and_install_deps

# 3. Userspace VFIO Engine kompilieren
echo -e "\n${BLUE}[2/5] Kompiliere EverLive Userspace VFIO Engine...${NC}"
make -C "${USERD_DIR}" clean >/dev/null 2>&1 || true
make -C "${USERD_DIR}" -j"$(nproc)"
echo -e "${BLUE}[*] Kompiliere GC570D (Live Gamer DUO) Userspace Engine...${NC}"
make -C "${GC570D_DIR}" clean >/dev/null 2>&1 || true
make -C "${GC570D_DIR}" -j"$(nproc)"
# Never leave build artifacts world-writable, and keep the binary setcap-safe.
chmod 0755 "${USERD_DIR}/gc573_user_streamer" "${USERD_DIR}/everlive_userd" "${USERD_DIR}/gc573_user_probe" \
"${GC570D_DIR}/opengc570d-userd" "${GC570D_DIR}/gc570d-ctl" "${SCRIPT_DIR}/play.sh"
make -C "${SCRIPT_DIR}" -j"$(nproc)"

# Never leave build artifacts world-writable, and keep binaries setcap-safe.
chmod 0755 "${USERD_DIR}/gc573_user_streamer" "${USERD_DIR}/everlive_userd" \
"${USERD_DIR}/gc573_user_probe" "${CORE_DIR}/everlive-ctl" \
"${GC570D_DIR}/opengc570d-userd" "${GC570D_DIR}/gc570d-ctl" \
"${SCRIPT_DIR}/play.sh"
chmod 0644 "${GC570D_DIR}/libgc570d-v4l2.so" 2>/dev/null || true

# Core library, everlive-ctl, everlive-service, headers, and systemd unit.
make -C "${CORE_DIR}" install

# Install the GC573 engine binaries into /usr/local/bin with cap_ipc_lock.
make -C "${USERD_DIR}" install

# Install the GC570D helpers (udev rule, memlock, systemd unit, sleep hook)
# through the engine's own Makefile so both installers stay in sync.
make -C "${GC570D_DIR}" install

# GC573 currently ships its bind helper from install.sh.
install -m 0755 "${USERD_DIR}/vfio_pci_bind.sh" /usr/local/bin/vfio_pci_bind.sh

setcap cap_ipc_lock=+ep "${USERD_DIR}/gc573_user_streamer" 2>/dev/null || true
setcap cap_ipc_lock=+ep /usr/local/bin/gc573_user_streamer 2>/dev/null || true
setcap cap_ipc_lock=+ep "${GC570D_DIR}/opengc570d-userd" 2>/dev/null || true
setcap cap_ipc_lock=+ep /usr/local/bin/opengc570d-userd 2>/dev/null || true
echo -e "${GREEN}[+] Userspace VFIO Engines erfolgreich gebaut & berechtigt!${NC}"

# Python GUI-Umgebung (PySide6) für Benutzer prüfen und bei Bedarf einrichten
Expand Down
77 changes: 55 additions & 22 deletions play.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,59 @@
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CORE_DIR="${SCRIPT_DIR}/tools/libeverlive-core"
CORE_CTL="${CORE_DIR}/everlive-ctl"
GC573_DIR="${SCRIPT_DIR}/tools/opengc573-userd"
GC570D_DIR="${SCRIPT_DIR}/tools/opengc570d-userd"
VIEWER="${SCRIPT_DIR}/tools/everlive/everlive_viewer.py"

# 0. Detect the installed capture card. GC573 and GC570D share PCI device
# 1461:0054; only the subsystem device ID distinguishes them.
CARD_MODEL="gc573"
# 1461:0054; only the subsystem device ID distinguishes them. Prefer the
# core registry and fall back to sysfs when everlive-ctl is unavailable.
detect_card_sysfs() {
local dev vendor device subsystem

CARD_MODEL=""
CARD_PCI=""
for dev in /sys/bus/pci/devices/*; do
[ -f "$dev/vendor" ] || continue
[ -f "$dev/device" ] || continue
vendor=$(cat "$dev/vendor" 2>/dev/null || true)
device=$(cat "$dev/device" 2>/dev/null || true)
if [ "$vendor" != "0x1461" ]; then
continue
fi
if [ "$device" != "0x0054" ] && [ "$device" != "0x0055" ]; then
continue
fi
CARD_PCI=$(basename "$dev")
subsystem=$(cat "$dev/subsystem_device" 2>/dev/null || true)
if [ "$device" = "0x0054" ] && [ "$subsystem" = "0x5700" ]; then
CARD_MODEL="gc570d"
else
CARD_MODEL="gc573"
fi
break
done
}

CARD_MODEL=""
CARD_PCI=""
for dev in /sys/bus/pci/devices/*; do
[ -f "$dev/vendor" ] || continue
[ -f "$dev/device" ] || continue
vendor=$(cat "$dev/vendor" 2>/dev/null || true)
device=$(cat "$dev/device" 2>/dev/null || true)
if [ "$vendor" != "0x1461" ]; then
continue
fi
if [ "$device" != "0x0054" ] && [ "$device" != "0x0055" ]; then
continue
fi
CARD_PCI=$(basename "$dev")
subsystem=$(cat "$dev/subsystem_device" 2>/dev/null || true)
if [ "$device" = "0x0054" ] && [ "$subsystem" = "0x5700" ]; then
CARD_MODEL="gc570d"
fi
break
done
if [ -x "${CORE_CTL}" ]; then
DETECT_OUT="$("${CORE_CTL}" detect 2>/dev/null || true)"
CARD_MODEL="$(printf '%s\n' "${DETECT_OUT}" \
| sed -n 's/.*Model Slug:[[:space:]]*//p' | head -n 1)"
CARD_PCI="$(printf '%s\n' "${DETECT_OUT}" \
| sed -n 's/.*PCI BDF:[[:space:]]*//p' | head -n 1)"
case "${CARD_MODEL}" in
gc573|gc570d) ;;
*) CARD_MODEL="" ;;
esac
fi
if [ -z "${CARD_MODEL}" ]; then
detect_card_sysfs
fi
CARD_MODEL="${CARD_MODEL:-gc573}"

if [ "$CARD_MODEL" = "gc570d" ]; then
USERD_DIR="${GC570D_DIR}"
Expand All @@ -48,8 +75,14 @@ else
LOOPBACK_LABEL_2=""
fi

# 1. Ensure userspace engine binaries are built and up to date
if ! make -C "${USERD_DIR}" -q >/dev/null 2>&1; then
# 1. Ensure the core and userspace engine binaries are built and up to date
if [ ! -x "${CORE_CTL}" ] || \
! make -q -C "${CORE_DIR}" everlive-ctl >/dev/null 2>&1; then
echo "[*] Aktualisiere/Kompiliere EverLive Core Library..."
make -C "${CORE_DIR}" -j"$(nproc)"
fi
if [ ! -x "${STREAMER_BIN}" ] || \
! make -q -C "${USERD_DIR}" "$(basename "${STREAMER_BIN}")" >/dev/null 2>&1; then
echo "[*] Aktualisiere/Kompiliere EverLive Userspace VFIO Engine..."
make -C "${USERD_DIR}" -j"$(nproc)"
fi
Expand Down
Loading
Loading