HamBook – Blame information for rev 30

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;
25 office 31 using System.Diagnostics;
32 using Newtonsoft.Json.Linq;
26 office 33 using System.Collections.Concurrent;
34 using Org.BouncyCastle.Math.Field;
1 office 35  
36 namespace HamBook
37 {
38 public partial class Form1 : Form
39 {
40 private ScheduledContinuation _changedConfigurationContinuation;
25 office 41 private ScheduledContinuation _squelchScheduledContinuation;
42 private ScheduledContinuation _powerScheduledContinuation;
43  
1 office 44 private Configuration.Configuration Configuration { get; set; }
9 office 45 private SerialPortStream _serialPort;
1 office 46 private LogMemorySink _memorySink;
47 private ViewLogsForm _viewLogsForm;
48 private AboutForm _aboutForm;
49 private SettingsForm _settingsForm;
50 private SparkleUpdater _sparkle;
51 private readonly CancellationToken _cancellationToken;
52 private readonly CancellationTokenSource _cancellationTokenSource;
53 private CatAssemblies _catAssemblies;
3 office 54 private BandScan _bandScan;
10 office 55 private SpectrogramForm _spectrogramForm;
15 office 56 private MemoryOrganizerForm _memoryOrganizerForm;
1 office 57  
15 office 58 private CancellationTokenSource _tagTickerCancellationTokenSource;
59 private CancellationToken _tagTickerCancellationToken;
60 private string _storedMemoryChannelTagText;
61 private string _storedMemoryChannelLocation;
62 private MemoryChannel _tickerTextMemoryChannel;
63 private Task _tickerTask;
64 private volatile bool _tickerTaskRunning;
65  
26 office 66 private ConcurrentDictionary<int, MemoryChannel> _memoryChannelStore = new ConcurrentDictionary<int, MemoryChannel>();
67  
1 office 68 public bool MemorySinkEnabled { get; set; }
69  
70 private Form1()
71 {
72 _cancellationTokenSource = new CancellationTokenSource();
73 _cancellationToken = _cancellationTokenSource.Token;
74  
75 _changedConfigurationContinuation = new ScheduledContinuation();
3 office 76  
25 office 77 _squelchScheduledContinuation = new ScheduledContinuation();
78 _powerScheduledContinuation = new ScheduledContinuation();
27 office 79 _vfoAScheduledContinuation = new ScheduledContinuation();
80 _vfoBScheduledContinuation = new ScheduledContinuation();
25 office 81  
27 office 82 _vfoAReaderWriterLockSlim = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
83 _vfoBReaderWriterLockSlim = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
84  
1 office 85 }
86  
87 public Form1(Mutex mutex) : this()
88 {
89 InitializeComponent();
90  
91 _memorySink = new LogMemorySink();
92  
93 Log.Logger = new LoggerConfiguration()
94 .MinimumLevel.Debug()
95 .WriteTo.Conditional(condition => MemorySinkEnabled, configureSink => configureSink.Sink(_memorySink))
96 .WriteTo.File(Path.Combine(Constants.UserApplicationDirectory, "Logs", $"{Constants.AssemblyName}.log"),
97 rollingInterval: RollingInterval.Day)
98 .CreateLogger();
99  
100 // Start application update.
101 var manifestModuleName = Assembly.GetEntryAssembly().ManifestModule.FullyQualifiedName;
102 var icon = Icon.ExtractAssociatedIcon(manifestModuleName);
103  
104 _sparkle = new SparkleUpdater("https://hambook.grimore.org/update/appcast.xml",
105 new Ed25519Checker(SecurityMode.Strict, "LonrgxVjSF0GnY4hzwlRJnLkaxnDn2ikdmOifILzLJY="))
106 {
107 UIFactory = new UIFactory(icon),
108 RelaunchAfterUpdate = true
109 };
110 }
111  
112 private async void Form1_Load(object sender, EventArgs e)
113 {
13 office 114 _sparkle.StartLoop(true, true);
115  
1 office 116 Configuration = await LoadConfiguration();
117  
7 office 118 _serialPort = InitializeSerialPort(Configuration);
1 office 119  
7 office 120 _catAssemblies = InitializeAssemblies(_serialPort);
1 office 121  
122 try
123 {
9 office 124 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
1 office 125 {
126 case PowerState.ON:
7 office 127 Log.Information(Resources.Attempting_to_initialize_radio);
9 office 128 if(!await InitializeRadio())
7 office 129 {
130 return;
131 }
132  
133 Log.Information(Resources.Initializing_GUI);
1 office 134 break;
135 }
136 }
137 catch(Exception exception)
138 {
139 Log.Error(exception, Resources.Failed_to_read_power_state);
140 }
26 office 141  
142 var memoryBankQueue = new ConcurrentQueue<int>();
143 var memoryBankTaskCompletionSource = new TaskCompletionSource<bool>();
144  
145 async void IdleHandler(object idleHandlerSender, EventArgs idleHandlerArgs)
146 {
147 await memoryBankTaskCompletionSource.Task;
148  
149 try
150 {
151 if (!memoryBankQueue.TryDequeue(out var memoryBank))
152 {
153 System.Windows.Forms.Application.Idle -= IdleHandler;
154  
155 return;
156 }
157  
158 var location = $"{memoryBank:000}";
159  
160 MemoryChannel memoryChannel = new MemoryChannel();
161  
162 try
163 {
164 memoryChannel = await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { location }, _cancellationToken);
165  
166 scrollableToolStripComboBox5.Items.Add(location);
167  
168 }
169 catch(Exception exception)
170 {
171 Log.Warning(exception, Resources.Could_not_read_memory_bank);
172  
173 return;
174 }
175  
176 _memoryChannelStore.TryAdd(memoryBank, memoryChannel);
177  
178 }
179 catch (Exception exception)
180 {
181 Log.Error(exception, Resources.Could_not_update_data_grid_view);
182 }
183 }
184  
185 System.Windows.Forms.Application.Idle += IdleHandler;
186 try
187 {
188 foreach (var memoryBank in Enumerable.Range(1, 99))
189 {
190 memoryBankQueue.Enqueue(memoryBank);
191 }
192  
193 memoryBankTaskCompletionSource.TrySetResult(true);
194 }
195 catch (Exception exception)
196 {
197 System.Windows.Forms.Application.Idle -= IdleHandler;
198  
199 Log.Error(exception, Resources.Unable_to_create_memory_banks);
200 }
1 office 201 }
202  
9 office 203 private async void quitToolStripMenuItem_Click(object sender, EventArgs e)
1 office 204 {
9 office 205 if(_bandScan != null)
206 {
207 await _bandScan.Stop();
208 _bandScan = null;
209 }
210  
14 office 211 // Save configuration on quit.
212 await SaveConfiguration();
213  
1 office 214 Close();
215 }
216  
217 private void viewLogsToolStripMenuItem_Click(object sender, EventArgs e)
218 {
219 if (_viewLogsForm != null)
220 {
221 return;
222 }
223  
224 _viewLogsForm = new ViewLogsForm(this, _memorySink, _cancellationToken);
225 _viewLogsForm.Closing += ViewLogsForm_Closing;
226 _viewLogsForm.Show();
227 }
228  
229 private void ViewLogsForm_Closing(object sender, CancelEventArgs e)
230 {
231 if (_viewLogsForm == null)
232 {
233 return;
234 }
235  
236 _viewLogsForm.Closing -= ViewLogsForm_Closing;
237 _viewLogsForm.Close();
238 _viewLogsForm = null;
239 }
240  
241 private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
242 {
243 if (_aboutForm != null)
244 {
245 return;
246 }
247  
248 _aboutForm = new AboutForm(_cancellationToken);
249 _aboutForm.Closing += AboutForm_Closing;
250 _aboutForm.Show();
251 }
252  
253 private void AboutForm_Closing(object sender, CancelEventArgs e)
254 {
255 if (_aboutForm == null)
256 {
257 return;
258 }
259  
260 _aboutForm.Dispose();
261 _aboutForm = null;
262 }
263  
264 private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
265 {
266 if (_settingsForm != null)
267 {
268 return;
269 }
270  
271 _settingsForm = new SettingsForm(Configuration, _cancellationToken);
272 _settingsForm.Closing += SettingsForm_Closing;
273 _settingsForm.Show();
274 }
275  
276 private void SettingsForm_Closing(object sender, CancelEventArgs e)
277 {
278 if (_settingsForm == null)
279 {
280 return;
281 }
282  
283 if(_settingsForm.SaveOnClose)
284 {
285 // Commit the configuration.
286 _changedConfigurationContinuation.Schedule(TimeSpan.FromSeconds(1),
287 async () => {
288 await SaveConfiguration();
289  
11 office 290 if(_bandScan != null)
291 {
292 await _bandScan.Stop();
293 _bandScan = null;
294 }
295  
296  
1 office 297 Miscellaneous.LaunchOnBootSet(Configuration.LaunchOnBoot);
298  
7 office 299 _serialPort = InitializeSerialPort(Configuration);
1 office 300  
7 office 301 _catAssemblies = InitializeAssemblies(_serialPort);
302  
303 try
304 {
9 office 305 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
7 office 306 {
307 case PowerState.ON:
308 Log.Information(Resources.Attempting_to_initialize_radio);
9 office 309 if (!await InitializeRadio())
7 office 310 {
311 return;
312 }
313 Log.Information(Resources.Initializing_GUI);
314 break;
315 }
316 }
317 catch (Exception exception)
318 {
319 Log.Error(exception, Resources.Failed_to_read_power_state);
320 }
321  
1 office 322 }, _cancellationToken);
323 }
324  
325 _settingsForm.Dispose();
326 _settingsForm = null;
327 }
328  
329 public async Task SaveConfiguration()
330 {
331 if (!Directory.Exists(Constants.UserApplicationDirectory))
332 {
333 Directory.CreateDirectory(Constants.UserApplicationDirectory);
334 }
335  
336 switch (await Serialization.Serialize(Configuration, Constants.ConfigurationFile, "Configuration",
337 "<!ATTLIST Configuration xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>",
338 CancellationToken.None))
339 {
3 office 340 case SerializationSuccess<Configuration.Configuration> configuration:
16 office 341 Log.Information(Resources.Configuration_serialized_successfully);
1 office 342 break;
343 case SerializationFailure serializationFailure:
16 office 344 Log.Warning(serializationFailure.Exception.Message, Resources.Configuration_failed_to_serialize);
1 office 345 break;
346 }
347 }
348  
349 public static async Task<Configuration.Configuration> LoadConfiguration()
350 {
351 if (!Directory.Exists(Constants.UserApplicationDirectory))
352 {
353 Directory.CreateDirectory(Constants.UserApplicationDirectory);
354 }
355  
356 var deserializationResult =
357 await Serialization.Deserialize<Configuration.Configuration>(Constants.ConfigurationFile,
358 Constants.ConfigurationNamespace, Constants.ConfigurationXsd, CancellationToken.None);
359  
360 switch (deserializationResult)
361 {
362 case SerializationSuccess<Configuration.Configuration> serializationSuccess:
363 return serializationSuccess.Result;
364 case SerializationFailure serializationFailure:
16 office 365 Log.Warning(serializationFailure.Exception, Resources.Configuration_failed_to_deserialize);
1 office 366 return new Configuration.Configuration();
367 default:
368 return new Configuration.Configuration();
369 }
370 }
371  
9 office 372 private async Task<bool> InitializeRadio()
1 office 373 {
374 try
375 {
9 office 376 await _catAssemblies.CatWriteAsync<InformationState>("AI", new object[] { InformationState.OFF }, _cancellationToken);
377  
11 office 378 return await _catAssemblies.CatReadAsync<bool>("ID", new object[] { }, _cancellationToken);
1 office 379 }
380 catch(Exception exception)
381 {
7 office 382 Log.Error(exception, Resources.Unable_to_initialize_radio);
11 office 383  
7 office 384 return false;
1 office 385 }
7 office 386 }
387  
9 office 388 private CatAssemblies InitializeAssemblies(SerialPortStream serialPort)
7 office 389 {
390 if(_catAssemblies != null)
1 office 391 {
7 office 392 _catAssemblies.Dispose();
393 _catAssemblies = null;
1 office 394 }
395  
7 office 396 return new CatAssemblies(serialPort, Configuration.Radio);
397 }
398  
9 office 399 private SerialPortStream InitializeSerialPort(Configuration.Configuration configuration)
7 office 400 {
401 if (_serialPort != null)
1 office 402 {
7 office 403 if (_serialPort.IsOpen)
404 {
405 _serialPort.Close();
406 }
26 office 407  
7 office 408 _serialPort.Dispose();
409 _serialPort = null;
1 office 410 }
411  
7 office 412 // Set up serial connection.
9 office 413 var serialPort = new SerialPortStream(configuration.Port, configuration.Speed, configuration.DataBits, configuration.Parity, configuration.StopBits);
7 office 414 serialPort.ReadTimeout = configuration.SerialPortTimeout.Read;
415 serialPort.WriteTimeout = configuration.SerialPortTimeout.Write;
416 serialPort.Handshake = configuration.Handshake;
9 office 417 serialPort.Encoding = Encoding.ASCII;
1 office 418  
7 office 419 Log.Information($"{Resources.Initialized_serial_port} {configuration.Port} {configuration.Speed} {configuration.Parity} {configuration.DataBits} {configuration.StopBits}");
420  
421 return serialPort;
1 office 422 }
423  
424 private async void updateToolStripMenuItem_Click(object sender, EventArgs e)
425 {
426 // Manually check for updates, this will not show a ui
427 var result = await _sparkle.CheckForUpdatesQuietly();
428 if (result.Status == NetSparkleUpdater.Enums.UpdateStatus.UpdateAvailable)
429 {
430 // if update(s) are found, then we have to trigger the UI to show it gracefully
431 _sparkle.ShowUpdateNeededUI();
432 return;
433 }
434  
435 MessageBox.Show(Resources.No_updates_available_at_this_time, Resources.HamBook, MessageBoxButtons.OK,
436 MessageBoxIcon.Asterisk,
437 MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, false);
438 }
439  
440 private async void onToolStripMenuItem_Click(object sender, EventArgs e)
441 {
442 try
443 {
15 office 444 await _catAssemblies.CatSetAsync<PowerState, bool>("PS", new object[] { PowerState.ON }, _cancellationToken);
1 office 445 }
446 catch(Exception exception)
447 {
448 Log.Error(exception, Resources.Failed_to_set_power_state);
449 }
450 }
451  
452 private async void offToolStripMenuItem_Click(object sender, EventArgs e)
453 {
454 try
455 {
15 office 456 await _catAssemblies.CatSetAsync<PowerState, bool>("PS", new object[] { PowerState.OFF }, _cancellationToken);
1 office 457 }
458 catch(Exception exception)
459 {
460 Log.Error(exception, Resources.Failed_to_set_power_state);
461 }
462 }
463  
29 office 464 private async void scrollableToolStripComboBox2_MouseWheel(object sender, MouseEventArgs e)
1 office 465 {
27 office 466 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
467 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1 office 468 {
27 office 469 switch (Math.Sign(e.Delta))
3 office 470 {
27 office 471 case -1:
472 frequency = frequency - Configuration.Navigation.FrequencyStep;
473 break;
474 case 1:
475 frequency = frequency + Configuration.Navigation.FrequencyStep;
476 break;
477 }
5 office 478  
27 office 479 try
3 office 480 {
27 office 481 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
482 {
29 office 483 if (await _catAssemblies.CatSetAsync<int, bool>("FB", new object[] { frequency }, _cancellationToken))
484 {
485 toolStripComboBox.Text = $"{frequency}";
27 office 486  
29 office 487 soundPlayer.Play();
488 }
27 office 489 }
3 office 490 }
491 catch (Exception exception)
492 {
27 office 493 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
3 office 494 }
1 office 495 }
496 }
497  
29 office 498 private async void scrollableToolStripComboBox2_KeyPress(object sender, KeyPressEventArgs e)
1 office 499 {
29 office 500 switch (e.KeyChar)
1 office 501 {
29 office 502 case (char)Keys.Enter:
503 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
27 office 504  
29 office 505 if (int.TryParse(toolStripComboBox.Text, out var frequency))
27 office 506 {
29 office 507 try
508 {
509 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
510 {
511 if (await _catAssemblies.CatSetAsync<int, bool>("FB", new object[] { frequency }, _cancellationToken))
512 {
513 e.Handled = true;
27 office 514  
29 office 515 soundPlayer.Play();
516 }
517 }
518 }
519 catch (Exception exception)
520 {
521 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
522 }
523 }
524 break;
27 office 525 }
3 office 526 }
527  
9 office 528 private async void toolStripMenuItem1_Click(object sender, EventArgs e)
3 office 529 {
530 if (_bandScan == null)
531 {
1 office 532 return;
533 }
534  
9 office 535 await _bandScan.Stop();
3 office 536 _bandScan = null;
1 office 537 }
3 office 538  
9 office 539 private async void scanToolStripMenuItem_Click(object sender, EventArgs e)
3 office 540 {
5 office 541 if (!(sender is ToolStripMenuItem toolStripMenuItem) ||
542 !int.TryParse(toolStripMenuItem.Tag.ToString(), out var meters))
3 office 543 {
5 office 544 return;
3 office 545 }
546  
5 office 547 if (!int.TryParse(scrollableToolStripComboBox3.Text, out var pause))
3 office 548 {
5 office 549 pause = 5;
3 office 550 }
551  
5 office 552 if(!int.TryParse(scrollableToolStripComboBox4.Text, out var step))
3 office 553 {
5 office 554 step = 5000;
3 office 555 }
556  
21 office 557 if(!int.TryParse(scrollableToolStripComboBox6.Text, out var scanDetectPause))
558 {
559 scanDetectPause = 10;
560 }
561  
5 office 562 if (!Configuration.Definitions.TryGetBand(meters, out var band))
3 office 563 {
5 office 564 return;
3 office 565 }
566  
567 if (_bandScan != null)
568 {
9 office 569 await _bandScan.Stop();
570 _bandScan = null;
3 office 571 }
572  
21 office 573 _bandScan = new BandScan(_catAssemblies, (int)band.Min, (int)band.Max, _serialPort, Configuration);
9 office 574  
23 office 575 //toolStripMenuItem16
21 office 576 if (toolStripMenuItem14.Checked)
577 {
23 office 578 _bandScan.Start(step, pause, scanDetectPause, toolStripMenuItem16.Checked);
21 office 579  
580 return;
581 }
582  
23 office 583 _bandScan.Start(step, pause, toolStripMenuItem16.Checked);
3 office 584 }
585  
11 office 586 private void modeToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
3 office 587 {
11 office 588 Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken).ContinueWith(async task =>
7 office 589 {
11 office 590 try
591 {
592 var mode = await _catAssemblies.CatReadAsync<RadioMode>("MD", new object[] { }, _cancellationToken);
7 office 593  
11 office 594 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
595 {
596 toolStripComboBox1.Text = mode;
597 });
598 }
599 catch (Exception exception)
600 {
601 Log.Error(exception, Resources.Failed_to_read_radio_mode);
602 }
7 office 603  
11 office 604 try
605 {
606 var fa = await _catAssemblies.CatReadAsync<int>("FA", new object[] { }, _cancellationToken);
7 office 607  
11 office 608 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
609 {
29 office 610 scrollableToolStripComboBox1.Text = $"{fa}";
11 office 611  
612 });
613  
614 }
615 catch (Exception exception)
616 {
617 Log.Error(exception, Resources.Failed_to_read_VFO_A);
618 }
619  
620 try
621 {
622 var fb = await _catAssemblies.CatReadAsync<int>("FB", new object[] { }, _cancellationToken);
623  
624 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
625 {
29 office 626 scrollableToolStripComboBox2.Text = $"{fb}";
11 office 627  
628 });
629 }
630 catch (Exception exception)
631 {
632 Log.Error(exception, Resources.Failed_to_read_VFO_B);
633 }
19 office 634  
635 try
636 {
637 var mc = await _catAssemblies.CatReadAsync<int>("MC", new object[] { }, _cancellationToken);
638  
639 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
640 {
26 office 641 scrollableToolStripComboBox5.Text = $"{mc:000}";
19 office 642  
26 office 643 if(_memoryChannelStore.TryGetValue(mc, out var memoryChannel))
644 {
645 toolStripMenuItem27.Text = memoryChannel.Text;
646 }
647  
19 office 648 });
649 }
650 catch (Exception exception)
651 {
652 Log.Error(exception, Resources.Failed_to_read_memory_channel);
653 }
24 office 654  
655 try
656 {
657 var pc = await _catAssemblies.CatReadAsync<int>("PC", new object[] { }, _cancellationToken);
658  
659 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
660 {
661 scrollableToolStripComboBox7.Text = $"{pc}";
662  
663 });
664 }
665 catch (Exception exception)
666 {
25 office 667 Log.Error(exception, Resources.Failed_to_read_power_state);
24 office 668 }
11 office 669 }, _cancellationToken);
3 office 670 }
10 office 671  
672 private void spectrogramToolStripMenuItem_Click(object sender, EventArgs e)
673 {
674 if (_spectrogramForm != null)
675 {
676 return;
677 }
678  
679 _spectrogramForm = new SpectrogramForm(Configuration, _cancellationToken);
680 _spectrogramForm.Closing += SpectrogramForm_Closing;
681 _spectrogramForm.Show();
682 }
683  
684 private void SpectrogramForm_Closing(object sender, CancelEventArgs e)
685 {
686 if (_spectrogramForm == null)
687 {
688 return;
689 }
690  
691 _spectrogramForm.Dispose();
692 _spectrogramForm = null;
14 office 693  
694 // Commit the configuration.
695 _changedConfigurationContinuation.Schedule(TimeSpan.FromSeconds(1),
696 async () =>
697 {
698 await SaveConfiguration();
699 }, _cancellationToken);
10 office 700 }
15 office 701  
702 private void toolStripMenuItem3_Click(object sender, EventArgs e)
703 {
704 if (_memoryOrganizerForm != null)
705 {
706 return;
707 }
708  
709 _memoryOrganizerForm = new MemoryOrganizerForm(Configuration, _catAssemblies, _cancellationToken);
710 _memoryOrganizerForm.Closing += MemoryOrganizerForm_Closing;
711 _memoryOrganizerForm.Show();
712 }
713  
714 private void MemoryOrganizerForm_Closing(object sender, CancelEventArgs e)
715 {
716 if (_memoryOrganizerForm == null)
717 {
718 return;
719 }
720  
721 _memoryOrganizerForm.Dispose();
722 _memoryOrganizerForm = null;
723  
724 }
725  
726 private async void toolStripMenuItem4_Click(object sender, EventArgs e)
727 {
728 if (_tickerTaskRunning)
729 {
730 return;
731 }
732  
733 var toolStripTextBox = (ToolStripTextBox)toolStripTextBox6;
734  
735 try
736 {
737 var result = await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { "001" }, _cancellationToken);
738  
739 _tickerTextMemoryChannel = await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { $"{result.CurrentLocation}" }, _cancellationToken);
740  
741 _storedMemoryChannelTagText = _tickerTextMemoryChannel.Text;
742 _storedMemoryChannelLocation = _tickerTextMemoryChannel.CurrentLocation;
743 }
744 catch(Exception exception)
745 {
746 Log.Error(exception, Resources.Could_not_read_memory_bank);
747 }
748  
749 var tickerText = $"{toolStripTextBox.Text,-12}";
750  
751 _tagTickerCancellationTokenSource = new CancellationTokenSource();
752 _tagTickerCancellationToken = _tagTickerCancellationTokenSource.Token;
753  
754 var characterQueue = new Queue<char>(12);
755 foreach(var i in Enumerable.Range(0, 12))
756 {
757 var x = tickerText.ElementAtOrDefault(i);
758  
759 if(x == default)
760 {
761 characterQueue.Enqueue(' ');
762 continue;
763 }
764  
765 characterQueue.Enqueue(x);
766 }
767  
768 #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
769 _tickerTask = Task.Run(() => CycleText(characterQueue), _cancellationToken);
770 #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
771 }
772  
773 private async void toolStripMenuItem5_Click(object sender, EventArgs e)
774 {
775 if(!_tickerTaskRunning)
776 {
777 return;
778 }
779  
780 _tagTickerCancellationTokenSource.Cancel();
781 if (_tickerTask != null)
782 {
783 await _tickerTask;
784 _tickerTask = null;
785 }
786  
787 try
788 {
789 _tickerTextMemoryChannel.CurrentLocation = $"{_storedMemoryChannelLocation:000}";
17 office 790 _tickerTextMemoryChannel.Text = $"{_storedMemoryChannelTagText, -12}";
15 office 791  
792 var success = await _catAssemblies.CatSetAsync<MemoryChannel, bool>("MT", new object[] { _tickerTextMemoryChannel }, _cancellationToken);
793 if (!success)
794 {
795 Log.Error(Resources.Error_while_restoring_memory_text);
796  
797 return;
798 }
799 }
800 catch(Exception exception)
801 {
802 Log.Error(exception, Resources.Error_while_restoring_memory_text);
803 }
17 office 804 finally
805 {
806 _tickerTaskRunning = false;
807 }
15 office 808 }
809  
810 private async Task CycleText(Queue<char> characterQueue)
811 {
812 _tickerTaskRunning = true;
813 try
814 {
815 do
816 {
817 var text = string.Join("", characterQueue.OfType<char>());
818  
819 _tickerTextMemoryChannel.Text = text;
820  
821 await _catAssemblies.CatWriteAsync<MemoryChannel>("MT", new object[] { _tickerTextMemoryChannel }, _cancellationToken);
822  
823 var x = characterQueue.Dequeue();
824 characterQueue.Enqueue(x);
825  
826 await Task.Delay(250);
827  
828 } while (!_tagTickerCancellationToken.IsCancellationRequested);
829 }
830 catch(Exception exception)
831 {
832 Log.Error(exception, Resources.Error_while_cycling_text);
833 }
834 }
19 office 835  
27 office 836 private async void scrollableToolStripComboBox5_SelectedIndexChanged(object sender, EventArgs e)
19 office 837 {
27 office 838 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
19 office 839 {
27 office 840 var toolStripComboBox = (ToolStripComboBox)sender;
841 if (int.TryParse(toolStripComboBox.Text, out var channel))
19 office 842 {
27 office 843 if (_memoryChannelStore.TryGetValue(channel, out var memoryChannel))
844 {
845 try
846 {
847 await _catAssemblies.CatWriteAsync<int>("MC", new object[] { channel }, _cancellationToken);
19 office 848  
27 office 849 scrollableToolStripComboBox1.Text = $"{memoryChannel.Frequency}";
24 office 850  
27 office 851 toolStripMenuItem27.Text = memoryChannel.Text;
24 office 852  
27 office 853 soundPlayer.Play();
854 }
855 catch (Exception exception)
856 {
857 Log.Error(exception, Resources.Failed_to_set_memory_channel);
858 }
26 office 859 }
19 office 860 }
861 }
862 }
20 office 863  
864 private async void powerToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
865 {
866 var toolStripMenuItem = toolStripMenuItem11;
867  
868 try
869 {
870 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
871 {
872 case PowerState.ON:
873 toolStripMenuItem.Text = Resources.On;
874 break;
875 case PowerState.OFF:
876 toolStripMenuItem.Text = Resources.Off;
877 break;
878 }
879 }
880 catch (Exception exception)
881 {
882 Log.Error(exception, Resources.Failed_to_read_power_state);
883 }
884 }
23 office 885  
886 private async void toolStripMenuItem17_Click(object sender, EventArgs e)
887 {
888 try
889 {
890 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON }, _cancellationToken);
891  
892 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START }, _cancellationToken);
893 }
894 catch (Exception exception)
895 {
896 Log.Error(exception, Resources.Failed_tuning_current_frequency);
897 }
898 }
24 office 899  
900 private async void toolStripMenuItem22_CheckStateChanged(object sender, EventArgs e)
901 {
902 var toolStripMenuItem = (ToolStripMenuItem)sender;
903 try
904 {
905 if (toolStripMenuItem.Checked)
906 {
907 await _catAssemblies.CatWriteAsync<IpoState>("PA", new object[] { IpoState.IPO }, _cancellationToken);
908 return;
909 }
910  
911 await _catAssemblies.CatWriteAsync<IpoState>("PA", new object[] { IpoState.AMP }, _cancellationToken);
912 }
913 catch (Exception exception)
914 {
915 Log.Error(exception, Resources.Failed_setting_IPO);
916 }
917 }
918  
919 private async void toolStripMenuItem23_CheckStateChanged(object sender, EventArgs e)
920 {
921 var toolStripMenuItem = (ToolStripMenuItem)sender;
922  
923 try
924 {
925 if (toolStripMenuItem.Checked)
926 {
927 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON }, _cancellationToken);
928  
929 return;
930 }
931  
932 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_OFF }, _cancellationToken);
933 }
934 catch (Exception exception)
935 {
936 Log.Error(exception, Resources.Failed_setting_the_tuner_state);
937 }
938 }
939  
940 private async void toolStripMenuItem24_Click(object sender, EventArgs e)
941 {
942 try
943 {
944 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START }, _cancellationToken);
945 }
946 catch(Exception exception)
947 {
948  
949 }
950 }
25 office 951  
952 private void toolStripMenuItem21_DropDownOpened(object sender, EventArgs e)
953 {
954 Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken).ContinueWith(async task =>
955 {
956 try
957 {
958 var ac = await _catAssemblies.CatReadAsync<TunerState>("AC", new object[] { }, _cancellationToken);
959  
960 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
961 {
962 switch (ac)
963 {
964 case TunerState.TUNING_START:
965 case TunerState.TUNER_ON:
966 toolStripMenuItem23.Checked = true;
967 break;
968 case TunerState.TUNER_OFF:
969 toolStripMenuItem23.Checked = false;
970 break;
971 }
972  
973  
974 });
975 }
976 catch (Exception exception)
977 {
978 Log.Error(exception, Resources.Failed_to_read_the_tuner_state);
979 }
980  
981 try
982 {
983 var pa = await _catAssemblies.CatReadAsync<IpoState>("PA", new object[] { }, _cancellationToken);
984  
985 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
986 {
987 switch (pa)
988 {
989 case IpoState.AMP:
990 toolStripMenuItem22.Checked = false;
991 break;
992 case IpoState.IPO:
993 toolStripMenuItem22.Checked = true;
994 break;
995 }
996  
997  
998 });
999 }
1000 catch (Exception exception)
1001 {
1002 Log.Error(exception, Resources.Failed_to_read_IPO);
1003 }
1004 }, _cancellationToken);
1005 }
1006  
1007 private async void toolStripMenuItem19_DropDownOpened(object sender, EventArgs e)
1008 {
1009 try
1010 {
1011 var sq = await _catAssemblies.CatReadAsync<int>("SQ", new object[] { }, _cancellationToken);
1012  
1013 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
1014 {
1015 scrollableToolStripComboBox8.Text = $"{sq}";
1016  
1017 });
1018 }
1019 catch (Exception exception)
1020 {
1021 Log.Error(exception, Resources.Failed_to_read_squelch);
1022 }
1023 }
1024  
29 office 1025 private async void scrollableToolStripComboBox1_MouseWheel(object sender, MouseEventArgs e)
25 office 1026 {
1027 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
27 office 1028 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1029 {
1030 switch (Math.Sign(e.Delta))
1031 {
1032 case -1:
1033 frequency = frequency - Configuration.Navigation.FrequencyStep;
1034 break;
1035 case 1:
1036 frequency = frequency + Configuration.Navigation.FrequencyStep;
1037 break;
1038 }
25 office 1039  
27 office 1040 try
1041 {
29 office 1042 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
25 office 1043 {
29 office 1044 if (await _catAssemblies.CatSetAsync<int, bool>("FA", new object[] { frequency }, _cancellationToken))
1045 {
1046 toolStripComboBox.Text = $"{frequency}";
25 office 1047  
29 office 1048 soundPlayer.Play();
1049 }
25 office 1050 }
27 office 1051 }
1052 catch (Exception exception)
1053 {
1054 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
1055 }
1056 }
1057 }
25 office 1058  
29 office 1059 private async void scrollableToolStripComboBox1_KeyPress(object sender, KeyPressEventArgs e)
27 office 1060 {
29 office 1061 switch (e.KeyChar)
27 office 1062 {
29 office 1063 case (char)Keys.Enter:
1064 e.Handled = true;
25 office 1065  
29 office 1066 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
27 office 1067  
29 office 1068 if (int.TryParse(toolStripComboBox.Text, out var frequency))
27 office 1069 {
29 office 1070 try
1071 {
1072 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
1073 {
1074 if (await _catAssemblies.CatSetAsync<int, bool>("FA", new object[] { frequency }, _cancellationToken))
1075 {
1076  
1077 soundPlayer.Play();
1078 }
1079 }
1080 }
1081 catch (Exception exception)
1082 {
1083 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
1084 }
1085 }
1086 break;
27 office 1087 }
25 office 1088 }
1089  
27 office 1090 private void scrollableToolStripComboBox8_SelectedIndexChanged(object sender, EventArgs e)
25 office 1091 {
1092 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
1093  
1094 _squelchScheduledContinuation.Schedule(TimeSpan.FromSeconds(1), () =>
1095 {
1096 contextMenuStrip1.InvokeIfRequired(async contextMenuStrip1 =>
1097 {
1098 if (int.TryParse(toolStripComboBox.Text, out var squelch))
1099 {
1100  
1101 try
1102 {
1103 await _catAssemblies.CatWriteAsync<int>("SQ", new object[] { squelch }, _cancellationToken);
1104  
1105 toolStripComboBox.Text = $"{squelch}";
1106  
27 office 1107 Log.Information($"{Resources.Squelch_set} {squelch}");
25 office 1108 }
1109 catch (Exception exception)
1110 {
1111 Log.Error(exception, Resources.Failed_to_set_squelch);
1112 }
1113 }
1114 });
1115 }, _cancellationToken);
1116 }
27 office 1117  
1118 private async void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
1119 {
1120 var toolStripComboBox = (ToolStripComboBox)sender;
1121 if (RadioMode.TryParse(toolStripComboBox.Text, out var radioMode))
1122 {
1123 try
1124 {
1125 await _catAssemblies.CatSetAsync<RadioMode, bool>("MD", new object[] { radioMode }, _cancellationToken);
1126 }
1127 catch (Exception exception)
1128 {
1129 Log.Error(exception, Resources.Failed_to_set_radio_mode, radioMode);
1130 }
1131 }
1132 }
1133  
1134 private void scrollableToolStripComboBox7_SelectedIndexChanged(object sender, EventArgs e)
1135 {
1136 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
1137  
1138 _powerScheduledContinuation.Schedule(TimeSpan.FromSeconds(1), () =>
1139 {
1140 contextMenuStrip1.InvokeIfRequired(async contextMenuStrip1 =>
1141 {
1142 if (int.TryParse(toolStripComboBox.Text, out var amplification))
1143 {
1144  
1145 try
1146 {
1147 await _catAssemblies.CatWriteAsync<int>("PC", new object[] { amplification }, _cancellationToken);
1148  
1149 toolStripComboBox.Text = $"{amplification}";
1150  
1151 Log.Information($"{Resources.Amplification_set} {amplification}W");
1152 }
1153 catch (Exception exception)
1154 {
1155 Log.Error(exception, Resources.Failed_to_set_amplification);
1156 }
1157 }
1158 });
1159 }, _cancellationToken);
1160 }
1161  
29 office 1162  
1 office 1163 }
1164 }