HamBook – Blame information for rev 38

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