Recording fixes: date folders on top, and multi-track honours the Source setting

Two issues Ed found testing:
 * The default recordings path was recordings\<machine>\, so date folders nested under a
   machine-name folder. Dropped the per-machine subfolder — recordings now nest by date at the
   top (recordings\<yyyy-MM-dd>\...); the machine name still appears in split-track file names.
 * Multi-track always created the "me" (sent) track regardless of the Source setting, so a
   receive-only recording wrongly produced a track of your own machine. Multi-track now follows
   Source like single-file does: peer (received) tracks unless "sent only", and your own (sent)
   track only when Source is "both" or "sent only".

Held for next release.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-07-07 20:10:39 +01:00
co-authored by Claude Opus 4.8
parent 6b1e65f418
commit fc4ad3bb92
2 changed files with 30 additions and 21 deletions
+27 -17
View File
@@ -154,30 +154,40 @@ internal sealed class RecordingController
var ext = AudioRecorder.ExtensionFor(s.FileFormat);
var time = now.ToString("HH-mm-ss");
// Multi-track follows the Source setting like single-file recording does: peer (received)
// tracks unless "sent only", and your own (sent) track only when you're actually recording
// your send ("both" or "sent only") — so a receive-only recording no longer makes a "me" file.
// One track per connected peer (their received audio only), created up front on the UI thread
// so the audio-thread tap never has to open a file. Peers that join mid-recording aren't added.
var recs = new Dictionary<string, PeerTrack>();
var usedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var byAddr = new Dictionary<string, string>();
foreach (var (addr, name) in ConnectedPeersProvider?.Invoke() ?? []) byAddr[addr.ToString()] = name;
foreach (var (addrKey, name) in byAddr)
if (s.Source != RecordingSource.SentOnly)
{
var baseName = Sanitize(string.IsNullOrWhiteSpace(name) ? addrKey : name);
var fileName = $"{baseName} {time}";
if (!usedNames.Add(fileName)) fileName = $"{baseName} ({addrKey}) {time}";
var path = Path.Combine(folder, $"{fileName}.{ext}");
recs[addrKey] = new PeerTrack(new AudioRecorder(WithSource(s, RecordingSource.ReceivedOnly), diagnostic, OnRecorderFinished, path));
var recs = new Dictionary<string, PeerTrack>();
var usedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var byAddr = new Dictionary<string, string>();
foreach (var (addr, name) in ConnectedPeersProvider?.Invoke() ?? []) byAddr[addr.ToString()] = name;
foreach (var (addrKey, name) in byAddr)
{
var baseName = Sanitize(string.IsNullOrWhiteSpace(name) ? addrKey : name);
var fileName = $"{baseName} {time}";
if (!usedNames.Add(fileName)) fileName = $"{baseName} ({addrKey}) {time}";
var path = Path.Combine(folder, $"{fileName}.{ext}");
recs[addrKey] = new PeerTrack(new AudioRecorder(WithSource(s, RecordingSource.ReceivedOnly), diagnostic, OnRecorderFinished, path));
}
peerTracks = recs;
receiver.SetPeerRecordTap(OnPeerRecordBlock, raw: s.BypassShaping);
receiver.OnRecordBlockComplete = FlushPeerTracks;
}
peerTracks = recs;
receiver.SetPeerRecordTap(OnPeerRecordBlock, raw: s.BypassShaping);
receiver.OnRecordBlockComplete = FlushPeerTracks;
// Your own track — your sent audio.
var mePath = Path.Combine(folder, $"{Sanitize(Environment.MachineName)} {time}.{ext}");
meRecorder = new AudioRecorder(WithSource(s, RecordingSource.SentOnly), diagnostic, OnRecorderFinished, mePath);
sender.OnSentSamples = meRecorder.WriteSent;
if (s.Source != RecordingSource.ReceivedOnly)
{
var mePath = Path.Combine(folder, $"{Sanitize(Environment.MachineName)} {time}.{ext}");
meRecorder = new AudioRecorder(WithSource(s, RecordingSource.SentOnly), diagnostic, OnRecorderFinished, mePath);
sender.OnSentSamples = meRecorder.WriteSent;
}
diagnostic($"recording: started multi-track → {folder} ({recs.Count} peer track(s), format={s.FileFormat}, bypass={s.BypassShaping})");
diagnostic($"recording: started multi-track → {folder} ({(peerTracks?.Count ?? 0)} peer track(s){(meRecorder is not null ? " + your send" : "")}, source={s.Source}, format={s.FileFormat}, bypass={s.BypassShaping})");
}
// Audio thread. Route each peer's block to that peer's recorder. peerRecorders is fully built at