HamBook – Blame information for rev 44

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