namespace Nonemm.Keying; /// Something that sends a message on the air: a CW keyer, or a voice keyer /// playing a recording. public interface MessageSender : IDisposable { bool IsReady { get; } /// True when the keyer tells us the message has gone out. Alternating CQ /// needs it: timing a message from the length of its text is a guess that /// goes wrong exactly when the contest is busy. bool ReportsCompletion { get; } /// Everything sent has now gone out on the air. Never raised by a keyer /// whose `ReportsCompletion` is false. It arrives on whatever thread the /// keyer reads on, so a handler that touches the screen has to post. event EventHandler? Finished; /// Sends the text. Whatever is already going out is finished first unless /// `Abort` is called. Task SendAsync(string text, CancellationToken cancellation = default); /// Stops sending straight away, which is what Escape does mid-message. Task AbortAsync(CancellationToken cancellation = default); Task SetSpeedAsync(int wordsPerMinute, CancellationToken cancellation = default); }