HamBook – Blame information for rev 27

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  
27 office 468 private 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 (frequency < 0)
484 {
485 frequency = 0;
486 }
24 office 487  
27 office 488 if (!_vfoAReaderWriterLockSlim.TryEnterReadLock(250))
489 {
490 return;
3 office 491 }
1 office 492  
27 office 493 try
3 office 494 {
27 office 495 toolStripComboBox.Value = $"{frequency}";
496 }
497 finally
498 {
499 if (_vfoAReaderWriterLockSlim.IsReadLockHeld)
5 office 500 {
27 office 501 _vfoAReaderWriterLockSlim.ExitReadLock();
5 office 502 }
1 office 503 }
504 }
505 }
506  
27 office 507 private async void scrollableToolStripComboBox2_SelectedIndexChanged(object sender, EventArgs e)
1 office 508 {
3 office 509 var toolStripComboBox = (ToolStripComboBox)sender;
510 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1 office 511 {
3 office 512 try
513 {
27 office 514 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
515 {
516 await _catAssemblies.CatSetAsync<int, bool>("FB", new object[] { frequency }, _cancellationToken);
517  
518 soundPlayer.Play();
519 }
3 office 520 }
521 catch (Exception exception)
522 {
27 office 523 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
3 office 524 }
1 office 525 }
526 }
527  
27 office 528 private void scrollableToolStripComboBox2_TextChanged(object sender, EventArgs e)
1 office 529 {
27 office 530 if (!_vfoAReaderWriterLockSlim.TryEnterReadLock(250))
1 office 531 {
27 office 532 return;
533 }
534  
535 try
536 {
537 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
538 var frequency = toolStripComboBox.Text;
539  
540 _vfoAScheduledContinuation.Schedule(TimeSpan.FromSeconds(1), async () =>
1 office 541 {
27 office 542 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
543 {
544 toolStripComboBox.Value = $"{frequency}";
545 });
546  
547 }, _cancellationToken);
548 }
549 finally
550 {
551 if (_vfoAReaderWriterLockSlim.IsReadLockHeld)
1 office 552 {
27 office 553 _vfoAReaderWriterLockSlim.ExitReadLock();
1 office 554 }
3 office 555 }
556 }
557  
9 office 558 private async void toolStripMenuItem1_Click(object sender, EventArgs e)
3 office 559 {
560 if (_bandScan == null)
561 {
1 office 562 return;
563 }
564  
9 office 565 await _bandScan.Stop();
3 office 566 _bandScan = null;
1 office 567 }
3 office 568  
9 office 569 private async void scanToolStripMenuItem_Click(object sender, EventArgs e)
3 office 570 {
5 office 571 if (!(sender is ToolStripMenuItem toolStripMenuItem) ||
572 !int.TryParse(toolStripMenuItem.Tag.ToString(), out var meters))
3 office 573 {
5 office 574 return;
3 office 575 }
576  
5 office 577 if (!int.TryParse(scrollableToolStripComboBox3.Text, out var pause))
3 office 578 {
5 office 579 pause = 5;
3 office 580 }
581  
5 office 582 if(!int.TryParse(scrollableToolStripComboBox4.Text, out var step))
3 office 583 {
5 office 584 step = 5000;
3 office 585 }
586  
21 office 587 if(!int.TryParse(scrollableToolStripComboBox6.Text, out var scanDetectPause))
588 {
589 scanDetectPause = 10;
590 }
591  
5 office 592 if (!Configuration.Definitions.TryGetBand(meters, out var band))
3 office 593 {
5 office 594 return;
3 office 595 }
596  
597 if (_bandScan != null)
598 {
9 office 599 await _bandScan.Stop();
600 _bandScan = null;
3 office 601 }
602  
21 office 603 _bandScan = new BandScan(_catAssemblies, (int)band.Min, (int)band.Max, _serialPort, Configuration);
9 office 604  
23 office 605 //toolStripMenuItem16
21 office 606 if (toolStripMenuItem14.Checked)
607 {
23 office 608 _bandScan.Start(step, pause, scanDetectPause, toolStripMenuItem16.Checked);
21 office 609  
610 return;
611 }
612  
23 office 613 _bandScan.Start(step, pause, toolStripMenuItem16.Checked);
3 office 614 }
615  
11 office 616 private void modeToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
3 office 617 {
11 office 618 Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken).ContinueWith(async task =>
7 office 619 {
11 office 620 try
621 {
622 var mode = await _catAssemblies.CatReadAsync<RadioMode>("MD", new object[] { }, _cancellationToken);
7 office 623  
11 office 624 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
625 {
626 toolStripComboBox1.Text = mode;
627 });
628 }
629 catch (Exception exception)
630 {
631 Log.Error(exception, Resources.Failed_to_read_radio_mode);
632 }
7 office 633  
11 office 634 try
635 {
636 var fa = await _catAssemblies.CatReadAsync<int>("FA", new object[] { }, _cancellationToken);
7 office 637  
11 office 638 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
639 {
27 office 640 scrollableToolStripComboBox1.Value = $"{fa}";
11 office 641  
642 });
643  
644 }
645 catch (Exception exception)
646 {
647 Log.Error(exception, Resources.Failed_to_read_VFO_A);
648 }
649  
650 try
651 {
652 var fb = await _catAssemblies.CatReadAsync<int>("FB", new object[] { }, _cancellationToken);
653  
654 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
655 {
27 office 656 scrollableToolStripComboBox2.Value = $"{fb}";
11 office 657  
658 });
659 }
660 catch (Exception exception)
661 {
662 Log.Error(exception, Resources.Failed_to_read_VFO_B);
663 }
19 office 664  
665 try
666 {
667 var mc = await _catAssemblies.CatReadAsync<int>("MC", new object[] { }, _cancellationToken);
668  
669 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
670 {
26 office 671 scrollableToolStripComboBox5.Text = $"{mc:000}";
19 office 672  
26 office 673 if(_memoryChannelStore.TryGetValue(mc, out var memoryChannel))
674 {
675 toolStripMenuItem27.Text = memoryChannel.Text;
676 }
677  
19 office 678 });
679 }
680 catch (Exception exception)
681 {
682 Log.Error(exception, Resources.Failed_to_read_memory_channel);
683 }
24 office 684  
685 try
686 {
687 var pc = await _catAssemblies.CatReadAsync<int>("PC", new object[] { }, _cancellationToken);
688  
689 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
690 {
691 scrollableToolStripComboBox7.Text = $"{pc}";
692  
693 });
694 }
695 catch (Exception exception)
696 {
25 office 697 Log.Error(exception, Resources.Failed_to_read_power_state);
24 office 698 }
11 office 699 }, _cancellationToken);
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 {
27 office 868 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
19 office 869 {
27 office 870 var toolStripComboBox = (ToolStripComboBox)sender;
871 if (int.TryParse(toolStripComboBox.Text, out var channel))
19 office 872 {
27 office 873 if (_memoryChannelStore.TryGetValue(channel, out var memoryChannel))
874 {
875 try
876 {
877 await _catAssemblies.CatWriteAsync<int>("MC", new object[] { channel }, _cancellationToken);
19 office 878  
27 office 879 scrollableToolStripComboBox1.Text = $"{memoryChannel.Frequency}";
24 office 880  
27 office 881 toolStripMenuItem27.Text = memoryChannel.Text;
24 office 882  
27 office 883 soundPlayer.Play();
884 }
885 catch (Exception exception)
886 {
887 Log.Error(exception, Resources.Failed_to_set_memory_channel);
888 }
26 office 889 }
19 office 890 }
891 }
892 }
20 office 893  
894 private async void powerToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
895 {
896 var toolStripMenuItem = toolStripMenuItem11;
897  
898 try
899 {
900 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
901 {
902 case PowerState.ON:
903 toolStripMenuItem.Text = Resources.On;
904 break;
905 case PowerState.OFF:
906 toolStripMenuItem.Text = Resources.Off;
907 break;
908 }
909 }
910 catch (Exception exception)
911 {
912 Log.Error(exception, Resources.Failed_to_read_power_state);
913 }
914 }
23 office 915  
916 private async void toolStripMenuItem17_Click(object sender, EventArgs e)
917 {
918 try
919 {
920 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON }, _cancellationToken);
921  
922 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START }, _cancellationToken);
923 }
924 catch (Exception exception)
925 {
926 Log.Error(exception, Resources.Failed_tuning_current_frequency);
927 }
928 }
24 office 929  
930 private async void toolStripMenuItem22_CheckStateChanged(object sender, EventArgs e)
931 {
932 var toolStripMenuItem = (ToolStripMenuItem)sender;
933 try
934 {
935 if (toolStripMenuItem.Checked)
936 {
937 await _catAssemblies.CatWriteAsync<IpoState>("PA", new object[] { IpoState.IPO }, _cancellationToken);
938 return;
939 }
940  
941 await _catAssemblies.CatWriteAsync<IpoState>("PA", new object[] { IpoState.AMP }, _cancellationToken);
942 }
943 catch (Exception exception)
944 {
945 Log.Error(exception, Resources.Failed_setting_IPO);
946 }
947 }
948  
949 private async void toolStripMenuItem23_CheckStateChanged(object sender, EventArgs e)
950 {
951 var toolStripMenuItem = (ToolStripMenuItem)sender;
952  
953 try
954 {
955 if (toolStripMenuItem.Checked)
956 {
957 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON }, _cancellationToken);
958  
959 return;
960 }
961  
962 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_OFF }, _cancellationToken);
963 }
964 catch (Exception exception)
965 {
966 Log.Error(exception, Resources.Failed_setting_the_tuner_state);
967 }
968 }
969  
970 private async void toolStripMenuItem24_Click(object sender, EventArgs e)
971 {
972 try
973 {
974 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START }, _cancellationToken);
975 }
976 catch(Exception exception)
977 {
978  
979 }
980 }
25 office 981  
982 private void toolStripMenuItem21_DropDownOpened(object sender, EventArgs e)
983 {
984 Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken).ContinueWith(async task =>
985 {
986 try
987 {
988 var ac = await _catAssemblies.CatReadAsync<TunerState>("AC", new object[] { }, _cancellationToken);
989  
990 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
991 {
992 switch (ac)
993 {
994 case TunerState.TUNING_START:
995 case TunerState.TUNER_ON:
996 toolStripMenuItem23.Checked = true;
997 break;
998 case TunerState.TUNER_OFF:
999 toolStripMenuItem23.Checked = false;
1000 break;
1001 }
1002  
1003  
1004 });
1005 }
1006 catch (Exception exception)
1007 {
1008 Log.Error(exception, Resources.Failed_to_read_the_tuner_state);
1009 }
1010  
1011 try
1012 {
1013 var pa = await _catAssemblies.CatReadAsync<IpoState>("PA", new object[] { }, _cancellationToken);
1014  
1015 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
1016 {
1017 switch (pa)
1018 {
1019 case IpoState.AMP:
1020 toolStripMenuItem22.Checked = false;
1021 break;
1022 case IpoState.IPO:
1023 toolStripMenuItem22.Checked = true;
1024 break;
1025 }
1026  
1027  
1028 });
1029 }
1030 catch (Exception exception)
1031 {
1032 Log.Error(exception, Resources.Failed_to_read_IPO);
1033 }
1034 }, _cancellationToken);
1035 }
1036  
1037 private async void toolStripMenuItem19_DropDownOpened(object sender, EventArgs e)
1038 {
1039 try
1040 {
1041 var sq = await _catAssemblies.CatReadAsync<int>("SQ", new object[] { }, _cancellationToken);
1042  
1043 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
1044 {
1045 scrollableToolStripComboBox8.Text = $"{sq}";
1046  
1047 });
1048 }
1049 catch (Exception exception)
1050 {
1051 Log.Error(exception, Resources.Failed_to_read_squelch);
1052 }
1053 }
1054  
27 office 1055 private void scrollableToolStripComboBox1_MouseWheel(object sender, MouseEventArgs e)
25 office 1056 {
1057 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
27 office 1058 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1059 {
1060 switch (Math.Sign(e.Delta))
1061 {
1062 case -1:
1063 frequency = frequency - Configuration.Navigation.FrequencyStep;
1064 break;
1065 case 1:
1066 frequency = frequency + Configuration.Navigation.FrequencyStep;
1067 break;
1068 }
25 office 1069  
27 office 1070 if (frequency < 0)
1071 {
1072 frequency = 0;
1073 }
25 office 1074  
27 office 1075 if (!_vfoAReaderWriterLockSlim.TryEnterReadLock(250))
25 office 1076 {
27 office 1077 return;
1078 }
1079  
1080 try
1081 {
1082 toolStripComboBox.Value = $"{frequency}";
1083 }
1084 finally
1085 {
1086 if (_vfoAReaderWriterLockSlim.IsReadLockHeld)
25 office 1087 {
27 office 1088 _vfoAReaderWriterLockSlim.ExitReadLock();
25 office 1089 }
27 office 1090 }
1091 }
1092 }
25 office 1093  
27 office 1094 private async void scrollableToolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
1095 {
1096 var toolStripComboBox = (ToolStripComboBox)sender;
1097 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1098 {
1099 try
1100 {
1101 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
25 office 1102 {
27 office 1103 await _catAssemblies.CatSetAsync<int, bool>("FA", new object[] { frequency }, _cancellationToken);
1104 soundPlayer.Play();
25 office 1105 }
27 office 1106 }
1107 catch (Exception exception)
1108 {
1109 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
1110 }
1111 }
1112 }
25 office 1113  
27 office 1114 private void scrollableToolStripComboBox1_TextChanged(object sender, EventArgs e)
1115 {
1116 if(!_vfoAReaderWriterLockSlim.TryEnterReadLock(250))
1117 {
1118 return;
1119 }
25 office 1120  
27 office 1121 try
1122 {
1123 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
1124 var frequency = toolStripComboBox.Text;
1125  
1126 _vfoAScheduledContinuation.Schedule(TimeSpan.FromSeconds(1), async () =>
1127 {
1128 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
1129 {
1130 toolStripComboBox.Value = $"{frequency}";
1131 });
1132  
1133 }, _cancellationToken);
1134 }
1135 finally
1136 {
1137 if (_vfoAReaderWriterLockSlim.IsReadLockHeld)
1138 {
1139 _vfoAReaderWriterLockSlim.ExitReadLock();
25 office 1140 }
27 office 1141 }
25 office 1142 }
1143  
27 office 1144 private void scrollableToolStripComboBox8_SelectedIndexChanged(object sender, EventArgs e)
25 office 1145 {
1146 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
1147  
1148 _squelchScheduledContinuation.Schedule(TimeSpan.FromSeconds(1), () =>
1149 {
1150 contextMenuStrip1.InvokeIfRequired(async contextMenuStrip1 =>
1151 {
1152 if (int.TryParse(toolStripComboBox.Text, out var squelch))
1153 {
1154  
1155 try
1156 {
1157 await _catAssemblies.CatWriteAsync<int>("SQ", new object[] { squelch }, _cancellationToken);
1158  
1159 toolStripComboBox.Text = $"{squelch}";
1160  
27 office 1161 Log.Information($"{Resources.Squelch_set} {squelch}");
25 office 1162 }
1163 catch (Exception exception)
1164 {
1165 Log.Error(exception, Resources.Failed_to_set_squelch);
1166 }
1167 }
1168 });
1169 }, _cancellationToken);
1170 }
27 office 1171  
1172 private async void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
1173 {
1174 var toolStripComboBox = (ToolStripComboBox)sender;
1175 if (RadioMode.TryParse(toolStripComboBox.Text, out var radioMode))
1176 {
1177 try
1178 {
1179 await _catAssemblies.CatSetAsync<RadioMode, bool>("MD", new object[] { radioMode }, _cancellationToken);
1180 }
1181 catch (Exception exception)
1182 {
1183 Log.Error(exception, Resources.Failed_to_set_radio_mode, radioMode);
1184 }
1185 }
1186 }
1187  
1188 private void scrollableToolStripComboBox7_SelectedIndexChanged(object sender, EventArgs e)
1189 {
1190 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
1191  
1192 _powerScheduledContinuation.Schedule(TimeSpan.FromSeconds(1), () =>
1193 {
1194 contextMenuStrip1.InvokeIfRequired(async contextMenuStrip1 =>
1195 {
1196 if (int.TryParse(toolStripComboBox.Text, out var amplification))
1197 {
1198  
1199 try
1200 {
1201 await _catAssemblies.CatWriteAsync<int>("PC", new object[] { amplification }, _cancellationToken);
1202  
1203 toolStripComboBox.Text = $"{amplification}";
1204  
1205 Log.Information($"{Resources.Amplification_set} {amplification}W");
1206 }
1207 catch (Exception exception)
1208 {
1209 Log.Error(exception, Resources.Failed_to_set_amplification);
1210 }
1211 }
1212 });
1213 }, _cancellationToken);
1214 }
1215  
1 office 1216 }
1217 }