From 8ed53faefd32873e2d76af17fc203fb7e8951ea3 Mon Sep 17 00:00:00 2001 From: oiupoyt Date: Sat, 5 Sep 2026 15:21:30 +0530 Subject: [PATCH] rebrand: rename project and components to scythe --- Cargo.lock | 60 ++++++------ Cargo.toml | 10 +- install.sh | 38 +++++--- packaging/aur/PKGBUILD | 27 +++--- ....vrec.Vrec.yaml => com.scythe.Scythe.yaml} | 20 ++-- packaging/rpm/{vrec.spec => scythe.spec} | 22 +++-- packaging/{vrec.desktop => scythe.desktop} | 6 +- ...rec-installer.nsi => scythe-installer.nsi} | 32 +++---- packaging/windows/scythe-standalone.nsi | 22 +++++ packaging/windows/vrec-standalone.nsi | 22 ----- src/bin/{vrec-daemon.rs => scythe-daemon.rs} | 60 ++++++------ src/bin/{vrec-ui.rs => scythe-ui.rs} | 92 ++++++++++--------- src/capture/wayland_stream.rs | 2 +- src/config.rs | 47 +++++++--- src/hyprland_binds.rs | 53 ++++++----- src/ipc.rs | 16 +++- src/overlay.rs | 43 +++++---- src/overlay_egui.rs | 38 ++++---- src/settings_ui.rs | 20 ++-- tests/e2e_test.sh | 22 ++--- 20 files changed, 373 insertions(+), 279 deletions(-) rename packaging/flatpak/{com.vrec.Vrec.yaml => com.scythe.Scythe.yaml} (50%) rename packaging/rpm/{vrec.spec => scythe.spec} (50%) rename packaging/{vrec.desktop => scythe.desktop} (68%) rename packaging/windows/{vrec-installer.nsi => scythe-installer.nsi} (57%) create mode 100644 packaging/windows/scythe-standalone.nsi delete mode 100644 packaging/windows/vrec-standalone.nsi rename src/bin/{vrec-daemon.rs => scythe-daemon.rs} (92%) rename src/bin/{vrec-ui.rs => scythe-ui.rs} (78%) diff --git a/Cargo.lock b/Cargo.lock index 2c1ccef..5c9229b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3698,6 +3698,36 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "scythe" +version = "0.1.0" +dependencies = [ + "ashpd", + "cpal", + "crossbeam-channel", + "dirs", + "eframe", + "egui", + "ffmpeg-next", + "ffmpeg-sys-next", + "gdk", + "glib 0.22.9", + "global-hotkey", + "gtk", + "gtk-layer-shell", + "libc", + "memmap2", + "mp4", + "pipewire", + "ringbuf", + "rubato", + "serde", + "serde_json", + "tokio", + "windows 0.58.0", + "xcb", +] + [[package]] name = "semver" version = "1.0.28" @@ -4480,36 +4510,6 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "vrec" -version = "0.1.0" -dependencies = [ - "ashpd", - "cpal", - "crossbeam-channel", - "dirs", - "eframe", - "egui", - "ffmpeg-next", - "ffmpeg-sys-next", - "gdk", - "glib 0.22.9", - "global-hotkey", - "gtk", - "gtk-layer-shell", - "libc", - "memmap2", - "mp4", - "pipewire", - "ringbuf", - "rubato", - "serde", - "serde_json", - "tokio", - "windows 0.58.0", - "xcb", -] - [[package]] name = "walkdir" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index 44f0ba2..8616728 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,16 @@ [package] -name = "vrec" +name = "scythe" version = "0.1.0" edition = "2024" +[[bin]] +name = "scythe-daemon" +path = "src/bin/scythe-daemon.rs" + +[[bin]] +name = "scythe-ui" +path = "src/bin/scythe-ui.rs" + [dependencies] crossbeam-channel = "0.5.16" ffmpeg-next = "9.0.0" diff --git a/install.sh b/install.sh index 781305d..1e0b8db 100755 --- a/install.sh +++ b/install.sh @@ -2,7 +2,7 @@ set -e echo "=============================================" -echo " Installing vrec Screen Recorder " +echo " Installing Scythe Screen Recorder " echo "=============================================" # Compile release binaries @@ -16,22 +16,30 @@ mkdir -p "$BIN_DIR" mkdir -p "$APP_DIR" echo "[2/4] Installing binaries to $BIN_DIR..." -install -m 755 target/release/vrec-daemon "$BIN_DIR/vrec-daemon" -install -m 755 target/release/vrec-ui "$BIN_DIR/vrec-ui" +install -m 755 target/release/scythe-daemon "$BIN_DIR/scythe-daemon" +install -m 755 target/release/scythe-ui "$BIN_DIR/scythe-ui" +ln -sf "$BIN_DIR/scythe-ui" "$BIN_DIR/scythe" + +# Backward-compatible symlinks +ln -sf "$BIN_DIR/scythe-daemon" "$BIN_DIR/vrec-daemon" +ln -sf "$BIN_DIR/scythe-ui" "$BIN_DIR/vrec-ui" +ln -sf "$BIN_DIR/scythe-ui" "$BIN_DIR/vrec" echo "[3/4] Creating application launcher..." -cat > "$APP_DIR/vrec.desktop" << EOF +cat > "$APP_DIR/scythe.desktop" << EOF [Desktop Entry] Type=Application -Name=vrec Screen Recorder +Name=Scythe Screen Recorder Comment=Fast GPU Hardware Screen Recorder & Instant Replay -Exec=vrec-ui --menu +Exec=scythe-ui --menu Icon=media-record Terminal=false Categories=AudioVideo;Recorder; -Keywords=screen;recorder;replay;capture; +Keywords=screen;recorder;replay;capture;scythe;shadowplay; EOF +ln -sf "$APP_DIR/scythe.desktop" "$APP_DIR/vrec.desktop" + echo "[4/4] Verifying PATH..." if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then echo "Notice: $BIN_DIR is not in your PATH. Consider adding:" @@ -39,15 +47,15 @@ if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then fi echo "=============================================" -echo " vrec successfully installed! " +echo " Scythe successfully installed! " echo "=============================================" echo "You can now run:" -echo " vrec-daemon # Starts background recording engine" -echo " vrec-ui --menu # Opens the HUD overlay menu" -echo " vrec-ui --record # Toggles normal recording" -echo " vrec-ui --save # Saves instant replay" +echo " scythe-daemon # Starts background recording engine" +echo " scythe-ui --menu # Opens the HUD overlay menu" +echo " scythe-ui --record # Toggles normal recording" +echo " scythe-ui --save # Saves instant replay" echo "" -echo "Tip: You can bind 'vrec-ui --menu' or 'vrec-ui --save' in Hyprland config (hyprland.conf):" -echo ' bind = ALT, Z, exec, vrec-ui --menu' -echo ' bind = CONTROL SHIFT, R, exec, vrec-ui --save' +echo "Tip: You can bind 'scythe-ui --menu' or 'scythe-ui --save' in Hyprland config (hyprland.conf):" +echo ' bind = ALT, Z, exec, scythe-ui --menu' +echo ' bind = CONTROL SHIFT, R, exec, scythe-ui --save' echo "=============================================" diff --git a/packaging/aur/PKGBUILD b/packaging/aur/PKGBUILD index 617683a..9cd399d 100644 --- a/packaging/aur/PKGBUILD +++ b/packaging/aur/PKGBUILD @@ -1,31 +1,36 @@ # Maintainer: oiupoyt -pkgname=vrec-git +pkgname=scythe-git pkgver=0.1.0 pkgrel=1 pkgdesc="High-performance GPU hardware screen recorder and instant replay overlay for Wayland and X11" arch=('x86_64') -url="https://github.com/oiupoyt/vrec" +url="https://github.com/oiupoyt/scythe" license=('MIT' 'Apache-2.0') depends=('ffmpeg' 'pipewire' 'gtk3' 'gtk-layer-shell' 'libpulse' 'libva' 'libxcb') makedepends=('cargo' 'git' 'pkgconf' 'clang') -provides=('vrec') -conflicts=('vrec') -source=("git+https://github.com/oiupoyt/vrec.git") +provides=('scythe' 'vrec' 'vrec-git') +conflicts=('scythe' 'vrec') +source=("git+https://github.com/oiupoyt/scythe.git") sha256sums=('SKIP') pkgver() { - cd "$srcdir/vrec" + cd "$srcdir/scythe" git describe --long --tags 2>/dev/null | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g' || echo "0.1.0" } build() { - cd "$srcdir/vrec" + cd "$srcdir/scythe" cargo build --release --locked } package() { - cd "$srcdir/vrec" - install -Dm755 target/release/vrec-daemon "$pkgdir/usr/bin/vrec-daemon" - install -Dm755 target/release/vrec-ui "$pkgdir/usr/bin/vrec-ui" - install -Dm644 packaging/vrec.desktop "$pkgdir/usr/share/applications/vrec.desktop" + cd "$srcdir/scythe" + install -Dm755 target/release/scythe-daemon "$pkgdir/usr/bin/scythe-daemon" + install -Dm755 target/release/scythe-ui "$pkgdir/usr/bin/scythe-ui" + install -Dm755 target/release/scythe "$pkgdir/usr/bin/scythe" + ln -sf "/usr/bin/scythe-daemon" "$pkgdir/usr/bin/vrec-daemon" + ln -sf "/usr/bin/scythe-ui" "$pkgdir/usr/bin/vrec-ui" + ln -sf "/usr/bin/scythe" "$pkgdir/usr/bin/vrec" + install -Dm644 packaging/scythe.desktop "$pkgdir/usr/share/applications/scythe.desktop" + ln -sf "/usr/share/applications/scythe.desktop" "$pkgdir/usr/share/applications/vrec.desktop" } diff --git a/packaging/flatpak/com.vrec.Vrec.yaml b/packaging/flatpak/com.scythe.Scythe.yaml similarity index 50% rename from packaging/flatpak/com.vrec.Vrec.yaml rename to packaging/flatpak/com.scythe.Scythe.yaml index a1ef811..32c5248 100644 --- a/packaging/flatpak/com.vrec.Vrec.yaml +++ b/packaging/flatpak/com.scythe.Scythe.yaml @@ -1,10 +1,10 @@ -app-id: com.vrec.Vrec +app-id: com.scythe.Scythe runtime: org.gnome.Platform runtime-version: '46' sdk: org.gnome.Sdk sdk-extensions: - org.freedesktop.Sdk.Extension.rust-stable -command: vrec-ui +command: scythe-ui finish-args: - --share=ipc - --socket=fallback-x11 @@ -19,17 +19,21 @@ finish-args: build-options: append-path: /usr/lib/sdk/rust-stable/bin env: - CARGO_HOME: /run/build/vrec/cargo + CARGO_HOME: /run/build/scythe/cargo modules: - - name: vrec + - name: scythe buildsystem: simple build-commands: - cargo build --release --verbose - - install -Dm755 target/release/vrec-daemon /app/bin/vrec-daemon - - install -Dm755 target/release/vrec-ui /app/bin/vrec-ui - - install -Dm644 packaging/vrec.desktop /app/share/applications/com.vrec.Vrec.desktop + - install -Dm755 target/release/scythe-daemon /app/bin/scythe-daemon + - install -Dm755 target/release/scythe-ui /app/bin/scythe-ui + - install -Dm755 target/release/scythe /app/bin/scythe + - ln -sf /app/bin/scythe-daemon /app/bin/vrec-daemon + - ln -sf /app/bin/scythe-ui /app/bin/vrec-ui + - ln -sf /app/bin/scythe /app/bin/vrec + - install -Dm644 packaging/scythe.desktop /app/share/applications/com.scythe.Scythe.desktop sources: - type: git - url: https://github.com/oiupoyt/vrec.git + url: https://github.com/oiupoyt/scythe.git branch: main diff --git a/packaging/rpm/vrec.spec b/packaging/rpm/scythe.spec similarity index 50% rename from packaging/rpm/vrec.spec rename to packaging/rpm/scythe.spec index 84c3050..5d92f8f 100644 --- a/packaging/rpm/vrec.spec +++ b/packaging/rpm/scythe.spec @@ -1,10 +1,10 @@ -Name: vrec +Name: scythe Version: 0.1.0 Release: 1%{?dist} Summary: High-performance GPU hardware screen recorder and instant replay overlay License: MIT -URL: https://github.com/oiupoyt/vrec +URL: https://github.com/oiupoyt/scythe Source0: %{name}-%{version}.tar.gz BuildRequires: cargo @@ -32,15 +32,25 @@ cargo build --release %install rm -rf $RPM_BUILD_ROOT -install -D -m 0755 target/release/vrec-daemon %{buildroot}%{_bindir}/vrec-daemon -install -D -m 0755 target/release/vrec-ui %{buildroot}%{_bindir}/vrec-ui -install -D -m 0644 packaging/vrec.desktop %{buildroot}%{_datadir}/applications/vrec.desktop +install -D -m 0755 target/release/scythe-daemon %{buildroot}%{_bindir}/scythe-daemon +install -D -m 0755 target/release/scythe-ui %{buildroot}%{_bindir}/scythe-ui +install -D -m 0755 target/release/scythe %{buildroot}%{_bindir}/scythe +ln -sf %{_bindir}/scythe-daemon %{buildroot}%{_bindir}/vrec-daemon +ln -sf %{_bindir}/scythe-ui %{buildroot}%{_bindir}/vrec-ui +ln -sf %{_bindir}/scythe %{buildroot}%{_bindir}/vrec +install -D -m 0644 packaging/scythe.desktop %{buildroot}%{_datadir}/applications/scythe.desktop +ln -sf %{_datadir}/applications/scythe.desktop %{buildroot}%{_datadir}/applications/vrec.desktop %files +%{_bindir}/scythe-daemon +%{_bindir}/scythe-ui +%{_bindir}/scythe %{_bindir}/vrec-daemon %{_bindir}/vrec-ui +%{_bindir}/vrec +%{_datadir}/applications/scythe.desktop %{_datadir}/applications/vrec.desktop %changelog * Wed Sep 02 2026 oiupoyt - 0.1.0-1 -- Initial release of vrec +- Initial release of scythe diff --git a/packaging/vrec.desktop b/packaging/scythe.desktop similarity index 68% rename from packaging/vrec.desktop rename to packaging/scythe.desktop index 1e86e76..1997091 100644 --- a/packaging/vrec.desktop +++ b/packaging/scythe.desktop @@ -1,11 +1,11 @@ [Desktop Entry] Type=Application -Name=vrec Screen Recorder +Name=Scythe Screen Recorder GenericName=Screen Recorder & Instant Replay Comment=High-performance GPU hardware screen recorder and instant replay overlay -Exec=vrec-ui --menu +Exec=scythe-ui --menu Icon=media-record Terminal=false Categories=AudioVideo;Recorder; -Keywords=screen;recorder;replay;capture;game;shadowplay; +Keywords=screen;recorder;replay;capture;game;shadowplay;scythe; StartupNotify=false diff --git a/packaging/windows/vrec-installer.nsi b/packaging/windows/scythe-installer.nsi similarity index 57% rename from packaging/windows/vrec-installer.nsi rename to packaging/windows/scythe-installer.nsi index ab11a6f..0d87f44 100644 --- a/packaging/windows/vrec-installer.nsi +++ b/packaging/windows/scythe-installer.nsi @@ -1,9 +1,9 @@ !include "MUI2.nsh" !include "FileFunc.nsh" -Name "vrec" -OutFile "..\..\dist\vrec-setup.exe" -InstallDir "$LOCALAPPDATA\Programs\vrec" +Name "Scythe" +OutFile "..\..\dist\scythe-setup.exe" +InstallDir "$LOCALAPPDATA\Programs\scythe" RequestExecutionLevel user !define MUI_ABORTWARNING @@ -12,9 +12,9 @@ RequestExecutionLevel user !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES -!define MUI_FINISHPAGE_RUN "$INSTDIR\vrec-ui.exe" +!define MUI_FINISHPAGE_RUN "$INSTDIR\scythe-ui.exe" !define MUI_FINISHPAGE_RUN_PARAMETERS "--menu" -!define MUI_FINISHPAGE_RUN_TEXT "Launch vrec" +!define MUI_FINISHPAGE_RUN_TEXT "Launch Scythe" !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_CONFIRM @@ -22,26 +22,26 @@ RequestExecutionLevel user !insertmacro MUI_LANGUAGE "English" -Section "vrec" SecMain +Section "Scythe" SecMain SetOutPath "$INSTDIR" File /r "..\..\dist\bundle\*.*" ; Create Start Menu and Desktop shortcuts - CreateDirectory "$SMPROGRAMS\vrec" - CreateShortcut "$SMPROGRAMS\vrec\vrec.lnk" "$INSTDIR\vrec-ui.exe" "--menu" - CreateShortcut "$DESKTOP\vrec.lnk" "$INSTDIR\vrec-ui.exe" "--menu" + CreateDirectory "$SMPROGRAMS\scythe" + CreateShortcut "$SMPROGRAMS\scythe\scythe.lnk" "$INSTDIR\scythe-ui.exe" "--menu" + CreateShortcut "$DESKTOP\scythe.lnk" "$INSTDIR\scythe-ui.exe" "--menu" ; Register uninstaller with Windows Control Panel / Settings WriteUninstaller "$INSTDIR\uninstall.exe" - WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\vrec" "DisplayName" "vrec Screen Recorder" - WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\vrec" "UninstallString" '"$INSTDIR\uninstall.exe"' - WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\vrec" "DisplayIcon" "$INSTDIR\vrec-ui.exe" - WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\vrec" "Publisher" "oiupoyt" + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\scythe" "DisplayName" "Scythe Screen Recorder" + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\scythe" "UninstallString" '"$INSTDIR\uninstall.exe"' + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\scythe" "DisplayIcon" "$INSTDIR\scythe-ui.exe" + WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\scythe" "Publisher" "oiupoyt" SectionEnd Section "Uninstall" - Delete "$DESKTOP\vrec.lnk" - RMDir /r "$SMPROGRAMS\vrec" + Delete "$DESKTOP\scythe.lnk" + RMDir /r "$SMPROGRAMS\scythe" RMDir /r "$INSTDIR" - DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\vrec" + DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\scythe" SectionEnd diff --git a/packaging/windows/scythe-standalone.nsi b/packaging/windows/scythe-standalone.nsi new file mode 100644 index 0000000..c86453b --- /dev/null +++ b/packaging/windows/scythe-standalone.nsi @@ -0,0 +1,22 @@ +!include "FileFunc.nsh" +!include "LogicLib.nsh" + +Name "Scythe" +OutFile "..\..\dist\scythe.exe" +Caption "Scythe Screen Recorder" +SilentInstall silent +RequestExecutionLevel user + +Section + ; Extract self-contained binaries and all runtime DLLs directly to user app data + SetOutPath "$LOCALAPPDATA\scythe" + File /r "..\..\dist\bundle\*.*" + + ; Execute scythe-ui with any forwarded command-line arguments, or default to overlay menu + ${GetParameters} $R0 + ${If} $R0 == "" + Exec '"$LOCALAPPDATA\scythe\scythe-ui.exe" --menu' + ${Else} + Exec '"$LOCALAPPDATA\scythe\scythe-ui.exe" $R0' + ${EndIf} +SectionEnd diff --git a/packaging/windows/vrec-standalone.nsi b/packaging/windows/vrec-standalone.nsi deleted file mode 100644 index c798d38..0000000 --- a/packaging/windows/vrec-standalone.nsi +++ /dev/null @@ -1,22 +0,0 @@ -!include "FileFunc.nsh" -!include "LogicLib.nsh" - -Name "vrec" -OutFile "..\..\dist\vrec.exe" -Caption "vrec Screen Recorder" -SilentInstall silent -RequestExecutionLevel user - -Section - ; Extract self-contained binaries and all runtime DLLs directly to user app data - SetOutPath "$LOCALAPPDATA\vrec" - File /r "..\..\dist\bundle\*.*" - - ; Execute vrec-ui with any forwarded command-line arguments, or default to overlay menu - ${GetParameters} $R0 - ${If} $R0 == "" - Exec '"$LOCALAPPDATA\vrec\vrec-ui.exe" --menu' - ${Else} - Exec '"$LOCALAPPDATA\vrec\vrec-ui.exe" $R0' - ${EndIf} -SectionEnd diff --git a/src/bin/vrec-daemon.rs b/src/bin/scythe-daemon.rs similarity index 92% rename from src/bin/vrec-daemon.rs rename to src/bin/scythe-daemon.rs index 2014fba..5a77f87 100644 --- a/src/bin/vrec-daemon.rs +++ b/src/bin/scythe-daemon.rs @@ -1,10 +1,10 @@ #![cfg_attr(target_os = "windows", windows_subsystem = "windows")] -use vrec::capture::{Frame, FrameSource}; -use vrec::encoder::VideoEncoder; -use vrec::ring::Packet; -use vrec::muxer::Muxer; -use vrec::ipc::{Command, DaemonStatus}; +use scythe::capture::{Frame, FrameSource}; +use scythe::encoder::VideoEncoder; +use scythe::ring::Packet; +use scythe::muxer::Muxer; +use scythe::ipc::{Command, DaemonStatus}; use ringbuf::HeapRb; use ringbuf::traits::{RingBuffer, Consumer, Observer}; use crossbeam_channel::bounded; @@ -54,7 +54,7 @@ async fn main() -> Result<(), Box> { #[cfg(unix)] let _lock_file = { let runtime_dir = env::var("XDG_RUNTIME_DIR").unwrap_or_else(|_| format!("/run/user/{}", unsafe { libc::getuid() })); - let lock_path = format!("{}/vrec.lock", runtime_dir); + let lock_path = format!("{}/scythe.lock", runtime_dir); match std::fs::OpenOptions::new() .create(true) .read(true) @@ -66,7 +66,7 @@ async fn main() -> Result<(), Box> { use std::os::unix::io::AsRawFd; let res = unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_EX | libc::LOCK_NB) }; if res != 0 { - eprintln!("Another instance of vrec-daemon is already running. Exiting."); + eprintln!("Another instance of scythe-daemon is already running. Exiting."); return Ok(()); } Some(file) @@ -74,11 +74,11 @@ async fn main() -> Result<(), Box> { Err(_) => None, } }; - let initial_config = vrec::config::VrecConfig::load(); + let initial_config = scythe::config::ScytheConfig::load(); // Automatically register dynamic keybindings on Hyprland if active (no config edits needed) - vrec::hyprland_binds::register_hyprland_binds(&initial_config); - vrec::hyprland_binds::spawn_hyprland_reload_watcher(); + scythe::hyprland_binds::register_hyprland_binds(&initial_config); + scythe::hyprland_binds::spawn_hyprland_reload_watcher(); let (frame_tx, frame_rx) = bounded::(5); let (cmd_tx, cmd_rx) = bounded::(32); @@ -92,7 +92,7 @@ async fn main() -> Result<(), Box> { #[cfg(unix)] let listener = { - let socket_path = vrec::ipc::get_socket_path(); + let socket_path = scythe::ipc::get_socket_path(); let _ = std::fs::remove_file(&socket_path); let l = std::os::unix::net::UnixListener::bind(&socket_path)?; println!("Daemon listening on IPC socket: {}", socket_path); @@ -107,8 +107,8 @@ async fn main() -> Result<(), Box> { l } Err(e) => { - if vrec::ipc::query_status().is_ok() { - println!("Another instance of vrec-daemon is already running. Exiting cleanly."); + if scythe::ipc::query_status().is_ok() { + println!("Another instance of scythe-daemon is already running. Exiting cleanly."); return Ok(()); } std::thread::sleep(std::time::Duration::from_millis(500)); @@ -152,7 +152,7 @@ async fn main() -> Result<(), Box> { } else { 0 }; - let cfg = vrec::config::VrecConfig::load(); + let cfg = scythe::config::ScytheConfig::load(); let status = DaemonStatus { is_recording: rec, recording_duration_sec: duration, @@ -170,7 +170,7 @@ async fn main() -> Result<(), Box> { } }, Command::ToggleCursor => { - let mut cfg = vrec::config::VrecConfig::load(); + let mut cfg = scythe::config::ScytheConfig::load(); cfg.show_cursor = !cfg.show_cursor; let _ = cfg.save(); #[cfg(target_os = "linux")] @@ -186,7 +186,7 @@ async fn main() -> Result<(), Box> { println!("Cursor display toggled to: {}", cfg.show_cursor); }, Command::CycleAudioMode => { - let mut cfg = vrec::config::VrecConfig::load(); + let mut cfg = scythe::config::ScytheConfig::load(); cfg.audio_mode = match cfg.audio_mode.as_str() { "system" => "mic", "mic" => "both", @@ -199,7 +199,7 @@ async fn main() -> Result<(), Box> { }, Command::StopDaemon => { println!("StopDaemon requested: Finalizing active recordings..."); - vrec::hyprland_binds::unregister_hyprland_binds(&vrec::config::VrecConfig::load()); + scythe::hyprland_binds::unregister_hyprland_binds(&scythe::config::ScytheConfig::load()); let _ = cmd_tx_ipc.send(Command::StopRecording); std::thread::sleep(std::time::Duration::from_millis(350)); std::process::exit(0); @@ -225,7 +225,7 @@ async fn main() -> Result<(), Box> { println!("\nReceived shutdown signal. Finalizing recordings..."); let _ = cmd_tx_sig.send(Command::StopRecording); tokio::time::sleep(std::time::Duration::from_millis(350)).await; - vrec::hyprland_binds::unregister_hyprland_binds(&vrec::config::VrecConfig::load()); + scythe::hyprland_binds::unregister_hyprland_binds(&scythe::config::ScytheConfig::load()); std::process::exit(0); } }); @@ -233,7 +233,7 @@ async fn main() -> Result<(), Box> { let session_type = env::var("XDG_SESSION_TYPE").unwrap_or_else(|_| "x11".to_string()); println!("Detected session type: {}", session_type); - let audio_capture_initial = vrec::capture::audio::AudioCapture::new_with_device_mode_and_volumes( + let audio_capture_initial = scythe::capture::audio::AudioCapture::new_with_device_mode_and_volumes( audio_tx.clone(), Some(&initial_config.audio_device), &initial_config.audio_mode, @@ -243,12 +243,12 @@ async fn main() -> Result<(), Box> { let mut source: Box = if std::env::args().any(|a| a == "--mock") { println!("Initializing MOCK capture..."); - Box::new(vrec::capture::mock::MockCapture::new()) + Box::new(scythe::capture::mock::MockCapture::new()) } else if cfg!(target_os = "windows") { #[cfg(target_os = "windows")] { println!("Initializing Windows DXGI capture..."); - Box::new(vrec::capture::windows::WindowsCapture::new()?) + Box::new(scythe::capture::windows::WindowsCapture::new()?) } #[cfg(not(target_os = "windows"))] { @@ -258,7 +258,7 @@ async fn main() -> Result<(), Box> { #[cfg(target_os = "linux")] { println!("Initializing Wayland capture (cursor: {})...", initial_config.show_cursor); - Box::new(vrec::capture::wayland::WaylandCapture::new_with_cursor(initial_config.show_cursor).await?) + Box::new(scythe::capture::wayland::WaylandCapture::new_with_cursor(initial_config.show_cursor).await?) } #[cfg(not(target_os = "linux"))] { @@ -268,7 +268,7 @@ async fn main() -> Result<(), Box> { #[cfg(target_os = "linux")] { println!("Initializing X11 capture..."); - Box::new(vrec::capture::x11::X11Capture::new()?) + Box::new(scythe::capture::x11::X11Capture::new()?) } #[cfg(not(target_os = "linux"))] { @@ -311,7 +311,7 @@ async fn main() -> Result<(), Box> { let mut audio_capture = audio_capture_initial.map(|(c, _, _)| c); let recorder_handle = thread::spawn(move || { - let mut config = vrec::config::VrecConfig::load(); + let mut config = scythe::config::ScytheConfig::load(); replay_state_clone.store(config.replay_enabled, Ordering::SeqCst); let mut encoder = VideoEncoder::new_with_params(width, height, config.record_bitrate_kbps, config.fps, &config.video_codec) @@ -319,9 +319,9 @@ async fn main() -> Result<(), Box> { let codec_ctx_ptr = encoder.codec_ctx() as usize; let mut audio_encoder = if let Some((sr, ch)) = audio_info { - vrec::encoder::AudioEncoder::new(sr as i32, ch as i32).ok() + scythe::encoder::AudioEncoder::new(sr as i32, ch as i32).ok() } else { - vrec::encoder::AudioEncoder::new(48000, 2).ok() + scythe::encoder::AudioEncoder::new(48000, 2).ok() }; let audio_codec_ctx_ptr = audio_encoder.as_ref().map(|e| e.codec_ctx() as usize); @@ -339,7 +339,7 @@ async fn main() -> Result<(), Box> { while let Ok(drain) = mux_rx.recv() { let ts = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs(); let filename = format!("replay_{}.mp4", ts); - let full_path = vrec::config::VrecConfig::load().resolve_save_path(&filename); + let full_path = scythe::config::ScytheConfig::load().resolve_save_path(&filename); println!("Saving replay to {}...", full_path); // Find the first video IDR keyframe (ignore audio packets which always have keyframe flag set) @@ -425,7 +425,7 @@ async fn main() -> Result<(), Box> { if let Ok(cmd) = cmd_res { match cmd { Command::ReloadConfig => { - let new_config = vrec::config::VrecConfig::load(); + let new_config = scythe::config::ScytheConfig::load(); if new_config.show_cursor != config.show_cursor { println!("Cursor display changed ({} -> {}). Restarting daemon for new capture session...", config.show_cursor, new_config.show_cursor); if let Some(mut m) = normal_muxer.take() { @@ -443,8 +443,8 @@ async fn main() -> Result<(), Box> { ring = HeapRb::::new(new_capacity); println!("Replay buffer resized to {} packets.", new_capacity); } - vrec::hyprland_binds::register_hyprland_binds(&config); - audio_capture = match vrec::capture::audio::AudioCapture::new_with_device_mode_and_volumes( + scythe::hyprland_binds::register_hyprland_binds(&config); + audio_capture = match scythe::capture::audio::AudioCapture::new_with_device_mode_and_volumes( audio_tx_clone.clone(), Some(&config.audio_device), &config.audio_mode, diff --git a/src/bin/vrec-ui.rs b/src/bin/scythe-ui.rs similarity index 78% rename from src/bin/vrec-ui.rs rename to src/bin/scythe-ui.rs index 0dbec45..551dd8b 100644 --- a/src/bin/vrec-ui.rs +++ b/src/bin/scythe-ui.rs @@ -1,7 +1,7 @@ #![cfg_attr(target_os = "windows", windows_subsystem = "windows")] -use vrec::ipc::{Command, send_command, query_status}; -use vrec::overlay::show_notification; +use scythe::ipc::{Command, send_command, query_status}; +use scythe::overlay::show_notification; use std::env; use global_hotkey::{GlobalHotKeyManager, hotkey::{HotKey, Modifiers, Code}, GlobalHotKeyEvent}; @@ -48,30 +48,36 @@ fn get_daemon_cmd() -> std::process::Command { let mut cmd = if let Ok(mut path) = std::env::current_exe() { path.pop(); #[cfg(target_os = "windows")] - let candidate = path.join("vrec-daemon.exe"); + let primary = path.join("scythe-daemon.exe"); + #[cfg(target_os = "windows")] + let fallback = path.join("vrec-daemon.exe"); #[cfg(not(target_os = "windows"))] - let candidate = path.join("vrec-daemon"); + let primary = path.join("scythe-daemon"); + #[cfg(not(target_os = "windows"))] + let fallback = path.join("vrec-daemon"); - if candidate.exists() { - std::process::Command::new(candidate) + if primary.exists() { + std::process::Command::new(primary) + } else if fallback.exists() { + std::process::Command::new(fallback) } else { #[cfg(target_os = "windows")] { - std::process::Command::new("vrec-daemon.exe") + std::process::Command::new("scythe-daemon.exe") } #[cfg(not(target_os = "windows"))] { - std::process::Command::new("vrec-daemon") + std::process::Command::new("scythe-daemon") } } } else { #[cfg(target_os = "windows")] { - std::process::Command::new("vrec-daemon.exe") + std::process::Command::new("scythe-daemon.exe") } #[cfg(not(target_os = "windows"))] { - std::process::Command::new("vrec-daemon") + std::process::Command::new("scythe-daemon") } }; @@ -91,11 +97,11 @@ fn get_ui_cmd() -> std::process::Command { } else { #[cfg(target_os = "windows")] { - std::process::Command::new("vrec-ui.exe") + std::process::Command::new("scythe-ui.exe") } #[cfg(not(target_os = "windows"))] { - std::process::Command::new("vrec-ui") + std::process::Command::new("scythe-ui") } }; @@ -131,7 +137,7 @@ fn ensure_hotkeys_running() { use windows::Win32::Foundation::{CloseHandle, GetLastError, WIN32_ERROR}; use windows::Win32::System::Threading::CreateMutexW; - if let Ok(handle) = CreateMutexW(None, false, windows::core::w!("Global\\vrec_hotkeys_single_instance")) { + if let Ok(handle) = CreateMutexW(None, false, windows::core::w!("Global\\scythe_hotkeys_single_instance")) { if GetLastError() == WIN32_ERROR(183) { // ERROR_ALREADY_EXISTS let _ = CloseHandle(handle); return; @@ -157,7 +163,7 @@ fn send_with_notification(cmd: Command, success_msg: &str) -> Result<(), Box { - show_notification("Error: failed to connect to vrec-daemon"); + show_notification("Error: failed to connect to scythe-daemon"); Err(e) } } @@ -177,7 +183,7 @@ fn handle_toggle_recording() -> Result<(), Box { - show_notification("Error: failed to connect to vrec-daemon"); + show_notification("Error: failed to connect to scythe-daemon"); Err(e) } } @@ -197,7 +203,7 @@ fn handle_toggle_cursor() -> Result<(), Box Ok(()) } Err(e) => { - show_notification("Error: failed to connect to vrec-daemon"); + show_notification("Error: failed to connect to scythe-daemon"); Err(e) } } @@ -215,16 +221,16 @@ fn main() -> Result<(), Box> { "--menu" => { ensure_daemon_running(); ensure_hotkeys_running(); - #[cfg(not(target_os = "windows"))] - vrec::overlay::show_menu_overlay(); - #[cfg(target_os = "windows")] - vrec::overlay_egui::run_egui_overlay(); + #[cfg(not(target_os = "linux"))] + scythe::overlay_egui::run_egui_overlay(); + #[cfg(target_os = "linux")] + scythe::overlay::show_menu_overlay(); return Ok(()); } "--egui" => { ensure_daemon_running(); ensure_hotkeys_running(); - vrec::overlay_egui::run_egui_overlay(); + scythe::overlay_egui::run_egui_overlay(); return Ok(()); } "--hotkeys" | "--background" => { @@ -259,7 +265,7 @@ fn main() -> Result<(), Box> { return Ok(()); } Err(e) => { - eprintln!("Failed to connect to vrec daemon: {}", e); + eprintln!("Failed to connect to scythe daemon: {}", e); std::process::exit(1); } } @@ -268,19 +274,19 @@ fn main() -> Result<(), Box> { return send_command(Command::StopDaemon); } "--help" | "-h" => { - println!("vrec-ui - UI Overlay and Hotkey listener for vrec"); + println!("scythe-ui - UI Overlay and Hotkey listener for scythe"); println!("Usage:"); - println!(" vrec-ui Open the interactive overlay UI menu (default)"); - println!(" vrec-ui --menu Open the interactive overlay UI menu"); - println!(" vrec-ui --hotkeys Run global hotkey manager in background"); - println!(" vrec-ui --status Query current daemon status"); - println!(" vrec-ui --save Save instant replay and show notification"); - println!(" vrec-ui --record Toggle normal recording on/off (with notification)"); - println!(" vrec-ui --cursor Toggle mouse cursor recording on/off (with notification)"); - println!(" vrec-ui --start Start normal recording"); - println!(" vrec-ui --stop Stop normal recording"); - println!(" vrec-ui --reload Reload daemon configuration"); - println!(" vrec-ui --quit Stop background daemon"); + println!(" scythe-ui Open the interactive overlay UI menu (default)"); + println!(" scythe-ui --menu Open the interactive overlay UI menu"); + println!(" scythe-ui --hotkeys Run global hotkey manager in background"); + println!(" scythe-ui --status Query current daemon status"); + println!(" scythe-ui --save Save instant replay and show notification"); + println!(" scythe-ui --record Toggle normal recording on/off (with notification)"); + println!(" scythe-ui --cursor Toggle mouse cursor recording on/off (with notification)"); + println!(" scythe-ui --start Start normal recording"); + println!(" scythe-ui --stop Stop normal recording"); + println!(" scythe-ui --reload Reload daemon configuration"); + println!(" scythe-ui --quit Stop background daemon"); return Ok(()); } _ => {} @@ -288,10 +294,10 @@ fn main() -> Result<(), Box> { } else { ensure_daemon_running(); ensure_hotkeys_running(); - #[cfg(not(target_os = "windows"))] - vrec::overlay::show_menu_overlay(); - #[cfg(target_os = "windows")] - vrec::overlay_egui::run_egui_overlay(); + #[cfg(not(target_os = "linux"))] + scythe::overlay_egui::run_egui_overlay(); + #[cfg(target_os = "linux")] + scythe::overlay::show_menu_overlay(); return Ok(()); } @@ -300,14 +306,14 @@ fn main() -> Result<(), Box> { use windows::Win32::Foundation::{GetLastError, WIN32_ERROR}; use windows::Win32::System::Threading::CreateMutexW; - let handle = CreateMutexW(None, true, windows::core::w!("Global\\vrec_hotkeys_single_instance")); + let handle = CreateMutexW(None, true, windows::core::w!("Global\\scythe_hotkeys_single_instance")); if GetLastError() == WIN32_ERROR(183) { return Ok(()); } handle.ok() }; - println!("Starting vrec UI/Hotkey process..."); + println!("Starting scythe UI/Hotkey process..."); let session_type = env::var("XDG_SESSION_TYPE").unwrap_or_else(|_| "x11".to_string()); let desktop = env::var("XDG_CURRENT_DESKTOP").unwrap_or_else(|_| "".to_string()).to_lowercase(); @@ -319,11 +325,11 @@ fn main() -> Result<(), Box> { if is_gnome || is_kde { println!("Note: Wayland native layer shell used. Ensure your compositor allows it."); println!("Tip: Global hotkeys may be restricted by Wayland compositors."); - println!(" You can bind `vrec-ui --menu` or `vrec-ui --save` in your system shortcut settings."); + println!(" You can bind `scythe-ui --menu` or `scythe-ui --save` in your system shortcut settings."); } else { println!("wlroots/Hyprland compositor detected."); - vrec::hyprland_binds::register_hyprland_binds(&vrec::config::VrecConfig::load()); - vrec::hyprland_binds::spawn_hyprland_reload_watcher(); + scythe::hyprland_binds::register_hyprland_binds(&scythe::config::ScytheConfig::load()); + scythe::hyprland_binds::spawn_hyprland_reload_watcher(); } } else { println!("X11 session detected."); diff --git a/src/capture/wayland_stream.rs b/src/capture/wayland_stream.rs index fcd78b0..1784b66 100644 --- a/src/capture/wayland_stream.rs +++ b/src/capture/wayland_stream.rs @@ -39,7 +39,7 @@ impl PipeWireStream { let stream = pw::stream::StreamBox::new( &core, - "vrec-capture", + "scythe-capture", properties! { *pw::keys::MEDIA_TYPE => "Video", *pw::keys::MEDIA_CATEGORY => "Capture", diff --git a/src/config.rs b/src/config.rs index fccfc00..8bc6f78 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,7 +20,7 @@ fn default_mic_volume() -> f32 { 0.60 } fn default_system_volume() -> f32 { 1.00 } #[derive(Debug, Serialize, Deserialize, Clone)] -pub struct VrecConfig { +pub struct ScytheConfig { #[serde(default = "default_true")] pub replay_enabled: bool, #[serde(default = "default_replay_duration")] @@ -36,7 +36,7 @@ pub struct VrecConfig { pub fps: u32, #[serde(default = "default_video_codec")] pub video_codec: String, - #[serde(default = "VrecConfig::default_output_directory")] + #[serde(default = "ScytheConfig::default_output_directory")] pub output_directory: String, #[serde(default = "default_true")] pub show_cursor: bool, @@ -65,7 +65,9 @@ pub struct VrecConfig { pub cursor_hotkey: String, } -impl Default for VrecConfig { +pub type VrecConfig = ScytheConfig; + +impl Default for ScytheConfig { fn default() -> Self { Self { replay_enabled: true, @@ -94,18 +96,21 @@ impl Default for VrecConfig { } } -impl VrecConfig { +impl ScytheConfig { pub fn default_output_directory() -> String { let mut p = dirs::video_dir().unwrap_or_else(|| PathBuf::from(".")); - p.push("vrec"); + p.push("Scythe"); p.to_string_lossy().to_string() } pub fn config_path() -> PathBuf { - let mut path = dirs::config_dir().unwrap_or_else(|| PathBuf::from(".")); - path.push("vrec"); - path.push("config.json"); - path + let base = dirs::config_dir().unwrap_or_else(|| PathBuf::from(".")); + base.join("scythe").join("config.json") + } + + pub fn legacy_config_path() -> PathBuf { + let base = dirs::config_dir().unwrap_or_else(|| PathBuf::from(".")); + base.join("vrec").join("config.json") } pub fn expand_tilde(path: &str) -> PathBuf { @@ -134,6 +139,16 @@ impl VrecConfig { && let Ok(cfg) = serde_json::from_str(&content) { return cfg; } + let legacy = Self::legacy_config_path(); + if let Ok(content) = fs::read_to_string(&legacy) + && let Ok(mut cfg) = serde_json::from_str::(&content) { + // If the legacy config used the old default directory, update it to the new Scythe directory + if cfg.output_directory.ends_with("/Videos/vrec") || cfg.output_directory.ends_with("\\Videos\\vrec") { + cfg.output_directory = Self::default_output_directory(); + } + let _ = cfg.save(); + return cfg; + } let default_cfg = Self::default(); let _ = default_cfg.save(); default_cfg @@ -145,7 +160,15 @@ impl VrecConfig { fs::create_dir_all(parent)?; } let json = serde_json::to_string_pretty(self)?; - fs::write(path, json)?; + fs::write(&path, &json)?; + + // Also update legacy config if its directory exists, ensuring backward compatibility + let legacy = Self::legacy_config_path(); + if let Some(parent) = legacy.parent() + && parent.exists() { + let _ = fs::write(legacy, &json); + } + Ok(()) } @@ -160,7 +183,7 @@ mod tests { #[test] fn test_config_defaults_and_json() { - let cfg = VrecConfig::default(); + let cfg = ScytheConfig::default(); assert_eq!(cfg.replay_duration_sec, 60); assert_eq!(cfg.replay_bitrate_kbps, 18000); assert_eq!(cfg.fps, 60); @@ -168,7 +191,7 @@ mod tests { assert_eq!(cfg.audio_mode, "system"); assert!(cfg.show_cursor); let json = serde_json::to_string(&cfg).unwrap(); - let parsed: VrecConfig = serde_json::from_str(&json).unwrap(); + let parsed: ScytheConfig = serde_json::from_str(&json).unwrap(); assert_eq!(parsed.replay_duration_sec, 60); assert_eq!(parsed.audio_mode, "system"); assert!(parsed.show_cursor); diff --git a/src/hyprland_binds.rs b/src/hyprland_binds.rs index 6a14f54..2b288e6 100644 --- a/src/hyprland_binds.rs +++ b/src/hyprland_binds.rs @@ -8,7 +8,8 @@ use std::io::{BufRead, BufReader}; use std::os::unix::net::UnixStream; #[cfg(unix)] use std::path::PathBuf; -use crate::config::VrecConfig; +use crate::config::ScytheConfig; +pub type VrecConfig = ScytheConfig; pub fn is_hyprland() -> bool { #[cfg(unix)] @@ -99,34 +100,42 @@ pub fn hotkey_to_hyprland_lua(hotkey: &str) -> Option { #[cfg(unix)] /// Dynamically inject binds and window rules into running Hyprland without touching hyprland.conf -pub fn register_hyprland_binds(config: &VrecConfig) { +pub fn register_hyprland_binds(config: &ScytheConfig) { if !is_hyprland() { return; } // Register modern Hyprland (0.55+) layer rules for genuine frosted glass blur & floating window rules + let _ = Command::new("hyprctl") + .args(["eval", r#"hl.layer_rule({ match = { namespace = "scythe-overlay" }, blur = true, ignore_alpha = 0.1 })"#]) + .output(); + let _ = Command::new("hyprctl") + .args(["eval", r#"hl.layer_rule({ match = { namespace = "scythe-notification" }, blur = true, ignore_alpha = 0.1 })"#]) + .output(); + let _ = Command::new("hyprctl") + .args(["eval", r#"hl.window_rule({ match = { class = "scythe-overlay" }, float = true, pin = true, stay_focused = true })"#]) + .output(); let _ = Command::new("hyprctl") .args(["eval", r#"hl.layer_rule({ match = { namespace = "vrec-overlay" }, blur = true, ignore_alpha = 0.1 })"#]) .output(); - let _ = Command::new("hyprctl") - .args(["eval", r#"hl.layer_rule({ match = { namespace = "vrec-notification" }, blur = true, ignore_alpha = 0.1 })"#]) - .output(); - let _ = Command::new("hyprctl") - .args(["eval", r#"hl.window_rule({ match = { class = "vrec-overlay" }, float = true, pin = true, stay_focused = true })"#]) - .output(); // Also register legacy window rules for backward compatibility with older Hyprland versions let legacy_rules = [ + "float, class:^(scythe-overlay)$", + "move 50% 45, class:^(scythe-overlay)$", + "pin, class:^(scythe-overlay)$", + "stayfocused, class:^(scythe-overlay)$", + "noborder, class:^(scythe-overlay)$", + "float, class:^(scythe-hud)$", + "move 50% 45, class:^(scythe-hud)$", + "pin, class:^(scythe-hud)$", + "stayfocused, class:^(scythe-hud)$", + "noborder, class:^(scythe-hud)$", "float, class:^(vrec-overlay)$", "move 50% 45, class:^(vrec-overlay)$", "pin, class:^(vrec-overlay)$", "stayfocused, class:^(vrec-overlay)$", "noborder, class:^(vrec-overlay)$", - "float, class:^(vrec-hud)$", - "move 50% 45, class:^(vrec-hud)$", - "pin, class:^(vrec-hud)$", - "stayfocused, class:^(vrec-hud)$", - "noborder, class:^(vrec-hud)$", ]; for rule in legacy_rules { let _ = Command::new("hyprctl") @@ -135,10 +144,10 @@ pub fn register_hyprland_binds(config: &VrecConfig) { } let binds = [ - (&config.menu_hotkey, "vrec-ui --menu"), - (&config.save_hotkey, "vrec-ui --save"), - (&config.record_hotkey, "vrec-ui --record"), - (&config.cursor_hotkey, "vrec-ui --cursor"), + (&config.menu_hotkey, "scythe-ui --menu"), + (&config.save_hotkey, "scythe-ui --save"), + (&config.record_hotkey, "scythe-ui --record"), + (&config.cursor_hotkey, "scythe-ui --cursor"), ]; for (hotkey, cmd) in binds { @@ -170,11 +179,11 @@ pub fn register_hyprland_binds(config: &VrecConfig) { } #[cfg(not(unix))] -pub fn register_hyprland_binds(_config: &VrecConfig) {} +pub fn register_hyprland_binds(_config: &ScytheConfig) {} #[cfg(unix)] /// Dynamically remove binds from running Hyprland -pub fn unregister_hyprland_binds(config: &VrecConfig) { +pub fn unregister_hyprland_binds(config: &ScytheConfig) { if !is_hyprland() { return; } @@ -207,7 +216,7 @@ pub fn unregister_hyprland_binds(config: &VrecConfig) { } #[cfg(not(unix))] -pub fn unregister_hyprland_binds(_config: &VrecConfig) {} +pub fn unregister_hyprland_binds(_config: &ScytheConfig) {} #[cfg(unix)] /// Find Hyprland socket2 for live event listening @@ -240,8 +249,8 @@ pub fn spawn_hyprland_reload_watcher() { let reader = BufReader::new(stream); for line in reader.lines().map_while(Result::ok) { if line.starts_with("configreloaded") { - println!("Hyprland config reload detected! Re-registering vrec dynamic binds..."); - let config = VrecConfig::load(); + println!("Hyprland config reload detected! Re-registering scythe dynamic binds..."); + let config = ScytheConfig::load(); register_hyprland_binds(&config); } } diff --git a/src/ipc.rs b/src/ipc.rs index ec241ab..4f8bfe1 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -49,6 +49,13 @@ fn default_audio_mode_str() -> String { #[cfg(unix)] pub fn get_socket_path() -> String { + let runtime_dir = std::env::var("XDG_RUNTIME_DIR") + .unwrap_or_else(|_| format!("/run/user/{}", unsafe { libc::getuid() })); + format!("{}/scythe.sock", runtime_dir) +} + +#[cfg(unix)] +pub fn get_legacy_socket_path() -> String { let runtime_dir = std::env::var("XDG_RUNTIME_DIR") .unwrap_or_else(|_| format!("/run/user/{}", unsafe { libc::getuid() })); format!("{}/vrec.sock", runtime_dir) @@ -71,7 +78,9 @@ pub fn send_command(cmd: Command) -> Result<(), Box { let _ = stream.set_write_timeout(Some(Duration::from_millis(1000))); let _ = stream.set_read_timeout(Some(Duration::from_millis(1000))); @@ -104,7 +113,7 @@ pub fn send_command(cmd: Command) -> Result<(), Box Result> { @@ -125,6 +134,7 @@ pub fn query_status() -> Result Result Vec { - let dir = VrecConfig::expand_tilde(dir_str); + let dir = ScytheConfig::expand_tilde(dir_str); let mut clips = Vec::new(); if let Ok(entries) = std::fs::read_dir(&dir) { for entry in entries.flatten() { @@ -424,8 +424,8 @@ fn render_section_card(ui: &mut egui::Ui, header: &str, add_contents: impl FnOnc }); } -pub struct VrecOverlayApp { - config: VrecConfig, +pub struct ScytheOverlayApp { + config: ScytheConfig, status: DaemonStatus, daemon_connected: bool, current_view: ShadowPlayView, @@ -449,15 +449,17 @@ pub struct VrecOverlayApp { initial_pos_set: bool, } -impl Default for VrecOverlayApp { +pub type VrecOverlayApp = ScytheOverlayApp; + +impl Default for ScytheOverlayApp { fn default() -> Self { Self::new() } } -impl VrecOverlayApp { +impl ScytheOverlayApp { pub fn new() -> Self { - let config = VrecConfig::load(); + let config = ScytheConfig::load(); let replay_sec = config.replay_duration_sec; let bitrate_mbps = (config.record_bitrate_kbps / 1000).max(1); let target_fps = config.fps; @@ -571,13 +573,13 @@ impl VrecOverlayApp { .show(ui, |ui| { ui.set_width(730.0); ui.horizontal(|ui| { - // VREC Badge - let (badge_rect, _) = ui.allocate_exact_size(Vec2::new(44.0, 20.0), egui::Sense::hover()); + // SCYTHE Badge + let (badge_rect, _) = ui.allocate_exact_size(Vec2::new(56.0, 20.0), egui::Sense::hover()); ui.painter().rect_filled(badge_rect, CornerRadius::same(4_u8), Color32::from_rgb(118, 185, 0)); ui.painter().text( badge_rect.center(), egui::Align2::CENTER_CENTER, - "VREC", + "SCYTHE", FontId::proportional(11.0), Color32::from_rgb(11, 18, 4), ); @@ -674,10 +676,10 @@ impl VrecOverlayApp { render_dropdown_menu(ui, card_w, |ui| { let toggle_text = if is_replay_active { "Turn off" } else { "Turn on" }; if render_menu_item(ui, toggle_text) { - let mut cfg = VrecConfig::load(); + let mut cfg = ScytheConfig::load(); cfg.replay_enabled = !cfg.replay_enabled; let _ = cfg.save(); - VrecConfig::notify_daemon_reload(); + ScytheConfig::notify_daemon_reload(); self.config.replay_enabled = cfg.replay_enabled; self.status.is_replay_active = cfg.replay_enabled; self.replay_dropdown_open = false; @@ -958,7 +960,7 @@ impl VrecOverlayApp { pick_folder(&self.output_dir, self.folder_tx.clone()); } if ui.button(egui::RichText::new("Open").size(11.0)).clicked() { - open_folder(&VrecConfig::expand_tilde(&self.output_dir)); + open_folder(&ScytheConfig::expand_tilde(&self.output_dir)); } }); ui.label(egui::RichText::new(format!("{} video recordings in destination folder.", self.clips.len())).size(10.5).color(Color32::from_rgb(148, 163, 184))); @@ -1027,7 +1029,7 @@ impl VrecOverlayApp { } } -impl eframe::App for VrecOverlayApp { +impl eframe::App for ScytheOverlayApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { self.poll_async_events(); self.anim_time += 0.033; @@ -1075,8 +1077,8 @@ impl eframe::App for VrecOverlayApp { pub fn run_egui_overlay() { let options = eframe::NativeOptions { viewport: egui::ViewportBuilder::default() - .with_title("vrec ShadowPlay") - .with_app_id("vrec-overlay") + .with_title("Scythe") + .with_app_id("scythe-overlay") .with_position([400.0, 50.0]) .with_inner_size([760.0, 270.0]) .with_min_inner_size([740.0, 250.0]) @@ -1089,8 +1091,8 @@ pub fn run_egui_overlay() { }; let _ = eframe::run_native( - "vrec-overlay", + "scythe-overlay", options, - Box::new(|_cc| Ok(Box::new(VrecOverlayApp::new()))), + Box::new(|_cc| Ok(Box::new(ScytheOverlayApp::new()))), ); } diff --git a/src/settings_ui.rs b/src/settings_ui.rs index b24925f..8b4048d 100644 --- a/src/settings_ui.rs +++ b/src/settings_ui.rs @@ -1,8 +1,8 @@ use gtk::prelude::*; use gtk::{Window, WindowType, Box, Orientation, Label, Entry, Button, Switch, ComboBoxText}; -use crate::config::VrecConfig; +use crate::config::ScytheConfig; -pub fn open_replay_settings(config_in: &VrecConfig) { +pub fn open_replay_settings(config_in: &ScytheConfig) { let window = Window::new(WindowType::Toplevel); window.set_title("Replay Settings"); window.set_default_size(320, 200); @@ -32,7 +32,7 @@ pub fn open_replay_settings(config_in: &VrecConfig) { let window_clone = window.clone(); save_btn.connect_clicked(move |_| { - let mut cfg = VrecConfig::load(); + let mut cfg = ScytheConfig::load(); if let Ok(val) = duration_entry.text().parse() { cfg.replay_duration_sec = val; } @@ -40,7 +40,7 @@ pub fn open_replay_settings(config_in: &VrecConfig) { cfg.replay_bitrate_kbps = val; } let _ = cfg.save(); - VrecConfig::notify_daemon_reload(); + ScytheConfig::notify_daemon_reload(); window_clone.close(); }); @@ -57,7 +57,7 @@ pub fn open_replay_settings(config_in: &VrecConfig) { window.show_all(); } -pub fn open_record_settings(config_in: &VrecConfig) { +pub fn open_record_settings(config_in: &ScytheConfig) { let window = Window::new(WindowType::Toplevel); window.set_title("Record Settings"); window.set_default_size(320, 150); @@ -80,12 +80,12 @@ pub fn open_record_settings(config_in: &VrecConfig) { let window_clone = window.clone(); save_btn.connect_clicked(move |_| { - let mut cfg = VrecConfig::load(); + let mut cfg = ScytheConfig::load(); if let Ok(val) = bitrate_entry.text().parse() { cfg.record_bitrate_kbps = val; } let _ = cfg.save(); - VrecConfig::notify_daemon_reload(); + ScytheConfig::notify_daemon_reload(); window_clone.close(); }); @@ -102,7 +102,7 @@ pub fn open_record_settings(config_in: &VrecConfig) { window.show_all(); } -pub fn open_general_settings(config_in: &VrecConfig) { +pub fn open_general_settings(config_in: &ScytheConfig) { let window = Window::new(WindowType::Toplevel); window.set_title("General Settings"); window.set_default_size(380, 320); @@ -160,7 +160,7 @@ pub fn open_general_settings(config_in: &VrecConfig) { let window_clone = window.clone(); save_btn.connect_clicked(move |_| { - let mut cfg = VrecConfig::load(); + let mut cfg = ScytheConfig::load(); cfg.autostart = auto_switch.is_active(); if let Some(txt) = theme_combo.active_text() { cfg.ui_color_theme = txt.to_string(); @@ -169,7 +169,7 @@ pub fn open_general_settings(config_in: &VrecConfig) { cfg.menu_hotkey = menu_hk_entry.text().to_string(); cfg.save_hotkey = save_hk_entry.text().to_string(); let _ = cfg.save(); - VrecConfig::notify_daemon_reload(); + ScytheConfig::notify_daemon_reload(); window_clone.close(); }); diff --git a/tests/e2e_test.sh b/tests/e2e_test.sh index 06afef6..ab5e63c 100755 --- a/tests/e2e_test.sh +++ b/tests/e2e_test.sh @@ -2,27 +2,27 @@ set -e echo "=============================================" -echo " vrec Automated End-to-End Test Suite " +echo " Scythe Automated End-to-End Test Suite " echo "=============================================" # Ensure binaries are compiled echo "[1/6] Building release binaries..." cargo build --release --quiet -SOCKET_PATH="${XDG_RUNTIME_DIR:-/tmp}/vrec.sock" +SOCKET_PATH="${XDG_RUNTIME_DIR:-/tmp}/scythe.sock" rm -f "$SOCKET_PATH" rm -f record_*.mp4 replay_*.mp4 -SAVE_DIR=$(python3 -c 'import json, os; print(json.load(open(os.path.expanduser("~/.config/vrec/config.json")))["output_directory"])' 2>/dev/null || echo "$HOME/Videos/vrec") +SAVE_DIR=$(python3 -c 'import json, os; p=os.path.expanduser("~/.config/scythe/config.json"); print(json.load(open(p))["output_directory"]) if os.path.exists(p) else print(os.path.expanduser("~/Videos/Scythe"))' 2>/dev/null || echo "$HOME/Videos/Scythe") mkdir -p "$SAVE_DIR" -echo "[2/6] Starting vrec-daemon with mock capture..." -target/release/vrec-daemon --mock > daemon_test.log 2>&1 & +echo "[2/6] Starting scythe-daemon with mock capture..." +target/release/scythe-daemon --mock > daemon_test.log 2>&1 & DAEMON_PID=$! cleanup() { if kill -0 $DAEMON_PID 2>/dev/null; then - target/release/vrec-ui --quit 2>/dev/null || kill -9 $DAEMON_PID 2>/dev/null || true + target/release/scythe-ui --quit 2>/dev/null || kill -9 $DAEMON_PID 2>/dev/null || true fi rm -f daemon_test.log } @@ -46,23 +46,23 @@ echo "Daemon is live (PID: $DAEMON_PID, Socket: $SOCKET_PATH)" # Test 1: Start Normal Recording echo "[3/6] Testing: Start Normal Recording..." -target/release/vrec-ui --start +target/release/scythe-ui --start echo "Recording in progress for 3 seconds..." sleep 3 # Test 2: Stop Normal Recording echo "[4/6] Testing: Stop Normal Recording..." -target/release/vrec-ui --stop +target/release/scythe-ui --stop sleep 1 # Test 3: Save Instant Replay echo "[5/6] Testing: Save Instant Replay buffer..." -target/release/vrec-ui --save +target/release/scythe-ui --save sleep 2 # Test 4: Quit Daemon echo "[6/6] Testing: Clean Daemon Shutdown..." -target/release/vrec-ui --quit +target/release/scythe-ui --quit wait $DAEMON_PID 2>/dev/null || true echo "Daemon shutdown cleanly." @@ -72,7 +72,7 @@ echo " Verifying Generated Recordings with ffprobe" echo "=============================================" FOUND_ANY=0 -for f in $(find "$SAVE_DIR" ./vrec . -maxdepth 2 \( -name "record_*.mp4" -o -name "replay_*.mp4" \) 2>/dev/null); do +for f in $(find "$SAVE_DIR" "$HOME/Videos/Scythe" "$HOME/Videos/vrec" . -maxdepth 2 \( -name "record_*.mp4" -o -name "replay_*.mp4" \) 2>/dev/null); do if [ -f "$f" ]; then FOUND_ANY=1 echo "--> Testing file: $f ($(ls -lh "$f" | awk '{print $5}'))"