Add Linux support: cross-platform restart, nvidia-ml-py dep, README update
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
18
README.md
18
README.md
@@ -32,9 +32,10 @@ A Home Assistant integration exposes devices as entities for smart home automati
|
||||
- Color strip sources: audio-reactive, pattern generator, composite layering, audio-to-color mapping
|
||||
- Pattern templates with customizable effects
|
||||
|
||||
### Audio Integration (Windows)
|
||||
### Audio Integration
|
||||
|
||||
- Multichannel audio capture from any system device (input or loopback)
|
||||
- WASAPI engine on Windows, Sounddevice (PortAudio) engine on Linux/macOS
|
||||
- Per-channel mono extraction
|
||||
- Audio-reactive color strip sources driven by frequency analysis
|
||||
|
||||
@@ -64,7 +65,18 @@ A Home Assistant integration exposes devices as entities for smart home automati
|
||||
|
||||
- Python 3.11+ (or Docker)
|
||||
- A supported LED device on the local network or connected via USB
|
||||
- Windows for GPU-accelerated capture engines and audio capture; Linux/macOS supported via MSS
|
||||
- Windows, Linux, or macOS — all core features work cross-platform
|
||||
|
||||
### Platform Notes
|
||||
|
||||
| Feature | Windows | Linux / macOS |
|
||||
| ------- | ------- | ------------- |
|
||||
| Screen capture | DXCam, BetterCam, WGC, MSS | MSS |
|
||||
| Audio capture | WASAPI, Sounddevice | Sounddevice (PulseAudio/PipeWire) |
|
||||
| GPU monitoring | NVIDIA (pynvml) | NVIDIA (pynvml) |
|
||||
| Android capture | Scrcpy (ADB) | Scrcpy (ADB) |
|
||||
| Monitor names | Friendly names (WMI) | Generic ("Display 0") |
|
||||
| Profile conditions | Process/window detection | Not yet implemented |
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -104,7 +116,7 @@ wled-screen-controller/
|
||||
│ │ │ ├── capture/ # Screen capture, calibration, pixel processing
|
||||
│ │ │ ├── capture_engines/ # MSS, DXCam, BetterCam, WGC, Scrcpy backends
|
||||
│ │ │ ├── devices/ # WLED, Adalight, AmbileD, DDP clients
|
||||
│ │ │ ├── audio/ # Audio capture (Windows)
|
||||
│ │ │ ├── audio/ # Audio capture engines
|
||||
│ │ │ ├── filters/ # Post-processing filter pipeline
|
||||
│ │ │ ├── processing/ # Stream orchestration and target processors
|
||||
│ │ │ └── profiles/ # Condition-based profile automation
|
||||
|
||||
@@ -41,7 +41,7 @@ dependencies = [
|
||||
"zeroconf>=0.131.0",
|
||||
"pyserial>=3.5",
|
||||
"psutil>=5.9.0",
|
||||
"nvidia-ml-py>=12.0.0; sys_platform == 'win32'",
|
||||
"nvidia-ml-py>=12.0.0",
|
||||
"PyAudioWPatch>=0.2.12; sys_platform == 'win32'",
|
||||
"sounddevice>=0.5",
|
||||
]
|
||||
|
||||
27
server/restart.sh
Normal file
27
server/restart.sh
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# Restart the WLED Screen Controller server (Linux/macOS)
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
# Stop any running instance
|
||||
PIDS=$(pgrep -f 'wled_controller\.main' 2>/dev/null || true)
|
||||
if [ -n "$PIDS" ]; then
|
||||
echo "Stopping server (PID $PIDS)..."
|
||||
pkill -f 'wled_controller\.main' 2>/dev/null || true
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
# Start server detached
|
||||
echo "Starting server..."
|
||||
cd "$SCRIPT_DIR"
|
||||
nohup python -m wled_controller.main > /dev/null 2>&1 &
|
||||
sleep 3
|
||||
|
||||
# Verify it's running
|
||||
NEW_PID=$(pgrep -f 'wled_controller\.main' 2>/dev/null || true)
|
||||
if [ -n "$NEW_PID" ]; then
|
||||
echo "Server started (PID $NEW_PID)"
|
||||
else
|
||||
echo "WARNING: Server does not appear to be running!"
|
||||
fi
|
||||
@@ -273,19 +273,26 @@ STORE_MAP = {
|
||||
"profiles": "profiles_file",
|
||||
}
|
||||
|
||||
_RESTART_SCRIPT = Path(__file__).resolve().parents[4] / "restart.ps1"
|
||||
_SERVER_DIR = Path(__file__).resolve().parents[4]
|
||||
|
||||
|
||||
def _schedule_restart() -> None:
|
||||
"""Spawn restart.ps1 after a short delay so the HTTP response completes."""
|
||||
"""Spawn a restart script after a short delay so the HTTP response completes."""
|
||||
|
||||
def _restart():
|
||||
import time
|
||||
time.sleep(1)
|
||||
if sys.platform == "win32":
|
||||
subprocess.Popen(
|
||||
["powershell", "-ExecutionPolicy", "Bypass", "-File", str(_RESTART_SCRIPT)],
|
||||
["powershell", "-ExecutionPolicy", "Bypass", "-File",
|
||||
str(_SERVER_DIR / "restart.ps1")],
|
||||
creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP,
|
||||
)
|
||||
else:
|
||||
subprocess.Popen(
|
||||
["bash", str(_SERVER_DIR / "restart.sh")],
|
||||
start_new_session=True,
|
||||
)
|
||||
|
||||
threading.Thread(target=_restart, daemon=True).start()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user