Skip to content

Rebrand to ScreenSound (v2.0.0)#9

Merged
twibster merged 3 commits into
mainfrom
rebrand/screensound
Apr 15, 2026
Merged

Rebrand to ScreenSound (v2.0.0)#9
twibster merged 3 commits into
mainfrom
rebrand/screensound

Conversation

@twibster
Copy link
Copy Markdown
Owner

@twibster twibster commented Apr 15, 2026

Summary

Full rebrand from Audio Monitor RouterScreenSound. Every surface flipped: code, XAML, assembly metadata, installer, CI workflows, design assets. Version bumped 1.3.0 → 2.0.0 to signal the break. Fresh installer AppId so the rebrand gets its own Add/Remove Programs identity. Opportunistic single-instance mutex added during the churn.

Split into three commits for review sanity (each is independently buildable):

  1. Structural renames (f64f9c5) — git mv of solution/project folder/csproj so history follows, then a sed pass replacing the CamelCase AudioMonitorRouter token across every tracked text file. Catches namespaces, usings, XAML x:Class + xmlns, UpdateService API URL + User-Agent, RepositoryUrl, app.manifest assembly identity, SettingsService AppData folder literal, MainWindowViewModel Run-key constant, installer MyAppExeName/MyAppURL/OutputBaseFilename/SetupIconFile/ValueName/UninstallDelete, CI workflow sln + artifact names. 67 replacements across 30 files.
  2. User-facing strings + metadata + v2.0.0 (073e554) — flips the 8 remaining spaced-form Audio Monitor Router strings (window titles ×2, About page header, tray tooltip, <Product>, <AssemblyTitle>, installer MyAppName, installer header comment). Version bump to 2.0.0(.0) in csproj + app.manifest + installer fallback. New AppId GUID (3BBBE2CE-314A-48FE-85F7-BD0DD3762B6F) and rewritten <Description> to fit the new brand ("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.").
  3. Single-instance mutex (c85ed9b) — Local\ScreenSound-SingleInstance acquired in App.OnStartup before any side effects, released in OnExit. Handles AbandonedMutexException (previous crash) as success, shows a "check the system tray" message on the losing path. Not strictly part of the rebrand but the rebrand churn is the natural home for this fix.

Pre-flight that already happened

  • GitHub repo renamed twibster/AudioMonitorRoutertwibster/ScreenSound via gh repo rename (GitHub auto-redirects the old URL).
  • Local remote updated to the new SSH URL.
  • Old F4B8A24A-... AppId grep confirms zero remaining references outside of the comment explaining why we regenerated it.
  • Every tracked AudioMonitorRouter/Audio Monitor Router hit is gone (verified via git grep).

Why the AppId changed (differs from original plan)

Original plan was to keep the AppId for in-place upgrade. Changed course after confirming no v1 installs exist in the wild other than the maintainer's own dev box (already uninstalled). Fresh AppId + no settings migration gives the v2 product a clean slate. If a v1 install somehow surfaces later, the user will see it sitting next to v2 in Add/Remove Programs and can uninstall it manually — simpler than maintaining migration code for an audience of none.

Version bump 1.3.0 → 2.0.0 (not 1.0.0 → 2.0.0)

The csproj <Version> was stale at 1.0.0 but the actual release history (tag v1.3.0 from earlier today) is the real predecessor. Fixed in this PR so the next release metadata matches git truth.

Test plan

  • CI passes (rebuilt sln/csproj paths in ci.yml should resolve)
  • dotnet build ScreenSound/ScreenSound.csproj -c Release clean locally (done: 0 warnings, 0 errors)
  • Run the app — window title, About page header, tray tooltip all read "ScreenSound"
  • %APPDATA%\ScreenSound\settings.json is where settings land (not the old path)
  • "Check for updates" in About page hits api.github.com/repos/twibster/ScreenSound/releases/latest
  • Double-click the shortcut while the app is running — mutex kicks in, "already running" message appears, no second process
  • After merge: tag v2.0.0, auto-release workflow produces ScreenSound-Setup-2.0.0.exe and ScreenSound-2.0.0-portable.zip

Summary by CodeRabbit

Release Notes

  • New Features

    • Application now enforces single-instance mode—preventing multiple instances from running simultaneously.
  • Chores

    • Rebranded application from "Audio Monitor Router" to "ScreenSound."
    • Version bumped to 2.0.0.
    • Updated build pipelines and installer configuration to reflect the new branding.

Mechanical pass 1 of the rebrand. This commit covers the CamelCase form
of the name only; user-facing "Audio Monitor Router" strings, assembly
metadata, version bump, installer defines, single-instance mutex, and
description rewrite all follow in subsequent commits.

- git mv the solution, project folder, and .csproj so history follows
- Blanket sed-replace across .cs/.xaml/.csproj/.sln/.manifest/.iss/.yml/
  .html: "AudioMonitorRouter" -> "ScreenSound"
- This catches: all C# namespaces and usings, XAML x:Class + xmlns:
  local/vm, IconBuilder RootNamespace, app.manifest assembly identity
  name, UpdateService API URL + User-Agent product token + fallback
  URL repo path, XAML NavigateUri to GitHub, csproj RepositoryUrl,
  installer MyAppExeName + MyAppURL + OutputBaseFilename + SetupIconFile
  + Run-key ValueName + UninstallDelete path, CI/release workflow .sln
  and artifact names, design/preview.html and IconBuilder comments,
  SettingsService AppData folder literal, and MainWindowViewModel
  AppRegistryName constant.

Release build: 0 warnings, 0 errors. The remaining "Audio Monitor
Router" spaced-form hits (window titles x2, About page header, tray
tooltip, <Product>, <AssemblyTitle>, installer MyAppName, installer
comment header) are intentionally left for commit 2.
Mechanical pass 2 of the rebrand. This commit flips the 8 remaining
"Audio Monitor Router" spaced-form strings to "ScreenSound", bumps the
version from 1.0.0 (which was stale anyway — the real last release was
v1.3.0) straight to 2.0.0 to signal the rebrand as a major release,
and gives the installer a fresh AppId GUID so Windows treats the
rebranded app as its own identity in Add/Remove Programs.

- Spaced-form sed pass across .cs/.xaml/.csproj/.iss catches: window
  titles (MainWindow.xaml x2), About page header, tray tooltip,
  csproj <Product>/<AssemblyTitle>, installer MyAppName and comment
  header, wrapping up the CamelCase-vs-spaced split from commit 1.
- csproj <Version>/<AssemblyVersion>/<FileVersion> bumped to 2.0.0(.0)
- csproj <Description> rewritten to fit the ScreenSound brand: "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."
- app.manifest assembly identity version bumped to 2.0.0.0
- installer.iss AppId regenerated (3BBBE2CE-314A-48FE-85F7-BD0DD3762B6F).
  Updated the surrounding comment so the "NEVER change this" warning
  reflects that we just changed it — the v2 GUID is the new forever.
- installer.iss MyAppVersion fallback also bumped to 2.0.0 for local
  builds without APP_VERSION env var.

Release build: 0 warnings, 0 errors. Remaining work on this branch:
add single-instance mutex (commit 3), then verify and PR.
ScreenSound lives in the system tray and configures Windows-wide audio
routing state (per-app PolicyConfig calls, HKCU Run key for startup).
Two copies running would race on the Run-key writes, both try to own
the tray icon, and double-route the same audio sessions. Nothing in
the app was guarding against that — a user double-clicking the desktop
shortcut or the installer's post-install launch line while the app was
already in the tray would happily start a second process.

The guard is a named mutex with a "Local\" prefix. Local scope means
fast-user-switching still lets each Windows user have their own copy
(each login session has its own Local namespace), while blocking
accidental double-launches within one session.

Details worth calling out in code:
- Acquire the mutex before any side effects (DPI awareness config,
  window creation, tray setup). Nothing half-initialised.
- AbandonedMutexException handled: if a previous instance crashed
  without releasing, WaitOne still hands us ownership — we treat the
  exception as success, not failure.
- Explicit ReleaseMutex + Dispose in OnExit. The OS would clean it up
  on process exit anyway, but explicit release closes a brief race
  window where a fast relaunch sees the mutex as still held.
- Message on the losing path points the user at the tray — the
  primary failure mode is "I double-clicked the shortcut and nothing
  happened," and the app is already sitting in the tray a click away.

Release build: 0 warnings, 0 errors.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 15, 2026

📝 Walkthrough

Walkthrough

The project undergoes comprehensive rebranding from "AudioMonitorRouter" to "ScreenSound," including namespace refactoring across all source files, version bump to 2.0.0, updated GitHub repository references, and addition of single-instance mutex enforcement in the application startup. CI/CD pipelines, project configuration, and UI strings are updated accordingly.

Changes

Cohort / File(s) Summary
Namespace Refactoring
ScreenSound/Interop/*, ScreenSound/Models/*, ScreenSound/Services/*, ScreenSound/ViewModels/*, ScreenSound/Views/*
All public type namespaces changed from AudioMonitorRouter.* to ScreenSound.* across interop, model, service, viewmodel, and view layers without functional logic changes.
Application Startup & Single-Instance Enforcement
ScreenSound/App.xaml.cs
Added mutex-based single-instance mechanism in OnStartup to prevent multiple application instances; acquiring named mutex Local\ScreenSound-SingleInstance before initialization, showing informational dialog and shutting down if acquisition fails. Added OnExit override to properly release and dispose the mutex.
XAML and UI Branding
ScreenSound/App.xaml, ScreenSound/Views/MainWindow.xaml, ScreenSound/Views/MainWindow.xaml.cs, design/preview.html
Updated XAML class mappings and namespace references from AudioMonitorRouter to ScreenSound; changed window title, tray icon label, and design preview text from "Audio Monitor Router" to "ScreenSound"; updated GitHub hyperlinks to reference new repository.
Project & Assembly Configuration
ScreenSound/ScreenSound.csproj, ScreenSound.sln, ScreenSound/app.manifest, design/tools/IconBuilder/IconBuilder.csproj
Version bumped from 1.0.0 to 2.0.0; Product and AssemblyTitle renamed; RepositoryUrl updated to new GitHub repository; solution and manifest identity updated; tool root namespace adjusted.
Settings & Registry
ScreenSound/Services/SettingsService.cs, ScreenSound/ViewModels/MainWindowViewModel.cs
Application settings directory renamed from "AudioMonitorRouter" to "ScreenSound" in user appdata path; Windows AutoStart registry value name changed to "ScreenSound".
External Service Integration
ScreenSound/Services/UpdateService.cs
GitHub API endpoints and release URLs switched from twibster/AudioMonitorRouter to twibster/ScreenSound repository; User-Agent product name updated.
CI/CD Pipelines
.github/workflows/ci.yml, .github/workflows/release.yml
Build and release workflows updated to target ScreenSound.sln and ScreenSound\ScreenSound.csproj; artifact naming changed from AudioMonitorRouter-* to ScreenSound-*.
Installer Configuration
installer/installer.iss, design/tools/IconBuilder/Program.cs
Installer branding updated; AppId GUID regenerated for distinct product identity; version fallback bumped to 2.0.0; uninstall cleanup changed to remove ScreenSound settings directory; icon output paths adjusted.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The project hops to a brand new name,
From AudioMonitorRouter to ScreenSound's fame!
With mutex locks preventing double starts,
And GitHub links fresh from the heart. 🎵
Version two emerges, rebranded with care,
A rabbit approves this update everywhere!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: a rebrand from AudioMonitorRouter to ScreenSound with a version bump to 2.0.0.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rebrand/screensound

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
ScreenSound/App.xaml.cs (1)

82-83: Minor: Comment is slightly misleading.

The comment states "Not owned (e.g. after an AbandonedMutexException path)" but AbandonedMutexException actually grants ownership, so ReleaseMutex() would succeed in that case. The catch is still appropriate as a defensive measure for unexpected edge cases, but the example in the comment is incorrect.

Suggested comment fix
-            try { _singleInstanceMutex.ReleaseMutex(); }
-            catch (ApplicationException) { /* Not owned (e.g. after an AbandonedMutexException path) — nothing to release. */ }
+            try { _singleInstanceMutex.ReleaseMutex(); }
+            catch (ApplicationException) { /* Not owned — nothing to release. */ }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ScreenSound/App.xaml.cs` around lines 82 - 83, The comment next to the call
to _singleInstanceMutex.ReleaseMutex() is misleading about
AbandonedMutexException; update the comment to accurately explain that
AbandonedMutexException actually grants ownership (so ReleaseMutex would
normally succeed) and that the catch is a defensive fallback for unexpected
cases (e.g., mutex not owned or already disposed), keeping the existing
try/catch around _singleInstanceMutex.ReleaseMutex() intact; reference the
_singleInstanceMutex field and the ReleaseMutex() call when updating the
comment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ScreenSound/Services/SettingsService.cs`:
- Around line 9-13: Load currently only looks at SettingsDir/SettingsFile so
existing users under the old path (%AppData%\AudioMonitorRouter\settings.json)
will be ignored; update the SettingsService.Load() (and any save/initialization)
to check for the legacy path (e.g., Path.Combine(Environment.GetFolderPath(...),
"AudioMonitorRouter", "settings.json"), detect if the legacy file exists, create
the new SettingsDir if needed, atomically move/rename the legacy file to
SettingsFile (or copy and delete on failure) and log any errors, ensuring
subsequent calls use SettingsFile; also ensure Save() writes to the new
SettingsFile so future launches use the new location.

In `@ScreenSound/ViewModels/MainWindowViewModel.cs`:
- Line 138: The autostart rename left legacy registry entries behind; update
ApplyAutoStart (and any startup-related methods) to handle migration/cleanup by
checking for and deleting the old Run value name in addition to setting/deleting
the new AppRegistryName ("ScreenSound"), and when enabling autostart ensure any
legacy key is removed or migrated to the new name so toggling autostart off
truly stops an upgraded install from launching; reference the AppRegistryName
constant and the ApplyAutoStart method (and any autostart enable/disable
callers) to implement the check/delete of the previous registry value name.

---

Nitpick comments:
In `@ScreenSound/App.xaml.cs`:
- Around line 82-83: The comment next to the call to
_singleInstanceMutex.ReleaseMutex() is misleading about AbandonedMutexException;
update the comment to accurately explain that AbandonedMutexException actually
grants ownership (so ReleaseMutex would normally succeed) and that the catch is
a defensive fallback for unexpected cases (e.g., mutex not owned or already
disposed), keeping the existing try/catch around
_singleInstanceMutex.ReleaseMutex() intact; reference the _singleInstanceMutex
field and the ReleaseMutex() call when updating the comment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ca9be1c0-224c-42c5-8ffa-2e01aa3b3101

📥 Commits

Reviewing files that changed from the base of the PR and between 8487afa and c85ed9b.

⛔ Files ignored due to path filters (2)
  • ScreenSound/Assets/app-icon.png is excluded by !**/*.png
  • ScreenSound/app.ico is excluded by !**/*.ico
📒 Files selected for processing (32)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • ScreenSound.sln
  • ScreenSound/App.xaml
  • ScreenSound/App.xaml.cs
  • ScreenSound/AssemblyInfo.cs
  • ScreenSound/GlobalUsings.cs
  • ScreenSound/Interop/AudioPolicyConfig.cs
  • ScreenSound/Interop/NativeMethods.cs
  • ScreenSound/Interop/WinEventHook.cs
  • ScreenSound/Models/AppSettings.cs
  • ScreenSound/Models/AudioDeviceInfo.cs
  • ScreenSound/Models/AudioSessionInfo.cs
  • ScreenSound/Models/MonitorInfo.cs
  • ScreenSound/ScreenSound.csproj
  • ScreenSound/Services/AudioDeviceNotifier.cs
  • ScreenSound/Services/AudioDeviceService.cs
  • ScreenSound/Services/AudioRouterService.cs
  • ScreenSound/Services/AudioSessionNotifier.cs
  • ScreenSound/Services/AudioSessionService.cs
  • ScreenSound/Services/MonitorService.cs
  • ScreenSound/Services/RoutingEngine.cs
  • ScreenSound/Services/SettingsService.cs
  • ScreenSound/Services/UpdateService.cs
  • ScreenSound/ViewModels/MainWindowViewModel.cs
  • ScreenSound/Views/MainWindow.xaml
  • ScreenSound/Views/MainWindow.xaml.cs
  • ScreenSound/app.manifest
  • design/preview.html
  • design/tools/IconBuilder/IconBuilder.csproj
  • design/tools/IconBuilder/Program.cs
  • installer/installer.iss

Comment thread ScreenSound/Services/SettingsService.cs
Comment thread ScreenSound/ViewModels/MainWindowViewModel.cs
@twibster twibster added the release:major X.0.0 release - breaking change label Apr 15, 2026
@twibster twibster self-assigned this Apr 15, 2026
@twibster twibster merged commit 1a89b45 into main Apr 15, 2026
2 checks passed
@github-actions
Copy link
Copy Markdown

Released as v2.0.0.

@twibster twibster deleted the rebrand/screensound branch May 5, 2026 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:major X.0.0 release - breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant