Peer rename + details box on Connectivity tab; Add band dialog fixes
Add band dialog (from testing feedback): * Tab order is now Start, End, Gain, OK, Cancel (OK was after Cancel). * Gain box takes decimals like 1.5 (half-dB steps); parametric list shows one decimal. * The two frequency boxes start empty — nothing prepopulated to mislead; both required on OK. New Connectivity-tab feature (held for next release): * Rename peer (Alt+M) opens a dialog to give a peer a friendly name, with a Clear custom name button. Names are keyed by the peer's MACHINE NAME (stable across restarts, IP changes and networks), stored machine-wide in AppConfig.PeerFriendlyNames, and resolved everywhere a peer shows: both peer lists (via PeerListItem.DisplayNameProvider), the volume/pan/EQ list, the status line and split-recording filenames. Manual-by-IP peers with no announced name fall back to keying by address. * Peer details (Alt+E): a read-only box for the highlighted connected peer showing name, machine name, IP, connected-for, link health + ping, what they're sending, and whether they're receiving our audio. "Sending: 2 devices on ASIO at 48 kHz, Opus" is derived from the live receive streams — each stream is one device and its lane gives WASAPI vs ASIO — so NO protocol change and no new privacy exposure. AudioReceiver.ActiveFormatsFromAddress added for this. Manual updated (readme.html + MANUAL.md). Build clean; --selftest passes; deployed to both test folders. Held for next release. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
033edd776f
commit
f35f6c3c28
@@ -1,22 +1,25 @@
|
||||
using System.Globalization;
|
||||
using RemSound.Core;
|
||||
|
||||
namespace RemSound.App;
|
||||
|
||||
/// <summary>Modal dialog for adding one parametric EQ band. The user sets a start frequency, an end
|
||||
/// frequency and a gain; all three are spin-or-type boxes that refuse non-numbers and clamp to range.
|
||||
/// While the dialog is open it previews the in-progress band live (so the peer's sound changes as the
|
||||
/// values move); OK keeps the band, Cancel/Escape drops it and reverts the preview.</summary>
|
||||
/// The two frequency boxes start EMPTY (no prepopulated value to mislead the user); the gain defaults
|
||||
/// to a gentle boost. While the dialog is open it previews the in-progress band live (so the peer's
|
||||
/// sound changes as the values move); OK keeps the band, Cancel/Escape drops it and reverts.</summary>
|
||||
internal sealed class AddBandDialog : Form
|
||||
{
|
||||
private readonly NumericUpDown startFreq = new()
|
||||
{
|
||||
Minimum = (decimal)PeerEqBands.ParametricMinHz,
|
||||
Maximum = (decimal)PeerEqBands.ParametricMaxHz,
|
||||
Value = 200,
|
||||
Value = (decimal)PeerEqBands.ParametricMinHz,
|
||||
Increment = 10,
|
||||
DecimalPlaces = 0,
|
||||
Width = 120,
|
||||
TextAlign = HorizontalAlignment.Right,
|
||||
TabIndex = 0,
|
||||
AccessibleName = "Start frequency in Hertz (Alt+S)",
|
||||
};
|
||||
|
||||
@@ -24,11 +27,12 @@ internal sealed class AddBandDialog : Form
|
||||
{
|
||||
Minimum = (decimal)PeerEqBands.ParametricMinHz,
|
||||
Maximum = (decimal)PeerEqBands.ParametricMaxHz,
|
||||
Value = 2000,
|
||||
Value = (decimal)PeerEqBands.ParametricMinHz,
|
||||
Increment = 10,
|
||||
DecimalPlaces = 0,
|
||||
Width = 120,
|
||||
TextAlign = HorizontalAlignment.Right,
|
||||
TabIndex = 1,
|
||||
AccessibleName = "End frequency in Hertz (Alt+E)",
|
||||
};
|
||||
|
||||
@@ -37,27 +41,24 @@ internal sealed class AddBandDialog : Form
|
||||
Minimum = -(decimal)PeerEqBands.MaxGainDb,
|
||||
Maximum = (decimal)PeerEqBands.MaxGainDb,
|
||||
Value = 3,
|
||||
Increment = 1,
|
||||
DecimalPlaces = 0,
|
||||
Increment = 0.5m, // allow half-dB steps; typing any value like 1.5 works too
|
||||
DecimalPlaces = 1,
|
||||
Width = 120,
|
||||
TextAlign = HorizontalAlignment.Right,
|
||||
TabIndex = 2,
|
||||
AccessibleName = "Gain in dB (Alt+G)",
|
||||
};
|
||||
|
||||
private readonly Action<ParametricBand?>? livePreview;
|
||||
private ParametricBand? resultBand;
|
||||
private bool accepted;
|
||||
|
||||
/// <summary>The band the user built, valid only when <see cref="Form.ShowDialog()"/> returned OK.</summary>
|
||||
public ParametricBand Result => new()
|
||||
{
|
||||
StartHz = (float)startFreq.Value,
|
||||
EndHz = (float)endFreq.Value,
|
||||
GainDb = (float)gainDb.Value,
|
||||
};
|
||||
public ParametricBand Result => resultBand ?? new ParametricBand();
|
||||
|
||||
/// <param name="livePreview">Called with the in-progress band on every value change so the caller
|
||||
/// can apply it to the peer in real time, and with null when the dialog is cancelled/closed so the
|
||||
/// caller reverts to the saved shaping.</param>
|
||||
/// can apply it to the peer in real time, and with null when the band is incomplete or the dialog
|
||||
/// is cancelled/closed so the caller reverts to the saved shaping.</param>
|
||||
public AddBandDialog(Action<ParametricBand?>? livePreview = null)
|
||||
{
|
||||
this.livePreview = livePreview;
|
||||
@@ -84,29 +85,39 @@ internal sealed class AddBandDialog : Form
|
||||
AddRow(grid, 1, "&End frequency in Hz (Alt+E)", endFreq);
|
||||
AddRow(grid, 2, "&Gain in dB (Alt+G)", gainDb);
|
||||
|
||||
var okButton = new Button { Text = "OK", AutoSize = true, DialogResult = DialogResult.None };
|
||||
var cancelButton = new Button { Text = "Cancel", AutoSize = true, DialogResult = DialogResult.Cancel };
|
||||
var okButton = new Button { Text = "OK", AutoSize = true, DialogResult = DialogResult.None, TabIndex = 0 };
|
||||
var cancelButton = new Button { Text = "Cancel", AutoSize = true, DialogResult = DialogResult.Cancel, TabIndex = 1 };
|
||||
okButton.Click += (_, _) => TryAccept();
|
||||
|
||||
// OK before Cancel, in both tab order and left-to-right layout.
|
||||
var buttonRow = new FlowLayoutPanel
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
FlowDirection = FlowDirection.RightToLeft,
|
||||
FlowDirection = FlowDirection.LeftToRight,
|
||||
AutoSize = true,
|
||||
TabIndex = 3,
|
||||
};
|
||||
buttonRow.Controls.Add(cancelButton);
|
||||
buttonRow.Controls.Add(okButton);
|
||||
buttonRow.Controls.Add(cancelButton);
|
||||
grid.Controls.Add(buttonRow, 1, 3);
|
||||
|
||||
Controls.Add(grid);
|
||||
AcceptButton = okButton;
|
||||
CancelButton = cancelButton;
|
||||
|
||||
startFreq.ValueChanged += (_, _) => Preview();
|
||||
endFreq.ValueChanged += (_, _) => Preview();
|
||||
gainDb.ValueChanged += (_, _) => Preview();
|
||||
foreach (var box in new[] { startFreq, endFreq, gainDb })
|
||||
{
|
||||
box.ValueChanged += (_, _) => Preview();
|
||||
box.TextChanged += (_, _) => Preview();
|
||||
}
|
||||
|
||||
Shown += (_, _) => { startFreq.Focus(); Preview(); };
|
||||
Shown += (_, _) =>
|
||||
{
|
||||
// Blank the two frequency boxes so nothing is prepopulated; the user must enter both.
|
||||
startFreq.Text = "";
|
||||
endFreq.Text = "";
|
||||
startFreq.Focus();
|
||||
};
|
||||
}
|
||||
|
||||
// The mnemonic hint is embedded in each NumericUpDown's AccessibleName; the label carries the
|
||||
@@ -114,41 +125,72 @@ internal sealed class AddBandDialog : Form
|
||||
private static void AddRow(TableLayoutPanel grid, int row, string labelText, NumericUpDown box)
|
||||
{
|
||||
var label = new Label { Text = labelText, AutoSize = true, Anchor = AnchorStyles.Left, Margin = new Padding(0, 6, 8, 0) };
|
||||
// A plain Label with '&' wires the mnemonic to the next control in tab order (the box).
|
||||
grid.Controls.Add(label, 0, row);
|
||||
grid.Controls.Add(box, 1, row);
|
||||
}
|
||||
|
||||
private ParametricBand Current() => new()
|
||||
private static bool TryReadHz(NumericUpDown box, out float hz)
|
||||
{
|
||||
StartHz = (float)startFreq.Value,
|
||||
EndHz = (float)endFreq.Value,
|
||||
GainDb = (float)gainDb.Value,
|
||||
};
|
||||
hz = 0f;
|
||||
var t = box.Text.Trim();
|
||||
if (t.Length == 0) return false;
|
||||
if (!float.TryParse(t, NumberStyles.Float, CultureInfo.CurrentCulture, out hz)) return false;
|
||||
return hz >= PeerEqBands.ParametricMinHz && hz <= PeerEqBands.ParametricMaxHz;
|
||||
}
|
||||
|
||||
private void Preview() => livePreview?.Invoke(Current());
|
||||
private bool TryReadDb(out float db)
|
||||
{
|
||||
db = 0f;
|
||||
var t = gainDb.Text.Trim();
|
||||
if (t.Length == 0) return false;
|
||||
if (!float.TryParse(t, NumberStyles.Float, CultureInfo.CurrentCulture, out db)) return false;
|
||||
db = Math.Clamp(db, -PeerEqBands.MaxGainDb, PeerEqBands.MaxGainDb);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void Preview()
|
||||
{
|
||||
if (TryReadHz(startFreq, out float s) && TryReadHz(endFreq, out float e) && e > s)
|
||||
livePreview?.Invoke(new ParametricBand { StartHz = s, EndHz = e, GainDb = TryReadDb(out float d) ? d : 0f });
|
||||
else
|
||||
livePreview?.Invoke(null); // incomplete / invalid → nothing to preview
|
||||
}
|
||||
|
||||
private void TryAccept()
|
||||
{
|
||||
if (endFreq.Value <= startFreq.Value)
|
||||
if (!TryReadHz(startFreq, out float s) || !TryReadHz(endFreq, out float e))
|
||||
{
|
||||
var page = new TaskDialogPage
|
||||
{
|
||||
Caption = "Add EQ band",
|
||||
Heading = "End frequency must be higher than start",
|
||||
Text = $"The end frequency ({endFreq.Value:0} Hz) must be higher than the start frequency ({startFreq.Value:0} Hz). Adjust one of them and try again.",
|
||||
Icon = TaskDialogIcon.Warning,
|
||||
Buttons = { TaskDialogButton.OK },
|
||||
};
|
||||
TaskDialog.ShowDialog(this, page);
|
||||
Warn("Enter both frequencies",
|
||||
$"Enter a start and an end frequency, each between {PeerEqBands.ParametricMinHz:0} and {PeerEqBands.ParametricMaxHz:0} Hz.");
|
||||
startFreq.Focus();
|
||||
return;
|
||||
}
|
||||
if (e <= s)
|
||||
{
|
||||
Warn("End frequency must be higher than start",
|
||||
$"The end frequency ({e:0} Hz) must be higher than the start frequency ({s:0} Hz). Adjust one of them and try again.");
|
||||
endFreq.Focus();
|
||||
return;
|
||||
}
|
||||
resultBand = new ParametricBand { StartHz = s, EndHz = e, GainDb = TryReadDb(out float d) ? d : 0f };
|
||||
accepted = true;
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void Warn(string heading, string text)
|
||||
{
|
||||
var page = new TaskDialogPage
|
||||
{
|
||||
Caption = "Add EQ band",
|
||||
Heading = heading,
|
||||
Text = text,
|
||||
Icon = TaskDialogIcon.Warning,
|
||||
Buttons = { TaskDialogButton.OK },
|
||||
};
|
||||
TaskDialog.ShowDialog(this, page);
|
||||
}
|
||||
|
||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||
{
|
||||
base.OnFormClosing(e);
|
||||
|
||||
Reference in New Issue
Block a user