diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 920515f..8c14ae4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -111,6 +111,8 @@ jobs: mingw-w64-x86_64-ffmpeg mingw-w64-x86_64-pkg-config mingw-w64-x86_64-clang + mingw-w64-x86_64-ntldd + python3 - name: Build Release Binaries (Windows) shell: msys2 {0} @@ -119,20 +121,34 @@ jobs: BINDGEN_EXTRA_CLANG_ARGS: "--target=x86_64-w64-windows-gnu" run: | cargo build --release + mkdir -p dist/bundle + cp target/release/vrec-daemon.exe dist/bundle/ + cp target/release/vrec-ui.exe dist/bundle/ + python3 packaging/windows/bundle_deps.py dist/bundle - - name: Package Windows Zip + - name: Package Windows Standalone (.exe), Installer, and Zip shell: pwsh run: | - New-Item -ItemType Directory -Force -Path dist/vrec-windows-x64 - Copy-Item target/release/vrec-daemon.exe dist/vrec-windows-x64/ - Copy-Item target/release/vrec-ui.exe dist/vrec-windows-x64/ - Compress-Archive -Path dist/vrec-windows-x64 -DestinationPath dist/vrec-windows-x64.zip + if (!(Get-Command makensis -ErrorAction SilentlyContinue)) { + if (Test-Path "C:\Program Files (x86)\NSIS\makensis.exe") { + $env:Path += ";C:\Program Files (x86)\NSIS" + } else { + choco install nsis -y --no-progress + $env:Path += ";C:\Program Files (x86)\NSIS" + } + } + makensis packaging/windows/vrec-standalone.nsi + makensis packaging/windows/vrec-installer.nsi + Compress-Archive -Path dist/bundle/* -DestinationPath dist/vrec-windows-x64.zip - name: Upload Windows Artifacts uses: actions/upload-artifact@v4 with: - name: windows-package - path: dist/vrec-windows-x64.zip + name: windows-packages + path: | + dist/vrec.exe + dist/vrec-setup.exe + dist/vrec-windows-x64.zip publish-release: name: Publish GitHub Release @@ -166,14 +182,16 @@ jobs: - Multi-channel audio routing (System audio, Microphone, Combined, and Mute) ### Packages - - Windows: `vrec-windows-x64.zip` + - Windows Standalone: `vrec.exe` (Single standalone executable, zero install required) + - Windows Setup: `vrec-setup.exe` (Full installer with Start Menu & Desktop shortcuts) + - Windows Portable: `vrec-windows-x64.zip` (Zip with all binaries & runtime DLLs) - Universal Linux: `vrec-x86_64.AppImage` - Debian / Ubuntu / Mint: `vrec_0.1.0_amd64.deb` - Fedora / RHEL / openSUSE: `vrec-0.1.0-2.x86_64.rpm` - Generic Linux: `vrec-linux-x86_64.tar.gz` files: | artifacts/linux-packages/* - artifacts/windows-package/* + artifacts/windows-packages/* draft: false prerelease: false generate_release_notes: false diff --git a/packaging/windows/vrec-installer.nsi b/packaging/windows/vrec-installer.nsi new file mode 100644 index 0000000..2543704 --- /dev/null +++ b/packaging/windows/vrec-installer.nsi @@ -0,0 +1,48 @@ +!include "MUI2.nsh" +!include "FileFunc.nsh" + +Name "vrec" +OutFile "..\..\dist\vrec-setup.exe" +InstallDir "$LOCALAPPDATA\Programs\vrec" +RequestExecutionLevel user + +!define MUI_ABORTWARNING + +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES + +!define MUI_FINISHPAGE_RUN "$INSTDIR\vrec-ui.exe" +!define MUI_FINISHPAGE_RUN_PARAMETERS "--menu" +!define MUI_FINISHPAGE_RUN_TEXT "Launch vrec Studio Overlay" +!insertmacro MUI_PAGE_FINISH + +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +!insertmacro MUI_LANGUAGE "English" + +Section "vrec" SecMain + SetOutPath "$INSTDIR" + File /r "..\..\dist\bundle\*.*" + + ; Create Start Menu and Desktop shortcuts + CreateDirectory "$SMPROGRAMS\vrec" + CreateShortcut "$SMPROGRAMS\vrec\vrec Studio.lnk" "$INSTDIR\vrec-ui.exe" "--menu" + CreateShortcut "$SMPROGRAMS\vrec\vrec Background Engine.lnk" "$INSTDIR\vrec-daemon.exe" "" + CreateShortcut "$DESKTOP\vrec.lnk" "$INSTDIR\vrec-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" +SectionEnd + +Section "Uninstall" + Delete "$DESKTOP\vrec.lnk" + RMDir /r "$SMPROGRAMS\vrec" + RMDir /r "$INSTDIR" + DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\vrec" +SectionEnd diff --git a/packaging/windows/vrec-standalone.nsi b/packaging/windows/vrec-standalone.nsi new file mode 100644 index 0000000..c798d38 --- /dev/null +++ b/packaging/windows/vrec-standalone.nsi @@ -0,0 +1,22 @@ +!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-ui.rs b/src/bin/vrec-ui.rs index 165d83e..650543e 100644 --- a/src/bin/vrec-ui.rs +++ b/src/bin/vrec-ui.rs @@ -35,16 +35,34 @@ fn ensure_wayland_env() { } } +fn get_daemon_cmd() -> std::process::Command { + if let Ok(mut path) = std::env::current_exe() { + path.pop(); + #[cfg(target_os = "windows")] + let candidate = path.join("vrec-daemon.exe"); + #[cfg(not(target_os = "windows"))] + let candidate = path.join("vrec-daemon"); + + if candidate.exists() { + return std::process::Command::new(candidate); + } + } + #[cfg(target_os = "windows")] + return std::process::Command::new("vrec-daemon.exe"); + #[cfg(not(target_os = "windows"))] + return std::process::Command::new("vrec-daemon"); +} + fn ensure_daemon_running() { if query_status().is_err() { println!("vrec-daemon not running. Auto-launching vrec-daemon..."); - let _ = std::process::Command::new("vrec-daemon") + let _ = get_daemon_cmd() .stdin(std::process::Stdio::null()) .stdout(std::process::Stdio::null()) .stderr(std::process::Stdio::null()) .spawn(); - for _ in 0..15 { - std::thread::sleep(std::time::Duration::from_millis(100)); + for _ in 0..20 { + std::thread::sleep(std::time::Duration::from_millis(150)); if query_status().is_ok() { println!("vrec-daemon successfully connected."); break;