HamBook – Blame information for rev 20

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using HamBook.Radios;
2 using HamBook.Utilities;
3 using HamBook.Utilities.Serialization;
4 using NetSparkleUpdater.Enums;
5 using NetSparkleUpdater.SignatureVerifiers;
6 using NetSparkleUpdater.UI.WinForms;
7 using NetSparkleUpdater;
8 using Serilog;
9 using System;
10 using System.ComponentModel;
11 using System.Drawing;
12 using System.IO;
13 using System.IO.Ports;
14 using System.Reflection;
15 using System.Threading;
16 using System.Threading.Tasks;
17 using System.Windows.Forms;
18 using HamBook.Properties;
19 using HamBook.Radios.Generic;
20 using PowerState = HamBook.Radios.Generic.PowerState;
5 office 21 using System.Media;
7 office 22 using HamBook.Utilities.Controls;
9 office 23 using RJCP.IO.Ports;
24 using System.Text;
12 office 25 using System.Collections.ObjectModel;
26 using Configuration;
27 using System.Collections.Generic;
15 office 28 using NAudio.Utils;
29 using System.Linq;
30 using static System.Net.Mime.MediaTypeNames;
1 office 31  
32 namespace HamBook
33 {
34 public partial class Form1 : Form
35 {
36 private ScheduledContinuation _changedConfigurationContinuation;
37 private Configuration.Configuration Configuration { get; set; }
9 office 38 private SerialPortStream _serialPort;
1 office 39 private LogMemorySink _memorySink;
40 private ViewLogsForm _viewLogsForm;
41 private AboutForm _aboutForm;
42 private SettingsForm _settingsForm;
43 private SparkleUpdater _sparkle;
44 private readonly CancellationToken _cancellationToken;
45 private readonly CancellationTokenSource _cancellationTokenSource;
46 private CatAssemblies _catAssemblies;
3 office 47 private BandScan _bandScan;
10 office 48 private SpectrogramForm _spectrogramForm;
15 office 49 private MemoryOrganizerForm _memoryOrganizerForm;
1 office 50  
15 office 51 private CancellationTokenSource _tagTickerCancellationTokenSource;
52 private CancellationToken _tagTickerCancellationToken;
53 private string _storedMemoryChannelTagText;
54 private string _storedMemoryChannelLocation;
55 private MemoryChannel _tickerTextMemoryChannel;
56 private Task _tickerTask;
57 private volatile bool _tickerTaskRunning;
58  
1 office 59 public bool MemorySinkEnabled { get; set; }
60  
61 private Form1()
62 {
63 _cancellationTokenSource = new CancellationTokenSource();
64 _cancellationToken = _cancellationTokenSource.Token;
65  
66 _changedConfigurationContinuation = new ScheduledContinuation();
3 office 67  
1 office 68 }
69  
70 public Form1(Mutex mutex) : this()
71 {
72 InitializeComponent();
73  
74 _memorySink = new LogMemorySink();
75  
76 Log.Logger = new LoggerConfiguration()
77 .MinimumLevel.Debug()
78 .WriteTo.Conditional(condition => MemorySinkEnabled, configureSink => configureSink.Sink(_memorySink))
79 .WriteTo.File(Path.Combine(Constants.UserApplicationDirectory, "Logs", $"{Constants.AssemblyName}.log"),
80 rollingInterval: RollingInterval.Day)
81 .CreateLogger();
82  
83 // Start application update.
84 var manifestModuleName = Assembly.GetEntryAssembly().ManifestModule.FullyQualifiedName;
85 var icon = Icon.ExtractAssociatedIcon(manifestModuleName);
86  
87 _sparkle = new SparkleUpdater("https://hambook.grimore.org/update/appcast.xml",
88 new Ed25519Checker(SecurityMode.Strict, "LonrgxVjSF0GnY4hzwlRJnLkaxnDn2ikdmOifILzLJY="))
89 {
90 UIFactory = new UIFactory(icon),
91 RelaunchAfterUpdate = true
92 };
93 }
94  
95 private async void Form1_Load(object sender, EventArgs e)
96 {
13 office 97 _sparkle.StartLoop(true, true);
98  
1 office 99 Configuration = await LoadConfiguration();
100  
7 office 101 _serialPort = InitializeSerialPort(Configuration);
1 office 102  
7 office 103 _catAssemblies = InitializeAssemblies(_serialPort);
1 office 104  
105 try
106 {
9 office 107 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
1 office 108 {
109 case PowerState.ON:
7 office 110 Log.Information(Resources.Attempting_to_initialize_radio);
9 office 111 if(!await InitializeRadio())
7 office 112 {
113 return;
114 }
115  
116 Log.Information(Resources.Initializing_GUI);
1 office 117 break;
118 }
119 }
120 catch(Exception exception)
121 {
122 Log.Error(exception, Resources.Failed_to_read_power_state);
123 }
124 }
125  
9 office 126 private async void quitToolStripMenuItem_Click(object sender, EventArgs e)
1 office 127 {
9 office 128 if(_bandScan != null)
129 {
130 await _bandScan.Stop();
131 _bandScan = null;
132 }
133  
14 office 134 // Save configuration on quit.
135 await SaveConfiguration();
136  
1 office 137 Close();
138 }
139  
140 private void viewLogsToolStripMenuItem_Click(object sender, EventArgs e)
141 {
142 if (_viewLogsForm != null)
143 {
144 return;
145 }
146  
147 _viewLogsForm = new ViewLogsForm(this, _memorySink, _cancellationToken);
148 _viewLogsForm.Closing += ViewLogsForm_Closing;
149 _viewLogsForm.Show();
150 }
151  
152 private void ViewLogsForm_Closing(object sender, CancelEventArgs e)
153 {
154 if (_viewLogsForm == null)
155 {
156 return;
157 }
158  
159 _viewLogsForm.Closing -= ViewLogsForm_Closing;
160 _viewLogsForm.Close();
161 _viewLogsForm = null;
162 }
163  
164 private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
165 {
166 if (_aboutForm != null)
167 {
168 return;
169 }
170  
171 _aboutForm = new AboutForm(_cancellationToken);
172 _aboutForm.Closing += AboutForm_Closing;
173 _aboutForm.Show();
174 }
175  
176 private void AboutForm_Closing(object sender, CancelEventArgs e)
177 {
178 if (_aboutForm == null)
179 {
180 return;
181 }
182  
183 _aboutForm.Dispose();
184 _aboutForm = null;
185 }
186  
187 private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
188 {
189 if (_settingsForm != null)
190 {
191 return;
192 }
193  
194 _settingsForm = new SettingsForm(Configuration, _cancellationToken);
195 _settingsForm.Closing += SettingsForm_Closing;
196 _settingsForm.Show();
197 }
198  
199 private void SettingsForm_Closing(object sender, CancelEventArgs e)
200 {
201 if (_settingsForm == null)
202 {
203 return;
204 }
205  
206 if(_settingsForm.SaveOnClose)
207 {
208 // Commit the configuration.
209 _changedConfigurationContinuation.Schedule(TimeSpan.FromSeconds(1),
210 async () => {
211 await SaveConfiguration();
212  
11 office 213 if(_bandScan != null)
214 {
215 await _bandScan.Stop();
216 _bandScan = null;
217 }
218  
219  
1 office 220 Miscellaneous.LaunchOnBootSet(Configuration.LaunchOnBoot);
221  
7 office 222 _serialPort = InitializeSerialPort(Configuration);
1 office 223  
7 office 224 _catAssemblies = InitializeAssemblies(_serialPort);
225  
226 try
227 {
9 office 228 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
7 office 229 {
230 case PowerState.ON:
231 Log.Information(Resources.Attempting_to_initialize_radio);
9 office 232 if (!await InitializeRadio())
7 office 233 {
234 return;
235 }
236 Log.Information(Resources.Initializing_GUI);
237 break;
238 }
239 }
240 catch (Exception exception)
241 {
242 Log.Error(exception, Resources.Failed_to_read_power_state);
243 }
244  
1 office 245 }, _cancellationToken);
246 }
247  
248 _settingsForm.Dispose();
249 _settingsForm = null;
250 }
251  
252 public async Task SaveConfiguration()
253 {
254 if (!Directory.Exists(Constants.UserApplicationDirectory))
255 {
256 Directory.CreateDirectory(Constants.UserApplicationDirectory);
257 }
258  
259 switch (await Serialization.Serialize(Configuration, Constants.ConfigurationFile, "Configuration",
260 "<!ATTLIST Configuration xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>",
261 CancellationToken.None))
262 {
3 office 263 case SerializationSuccess<Configuration.Configuration> configuration:
16 office 264 Log.Information(Resources.Configuration_serialized_successfully);
1 office 265 break;
266 case SerializationFailure serializationFailure:
16 office 267 Log.Warning(serializationFailure.Exception.Message, Resources.Configuration_failed_to_serialize);
1 office 268 break;
269 }
270 }
271  
272 public static async Task<Configuration.Configuration> LoadConfiguration()
273 {
274 if (!Directory.Exists(Constants.UserApplicationDirectory))
275 {
276 Directory.CreateDirectory(Constants.UserApplicationDirectory);
277 }
278  
279 var deserializationResult =
280 await Serialization.Deserialize<Configuration.Configuration>(Constants.ConfigurationFile,
281 Constants.ConfigurationNamespace, Constants.ConfigurationXsd, CancellationToken.None);
282  
283 switch (deserializationResult)
284 {
285 case SerializationSuccess<Configuration.Configuration> serializationSuccess:
286 return serializationSuccess.Result;
287 case SerializationFailure serializationFailure:
16 office 288 Log.Warning(serializationFailure.Exception, Resources.Configuration_failed_to_deserialize);
1 office 289 return new Configuration.Configuration();
290 default:
291 return new Configuration.Configuration();
292 }
293 }
294  
9 office 295 private async Task<bool> InitializeRadio()
1 office 296 {
297 try
298 {
9 office 299 await _catAssemblies.CatWriteAsync<InformationState>("AI", new object[] { InformationState.OFF }, _cancellationToken);
300  
11 office 301 return await _catAssemblies.CatReadAsync<bool>("ID", new object[] { }, _cancellationToken);
1 office 302 }
303 catch(Exception exception)
304 {
7 office 305 Log.Error(exception, Resources.Unable_to_initialize_radio);
11 office 306  
7 office 307 return false;
1 office 308 }
7 office 309 }
310  
9 office 311 private CatAssemblies InitializeAssemblies(SerialPortStream serialPort)
7 office 312 {
313 if(_catAssemblies != null)
1 office 314 {
7 office 315 _catAssemblies.Dispose();
316 _catAssemblies = null;
1 office 317 }
318  
7 office 319 return new CatAssemblies(serialPort, Configuration.Radio);
320 }
321  
9 office 322 private SerialPortStream InitializeSerialPort(Configuration.Configuration configuration)
7 office 323 {
324 if (_serialPort != null)
1 office 325 {
7 office 326 if (_serialPort.IsOpen)
327 {
328 _serialPort.Close();
329 }
330 _serialPort.Dispose();
331 _serialPort = null;
1 office 332 }
333  
7 office 334 // Set up serial connection.
9 office 335 var serialPort = new SerialPortStream(configuration.Port, configuration.Speed, configuration.DataBits, configuration.Parity, configuration.StopBits);
7 office 336 serialPort.ReadTimeout = configuration.SerialPortTimeout.Read;
337 serialPort.WriteTimeout = configuration.SerialPortTimeout.Write;
338 serialPort.Handshake = configuration.Handshake;
9 office 339 serialPort.Encoding = Encoding.ASCII;
1 office 340  
7 office 341 Log.Information($"{Resources.Initialized_serial_port} {configuration.Port} {configuration.Speed} {configuration.Parity} {configuration.DataBits} {configuration.StopBits}");
342  
343 return serialPort;
1 office 344 }
345  
346 private async void updateToolStripMenuItem_Click(object sender, EventArgs e)
347 {
348 // Manually check for updates, this will not show a ui
349 var result = await _sparkle.CheckForUpdatesQuietly();
350 if (result.Status == NetSparkleUpdater.Enums.UpdateStatus.UpdateAvailable)
351 {
352 // if update(s) are found, then we have to trigger the UI to show it gracefully
353 _sparkle.ShowUpdateNeededUI();
354 return;
355 }
356  
357 MessageBox.Show(Resources.No_updates_available_at_this_time, Resources.HamBook, MessageBoxButtons.OK,
358 MessageBoxIcon.Asterisk,
359 MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, false);
360 }
361  
9 office 362 private async void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
1 office 363 {
364 var toolStripComboBox = (ToolStripComboBox)sender;
3 office 365 if(RadioMode.TryParse(toolStripComboBox.Text, out var radioMode))
1 office 366 {
3 office 367 try
1 office 368 {
15 office 369 await _catAssemblies.CatSetAsync<RadioMode, bool>("MD", new object[] { radioMode }, _cancellationToken);
1 office 370 }
3 office 371 catch (Exception exception)
372 {
373 Log.Error(exception, Resources.Failed_to_set_radio_mode, radioMode);
374 }
1 office 375 }
376 }
377  
378 private async void onToolStripMenuItem_Click(object sender, EventArgs e)
379 {
380 try
381 {
15 office 382 await _catAssemblies.CatSetAsync<PowerState, bool>("PS", new object[] { PowerState.ON }, _cancellationToken);
1 office 383 }
384 catch(Exception exception)
385 {
386 Log.Error(exception, Resources.Failed_to_set_power_state);
387 }
388 }
389  
390 private async void offToolStripMenuItem_Click(object sender, EventArgs e)
391 {
392 try
393 {
15 office 394 await _catAssemblies.CatSetAsync<PowerState, bool>("PS", new object[] { PowerState.OFF }, _cancellationToken);
1 office 395 }
396 catch(Exception exception)
397 {
398 Log.Error(exception, Resources.Failed_to_set_power_state);
399 }
400 }
401  
9 office 402 private async void toolStripComboBox2_MouseWheel(object sender, MouseEventArgs e)
1 office 403 {
5 office 404 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
1 office 405 {
7 office 406 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
5 office 407 if (int.TryParse(toolStripComboBox.Text, out var frequency))
3 office 408 {
5 office 409 switch (Math.Sign(e.Delta))
410 {
411 case -1:
412 frequency = frequency - 100;
413 break;
414 case 1:
415 frequency = frequency + 100;
416 break;
417 }
418  
419 soundPlayer.Play();
420  
421 try
422 {
15 office 423 await _catAssemblies.CatSetAsync<int, bool>("FA", new object[] { frequency }, _cancellationToken);
5 office 424 toolStripComboBox.Text = $"{frequency}";
7 office 425  
426 Log.Information($"{Resources.Set_VFO_A_frequency} {frequency}Hz");
5 office 427 }
428 catch (Exception exception)
429 {
430 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
431 }
3 office 432 }
1 office 433 }
434 }
435  
9 office 436 private async void scrollableToolStripComboBox1_MouseWheel(object sender, MouseEventArgs e)
1 office 437 {
5 office 438 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
1 office 439 {
7 office 440 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
5 office 441 if (int.TryParse(toolStripComboBox.Text, out var frequency))
3 office 442 {
5 office 443 switch (Math.Sign(e.Delta))
444 {
445 case -1:
446 frequency = frequency - 100;
447 break;
448 case 1:
449 frequency = frequency + 100;
450 break;
451 }
3 office 452  
6 office 453 soundPlayer.Play();
454  
5 office 455 try
456 {
15 office 457 await _catAssemblies.CatSetAsync<int, bool>("FB", new object[] { frequency }, _cancellationToken);
5 office 458 toolStripComboBox.Text = $"{frequency}";
7 office 459  
460 Log.Information($"{Resources.Set_VFO_B_frequency} {frequency}Hz");
5 office 461 }
462 catch (Exception exception)
463 {
464 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
465 }
1 office 466 }
467 }
468 }
469  
9 office 470 private async void scrollableToolStripComboBox1_TextChanged(object sender, EventArgs e)
1 office 471 {
3 office 472 var toolStripComboBox = (ToolStripComboBox)sender;
473 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1 office 474 {
3 office 475 try
476 {
15 office 477 await _catAssemblies.CatSetAsync<int, bool>("FA", new object[] { frequency }, _cancellationToken);
3 office 478 }
479 catch (Exception exception)
480 {
481 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
482 }
1 office 483 }
484 }
485  
9 office 486 private async void scrollableToolStripComboBox2_TextChanged(object sender, EventArgs e)
1 office 487 {
3 office 488 var toolStripComboBox = (ToolStripComboBox)sender;
489 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1 office 490 {
491 try
492 {
15 office 493 await _catAssemblies.CatSetAsync<int, bool>("FB", new object[] { frequency }, _cancellationToken);
1 office 494 }
495 catch (Exception exception)
496 {
497 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
498 }
3 office 499 }
500 }
501  
9 office 502 private async void toolStripMenuItem1_Click(object sender, EventArgs e)
3 office 503 {
504 if (_bandScan == null)
505 {
1 office 506 return;
507 }
508  
9 office 509 await _bandScan.Stop();
3 office 510 _bandScan = null;
1 office 511 }
3 office 512  
9 office 513 private async void scanToolStripMenuItem_Click(object sender, EventArgs e)
3 office 514 {
5 office 515 if (!(sender is ToolStripMenuItem toolStripMenuItem) ||
516 !int.TryParse(toolStripMenuItem.Tag.ToString(), out var meters))
3 office 517 {
5 office 518 return;
3 office 519 }
520  
5 office 521 if (!int.TryParse(scrollableToolStripComboBox3.Text, out var pause))
3 office 522 {
5 office 523 pause = 5;
3 office 524 }
525  
5 office 526 if(!int.TryParse(scrollableToolStripComboBox4.Text, out var step))
3 office 527 {
5 office 528 step = 5000;
3 office 529 }
530  
5 office 531 if (!Configuration.Definitions.TryGetBand(meters, out var band))
3 office 532 {
5 office 533 return;
3 office 534 }
535  
536 if (_bandScan != null)
537 {
9 office 538 await _bandScan.Stop();
539 _bandScan = null;
3 office 540 }
541  
12 office 542 _bandScan = new BandScan(_catAssemblies, band.Min, band.Max, _serialPort, Configuration);
9 office 543  
544 _bandScan.Start(step, pause, Configuration.ScanDetectPause);
3 office 545 }
546  
11 office 547 private void modeToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
3 office 548 {
11 office 549 Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken).ContinueWith(async task =>
7 office 550 {
11 office 551 try
552 {
553 var mode = await _catAssemblies.CatReadAsync<RadioMode>("MD", new object[] { }, _cancellationToken);
7 office 554  
11 office 555 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
556 {
557 toolStripComboBox1.Text = mode;
558 });
559 }
560 catch (Exception exception)
561 {
562 Log.Error(exception, Resources.Failed_to_read_radio_mode);
563 }
7 office 564  
11 office 565 try
566 {
567 var fa = await _catAssemblies.CatReadAsync<int>("FA", new object[] { }, _cancellationToken);
7 office 568  
11 office 569 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
570 {
571 scrollableToolStripComboBox1.Text = $"{fa}";
572  
573 });
574  
575 }
576 catch (Exception exception)
577 {
578 Log.Error(exception, Resources.Failed_to_read_VFO_A);
579 }
580  
581 try
582 {
583 var fb = await _catAssemblies.CatReadAsync<int>("FB", new object[] { }, _cancellationToken);
584  
585 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
586 {
587 scrollableToolStripComboBox2.Text = $"{fb}";
588  
589 });
590 }
591 catch (Exception exception)
592 {
593 Log.Error(exception, Resources.Failed_to_read_VFO_B);
594 }
19 office 595  
596 try
597 {
598 var mc = await _catAssemblies.CatReadAsync<int>("MC", new object[] { }, _cancellationToken);
599  
600 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
601 {
602 scrollableToolStripComboBox5.Text = $"{mc}";
603  
604 });
605 }
606 catch (Exception exception)
607 {
608 Log.Error(exception, Resources.Failed_to_read_memory_channel);
609 }
11 office 610 }, _cancellationToken);
3 office 611 }
10 office 612  
613 private void spectrogramToolStripMenuItem_Click(object sender, EventArgs e)
614 {
615 if (_spectrogramForm != null)
616 {
617 return;
618 }
619  
620 _spectrogramForm = new SpectrogramForm(Configuration, _cancellationToken);
621 _spectrogramForm.Closing += SpectrogramForm_Closing;
622 _spectrogramForm.Show();
623 }
624  
625 private void SpectrogramForm_Closing(object sender, CancelEventArgs e)
626 {
627 if (_spectrogramForm == null)
628 {
629 return;
630 }
631  
632 _spectrogramForm.Dispose();
633 _spectrogramForm = null;
14 office 634  
635 // Commit the configuration.
636 _changedConfigurationContinuation.Schedule(TimeSpan.FromSeconds(1),
637 async () =>
638 {
639 await SaveConfiguration();
640 }, _cancellationToken);
10 office 641 }
15 office 642  
643 private void toolStripMenuItem3_Click(object sender, EventArgs e)
644 {
645 if (_memoryOrganizerForm != null)
646 {
647 return;
648 }
649  
650 _memoryOrganizerForm = new MemoryOrganizerForm(Configuration, _catAssemblies, _cancellationToken);
651 _memoryOrganizerForm.Closing += MemoryOrganizerForm_Closing;
652 _memoryOrganizerForm.Show();
653 }
654  
655 private void MemoryOrganizerForm_Closing(object sender, CancelEventArgs e)
656 {
657 if (_memoryOrganizerForm == null)
658 {
659 return;
660 }
661  
662 _memoryOrganizerForm.Dispose();
663 _memoryOrganizerForm = null;
664  
665 }
666  
667 private async void toolStripMenuItem4_Click(object sender, EventArgs e)
668 {
669 if (_tickerTaskRunning)
670 {
671 return;
672 }
673  
674 var toolStripTextBox = (ToolStripTextBox)toolStripTextBox6;
675  
676 try
677 {
678 var result = await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { "001" }, _cancellationToken);
679  
680 _tickerTextMemoryChannel = await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { $"{result.CurrentLocation}" }, _cancellationToken);
681  
682 _storedMemoryChannelTagText = _tickerTextMemoryChannel.Text;
683 _storedMemoryChannelLocation = _tickerTextMemoryChannel.CurrentLocation;
684 }
685 catch(Exception exception)
686 {
687 Log.Error(exception, Resources.Could_not_read_memory_bank);
688 }
689  
690 var tickerText = $"{toolStripTextBox.Text,-12}";
691  
692 _tagTickerCancellationTokenSource = new CancellationTokenSource();
693 _tagTickerCancellationToken = _tagTickerCancellationTokenSource.Token;
694  
695 var characterQueue = new Queue<char>(12);
696 foreach(var i in Enumerable.Range(0, 12))
697 {
698 var x = tickerText.ElementAtOrDefault(i);
699  
700 if(x == default)
701 {
702 characterQueue.Enqueue(' ');
703 continue;
704 }
705  
706 characterQueue.Enqueue(x);
707 }
708  
709 #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
710 _tickerTask = Task.Run(() => CycleText(characterQueue), _cancellationToken);
711 #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
712 }
713  
714 private async void toolStripMenuItem5_Click(object sender, EventArgs e)
715 {
716 if(!_tickerTaskRunning)
717 {
718 return;
719 }
720  
721 _tagTickerCancellationTokenSource.Cancel();
722 if (_tickerTask != null)
723 {
724 await _tickerTask;
725 _tickerTask = null;
726 }
727  
728 try
729 {
730 _tickerTextMemoryChannel.CurrentLocation = $"{_storedMemoryChannelLocation:000}";
17 office 731 _tickerTextMemoryChannel.Text = $"{_storedMemoryChannelTagText, -12}";
15 office 732  
733 var success = await _catAssemblies.CatSetAsync<MemoryChannel, bool>("MT", new object[] { _tickerTextMemoryChannel }, _cancellationToken);
734 if (!success)
735 {
736 Log.Error(Resources.Error_while_restoring_memory_text);
737  
738 return;
739 }
740 }
741 catch(Exception exception)
742 {
743 Log.Error(exception, Resources.Error_while_restoring_memory_text);
744 }
17 office 745 finally
746 {
747 _tickerTaskRunning = false;
748 }
15 office 749 }
750  
751 private async Task CycleText(Queue<char> characterQueue)
752 {
753 _tickerTaskRunning = true;
754 try
755 {
756 do
757 {
758 var text = string.Join("", characterQueue.OfType<char>());
759  
760 _tickerTextMemoryChannel.Text = text;
761  
762 await _catAssemblies.CatWriteAsync<MemoryChannel>("MT", new object[] { _tickerTextMemoryChannel }, _cancellationToken);
763  
764 var x = characterQueue.Dequeue();
765 characterQueue.Enqueue(x);
766  
767 await Task.Delay(250);
768  
769 } while (!_tagTickerCancellationToken.IsCancellationRequested);
770 }
771 catch(Exception exception)
772 {
773 Log.Error(exception, Resources.Error_while_cycling_text);
774 }
775 }
19 office 776  
777 private async void scrollableToolStripComboBox5_MouseWheel(object sender, MouseEventArgs e)
778 {
779 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
780 {
781 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
782 if (int.TryParse(toolStripComboBox.Text, out var memoryChannel))
783 {
784 switch (Math.Sign(e.Delta))
785 {
786 case -1:
787 memoryChannel = memoryChannel - 1;
788 break;
789 case 1:
790 memoryChannel = memoryChannel + 1;
791 break;
792 }
793  
794 soundPlayer.Play();
795  
796 try
797 {
798 await _catAssemblies.CatSetAsync<int, bool>("MC", new object[] { memoryChannel }, _cancellationToken);
799 toolStripComboBox.Text = $"{memoryChannel}";
800  
801 Log.Information($"{Resources.Set_VFO_A_frequency} {memoryChannel}");
802 }
803 catch (Exception exception)
804 {
805 Log.Error(exception, Resources.Failed_to_set_memory_channel);
806 }
807 }
808 }
809 }
810  
811 private async void scrollableToolStripComboBox5_TextChanged(object sender, EventArgs e)
812 {
813 var toolStripComboBox = (ToolStripComboBox)sender;
814 if (int.TryParse(toolStripComboBox.Text, out var memoryChannel))
815 {
816 try
817 {
818 await _catAssemblies.CatSetAsync<int, bool>("MC", new object[] { memoryChannel }, _cancellationToken);
819 }
820 catch (Exception exception)
821 {
822 Log.Error(exception, Resources.Failed_to_set_memory_channel);
823 }
824 }
825 }
20 office 826  
827 private async void powerToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
828 {
829 var toolStripMenuItem = toolStripMenuItem11;
830  
831 try
832 {
833 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
834 {
835 case PowerState.ON:
836 toolStripMenuItem.Text = Resources.On;
837 break;
838 case PowerState.OFF:
839 toolStripMenuItem.Text = Resources.Off;
840 break;
841 }
842 }
843 catch (Exception exception)
844 {
845 Log.Error(exception, Resources.Failed_to_read_power_state);
846 }
847 }
1 office 848 }
849 }