diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2183cf..6f879a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: dotnet-version: '8.0.x' - name: Restore - run: dotnet restore AudioMonitorRouter.sln + run: dotnet restore ScreenSound.sln - name: Build - run: dotnet build AudioMonitorRouter.sln -c Release --no-restore + run: dotnet build ScreenSound.sln -c Release --no-restore diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 811f8bb..405c0cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,7 +65,7 @@ jobs: Write-Host "Building version $version (event=${{ github.event_name }})" - name: Restore - run: dotnet restore AudioMonitorRouter.sln + run: dotnet restore ScreenSound.sln - name: Publish framework-dependent (win-x64) # Framework-dependent: ~6 MB output vs ~85 MB self-contained. The installer @@ -74,7 +74,7 @@ jobs: # DirectWrite factory init — see https://github.com/dotnet/wpf/issues/6792 shell: pwsh run: | - dotnet publish AudioMonitorRouter\AudioMonitorRouter.csproj ` + dotnet publish ScreenSound\ScreenSound.csproj ` -c Release ` -r win-x64 ` --self-contained false ` @@ -86,7 +86,7 @@ jobs: - name: Package portable zip shell: pwsh run: | - $zipName = "AudioMonitorRouter-${{ steps.version.outputs.VERSION }}-portable.zip" + $zipName = "ScreenSound-${{ steps.version.outputs.VERSION }}-portable.zip" Compress-Archive -Path "publish\*" -DestinationPath "publish\$zipName" Write-Host "Created $zipName" @@ -100,13 +100,13 @@ jobs: - name: Upload portable build artifact uses: actions/upload-artifact@v4 with: - name: AudioMonitorRouter-portable - path: publish\AudioMonitorRouter-${{ steps.version.outputs.VERSION }}-portable.zip + name: ScreenSound-portable + path: publish\ScreenSound-${{ steps.version.outputs.VERSION }}-portable.zip - name: Upload installer artifact uses: actions/upload-artifact@v4 with: - name: AudioMonitorRouter-installer + name: ScreenSound-installer path: installer\Output\*.exe - name: Create GitHub Release @@ -134,5 +134,5 @@ jobs: prerelease: false generate_release_notes: true files: | - publish/AudioMonitorRouter-${{ steps.version.outputs.VERSION }}-portable.zip + publish/ScreenSound-${{ steps.version.outputs.VERSION }}-portable.zip installer/Output/*.exe diff --git a/AudioMonitorRouter.sln b/ScreenSound.sln similarity index 83% rename from AudioMonitorRouter.sln rename to ScreenSound.sln index 41d179e..5c3e35c 100644 --- a/AudioMonitorRouter.sln +++ b/ScreenSound.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioMonitorRouter", "AudioMonitorRouter\AudioMonitorRouter.csproj", "{1EC589BF-B74B-4DA1-B37F-FD128C16763D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScreenSound", "ScreenSound\ScreenSound.csproj", "{1EC589BF-B74B-4DA1-B37F-FD128C16763D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/AudioMonitorRouter/App.xaml b/ScreenSound/App.xaml similarity index 90% rename from AudioMonitorRouter/App.xaml rename to ScreenSound/App.xaml index 2cface0..cbd87b7 100644 --- a/AudioMonitorRouter/App.xaml +++ b/ScreenSound/App.xaml @@ -1,8 +1,8 @@ - diff --git a/AudioMonitorRouter/App.xaml.cs b/ScreenSound/App.xaml.cs similarity index 59% rename from AudioMonitorRouter/App.xaml.cs rename to ScreenSound/App.xaml.cs index 4526295..9b49705 100644 --- a/AudioMonitorRouter/App.xaml.cs +++ b/ScreenSound/App.xaml.cs @@ -1,15 +1,56 @@ -using AudioMonitorRouter.Interop; -using AudioMonitorRouter.Views; +using ScreenSound.Interop; +using ScreenSound.Views; using System.Globalization; +using System.Threading; using System.Windows; using System.Windows.Data; -namespace AudioMonitorRouter; +namespace ScreenSound; public partial class App : Application { + // Single-instance guard. Two ScreenSound processes would race on the + // same HKCU Run-at-startup state, both create tray icons, and both + // fight over the per-session audio-policy calls for the same sessions. + // The "Local\" prefix scopes the mutex to the current Windows login + // session, so fast-user-switching still lets each user have their own + // copy while a double-click on the shortcut won't spawn a second one. + private const string SingleInstanceMutexName = @"Local\ScreenSound-SingleInstance"; + private static Mutex? _singleInstanceMutex; + protected override void OnStartup(StartupEventArgs e) { + // Acquire the mutex FIRST, before any side effects (DPI config, + // window creation, tray icon). If another copy is already running + // we want to bail out cleanly with zero partial initialisation. + _singleInstanceMutex = new Mutex(initiallyOwned: false, name: SingleInstanceMutexName); + bool acquired; + try + { + acquired = _singleInstanceMutex.WaitOne(millisecondsTimeout: 0); + } + catch (AbandonedMutexException) + { + // Previous instance crashed without releasing. WaitOne still + // hands us ownership in that case, so treat as success — the + // mutex is now ours. + acquired = true; + } + + if (!acquired) + { + MessageBox.Show( + "ScreenSound is already running — check the system tray.", + "ScreenSound", + MessageBoxButton.OK, + MessageBoxImage.Information); + + _singleInstanceMutex.Dispose(); + _singleInstanceMutex = null; + Shutdown(); + return; + } + // Force PerMonitorV2 DPI awareness before WPF creates any windows. try { @@ -29,6 +70,22 @@ protected override void OnStartup(StartupEventArgs e) } // Otherwise, tray icon is already set up — window stays hidden } + + protected override void OnExit(ExitEventArgs e) + { + // Release + dispose so an immediate relaunch can acquire cleanly. + // Without this, the OS would still reap the mutex on process exit, + // but explicit release avoids a brief race window where a fast + // double-click sees the mutex as still held. + if (_singleInstanceMutex != null) + { + try { _singleInstanceMutex.ReleaseMutex(); } + catch (ApplicationException) { /* Not owned (e.g. after an AbandonedMutexException path) — nothing to release. */ } + _singleInstanceMutex.Dispose(); + _singleInstanceMutex = null; + } + base.OnExit(e); + } } public class ZeroToVisibilityConverter : IValueConverter diff --git a/AudioMonitorRouter/AssemblyInfo.cs b/ScreenSound/AssemblyInfo.cs similarity index 100% rename from AudioMonitorRouter/AssemblyInfo.cs rename to ScreenSound/AssemblyInfo.cs diff --git a/AudioMonitorRouter/Assets/app-icon.png b/ScreenSound/Assets/app-icon.png similarity index 100% rename from AudioMonitorRouter/Assets/app-icon.png rename to ScreenSound/Assets/app-icon.png diff --git a/AudioMonitorRouter/GlobalUsings.cs b/ScreenSound/GlobalUsings.cs similarity index 100% rename from AudioMonitorRouter/GlobalUsings.cs rename to ScreenSound/GlobalUsings.cs diff --git a/AudioMonitorRouter/Interop/AudioPolicyConfig.cs b/ScreenSound/Interop/AudioPolicyConfig.cs similarity index 99% rename from AudioMonitorRouter/Interop/AudioPolicyConfig.cs rename to ScreenSound/Interop/AudioPolicyConfig.cs index 4bdd84a..903a89d 100644 --- a/AudioMonitorRouter/Interop/AudioPolicyConfig.cs +++ b/ScreenSound/Interop/AudioPolicyConfig.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace AudioMonitorRouter.Interop; +namespace ScreenSound.Interop; public enum EDataFlow { diff --git a/AudioMonitorRouter/Interop/NativeMethods.cs b/ScreenSound/Interop/NativeMethods.cs similarity index 99% rename from AudioMonitorRouter/Interop/NativeMethods.cs rename to ScreenSound/Interop/NativeMethods.cs index cca17c6..77bedb7 100644 --- a/AudioMonitorRouter/Interop/NativeMethods.cs +++ b/ScreenSound/Interop/NativeMethods.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace AudioMonitorRouter.Interop; +namespace ScreenSound.Interop; public static class NativeMethods { diff --git a/AudioMonitorRouter/Interop/WinEventHook.cs b/ScreenSound/Interop/WinEventHook.cs similarity index 98% rename from AudioMonitorRouter/Interop/WinEventHook.cs rename to ScreenSound/Interop/WinEventHook.cs index beae61c..81d63a8 100644 --- a/AudioMonitorRouter/Interop/WinEventHook.cs +++ b/ScreenSound/Interop/WinEventHook.cs @@ -1,6 +1,6 @@ using System.Runtime.InteropServices; -namespace AudioMonitorRouter.Interop; +namespace ScreenSound.Interop; /// /// Thin wrapper around SetWinEventHook for observing global window events diff --git a/AudioMonitorRouter/Models/AppSettings.cs b/ScreenSound/Models/AppSettings.cs similarity index 96% rename from AudioMonitorRouter/Models/AppSettings.cs rename to ScreenSound/Models/AppSettings.cs index 9cc62aa..09b7e72 100644 --- a/AudioMonitorRouter/Models/AppSettings.cs +++ b/ScreenSound/Models/AppSettings.cs @@ -1,4 +1,4 @@ -namespace AudioMonitorRouter.Models; +namespace ScreenSound.Models; public class AppSettings { diff --git a/AudioMonitorRouter/Models/AudioDeviceInfo.cs b/ScreenSound/Models/AudioDeviceInfo.cs similarity index 83% rename from AudioMonitorRouter/Models/AudioDeviceInfo.cs rename to ScreenSound/Models/AudioDeviceInfo.cs index c6ac145..2a96e62 100644 --- a/AudioMonitorRouter/Models/AudioDeviceInfo.cs +++ b/ScreenSound/Models/AudioDeviceInfo.cs @@ -1,4 +1,4 @@ -namespace AudioMonitorRouter.Models; +namespace ScreenSound.Models; public class AudioDeviceInfo { diff --git a/AudioMonitorRouter/Models/AudioSessionInfo.cs b/ScreenSound/Models/AudioSessionInfo.cs similarity index 95% rename from AudioMonitorRouter/Models/AudioSessionInfo.cs rename to ScreenSound/Models/AudioSessionInfo.cs index 0ee37a9..b768eee 100644 --- a/AudioMonitorRouter/Models/AudioSessionInfo.cs +++ b/ScreenSound/Models/AudioSessionInfo.cs @@ -1,4 +1,4 @@ -namespace AudioMonitorRouter.Models; +namespace ScreenSound.Models; public class AudioSessionInfo { diff --git a/AudioMonitorRouter/Models/MonitorInfo.cs b/ScreenSound/Models/MonitorInfo.cs similarity index 93% rename from AudioMonitorRouter/Models/MonitorInfo.cs rename to ScreenSound/Models/MonitorInfo.cs index 8965fb7..030c1ba 100644 --- a/AudioMonitorRouter/Models/MonitorInfo.cs +++ b/ScreenSound/Models/MonitorInfo.cs @@ -1,4 +1,4 @@ -namespace AudioMonitorRouter.Models; +namespace ScreenSound.Models; public class MonitorInfo { diff --git a/AudioMonitorRouter/AudioMonitorRouter.csproj b/ScreenSound/ScreenSound.csproj similarity index 82% rename from AudioMonitorRouter/AudioMonitorRouter.csproj rename to ScreenSound/ScreenSound.csproj index d8520fa..90f1364 100644 --- a/AudioMonitorRouter/AudioMonitorRouter.csproj +++ b/ScreenSound/ScreenSound.csproj @@ -14,16 +14,16 @@ WFAC010 - 1.0.0 - 1.0.0.0 - 1.0.0.0 - Audio Monitor Router - Audio Monitor Router + 2.0.0 + 2.0.0.0 + 2.0.0.0 + ScreenSound + ScreenSound twibster twibster - Automatically routes per-app audio to different speakers based on monitor placement on Windows 11. + Sound follows your windows. Per-app audio routing for multi-monitor Windows 11 — each app plays through the speaker paired with the monitor it's on. Copyright (c) 2026 Omar Omran - https://github.com/twibster/AudioMonitorRouter + https://github.com/twibster/ScreenSound git diff --git a/AudioMonitorRouter/Services/AudioDeviceNotifier.cs b/ScreenSound/Services/AudioDeviceNotifier.cs similarity index 99% rename from AudioMonitorRouter/Services/AudioDeviceNotifier.cs rename to ScreenSound/Services/AudioDeviceNotifier.cs index 1280eb1..c70bb44 100644 --- a/AudioMonitorRouter/Services/AudioDeviceNotifier.cs +++ b/ScreenSound/Services/AudioDeviceNotifier.cs @@ -1,7 +1,7 @@ using NAudio.CoreAudioApi; using NAudio.CoreAudioApi.Interfaces; -namespace AudioMonitorRouter.Services; +namespace ScreenSound.Services; /// /// Subscribes to Core Audio endpoint notifications so the UI and routing engine diff --git a/AudioMonitorRouter/Services/AudioDeviceService.cs b/ScreenSound/Services/AudioDeviceService.cs similarity index 96% rename from AudioMonitorRouter/Services/AudioDeviceService.cs rename to ScreenSound/Services/AudioDeviceService.cs index 8920cfd..31d7dfe 100644 --- a/AudioMonitorRouter/Services/AudioDeviceService.cs +++ b/ScreenSound/Services/AudioDeviceService.cs @@ -1,7 +1,7 @@ -using AudioMonitorRouter.Models; +using ScreenSound.Models; using NAudio.CoreAudioApi; -namespace AudioMonitorRouter.Services; +namespace ScreenSound.Services; public class AudioDeviceService : IDisposable { diff --git a/AudioMonitorRouter/Services/AudioRouterService.cs b/ScreenSound/Services/AudioRouterService.cs similarity index 94% rename from AudioMonitorRouter/Services/AudioRouterService.cs rename to ScreenSound/Services/AudioRouterService.cs index 073183e..c708585 100644 --- a/AudioMonitorRouter/Services/AudioRouterService.cs +++ b/ScreenSound/Services/AudioRouterService.cs @@ -1,6 +1,6 @@ -using AudioMonitorRouter.Interop; +using ScreenSound.Interop; -namespace AudioMonitorRouter.Services; +namespace ScreenSound.Services; public class AudioRouterService : IDisposable { diff --git a/AudioMonitorRouter/Services/AudioSessionNotifier.cs b/ScreenSound/Services/AudioSessionNotifier.cs similarity index 98% rename from AudioMonitorRouter/Services/AudioSessionNotifier.cs rename to ScreenSound/Services/AudioSessionNotifier.cs index d202e94..3e119fe 100644 --- a/AudioMonitorRouter/Services/AudioSessionNotifier.cs +++ b/ScreenSound/Services/AudioSessionNotifier.cs @@ -1,6 +1,6 @@ using NAudio.CoreAudioApi; -namespace AudioMonitorRouter.Services; +namespace ScreenSound.Services; /// /// Subscribes to across all diff --git a/AudioMonitorRouter/Services/AudioSessionService.cs b/ScreenSound/Services/AudioSessionService.cs similarity index 96% rename from AudioMonitorRouter/Services/AudioSessionService.cs rename to ScreenSound/Services/AudioSessionService.cs index bdda480..089ede4 100644 --- a/AudioMonitorRouter/Services/AudioSessionService.cs +++ b/ScreenSound/Services/AudioSessionService.cs @@ -1,8 +1,8 @@ -using AudioMonitorRouter.Models; +using ScreenSound.Models; using NAudio.CoreAudioApi; using System.Diagnostics; -namespace AudioMonitorRouter.Services; +namespace ScreenSound.Services; public class AudioSessionService { diff --git a/AudioMonitorRouter/Services/MonitorService.cs b/ScreenSound/Services/MonitorService.cs similarity index 98% rename from AudioMonitorRouter/Services/MonitorService.cs rename to ScreenSound/Services/MonitorService.cs index 5c1cdce..017e9b7 100644 --- a/AudioMonitorRouter/Services/MonitorService.cs +++ b/ScreenSound/Services/MonitorService.cs @@ -1,9 +1,9 @@ -using AudioMonitorRouter.Interop; -using AudioMonitorRouter.Models; +using ScreenSound.Interop; +using ScreenSound.Models; using System.Diagnostics; using System.Runtime.InteropServices; -namespace AudioMonitorRouter.Services; +namespace ScreenSound.Services; public class MonitorService { diff --git a/AudioMonitorRouter/Services/RoutingEngine.cs b/ScreenSound/Services/RoutingEngine.cs similarity index 99% rename from AudioMonitorRouter/Services/RoutingEngine.cs rename to ScreenSound/Services/RoutingEngine.cs index ea6ad6c..02eab86 100644 --- a/AudioMonitorRouter/Services/RoutingEngine.cs +++ b/ScreenSound/Services/RoutingEngine.cs @@ -1,9 +1,9 @@ -using AudioMonitorRouter.Interop; -using AudioMonitorRouter.Models; +using ScreenSound.Interop; +using ScreenSound.Models; using Microsoft.Win32; using System.Collections.Concurrent; -namespace AudioMonitorRouter.Services; +namespace ScreenSound.Services; /// /// Drives audio routing in response to signals: diff --git a/AudioMonitorRouter/Services/SettingsService.cs b/ScreenSound/Services/SettingsService.cs similarity index 92% rename from AudioMonitorRouter/Services/SettingsService.cs rename to ScreenSound/Services/SettingsService.cs index d7f431e..aafdb51 100644 --- a/AudioMonitorRouter/Services/SettingsService.cs +++ b/ScreenSound/Services/SettingsService.cs @@ -1,14 +1,14 @@ -using AudioMonitorRouter.Models; +using ScreenSound.Models; using System.IO; using System.Text.Json; -namespace AudioMonitorRouter.Services; +namespace ScreenSound.Services; public class SettingsService { private static readonly string SettingsDir = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "AudioMonitorRouter"); + "ScreenSound"); private static readonly string SettingsFile = Path.Combine(SettingsDir, "settings.json"); diff --git a/AudioMonitorRouter/Services/UpdateService.cs b/ScreenSound/Services/UpdateService.cs similarity index 95% rename from AudioMonitorRouter/Services/UpdateService.cs rename to ScreenSound/Services/UpdateService.cs index 8cce53c..1e81208 100644 --- a/AudioMonitorRouter/Services/UpdateService.cs +++ b/ScreenSound/Services/UpdateService.cs @@ -4,7 +4,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace AudioMonitorRouter.Services; +namespace ScreenSound.Services; /// /// Outcome of an update probe. The About page binds its status text to one of @@ -41,7 +41,7 @@ public class UpdateService // Public, unauthenticated endpoint — rate-limited to 60 requests/hour per IP, // which is plenty for a user-initiated "check for updates" button. private const string LatestReleaseApi = - "https://api.github.com/repos/twibster/AudioMonitorRouter/releases/latest"; + "https://api.github.com/repos/twibster/ScreenSound/releases/latest"; // GitHub requires a User-Agent on every request; the product name is also // useful in their server logs if we ever need to correlate a rate-limit bug @@ -53,8 +53,8 @@ public class UpdateService private static ProductInfoHeaderValue BuildUserAgent() { - try { return new ProductInfoHeaderValue("AudioMonitorRouter", GetInformationalVersion()); } - catch { return new ProductInfoHeaderValue("AudioMonitorRouter", "1.0"); } + try { return new ProductInfoHeaderValue("ScreenSound", GetInformationalVersion()); } + catch { return new ProductInfoHeaderValue("ScreenSound", "1.0"); } } /// @@ -118,7 +118,7 @@ public async Task CheckForUpdateAsync(CancellationToken ct = // legally contain characters (/, #, spaces) that would otherwise // break the path segment. string releaseUrl = release.HtmlUrl ?? - $"https://github.com/twibster/AudioMonitorRouter/releases/tag/{Uri.EscapeDataString(release.TagName)}"; + $"https://github.com/twibster/ScreenSound/releases/tag/{Uri.EscapeDataString(release.TagName)}"; return CompareSemVer(latest, current) > 0 ? new UpdateCheckResult.UpdateAvailable(current, latest, releaseUrl) diff --git a/AudioMonitorRouter/ViewModels/MainWindowViewModel.cs b/ScreenSound/ViewModels/MainWindowViewModel.cs similarity index 99% rename from AudioMonitorRouter/ViewModels/MainWindowViewModel.cs rename to ScreenSound/ViewModels/MainWindowViewModel.cs index b4bf236..3f85942 100644 --- a/AudioMonitorRouter/ViewModels/MainWindowViewModel.cs +++ b/ScreenSound/ViewModels/MainWindowViewModel.cs @@ -1,5 +1,5 @@ -using AudioMonitorRouter.Models; -using AudioMonitorRouter.Services; +using ScreenSound.Models; +using ScreenSound.Services; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.Win32; @@ -11,7 +11,7 @@ using System.Windows.Media.Imaging; using System.Windows.Threading; -namespace AudioMonitorRouter.ViewModels; +namespace ScreenSound.ViewModels; public partial class MonitorMappingViewModel : ObservableObject { @@ -135,7 +135,7 @@ public partial class MainWindowViewModel : ObservableObject, IDisposable private static readonly TimeSpan DeviceRefreshDebounce = TimeSpan.FromMilliseconds(300); private const string AutoStartRegistryKey = @"Software\Microsoft\Windows\CurrentVersion\Run"; - private const string AppRegistryName = "AudioMonitorRouter"; + private const string AppRegistryName = "ScreenSound"; private readonly Dictionary _iconCache = new(); diff --git a/AudioMonitorRouter/Views/MainWindow.xaml b/ScreenSound/Views/MainWindow.xaml similarity index 99% rename from AudioMonitorRouter/Views/MainWindow.xaml rename to ScreenSound/Views/MainWindow.xaml index bedd91a..4e8cbfe 100644 --- a/AudioMonitorRouter/Views/MainWindow.xaml +++ b/ScreenSound/Views/MainWindow.xaml @@ -1,9 +1,9 @@ - @@ -516,7 +516,7 @@ VerticalAlignment="Center" Margin="0,0,16,0" RenderOptions.BitmapScalingMode="HighQuality"/> - + diff --git a/design/tools/IconBuilder/Program.cs b/design/tools/IconBuilder/Program.cs index d33f2f9..7c621cf 100644 --- a/design/tools/IconBuilder/Program.cs +++ b/design/tools/IconBuilder/Program.cs @@ -3,11 +3,11 @@ // // dotnet run --project design/tools/IconBuilder -- \ // design/app-icon.svg \ -// AudioMonitorRouter/app.ico +// ScreenSound/app.ico // // dotnet run --project design/tools/IconBuilder -- \ // design/app-icon.svg \ -// AudioMonitorRouter/Assets/app-icon.png +// ScreenSound/Assets/app-icon.png // // Why both formats: // - .ico is the Windows shell icon (tray, taskbar, file explorer, installer). diff --git a/installer/installer.iss b/installer/installer.iss index 018926d..b9a4285 100644 --- a/installer/installer.iss +++ b/installer/installer.iss @@ -1,4 +1,4 @@ -; Inno Setup script for Audio Monitor Router +; Inno Setup script for ScreenSound ; Builds a Windows installer that installs to Program Files, creates Start Menu ; shortcuts, registers an uninstaller, and launches the app after install. ; @@ -6,15 +6,15 @@ ; downloads + installs the .NET 8 Desktop Runtime on-demand if missing, ; keeping our installer ~10x smaller than a self-contained build. -#define MyAppName "Audio Monitor Router" -#define MyAppExeName "AudioMonitorRouter.exe" +#define MyAppName "ScreenSound" +#define MyAppExeName "ScreenSound.exe" #define MyAppPublisher "twibster" -#define MyAppURL "https://github.com/twibster/AudioMonitorRouter" +#define MyAppURL "https://github.com/twibster/ScreenSound" ; Version comes from the APP_VERSION env var (set by CI). Fallback for local runs. #define MyAppVersion GetEnv("APP_VERSION") #if MyAppVersion == "" - #define MyAppVersion "1.0.0" + #define MyAppVersion "2.0.0" #endif ; Pinned .NET 8 Desktop Runtime download. Bump this on major .NET 8 patch releases. @@ -23,9 +23,13 @@ #define DotNet8RuntimeUrl "https://builds.dotnet.microsoft.com/dotnet/Runtime/8.0.15/windowsdesktop-runtime-8.0.15-win-x64.exe" [Setup] -; AppId is a GUID that uniquely identifies the app for uninstall. NEVER change this -; once a release has shipped or upgrades will install side-by-side instead of replacing. -AppId={{F4B8A24A-3C7E-4D88-9F1C-B1D0A8E3E921} +; AppId is a GUID that uniquely identifies the app in Windows' uninstall registry. +; Regenerated for the ScreenSound rebrand (v2.0.0) so the rebranded product gets +; its own identity in Add/Remove Programs rather than silently upgrading an +; "Audio Monitor Router" v1 install. Do NOT change this again once v2 has +; shipped — changing it would cause future upgrades to install side-by-side +; instead of replacing. +AppId={{3BBBE2CE-314A-48FE-85F7-BD0DD3762B6F} AppName={#MyAppName} AppVersion={#MyAppVersion} AppVerName={#MyAppName} {#MyAppVersion} @@ -50,11 +54,11 @@ PrivilegesRequired=admin PrivilegesRequiredOverridesAllowed=dialog OutputDir=Output -OutputBaseFilename=AudioMonitorRouter-Setup-{#MyAppVersion} +OutputBaseFilename=ScreenSound-Setup-{#MyAppVersion} Compression=lzma2/max SolidCompression=yes WizardStyle=modern -SetupIconFile=..\AudioMonitorRouter\app.ico +SetupIconFile=..\ScreenSound\app.ico [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" @@ -73,7 +77,7 @@ Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: de [Registry] ; Opt-in auto-start via Run key. App's own "Run at startup" setting can override this later. -Root: HKCU; Subkey: "Software\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; ValueName: "AudioMonitorRouter"; ValueData: """{app}\{#MyAppExeName}"""; Flags: uninsdeletevalue; Tasks: startupicon +Root: HKCU; Subkey: "Software\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; ValueName: "ScreenSound"; ValueData: """{app}\{#MyAppExeName}"""; Flags: uninsdeletevalue; Tasks: startupicon [Run] ; Silent-install the .NET 8 Desktop Runtime if we had to download it. @@ -98,7 +102,7 @@ Filename: "{cmd}"; Parameters: "/C taskkill /F /IM {#MyAppExeName}"; Flags: runh [UninstallDelete] ; Remove the per-user settings folder on uninstall -Type: filesandordirs; Name: "{userappdata}\AudioMonitorRouter" +Type: filesandordirs; Name: "{userappdata}\ScreenSound" [Code] var