From 56417eb7c395d178437738b527cff913c4154e2d Mon Sep 17 00:00:00 2001 From: Ednunp <29843396+Ednunp@users.noreply.github.com> Date: Sat, 13 Jun 2026 06:53:36 +0100 Subject: [PATCH] Cues: send/receive checkboxes' own cue sounds take priority over the generic checkbox sound The Send/receive checkboxes have dedicated cue sounds (send/receive turned on/off) AND would otherwise also fire the generic checkbox tick/untick. AccessibleCheckBox gains a SuppressCheckSound gate; the send/receive checkboxes set it so that when their dedicated cue is on, only that cue plays. When the dedicated cue is "(none)", the gate returns false and the generic checkbox sound plays as normal - so the checkbox sound never overrides the purpose-built send/receive sounds. Co-Authored-By: Claude Opus 4.8 --- src/RemSound.App/AccessibleCheckBox.cs | 13 +++++++++++-- src/RemSound.App/MainForm.cs | 5 +++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/RemSound.App/AccessibleCheckBox.cs b/src/RemSound.App/AccessibleCheckBox.cs index a6ea60c..ba5a7a1 100644 --- a/src/RemSound.App/AccessibleCheckBox.cs +++ b/src/RemSound.App/AccessibleCheckBox.cs @@ -51,6 +51,14 @@ internal sealed class AccessibleCheckBox : CheckBox [DllImport("user32.dll")] private static extern void NotifyWinEvent(uint eventMin, nint hwnd, int idObject, int idChild); + /// Optional gate, called with the new Checked state just before the generic checkbox + /// tick/untick sound plays; return true to suppress it. The send/receive checkboxes set this so + /// that when their OWN dedicated cue (send/receive turned on/off) is enabled, only that cue + /// plays - the generic checkbox sound doesn't double up on top of it. When their dedicated cue + /// is set to "(none)", this returns false and the generic checkbox sound plays as normal. + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public Func? SuppressCheckSound { get; set; } + protected override void OnCheckedChanged(EventArgs e) { base.OnCheckedChanged(e); @@ -61,8 +69,9 @@ internal sealed class AccessibleCheckBox : CheckBox { NotifyWinEvent(EVENT_OBJECT_FOCUS, Handle, OBJID_CLIENT, CHILDID_SELF); // Audible tick/untick feedback. Gated on Focused so it fires for a genuine user toggle - // (click or spacebar) but stays silent for the bulk programmatic checking on profile load. - CheckSoundService.Play(Checked); + // (click or spacebar) but stays silent for the bulk programmatic checking on profile + // load - and skipped when a control has its own dedicated cue (send/receive). + if (SuppressCheckSound?.Invoke(Checked) != true) CheckSoundService.Play(Checked); } } } diff --git a/src/RemSound.App/MainForm.cs b/src/RemSound.App/MainForm.cs index 299d3f1..7682884 100644 --- a/src/RemSound.App/MainForm.cs +++ b/src/RemSound.App/MainForm.cs @@ -1009,6 +1009,11 @@ public sealed class MainForm : Form // --- Wire main-form events --- receiveAudioCheckbox.CheckedChanged += (_, _) => OnStreamingCheckboxChanged(receiveAudioCheckbox); sendMyAudioCheckbox.CheckedChanged += (_, _) => OnStreamingCheckboxChanged(sendMyAudioCheckbox); + // Send/receive have their own dedicated cue sounds (send/receive turned on/off). When that + // dedicated cue is on, only it plays - suppress the generic checkbox tick/untick on these two. + // When the dedicated cue is "(none)", these return false and the checkbox sound plays as normal. + sendMyAudioCheckbox.SuppressCheckSound = on => on ? AppConfig.Load().EnableSendOnCue : AppConfig.Load().EnableSendOffCue; + receiveAudioCheckbox.SuppressCheckSound = on => on ? AppConfig.Load().EnableReceiveOnCue : AppConfig.Load().EnableReceiveOffCue; volumeBar.Scroll += (_, _) => { receiver.Volume = volumeBar.Value / 100f; MarkProfileDirty(); }; WireCheckedListAccessibility(receiveOutputDevicesList, receiveOutputDevicesStatusLabel, "receive output device"); receiveOutputDevicesList.ItemCheck += (_, e) =>