Record a message with Ctrl+Shift+F, and open the editor with Alt+K
N1MM records a phone message from the entry window: Ctrl+Shift+F1 to Ctrl+Shift+F12 records into the file that key plays, and the same pair again stops and saves it. Escape and sending anything stop one too — there is one microphone, and it cannot be recorded and transmitted at the same time. The status line says what is being recorded and what was saved, which is where N1MM says it. The recording being made is the session's rather than the window's, for the same reason: the voice keyer window and these keys record into the same microphone, and now each can see what the other started. Alt+K opens the function key editor for the mode the radio is on, which is N1MM's shortcut for what right-clicking a key button already did. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0157i7PiZyqBkquxS9A6FTdQ
This commit is contained in:
@@ -41,6 +41,7 @@ public sealed class AppSession : IDisposable
|
||||
private DispatcherTimer? announcing;
|
||||
private MessageSender? keyer;
|
||||
private VoiceKeyer? voice;
|
||||
private CancellationTokenSource? recordingStop;
|
||||
private SoundCard sound = new CommandSoundCard(
|
||||
CommandSoundCard.DefaultPlay,
|
||||
CommandSoundCard.DefaultRecord);
|
||||
@@ -177,9 +178,49 @@ public sealed class AppSession : IDisposable
|
||||
public VoiceFiles Recordings { get; }
|
||||
|
||||
/// What plays and records a wav file. The voice keyer sends through it and
|
||||
/// the voice keyer window auditions and records through it.
|
||||
/// the voice keyer window auditions through it.
|
||||
public SoundCard Sound => sound;
|
||||
|
||||
/// The recording being made, or null. It is here rather than in the window
|
||||
/// that started it because there is one microphone: the voice keyer window
|
||||
/// and the entry window's Ctrl+Shift+F keys record into the same one.
|
||||
public string? Recording { get; private set; }
|
||||
|
||||
/// Records over the file named under `Wav` until `StopRecording`, and
|
||||
/// answers with what to tell the operator: the file recorded, or why
|
||||
/// nothing was.
|
||||
public async Task<string> RecordAsync(string name)
|
||||
{
|
||||
if (Recording is { } already)
|
||||
{
|
||||
return $"{already} is being recorded — stop that first";
|
||||
}
|
||||
recordingStop = new CancellationTokenSource();
|
||||
Recording = name;
|
||||
Changed?.Invoke(this, EventArgs.Empty);
|
||||
try
|
||||
{
|
||||
await sound.RecordAsync(Recordings.PathOf(name), recordingStop.Token)
|
||||
.ConfigureAwait(false);
|
||||
return $"recorded {name}";
|
||||
}
|
||||
catch (Exception failure) when (failure is InvalidOperationException or IOException)
|
||||
{
|
||||
return failure.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
recordingStop.Dispose();
|
||||
recordingStop = null;
|
||||
Recording = null;
|
||||
Changed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// Ends the recording, which is what saves it: the recorder is asked to
|
||||
/// stop so it can close the file it is writing.
|
||||
public void StopRecording() => recordingStop?.Cancel();
|
||||
|
||||
/// The digital modem, started by the digital window rather than at startup:
|
||||
/// it runs an engine under Wine, which is not something to do to an
|
||||
/// operator who is working CW.
|
||||
|
||||
Reference in New Issue
Block a user