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:
co-authored by
Claude Opus 4.8
parent
6b1e65f418
commit
fc4ad3bb92
@@ -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
|
||||
|
||||
@@ -127,11 +127,10 @@ public sealed class RecordingSettings
|
||||
|
||||
/// <summary>Default folder path used when <see cref="Folder"/> is blank. Computed at
|
||||
/// call time (not cached) so a launch from a different exe directory picks up that
|
||||
/// directory rather than the first-load one. The per-machine subfolder lets two
|
||||
/// machines sharing a Dropbox-backed RemSound install keep their recordings tidily
|
||||
/// separated by sender identity.</summary>
|
||||
/// directory rather than the first-load one. Recordings nest by DATE inside this — the
|
||||
/// machine name lives in the split-track file names, not a top-level folder.</summary>
|
||||
public static string DefaultFolder() =>
|
||||
Path.Combine(AppContext.BaseDirectory, "recordings", Environment.MachineName);
|
||||
Path.Combine(AppContext.BaseDirectory, "recordings");
|
||||
|
||||
/// <summary>Returns the resolved folder this profile would record into right now —
|
||||
/// either the explicit <see cref="Folder"/> if set, or <see cref="DefaultFolder"/>.
|
||||
|
||||
Reference in New Issue
Block a user