Bump to v3.1.2: tray icon re-stamps on state change, recording shows as a flag
- Tray icon now re-registers itself (hide+re-show) whenever the meaningful
state changes — peer connect/drop, send/receive toggle, recording
start/stop — so the name a screen reader announces stays in step with
the live state. Fixes the persistent "no peers" then "1 peer" double
announcement that the old "show window then minimise again" trick used
to clear by hand. Same root cause as the v3.1.1 stuck-tooltip fix, just
exposed when the state changes a moment after the icon appears.
- Recording shows as a plain "recording" flag in the tray rather than a
live timer. A ticking timer would have either flickered the icon once a
second or left a screen reader announcing a stale time next to the live
one. Removed the now-dead FormatRecordingElapsed helper.
- Bundles the earlier Win7 updater fix (6cbde0d): a failed secure
connection is no longer mislabelled as "you're up to date".
- About box, RELEASE_NOTES.md, readme.html and MANUAL.md updated to match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
6cbde0da12
commit
baf50baf73
@@ -188,11 +188,11 @@ Tab| What it's for
|
|||||||
|
|
||||||
When RemSound is **minimised to the tray** (via **File → Minimise to tray**, the “Show or hide window” global hotkey, or by starting minimised on launch), the main window hides and an icon appears in your Windows system tray (the small icons cluster next to the clock).
|
When RemSound is **minimised to the tray** (via **File → Minimise to tray**, the “Show or hide window” global hotkey, or by starting minimised on launch), the main window hides and an icon appears in your Windows system tray (the small icons cluster next to the clock).
|
||||||
|
|
||||||
**Hovering over the tray icon** shows a short summary of what RemSound is doing right now — the number of healthy peers, whether you're sending or receiving and in which mode (WASAPI, ASIO, or both), and how long any current recording has been running. The summary refreshes every second. Examples:
|
**Hovering over the tray icon** shows a short summary of what RemSound is doing right now — the number of healthy peers, whether you're sending or receiving and in which mode (WASAPI, ASIO, or both), and whether a recording is running. The summary keeps itself up to date as things change. It tells you a recording is in progress, but not its exact length — for that, glance at the main window. Examples:
|
||||||
|
|
||||||
* _RemSound — not connected_
|
* _RemSound — not connected_
|
||||||
* _RemSound — 2 peers, sending (WASAPI), receiving (WASAPI)_
|
* _RemSound — 2 peers, sending (WASAPI), receiving (WASAPI)_
|
||||||
* _RemSound — recording for 5:23, 1 peer, sending (WASAPI + ASIO), receiving (WASAPI + ASIO)_
|
* _RemSound — recording, 1 peer, sending (WASAPI + ASIO), receiving (WASAPI + ASIO)_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+20
-12
@@ -1,32 +1,40 @@
|
|||||||
# RemSound v3.1.1
|
# RemSound v3.1.2
|
||||||
|
|
||||||
Hot-fix for one small but annoying bug introduced in v3.1.
|
A small accessibility fix for the system tray icon, plus a clearer "check for updates" message for Windows 7 users. Minor update — safe to take, nothing else changes.
|
||||||
|
|
||||||
## What was happening
|
## The tray icon's double announcement (screen reader users)
|
||||||
|
|
||||||
If the v3.1 auto-update fired while RemSound was set to start minimised to the tray, the tray icon's hover tooltip could get stuck saying **"RemSound — starting up"** indefinitely, instead of switching to the live "X peers, sending, receiving" summary after a second or so. The workaround was to show the main window and then minimise it again — that cleared the stuck text.
|
If you run RemSound minimised to the tray with a screen reader, you may have noticed the tray icon reading out **two states one after the other** every time you landed on it — for example "no peers connected" and then immediately "1 peer connected". It always happened in that same order, and showing the window then minimising it again was the only thing that cleared it.
|
||||||
|
|
||||||
## Why it happened
|
### Why it happened
|
||||||
|
|
||||||
Windows registers a tray icon's tooltip text with the shell at the exact moment the icon becomes visible. RemSound was setting an initial "starting up" string at construction time, and the shell tended to keep showing that text on hover even after the live state had been computed and pushed through. The hide-then-re-show workaround forced the shell to rebuild its registration of the icon, which picked up whatever the current live text was.
|
Windows stamps a tray icon with its name at the exact moment the icon appears. On a fresh start — say, just after you log in — the icon appears a second or so before your other machine has reconnected, so the honest state at that instant really is "no peers". Windows remembers that as the icon's name and only ever refreshes the little hover bubble afterwards, never the stamped name. So your screen reader read the frozen name ("no peers") followed by the live bubble ("1 peer") — two readings of what should be one thing.
|
||||||
|
|
||||||
## The fix
|
### The fix
|
||||||
|
|
||||||
The right tooltip text is now computed once, just before the icon becomes visible for the first time, so Windows registers the icon with the correct live summary from the start. From there, the same 1-second refresh keeps it current — same as before.
|
RemSound now re-stamps the icon itself whenever something real changes — a peer connecting or dropping, sending or receiving switching on or off, or a recording starting or stopping. That's the automatic version of the old "show the window then minimise again" trick. Your screen reader now hears a single, current state.
|
||||||
|
|
||||||
|
## Recording shows as "recording" in the tray
|
||||||
|
|
||||||
|
While a recording is running, the tray summary now simply says **"recording"** rather than counting the seconds. A live timer would have forced the icon to flicker every second or left a screen reader announcing a stale time — neither was good. If you want the exact length, it's on the main window.
|
||||||
|
|
||||||
|
## Clearer update message on Windows 7
|
||||||
|
|
||||||
|
On a Windows 7 machine that can't make a secure (HTTPS) connection to the update server, **Check for updates** used to report "you're already on the latest version" — which was wrong and confusing. It now tells you plainly that the secure connection failed, names the Windows updates that fix it, and gives you a direct link to download the new version by hand if you'd rather. Windows 10 and 11 were never affected.
|
||||||
|
|
||||||
## Nothing else has changed
|
## Nothing else has changed
|
||||||
|
|
||||||
Same wire format, same codec list, same audio cues, same everything else from v3.1. If you didn't see the stuck-tooltip issue, this update is small and silent — but worth taking because the underlying cause was a real Windows shell behaviour and the fix is solid.
|
Same wire format, same codec list, same audio cues, same everything else from v3.1. v3.1.2 talks to v3.0.x and v3.1.x peers exactly as before.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
1. Download `RemSound-v3.1.1.zip` from this release.
|
1. Download `RemSound-v3.1.2.zip` from this release.
|
||||||
2. Close RemSound.
|
2. Close RemSound.
|
||||||
3. Extract the zip **over your existing RemSound folder**, overwriting program files when prompted. The zip is program files only — it will not touch your profiles, settings or recordings.
|
3. Extract the zip **over your existing RemSound folder**, overwriting program files when prompted. The zip is program files only — it will not touch your profiles, settings or recordings.
|
||||||
4. Run `RemSound.exe`.
|
4. Run `RemSound.exe`.
|
||||||
|
|
||||||
## Upgrading
|
## Upgrading
|
||||||
|
|
||||||
**v1.9 through v3.1:** Help → Check for updates works — it will fetch and install v3.1.1 automatically. If you've ticked "Check for updates on startup" and "Silently install updates", v3.1.1 installs itself shortly after launch.
|
**v1.9 through v3.1.1:** Help → Check for updates works — it will fetch and install v3.1.2 automatically. If you've ticked "Check for updates on startup" and "Silently install updates", v3.1.2 installs itself shortly after launch.
|
||||||
|
|
||||||
**v1.8 and earlier:** the auto-updater in those versions has a fault that prevents it from installing updates, so Check for updates will download v3.1.1 but not apply it. Install v3.1.1 by hand using the steps above — just this once. From the build you install onward, updates are automatic.
|
**v1.8 and earlier:** the auto-updater in those versions has a fault that prevents it from installing updates, so Check for updates will download v3.1.2 but not apply it. Install v3.1.2 by hand using the steps above — just this once. From the build you install onward, updates are automatic.
|
||||||
|
|||||||
+2
-2
@@ -217,12 +217,12 @@ ul, ol { padding-left: 1.4em; }
|
|||||||
|
|
||||||
<p>When RemSound is <strong>minimised to the tray</strong> (via <strong>File → Minimise to tray</strong>, the “Show or hide window” global hotkey, or by starting minimised on launch), the main window hides and an icon appears in your Windows system tray (the small icons cluster next to the clock).</p>
|
<p>When RemSound is <strong>minimised to the tray</strong> (via <strong>File → Minimise to tray</strong>, the “Show or hide window” global hotkey, or by starting minimised on launch), the main window hides and an icon appears in your Windows system tray (the small icons cluster next to the clock).</p>
|
||||||
|
|
||||||
<p><strong>Hovering over the tray icon</strong> shows a short summary of what RemSound is doing right now — the number of healthy peers, whether you're sending or receiving and in which mode (WASAPI, ASIO, or both), and how long any current recording has been running. The summary refreshes every second. Examples:</p>
|
<p><strong>Hovering over the tray icon</strong> shows a short summary of what RemSound is doing right now — the number of healthy peers, whether you're sending or receiving and in which mode (WASAPI, ASIO, or both), and whether a recording is running. The summary keeps itself up to date as things change. It tells you a recording is in progress, but not its exact length — for that, glance at the main window. Examples:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><em>RemSound — not connected</em></li>
|
<li><em>RemSound — not connected</em></li>
|
||||||
<li><em>RemSound — 2 peers, sending (WASAPI), receiving (WASAPI)</em></li>
|
<li><em>RemSound — 2 peers, sending (WASAPI), receiving (WASAPI)</em></li>
|
||||||
<li><em>RemSound — recording for 5:23, 1 peer, sending (WASAPI + ASIO), receiving (WASAPI + ASIO)</em></li>
|
<li><em>RemSound — recording, 1 peer, sending (WASAPI + ASIO), receiving (WASAPI + ASIO)</em></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p><strong>Right-clicking the tray icon</strong> opens a small menu with everything you might want to reach without re-opening the main window:</p>
|
<p><strong>Right-clicking the tray icon</strong> opens a small menu with everything you might want to reach without re-opening the main window:</p>
|
||||||
|
|||||||
@@ -20,6 +20,44 @@ internal sealed class AboutDialog : Form
|
|||||||
/// updates" path.</summary>
|
/// updates" path.</summary>
|
||||||
private const string ReleaseNotes =
|
private const string ReleaseNotes =
|
||||||
"""
|
"""
|
||||||
|
RemSound v3.1.2
|
||||||
|
|
||||||
|
A small accessibility fix for the system tray
|
||||||
|
icon, plus a clearer "check for updates" message
|
||||||
|
for Windows 7.
|
||||||
|
|
||||||
|
The tray icon's double announcement: if you use a
|
||||||
|
screen reader, the tray icon could read out two
|
||||||
|
states one after the other — for example "no peers"
|
||||||
|
and then "1 peer" — every time you landed on it. It
|
||||||
|
always happened in that same order. Windows stamps
|
||||||
|
a tray icon's name at the moment the icon appears,
|
||||||
|
which on a fresh start is a second before your other
|
||||||
|
machine has reconnected — so the name was frozen as
|
||||||
|
"no peers" while only the hover text caught up to
|
||||||
|
"1 peer". RemSound now refreshes the icon itself
|
||||||
|
whenever something real changes — a peer connecting
|
||||||
|
or dropping, sending or receiving switching on or
|
||||||
|
off, a recording starting or stopping — so the
|
||||||
|
screen reader hears a single, current state.
|
||||||
|
|
||||||
|
Recording in the tray: while a recording is running
|
||||||
|
the tray now simply says "recording" rather than
|
||||||
|
counting the seconds. A live timer would have made
|
||||||
|
the icon flicker or read out a stale time; the exact
|
||||||
|
length is on the main window if you need it.
|
||||||
|
|
||||||
|
Windows 7 update message: on a Windows 7 machine
|
||||||
|
that can't make a secure connection to the update
|
||||||
|
server, "Check for updates" used to say "you're on
|
||||||
|
the latest version", which was misleading. It now
|
||||||
|
explains that the secure connection failed and points
|
||||||
|
to the Windows updates that fix it, with a manual
|
||||||
|
download link as a fallback. Windows 10 and 11 were
|
||||||
|
never affected.
|
||||||
|
|
||||||
|
Everything else from v3.1 is unchanged.
|
||||||
|
|
||||||
RemSound v3.1.1
|
RemSound v3.1.1
|
||||||
|
|
||||||
Hot-fix for a small but annoying bug with the system
|
Hot-fix for a small but annoying bug with the system
|
||||||
|
|||||||
@@ -5292,14 +5292,15 @@ public sealed class MainForm : Form
|
|||||||
if (ph.State == PeerHealthState.Healthy) healthyPeers++;
|
if (ph.State == PeerHealthState.Healthy) healthyPeers++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Recording timer — only included when a recording is actually running. Slots in
|
// Recording status — a plain "recording" flag while a capture is running, with no
|
||||||
// right after the "RemSound" leader as Ed asked, so it reads as a status on the
|
// elapsed timer. A live timer would have to rewrite the tooltip every second, which
|
||||||
// app itself rather than a property of the peer list.
|
// fights the tray icon's re-stamp-on-change behaviour: it would either flicker the
|
||||||
string? recordingPart = null;
|
// icon once a second or leave a screen reader announcing a stale time next to the live
|
||||||
if (recordingController.IsRecording && recordingController.RecordingStartedUtc is { } startedUtc)
|
// one. Recording starting and stopping are real state changes that re-stamp cleanly;
|
||||||
{
|
// the second-by-second count is intentionally left to the main window. Slots in right
|
||||||
recordingPart = $"recording for {FormatRecordingElapsed(DateTime.UtcNow - startedUtc)}";
|
// after the "RemSound" leader so it reads as a status on the app itself rather than a
|
||||||
}
|
// property of the peer list.
|
||||||
|
string? recordingPart = recordingController.IsRecording ? "recording" : null;
|
||||||
if (healthyPeers == 0 && !sendMyAudioCheckbox.Checked && !receiveAudioCheckbox.Checked)
|
if (healthyPeers == 0 && !sendMyAudioCheckbox.Checked && !receiveAudioCheckbox.Checked)
|
||||||
{
|
{
|
||||||
return recordingPart is null
|
return recordingPart is null
|
||||||
@@ -5346,20 +5347,6 @@ public sealed class MainForm : Form
|
|||||||
return list.CheckedItems.Count > 0;
|
return list.CheckedItems.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Compact duration formatter for the tray tooltip's "recording for X" segment.
|
|
||||||
/// Under an hour shows MM:SS; from an hour on it shows H:MM:SS — the same shape Windows
|
|
||||||
/// uses for media-player elapsed-time displays, so it reads naturally to people who
|
|
||||||
/// don't otherwise know it's a custom format.</summary>
|
|
||||||
private static string FormatRecordingElapsed(TimeSpan elapsed)
|
|
||||||
{
|
|
||||||
// Negative elapsed (clock skew across a sleep cycle) gets clamped to zero — better
|
|
||||||
// than displaying "-00:01" mid-tooltip.
|
|
||||||
if (elapsed < TimeSpan.Zero) elapsed = TimeSpan.Zero;
|
|
||||||
return elapsed.TotalHours >= 1
|
|
||||||
? $"{(int)elapsed.TotalHours}:{elapsed.Minutes:D2}:{elapsed.Seconds:D2}"
|
|
||||||
: $"{elapsed.Minutes:D2}:{elapsed.Seconds:D2}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Pretty-print "WASAPI", "ASIO", "WASAPI + ASIO", or "no devices" depending
|
/// <summary>Pretty-print "WASAPI", "ASIO", "WASAPI + ASIO", or "no devices" depending
|
||||||
/// on which of the two flags are set. "no devices" covers the awkward case where the
|
/// on which of the two flags are set. "no devices" covers the awkward case where the
|
||||||
/// user has the send/receive checkbox on but hasn't ticked anything for the engine to
|
/// user has the send/receive checkbox on but hasn't ticked anything for the engine to
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ internal sealed class MainFormTrayController : IDisposable
|
|||||||
private readonly Func<string> buildTooltip;
|
private readonly Func<string> buildTooltip;
|
||||||
private readonly Action exit;
|
private readonly Action exit;
|
||||||
|
|
||||||
|
/// <summary>The tooltip text the icon was last (re-)registered with. We compare against
|
||||||
|
/// this so we only re-register on a real state change — a peer connecting or dropping, a
|
||||||
|
/// lane switching, a recording starting or stopping. The tray tooltip has no per-second
|
||||||
|
/// element (recording shows a plain "recording" flag, not a ticking timer), so the text
|
||||||
|
/// only changes on those real events and the icon never flickers. Null until first shown.</summary>
|
||||||
|
private string? lastRegistrationText;
|
||||||
|
|
||||||
private readonly ToolStripMenuItem sendingItem;
|
private readonly ToolStripMenuItem sendingItem;
|
||||||
private readonly ToolStripMenuItem receivingItem;
|
private readonly ToolStripMenuItem receivingItem;
|
||||||
private readonly ToolStripMenuItem profilesItem;
|
private readonly ToolStripMenuItem profilesItem;
|
||||||
@@ -152,6 +159,38 @@ internal sealed class MainFormTrayController : IDisposable
|
|||||||
// NotifyIcon.Text throws on the same string-assigning path under some shell
|
// NotifyIcon.Text throws on the same string-assigning path under some shell
|
||||||
// conditions (rare race during a session-end). Best-effort: swallow.
|
// conditions (rare race during a session-end). Best-effort: swallow.
|
||||||
try { trayIcon.Text = text; } catch { /* harmless */ }
|
try { trayIcon.Text = text; } catch { /* harmless */ }
|
||||||
|
|
||||||
|
// Keep the icon's *registered* name — the text a screen reader announces — in step
|
||||||
|
// with the live state. Windows stamps a tray icon's accessible name at the moment the
|
||||||
|
// icon is added (NIM_ADD) and afterwards only refreshes the little hover bubble, not
|
||||||
|
// that stamped name. So if the icon appears at launch before the first peer has
|
||||||
|
// connected, the name is frozen as "no peers"; when the peer links up a second later
|
||||||
|
// the bubble updates to "1 peer" but the frozen name stays — and NVDA reads BOTH (the
|
||||||
|
// stale name, then the live bubble), which is the confusing double announcement.
|
||||||
|
//
|
||||||
|
// The cure is to re-add the icon (hide then re-show = NIM_DELETE + NIM_ADD) whenever
|
||||||
|
// the text changes, which re-stamps the name with the current text. This is exactly
|
||||||
|
// what the old "show the window then minimise again" workaround did by hand. The tray
|
||||||
|
// tooltip has no per-second element (recording shows a plain "recording" flag, not a
|
||||||
|
// ticking timer), so the text only changes on real events and this never flickers.
|
||||||
|
if (!trayIcon.Visible)
|
||||||
|
{
|
||||||
|
// The first call arrives from Minimize() a moment before the icon is shown — just
|
||||||
|
// record the baseline so the NIM_ADD that immediately follows is our reference.
|
||||||
|
lastRegistrationText = text;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (text == lastRegistrationText) return;
|
||||||
|
// Don't yank the icon out from under an open right-click menu (that would dismiss it
|
||||||
|
// mid-navigation). Leave the record stale so the next tick re-stamps once it closes.
|
||||||
|
if (trayIcon.ContextMenuStrip?.Visible == true) return;
|
||||||
|
lastRegistrationText = text;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
trayIcon.Visible = false;
|
||||||
|
trayIcon.Visible = true;
|
||||||
|
}
|
||||||
|
catch { /* harmless — the 1 Hz snapshot tick will try again next second */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Toggle()
|
public void Toggle()
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
tag_name on the latest GitHub release; bump it on every public release. The
|
tag_name on the latest GitHub release; bump it on every public release. The
|
||||||
AssemblyVersion / FileVersion default to this value, and Assembly.GetName().Version
|
AssemblyVersion / FileVersion default to this value, and Assembly.GetName().Version
|
||||||
is what the About dialog and the updater both read. -->
|
is what the About dialog and the updater both read. -->
|
||||||
<Version>3.1.1</Version>
|
<Version>3.1.2</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user