HamBook – Blame information for rev 29

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