HamBook – Blame information for rev 37

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