rebrand: rename project and components to scythe
This commit is contained in:
parent
354b3e9558
commit
8ed53faefd
20 changed files with 373 additions and 279 deletions
60
Cargo.lock
generated
60
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
10
Cargo.toml
10
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"
|
||||
|
|
|
|||
38
install.sh
38
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 "============================================="
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
22
packaging/windows/scythe-standalone.nsi
Normal file
22
packaging/windows/scythe-standalone.nsi
Normal file
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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<dyn std::error::Error + Send + Sync>> {
|
|||
#[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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
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::<Frame>(5);
|
||||
let (cmd_tx, cmd_rx) = bounded::<Command>(32);
|
||||
|
|
@ -92,7 +92,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
|
||||
#[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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
} 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<dyn std::error::Error + Send + Sync>> {
|
|||
}
|
||||
},
|
||||
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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
},
|
||||
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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
|
||||
let mut source: Box<dyn FrameSource> = 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<dyn std::error::Error + Send + Sync>> {
|
|||
#[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<dyn std::error::Error + Send + Sync>> {
|
|||
#[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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
ring = HeapRb::<Packet>::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,
|
||||
|
|
@ -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<dyn
|
|||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
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<dyn std::error::Error + Send + Sy
|
|||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
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<dyn std::error::Error + Send + Sync>
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
"--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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
} 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<dyn std::error::Error + Send + Sync>> {
|
|||
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<dyn std::error::Error + Send + Sync>> {
|
|||
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.");
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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::<Self>(&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);
|
||||
|
|
|
|||
|
|
@ -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<String> {
|
|||
|
||||
#[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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
src/ipc.rs
16
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<dyn std::error::Error + Send
|
|||
{
|
||||
use std::os::unix::net::UnixStream;
|
||||
let socket_path = get_socket_path();
|
||||
match UnixStream::connect(&socket_path) {
|
||||
let connect_res = UnixStream::connect(&socket_path)
|
||||
.or_else(|_| UnixStream::connect(get_legacy_socket_path()));
|
||||
match connect_res {
|
||||
Ok(mut stream) => {
|
||||
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<dyn std::error::Error + Send
|
|||
}
|
||||
}
|
||||
|
||||
Err(last_err.unwrap_or_else(|| "Failed to communicate with vrec-daemon".into()))
|
||||
Err(last_err.unwrap_or_else(|| "Failed to communicate with scythe-daemon".into()))
|
||||
}
|
||||
|
||||
pub fn query_status() -> Result<DaemonStatus, Box<dyn std::error::Error + Send + Sync>> {
|
||||
|
|
@ -125,6 +134,7 @@ pub fn query_status() -> Result<DaemonStatus, Box<dyn std::error::Error + Send +
|
|||
use std::os::unix::net::UnixStream;
|
||||
let socket_path = get_socket_path();
|
||||
UnixStream::connect(&socket_path)
|
||||
.or_else(|_| UnixStream::connect(get_legacy_socket_path()))
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
|
|
@ -162,5 +172,5 @@ pub fn query_status() -> Result<DaemonStatus, Box<dyn std::error::Error + Send +
|
|||
}
|
||||
}
|
||||
|
||||
Err(last_err.unwrap_or_else(|| "Failed to query status from vrec-daemon".into()))
|
||||
Err(last_err.unwrap_or_else(|| "Failed to query status from scythe-daemon".into()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use std::f64::consts::PI;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use crate::config::VrecConfig;
|
||||
use crate::config::ScytheConfig;
|
||||
use crate::ipc::{self, Command};
|
||||
|
||||
pub fn show_notification_overlay() {
|
||||
|
|
@ -28,7 +28,7 @@ pub fn show_notification(message: &str) {
|
|||
$notify = new-object system.windows.forms.notifyicon; \
|
||||
$notify.icon = [System.Drawing.SystemIcons]::Information; \
|
||||
$notify.visible = $true; \
|
||||
$notify.showballoontip(2000, 'vrec', '{}', [system.windows.forms.tooltipicon]::Info); \
|
||||
$notify.showballoontip(2000, 'scythe', '{}', [system.windows.forms.tooltipicon]::Info); \
|
||||
Start-Sleep -Seconds 2; \
|
||||
$notify.dispose()",
|
||||
msg.replace('\'', "''")
|
||||
|
|
@ -51,7 +51,7 @@ pub fn show_notification(message: &str) {
|
|||
}
|
||||
|
||||
let app = Application::builder()
|
||||
.application_id("com.vrec.notification")
|
||||
.application_id("com.scythe.notification")
|
||||
.build();
|
||||
|
||||
let msg_text = message.to_string();
|
||||
|
|
@ -70,7 +70,7 @@ pub fn show_notification(message: &str) {
|
|||
if layer_shell_ok {
|
||||
window.init_layer_shell();
|
||||
window.set_layer(Layer::Overlay);
|
||||
window.set_namespace("vrec-notification");
|
||||
window.set_namespace("scythe-notification");
|
||||
window.set_layer_shell_margin(gtk_layer_shell::Edge::Top, 40);
|
||||
window.set_anchor(gtk_layer_shell::Edge::Top, true);
|
||||
} else {
|
||||
|
|
@ -141,7 +141,7 @@ pub fn show_notification(message: &str) {
|
|||
hbox.style_context().add_class("notify-box");
|
||||
hbox.set_halign(gtk::Align::Center);
|
||||
|
||||
let badge = Label::new(Some("VREC"));
|
||||
let badge = Label::new(Some("SCYTHE"));
|
||||
badge.style_context().add_class("notify-badge");
|
||||
let label = Label::new(Some(&msg_text));
|
||||
label.style_context().add_class("notify-label");
|
||||
|
|
@ -253,9 +253,16 @@ fn draw_gear_icon(cr: >k::cairo::Context, width: f64, height: f64) {
|
|||
}
|
||||
|
||||
pub fn show_menu_overlay() {
|
||||
#[cfg(unix)]
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
crate::overlay_egui::run_egui_overlay();
|
||||
return;
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
if std::env::var("WAYLAND_DISPLAY").is_err() && std::env::var("DISPLAY").is_err() {
|
||||
eprintln!("Note: No display server detected for GTK. Falling back to cross-platform egui overlay...");
|
||||
eprintln!("Warning: No display found for GTK menu overlay. Falling back to cross-platform egui overlay...");
|
||||
crate::overlay_egui::run_egui_overlay();
|
||||
return;
|
||||
}
|
||||
|
|
@ -266,12 +273,12 @@ pub fn show_menu_overlay() {
|
|||
}
|
||||
|
||||
let app = Application::builder()
|
||||
.application_id("com.vrec.hud")
|
||||
.application_id("com.scythe.hud")
|
||||
.flags(gtk::gio::ApplicationFlags::NON_UNIQUE)
|
||||
.build();
|
||||
|
||||
app.connect_activate(|app| {
|
||||
let config = VrecConfig::load();
|
||||
let config = ScytheConfig::load();
|
||||
|
||||
let window = ApplicationWindow::builder()
|
||||
.application(app)
|
||||
|
|
@ -287,7 +294,7 @@ pub fn show_menu_overlay() {
|
|||
if layer_shell_ok {
|
||||
window.init_layer_shell();
|
||||
window.set_layer(Layer::Overlay);
|
||||
window.set_namespace("vrec-overlay");
|
||||
window.set_namespace("scythe-overlay");
|
||||
window.set_keyboard_interactivity(true);
|
||||
// Shifted higher towards the top (50px margin) per user feedback
|
||||
window.set_layer_shell_margin(gtk_layer_shell::Edge::Top, 50);
|
||||
|
|
@ -335,8 +342,8 @@ pub fn show_menu_overlay() {
|
|||
let header_box = Box::new(Orientation::Horizontal, 10);
|
||||
header_box.style_context().add_class("header-bar");
|
||||
|
||||
let brand_badge = Label::new(Some("VREC"));
|
||||
brand_badge.style_context().add_class("vrec-badge");
|
||||
let brand_badge = Label::new(Some("SCYTHE"));
|
||||
brand_badge.style_context().add_class("scythe-badge");
|
||||
|
||||
let title_label = Label::new(Some("SHADOWPLAY OVERLAY"));
|
||||
title_label.style_context().add_class("overlay-title");
|
||||
|
|
@ -887,6 +894,7 @@ pub fn show_menu_overlay() {
|
|||
padding: 8px 18px;
|
||||
box-shadow: 0px 12px 32px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.16);
|
||||
}
|
||||
.scythe-badge,
|
||||
.vrec-badge {
|
||||
background-color: #76b900;
|
||||
color: #0b1204;
|
||||
|
|
@ -1181,10 +1189,10 @@ pub fn show_menu_overlay() {
|
|||
let rev_r_hide = replay_revealer.clone();
|
||||
let card_r_deactivate = replay_card_btn.clone();
|
||||
replay_toggle_item.connect_clicked(move |_| {
|
||||
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();
|
||||
|
||||
r_state_sync.store(cfg.replay_enabled, Ordering::Relaxed);
|
||||
r_icon_sync.queue_draw();
|
||||
|
|
@ -1251,7 +1259,7 @@ pub fn show_menu_overlay() {
|
|||
// Direct Mouse Cursor Switch Toggle
|
||||
let banner_cur = status_banner.clone();
|
||||
cursor_switch.connect_state_set(move |_, active| {
|
||||
let mut cfg = VrecConfig::load();
|
||||
let mut cfg = ScytheConfig::load();
|
||||
if cfg.show_cursor != active {
|
||||
cfg.show_cursor = active;
|
||||
let _ = cfg.save();
|
||||
|
|
@ -1275,7 +1283,7 @@ pub fn show_menu_overlay() {
|
|||
let cur_sw_sync = cursor_switch.clone();
|
||||
|
||||
apply_btn.connect_clicked(move |_| {
|
||||
let mut cfg = VrecConfig::load();
|
||||
let mut cfg = ScytheConfig::load();
|
||||
cfg.show_cursor = cur_sw_sync.is_active();
|
||||
cfg.fps = fps_spin.value() as u32;
|
||||
let bit_mbps = bit_spin.value() as u32;
|
||||
|
|
@ -1305,7 +1313,7 @@ pub fn show_menu_overlay() {
|
|||
cfg.autostart = auto_switch.is_active();
|
||||
|
||||
let _ = cfg.save();
|
||||
VrecConfig::notify_daemon_reload();
|
||||
ScytheConfig::notify_daemon_reload();
|
||||
|
||||
r_sub_lbl_sync.set_text(&format!("{}s Buffer", cfg.replay_duration_sec));
|
||||
rec_sub_lbl_sync.set_text(&format!("{} FPS • {} Mbps", cfg.fps, cfg.record_bitrate_kbps / 1000));
|
||||
|
|
@ -1386,4 +1394,5 @@ pub fn show_menu_overlay() {
|
|||
});
|
||||
|
||||
app.run_with_args(&[] as &[&str]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use egui::{Color32, CornerRadius, FontId, Margin, Stroke, Vec2};
|
|||
use std::path::PathBuf;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::time::{Duration, Instant, SystemTime};
|
||||
use crate::config::VrecConfig;
|
||||
use crate::config::ScytheConfig;
|
||||
use crate::ipc::{self, Command, DaemonStatus};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
|
@ -22,7 +22,7 @@ pub struct VideoClipInfo {
|
|||
}
|
||||
|
||||
fn scan_recordings(dir_str: &str) -> Vec<VideoClipInfo> {
|
||||
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()))),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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}'))"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue