HamBook – Blame information for rev 23

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;
1 office 31  
32 namespace HamBook
33 {
34 public partial class Form1 : Form
35 {
36 private ScheduledContinuation _changedConfigurationContinuation;
37 private Configuration.Configuration Configuration { get; set; }
9 office 38 private SerialPortStream _serialPort;
1 office 39 private LogMemorySink _memorySink;
40 private ViewLogsForm _viewLogsForm;
41 private AboutForm _aboutForm;
42 private SettingsForm _settingsForm;
43 private SparkleUpdater _sparkle;
44 private readonly CancellationToken _cancellationToken;
45 private readonly CancellationTokenSource _cancellationTokenSource;
46 private CatAssemblies _catAssemblies;
3 office 47 private BandScan _bandScan;
10 office 48 private SpectrogramForm _spectrogramForm;
15 office 49 private MemoryOrganizerForm _memoryOrganizerForm;
1 office 50  
15 office 51 private CancellationTokenSource _tagTickerCancellationTokenSource;
52 private CancellationToken _tagTickerCancellationToken;
53 private string _storedMemoryChannelTagText;
54 private string _storedMemoryChannelLocation;
55 private MemoryChannel _tickerTextMemoryChannel;
56 private Task _tickerTask;
57 private volatile bool _tickerTaskRunning;
58  
1 office 59 public bool MemorySinkEnabled { get; set; }
60  
61 private Form1()
62 {
63 _cancellationTokenSource = new CancellationTokenSource();
64 _cancellationToken = _cancellationTokenSource.Token;
65  
66 _changedConfigurationContinuation = new ScheduledContinuation();
3 office 67  
1 office 68 }
69  
70 public Form1(Mutex mutex) : this()
71 {
72 InitializeComponent();
73  
74 _memorySink = new LogMemorySink();
75  
76 Log.Logger = new LoggerConfiguration()
77 .MinimumLevel.Debug()
78 .WriteTo.Conditional(condition => MemorySinkEnabled, configureSink => configureSink.Sink(_memorySink))
79 .WriteTo.File(Path.Combine(Constants.UserApplicationDirectory, "Logs", $"{Constants.AssemblyName}.log"),
80 rollingInterval: RollingInterval.Day)
81 .CreateLogger();
82  
83 // Start application update.
84 var manifestModuleName = Assembly.GetEntryAssembly().ManifestModule.FullyQualifiedName;
85 var icon = Icon.ExtractAssociatedIcon(manifestModuleName);
86  
87 _sparkle = new SparkleUpdater("https://hambook.grimore.org/update/appcast.xml",
88 new Ed25519Checker(SecurityMode.Strict, "LonrgxVjSF0GnY4hzwlRJnLkaxnDn2ikdmOifILzLJY="))
89 {
90 UIFactory = new UIFactory(icon),
91 RelaunchAfterUpdate = true
92 };
93 }
94  
95 private async void Form1_Load(object sender, EventArgs e)
96 {
13 office 97 _sparkle.StartLoop(true, true);
98  
1 office 99 Configuration = await LoadConfiguration();
100  
7 office 101 _serialPort = InitializeSerialPort(Configuration);
1 office 102  
7 office 103 _catAssemblies = InitializeAssemblies(_serialPort);
1 office 104  
105 try
106 {
9 office 107 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
1 office 108 {
109 case PowerState.ON:
7 office 110 Log.Information(Resources.Attempting_to_initialize_radio);
9 office 111 if(!await InitializeRadio())
7 office 112 {
113 return;
114 }
115  
116 Log.Information(Resources.Initializing_GUI);
1 office 117 break;
118 }
119 }
120 catch(Exception exception)
121 {
122 Log.Error(exception, Resources.Failed_to_read_power_state);
123 }
124 }
125  
9 office 126 private async void quitToolStripMenuItem_Click(object sender, EventArgs e)
1 office 127 {
9 office 128 if(_bandScan != null)
129 {
130 await _bandScan.Stop();
131 _bandScan = null;
132 }
133  
14 office 134 // Save configuration on quit.
135 await SaveConfiguration();
136  
1 office 137 Close();
138 }
139  
140 private void viewLogsToolStripMenuItem_Click(object sender, EventArgs e)
141 {
142 if (_viewLogsForm != null)
143 {
144 return;
145 }
146  
147 _viewLogsForm = new ViewLogsForm(this, _memorySink, _cancellationToken);
148 _viewLogsForm.Closing += ViewLogsForm_Closing;
149 _viewLogsForm.Show();
150 }
151  
152 private void ViewLogsForm_Closing(object sender, CancelEventArgs e)
153 {
154 if (_viewLogsForm == null)
155 {
156 return;
157 }
158  
159 _viewLogsForm.Closing -= ViewLogsForm_Closing;
160 _viewLogsForm.Close();
161 _viewLogsForm = null;
162 }
163  
164 private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
165 {
166 if (_aboutForm != null)
167 {
168 return;
169 }
170  
171 _aboutForm = new AboutForm(_cancellationToken);
172 _aboutForm.Closing += AboutForm_Closing;
173 _aboutForm.Show();
174 }
175  
176 private void AboutForm_Closing(object sender, CancelEventArgs e)
177 {
178 if (_aboutForm == null)
179 {
180 return;
181 }
182  
183 _aboutForm.Dispose();
184 _aboutForm = null;
185 }
186  
187 private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
188 {
189 if (_settingsForm != null)
190 {
191 return;
192 }
193  
194 _settingsForm = new SettingsForm(Configuration, _cancellationToken);
195 _settingsForm.Closing += SettingsForm_Closing;
196 _settingsForm.Show();
197 }
198  
199 private void SettingsForm_Closing(object sender, CancelEventArgs e)
200 {
201 if (_settingsForm == null)
202 {
203 return;
204 }
205  
206 if(_settingsForm.SaveOnClose)
207 {
208 // Commit the configuration.
209 _changedConfigurationContinuation.Schedule(TimeSpan.FromSeconds(1),
210 async () => {
211 await SaveConfiguration();
212  
11 office 213 if(_bandScan != null)
214 {
215 await _bandScan.Stop();
216 _bandScan = null;
217 }
218  
219  
1 office 220 Miscellaneous.LaunchOnBootSet(Configuration.LaunchOnBoot);
221  
7 office 222 _serialPort = InitializeSerialPort(Configuration);
1 office 223  
7 office 224 _catAssemblies = InitializeAssemblies(_serialPort);
225  
226 try
227 {
9 office 228 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
7 office 229 {
230 case PowerState.ON:
231 Log.Information(Resources.Attempting_to_initialize_radio);
9 office 232 if (!await InitializeRadio())
7 office 233 {
234 return;
235 }
236 Log.Information(Resources.Initializing_GUI);
237 break;
238 }
239 }
240 catch (Exception exception)
241 {
242 Log.Error(exception, Resources.Failed_to_read_power_state);
243 }
244  
1 office 245 }, _cancellationToken);
246 }
247  
248 _settingsForm.Dispose();
249 _settingsForm = null;
250 }
251  
252 public async Task SaveConfiguration()
253 {
254 if (!Directory.Exists(Constants.UserApplicationDirectory))
255 {
256 Directory.CreateDirectory(Constants.UserApplicationDirectory);
257 }
258  
259 switch (await Serialization.Serialize(Configuration, Constants.ConfigurationFile, "Configuration",
260 "<!ATTLIST Configuration xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>",
261 CancellationToken.None))
262 {
3 office 263 case SerializationSuccess<Configuration.Configuration> configuration:
16 office 264 Log.Information(Resources.Configuration_serialized_successfully);
1 office 265 break;
266 case SerializationFailure serializationFailure:
16 office 267 Log.Warning(serializationFailure.Exception.Message, Resources.Configuration_failed_to_serialize);
1 office 268 break;
269 }
270 }
271  
272 public static async Task<Configuration.Configuration> LoadConfiguration()
273 {
274 if (!Directory.Exists(Constants.UserApplicationDirectory))
275 {
276 Directory.CreateDirectory(Constants.UserApplicationDirectory);
277 }
278  
279 var deserializationResult =
280 await Serialization.Deserialize<Configuration.Configuration>(Constants.ConfigurationFile,
281 Constants.ConfigurationNamespace, Constants.ConfigurationXsd, CancellationToken.None);
282  
283 switch (deserializationResult)
284 {
285 case SerializationSuccess<Configuration.Configuration> serializationSuccess:
286 return serializationSuccess.Result;
287 case SerializationFailure serializationFailure:
16 office 288 Log.Warning(serializationFailure.Exception, Resources.Configuration_failed_to_deserialize);
1 office 289 return new Configuration.Configuration();
290 default:
291 return new Configuration.Configuration();
292 }
293 }
294  
9 office 295 private async Task<bool> InitializeRadio()
1 office 296 {
297 try
298 {
9 office 299 await _catAssemblies.CatWriteAsync<InformationState>("AI", new object[] { InformationState.OFF }, _cancellationToken);
300  
11 office 301 return await _catAssemblies.CatReadAsync<bool>("ID", new object[] { }, _cancellationToken);
1 office 302 }
303 catch(Exception exception)
304 {
7 office 305 Log.Error(exception, Resources.Unable_to_initialize_radio);
11 office 306  
7 office 307 return false;
1 office 308 }
7 office 309 }
310  
9 office 311 private CatAssemblies InitializeAssemblies(SerialPortStream serialPort)
7 office 312 {
313 if(_catAssemblies != null)
1 office 314 {
7 office 315 _catAssemblies.Dispose();
316 _catAssemblies = null;
1 office 317 }
318  
7 office 319 return new CatAssemblies(serialPort, Configuration.Radio);
320 }
321  
9 office 322 private SerialPortStream InitializeSerialPort(Configuration.Configuration configuration)
7 office 323 {
324 if (_serialPort != null)
1 office 325 {
7 office 326 if (_serialPort.IsOpen)
327 {
328 _serialPort.Close();
329 }
330 _serialPort.Dispose();
331 _serialPort = null;
1 office 332 }
333  
7 office 334 // Set up serial connection.
9 office 335 var serialPort = new SerialPortStream(configuration.Port, configuration.Speed, configuration.DataBits, configuration.Parity, configuration.StopBits);
7 office 336 serialPort.ReadTimeout = configuration.SerialPortTimeout.Read;
337 serialPort.WriteTimeout = configuration.SerialPortTimeout.Write;
338 serialPort.Handshake = configuration.Handshake;
9 office 339 serialPort.Encoding = Encoding.ASCII;
1 office 340  
7 office 341 Log.Information($"{Resources.Initialized_serial_port} {configuration.Port} {configuration.Speed} {configuration.Parity} {configuration.DataBits} {configuration.StopBits}");
342  
343 return serialPort;
1 office 344 }
345  
346 private async void updateToolStripMenuItem_Click(object sender, EventArgs e)
347 {
348 // Manually check for updates, this will not show a ui
349 var result = await _sparkle.CheckForUpdatesQuietly();
350 if (result.Status == NetSparkleUpdater.Enums.UpdateStatus.UpdateAvailable)
351 {
352 // if update(s) are found, then we have to trigger the UI to show it gracefully
353 _sparkle.ShowUpdateNeededUI();
354 return;
355 }
356  
357 MessageBox.Show(Resources.No_updates_available_at_this_time, Resources.HamBook, MessageBoxButtons.OK,
358 MessageBoxIcon.Asterisk,
359 MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, false);
360 }
361  
9 office 362 private async void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
1 office 363 {
364 var toolStripComboBox = (ToolStripComboBox)sender;
3 office 365 if(RadioMode.TryParse(toolStripComboBox.Text, out var radioMode))
1 office 366 {
3 office 367 try
1 office 368 {
15 office 369 await _catAssemblies.CatSetAsync<RadioMode, bool>("MD", new object[] { radioMode }, _cancellationToken);
1 office 370 }
3 office 371 catch (Exception exception)
372 {
373 Log.Error(exception, Resources.Failed_to_set_radio_mode, radioMode);
374 }
1 office 375 }
376 }
377  
378 private async void onToolStripMenuItem_Click(object sender, EventArgs e)
379 {
380 try
381 {
15 office 382 await _catAssemblies.CatSetAsync<PowerState, bool>("PS", new object[] { PowerState.ON }, _cancellationToken);
1 office 383 }
384 catch(Exception exception)
385 {
386 Log.Error(exception, Resources.Failed_to_set_power_state);
387 }
388 }
389  
390 private async void offToolStripMenuItem_Click(object sender, EventArgs e)
391 {
392 try
393 {
15 office 394 await _catAssemblies.CatSetAsync<PowerState, bool>("PS", new object[] { PowerState.OFF }, _cancellationToken);
1 office 395 }
396 catch(Exception exception)
397 {
398 Log.Error(exception, Resources.Failed_to_set_power_state);
399 }
400 }
401  
9 office 402 private async void toolStripComboBox2_MouseWheel(object sender, MouseEventArgs e)
1 office 403 {
5 office 404 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
1 office 405 {
7 office 406 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
5 office 407 if (int.TryParse(toolStripComboBox.Text, out var frequency))
3 office 408 {
5 office 409 switch (Math.Sign(e.Delta))
410 {
411 case -1:
21 office 412 frequency = frequency - Configuration.Navigation.FrequencyStep;
5 office 413 break;
414 case 1:
21 office 415 frequency = frequency + Configuration.Navigation.FrequencyStep;
5 office 416 break;
417 }
418  
419 soundPlayer.Play();
420  
421 try
422 {
15 office 423 await _catAssemblies.CatSetAsync<int, bool>("FA", new object[] { frequency }, _cancellationToken);
5 office 424 toolStripComboBox.Text = $"{frequency}";
7 office 425  
426 Log.Information($"{Resources.Set_VFO_A_frequency} {frequency}Hz");
5 office 427 }
428 catch (Exception exception)
429 {
430 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
431 }
3 office 432 }
1 office 433 }
434 }
435  
9 office 436 private async void scrollableToolStripComboBox1_MouseWheel(object sender, MouseEventArgs e)
1 office 437 {
5 office 438 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
1 office 439 {
7 office 440 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
5 office 441 if (int.TryParse(toolStripComboBox.Text, out var frequency))
3 office 442 {
5 office 443 switch (Math.Sign(e.Delta))
444 {
445 case -1:
21 office 446 frequency = frequency - Configuration.Navigation.FrequencyStep;
5 office 447 break;
448 case 1:
21 office 449 frequency = frequency + Configuration.Navigation.FrequencyStep;
5 office 450 break;
451 }
3 office 452  
6 office 453 soundPlayer.Play();
454  
5 office 455 try
456 {
15 office 457 await _catAssemblies.CatSetAsync<int, bool>("FB", new object[] { frequency }, _cancellationToken);
5 office 458 toolStripComboBox.Text = $"{frequency}";
7 office 459  
460 Log.Information($"{Resources.Set_VFO_B_frequency} {frequency}Hz");
5 office 461 }
462 catch (Exception exception)
463 {
464 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
465 }
1 office 466 }
467 }
468 }
469  
9 office 470 private async void scrollableToolStripComboBox1_TextChanged(object sender, EventArgs e)
1 office 471 {
3 office 472 var toolStripComboBox = (ToolStripComboBox)sender;
473 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1 office 474 {
3 office 475 try
476 {
15 office 477 await _catAssemblies.CatSetAsync<int, bool>("FA", new object[] { frequency }, _cancellationToken);
3 office 478 }
479 catch (Exception exception)
480 {
481 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
482 }
1 office 483 }
484 }
485  
9 office 486 private async void scrollableToolStripComboBox2_TextChanged(object sender, EventArgs e)
1 office 487 {
3 office 488 var toolStripComboBox = (ToolStripComboBox)sender;
489 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1 office 490 {
491 try
492 {
15 office 493 await _catAssemblies.CatSetAsync<int, bool>("FB", new object[] { frequency }, _cancellationToken);
1 office 494 }
495 catch (Exception exception)
496 {
497 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
498 }
3 office 499 }
500 }
501  
9 office 502 private async void toolStripMenuItem1_Click(object sender, EventArgs e)
3 office 503 {
504 if (_bandScan == null)
505 {
1 office 506 return;
507 }
508  
9 office 509 await _bandScan.Stop();
3 office 510 _bandScan = null;
1 office 511 }
3 office 512  
9 office 513 private async void scanToolStripMenuItem_Click(object sender, EventArgs e)
3 office 514 {
5 office 515 if (!(sender is ToolStripMenuItem toolStripMenuItem) ||
516 !int.TryParse(toolStripMenuItem.Tag.ToString(), out var meters))
3 office 517 {
5 office 518 return;
3 office 519 }
520  
5 office 521 if (!int.TryParse(scrollableToolStripComboBox3.Text, out var pause))
3 office 522 {
5 office 523 pause = 5;
3 office 524 }
525  
5 office 526 if(!int.TryParse(scrollableToolStripComboBox4.Text, out var step))
3 office 527 {
5 office 528 step = 5000;
3 office 529 }
530  
21 office 531 if(!int.TryParse(scrollableToolStripComboBox6.Text, out var scanDetectPause))
532 {
533 scanDetectPause = 10;
534 }
535  
5 office 536 if (!Configuration.Definitions.TryGetBand(meters, out var band))
3 office 537 {
5 office 538 return;
3 office 539 }
540  
541 if (_bandScan != null)
542 {
9 office 543 await _bandScan.Stop();
544 _bandScan = null;
3 office 545 }
546  
21 office 547 _bandScan = new BandScan(_catAssemblies, (int)band.Min, (int)band.Max, _serialPort, Configuration);
9 office 548  
23 office 549 //toolStripMenuItem16
21 office 550 if (toolStripMenuItem14.Checked)
551 {
23 office 552 _bandScan.Start(step, pause, scanDetectPause, toolStripMenuItem16.Checked);
21 office 553  
554 return;
555 }
556  
23 office 557 _bandScan.Start(step, pause, toolStripMenuItem16.Checked);
3 office 558 }
559  
11 office 560 private void modeToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
3 office 561 {
11 office 562 Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken).ContinueWith(async task =>
7 office 563 {
11 office 564 try
565 {
566 var mode = await _catAssemblies.CatReadAsync<RadioMode>("MD", new object[] { }, _cancellationToken);
7 office 567  
11 office 568 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
569 {
570 toolStripComboBox1.Text = mode;
571 });
572 }
573 catch (Exception exception)
574 {
575 Log.Error(exception, Resources.Failed_to_read_radio_mode);
576 }
7 office 577  
11 office 578 try
579 {
580 var fa = await _catAssemblies.CatReadAsync<int>("FA", new object[] { }, _cancellationToken);
7 office 581  
11 office 582 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
583 {
584 scrollableToolStripComboBox1.Text = $"{fa}";
585  
586 });
587  
588 }
589 catch (Exception exception)
590 {
591 Log.Error(exception, Resources.Failed_to_read_VFO_A);
592 }
593  
594 try
595 {
596 var fb = await _catAssemblies.CatReadAsync<int>("FB", new object[] { }, _cancellationToken);
597  
598 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
599 {
600 scrollableToolStripComboBox2.Text = $"{fb}";
601  
602 });
603 }
604 catch (Exception exception)
605 {
606 Log.Error(exception, Resources.Failed_to_read_VFO_B);
607 }
19 office 608  
609 try
610 {
611 var mc = await _catAssemblies.CatReadAsync<int>("MC", new object[] { }, _cancellationToken);
612  
613 contextMenuStrip1.InvokeIfRequired(contextMenuStrip =>
614 {
615 scrollableToolStripComboBox5.Text = $"{mc}";
616  
617 });
618 }
619 catch (Exception exception)
620 {
621 Log.Error(exception, Resources.Failed_to_read_memory_channel);
622 }
11 office 623 }, _cancellationToken);
3 office 624 }
10 office 625  
626 private void spectrogramToolStripMenuItem_Click(object sender, EventArgs e)
627 {
628 if (_spectrogramForm != null)
629 {
630 return;
631 }
632  
633 _spectrogramForm = new SpectrogramForm(Configuration, _cancellationToken);
634 _spectrogramForm.Closing += SpectrogramForm_Closing;
635 _spectrogramForm.Show();
636 }
637  
638 private void SpectrogramForm_Closing(object sender, CancelEventArgs e)
639 {
640 if (_spectrogramForm == null)
641 {
642 return;
643 }
644  
645 _spectrogramForm.Dispose();
646 _spectrogramForm = null;
14 office 647  
648 // Commit the configuration.
649 _changedConfigurationContinuation.Schedule(TimeSpan.FromSeconds(1),
650 async () =>
651 {
652 await SaveConfiguration();
653 }, _cancellationToken);
10 office 654 }
15 office 655  
656 private void toolStripMenuItem3_Click(object sender, EventArgs e)
657 {
658 if (_memoryOrganizerForm != null)
659 {
660 return;
661 }
662  
663 _memoryOrganizerForm = new MemoryOrganizerForm(Configuration, _catAssemblies, _cancellationToken);
664 _memoryOrganizerForm.Closing += MemoryOrganizerForm_Closing;
665 _memoryOrganizerForm.Show();
666 }
667  
668 private void MemoryOrganizerForm_Closing(object sender, CancelEventArgs e)
669 {
670 if (_memoryOrganizerForm == null)
671 {
672 return;
673 }
674  
675 _memoryOrganizerForm.Dispose();
676 _memoryOrganizerForm = null;
677  
678 }
679  
680 private async void toolStripMenuItem4_Click(object sender, EventArgs e)
681 {
682 if (_tickerTaskRunning)
683 {
684 return;
685 }
686  
687 var toolStripTextBox = (ToolStripTextBox)toolStripTextBox6;
688  
689 try
690 {
691 var result = await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { "001" }, _cancellationToken);
692  
693 _tickerTextMemoryChannel = await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { $"{result.CurrentLocation}" }, _cancellationToken);
694  
695 _storedMemoryChannelTagText = _tickerTextMemoryChannel.Text;
696 _storedMemoryChannelLocation = _tickerTextMemoryChannel.CurrentLocation;
697 }
698 catch(Exception exception)
699 {
700 Log.Error(exception, Resources.Could_not_read_memory_bank);
701 }
702  
703 var tickerText = $"{toolStripTextBox.Text,-12}";
704  
705 _tagTickerCancellationTokenSource = new CancellationTokenSource();
706 _tagTickerCancellationToken = _tagTickerCancellationTokenSource.Token;
707  
708 var characterQueue = new Queue<char>(12);
709 foreach(var i in Enumerable.Range(0, 12))
710 {
711 var x = tickerText.ElementAtOrDefault(i);
712  
713 if(x == default)
714 {
715 characterQueue.Enqueue(' ');
716 continue;
717 }
718  
719 characterQueue.Enqueue(x);
720 }
721  
722 #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
723 _tickerTask = Task.Run(() => CycleText(characterQueue), _cancellationToken);
724 #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
725 }
726  
727 private async void toolStripMenuItem5_Click(object sender, EventArgs e)
728 {
729 if(!_tickerTaskRunning)
730 {
731 return;
732 }
733  
734 _tagTickerCancellationTokenSource.Cancel();
735 if (_tickerTask != null)
736 {
737 await _tickerTask;
738 _tickerTask = null;
739 }
740  
741 try
742 {
743 _tickerTextMemoryChannel.CurrentLocation = $"{_storedMemoryChannelLocation:000}";
17 office 744 _tickerTextMemoryChannel.Text = $"{_storedMemoryChannelTagText, -12}";
15 office 745  
746 var success = await _catAssemblies.CatSetAsync<MemoryChannel, bool>("MT", new object[] { _tickerTextMemoryChannel }, _cancellationToken);
747 if (!success)
748 {
749 Log.Error(Resources.Error_while_restoring_memory_text);
750  
751 return;
752 }
753 }
754 catch(Exception exception)
755 {
756 Log.Error(exception, Resources.Error_while_restoring_memory_text);
757 }
17 office 758 finally
759 {
760 _tickerTaskRunning = false;
761 }
15 office 762 }
763  
764 private async Task CycleText(Queue<char> characterQueue)
765 {
766 _tickerTaskRunning = true;
767 try
768 {
769 do
770 {
771 var text = string.Join("", characterQueue.OfType<char>());
772  
773 _tickerTextMemoryChannel.Text = text;
774  
775 await _catAssemblies.CatWriteAsync<MemoryChannel>("MT", new object[] { _tickerTextMemoryChannel }, _cancellationToken);
776  
777 var x = characterQueue.Dequeue();
778 characterQueue.Enqueue(x);
779  
780 await Task.Delay(250);
781  
782 } while (!_tagTickerCancellationToken.IsCancellationRequested);
783 }
784 catch(Exception exception)
785 {
786 Log.Error(exception, Resources.Error_while_cycling_text);
787 }
788 }
19 office 789  
790 private async void scrollableToolStripComboBox5_MouseWheel(object sender, MouseEventArgs e)
791 {
792 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
793 {
794 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
795 if (int.TryParse(toolStripComboBox.Text, out var memoryChannel))
796 {
797 switch (Math.Sign(e.Delta))
798 {
799 case -1:
800 memoryChannel = memoryChannel - 1;
801 break;
802 case 1:
803 memoryChannel = memoryChannel + 1;
804 break;
805 }
806  
807 soundPlayer.Play();
808  
809 try
810 {
811 await _catAssemblies.CatSetAsync<int, bool>("MC", new object[] { memoryChannel }, _cancellationToken);
812 toolStripComboBox.Text = $"{memoryChannel}";
813  
814 Log.Information($"{Resources.Set_VFO_A_frequency} {memoryChannel}");
815 }
816 catch (Exception exception)
817 {
818 Log.Error(exception, Resources.Failed_to_set_memory_channel);
819 }
820 }
821 }
822 }
823  
824 private async void scrollableToolStripComboBox5_TextChanged(object sender, EventArgs e)
825 {
826 var toolStripComboBox = (ToolStripComboBox)sender;
827 if (int.TryParse(toolStripComboBox.Text, out var memoryChannel))
828 {
829 try
830 {
831 await _catAssemblies.CatSetAsync<int, bool>("MC", new object[] { memoryChannel }, _cancellationToken);
832 }
833 catch (Exception exception)
834 {
835 Log.Error(exception, Resources.Failed_to_set_memory_channel);
836 }
837 }
838 }
20 office 839  
840 private async void powerToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
841 {
842 var toolStripMenuItem = toolStripMenuItem11;
843  
844 try
845 {
846 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
847 {
848 case PowerState.ON:
849 toolStripMenuItem.Text = Resources.On;
850 break;
851 case PowerState.OFF:
852 toolStripMenuItem.Text = Resources.Off;
853 break;
854 }
855 }
856 catch (Exception exception)
857 {
858 Log.Error(exception, Resources.Failed_to_read_power_state);
859 }
860 }
23 office 861  
862 private async void toolStripMenuItem17_Click(object sender, EventArgs e)
863 {
864 try
865 {
866 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNER_ON }, _cancellationToken);
867  
868 await _catAssemblies.CatWriteAsync<TunerState>("AC", new object[] { TunerState.TUNING_START }, _cancellationToken);
869 }
870 catch (Exception exception)
871 {
872 Log.Error(exception, Resources.Failed_tuning_current_frequency);
873 }
874 }
1 office 875 }
876 }