HamBook – Blame information for rev 10

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;
1 office 25  
26 namespace HamBook
27 {
28 public partial class Form1 : Form
29 {
30 private ScheduledContinuation _changedConfigurationContinuation;
31 private Configuration.Configuration Configuration { get; set; }
9 office 32 private SerialPortStream _serialPort;
1 office 33 private LogMemorySink _memorySink;
34 private ViewLogsForm _viewLogsForm;
35 private AboutForm _aboutForm;
36 private SettingsForm _settingsForm;
37 private SparkleUpdater _sparkle;
38 private readonly CancellationToken _cancellationToken;
39 private readonly CancellationTokenSource _cancellationTokenSource;
40 private CatAssemblies _catAssemblies;
3 office 41 private BandScan _bandScan;
10 office 42 private SpectrogramForm _spectrogramForm;
1 office 43  
44 public bool MemorySinkEnabled { get; set; }
45  
46 private Form1()
47 {
48 _cancellationTokenSource = new CancellationTokenSource();
49 _cancellationToken = _cancellationTokenSource.Token;
50  
51 _changedConfigurationContinuation = new ScheduledContinuation();
3 office 52  
1 office 53 }
54  
55 public Form1(Mutex mutex) : this()
56 {
57 InitializeComponent();
58  
59 _memorySink = new LogMemorySink();
60  
61 Log.Logger = new LoggerConfiguration()
62 .MinimumLevel.Debug()
63 .WriteTo.Conditional(condition => MemorySinkEnabled, configureSink => configureSink.Sink(_memorySink))
64 .WriteTo.File(Path.Combine(Constants.UserApplicationDirectory, "Logs", $"{Constants.AssemblyName}.log"),
65 rollingInterval: RollingInterval.Day)
66 .CreateLogger();
67  
68 // Start application update.
69 var manifestModuleName = Assembly.GetEntryAssembly().ManifestModule.FullyQualifiedName;
70 var icon = Icon.ExtractAssociatedIcon(manifestModuleName);
71  
72 _sparkle = new SparkleUpdater("https://hambook.grimore.org/update/appcast.xml",
73 new Ed25519Checker(SecurityMode.Strict, "LonrgxVjSF0GnY4hzwlRJnLkaxnDn2ikdmOifILzLJY="))
74 {
75 UIFactory = new UIFactory(icon),
76 RelaunchAfterUpdate = true
77 };
78 _sparkle.StartLoop(true, true);
79 }
80  
81 private async void Form1_Load(object sender, EventArgs e)
82 {
83 Configuration = await LoadConfiguration();
84  
7 office 85 _serialPort = InitializeSerialPort(Configuration);
1 office 86  
7 office 87 _catAssemblies = InitializeAssemblies(_serialPort);
1 office 88  
89 try
90 {
9 office 91 await _catAssemblies.CatWriteAsync<InformationState>("AI", new object[] { InformationState.OFF }, _cancellationToken);
92 }
93 finally
94 {
95  
96 }
97  
98 try
99 {
100 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
1 office 101 {
102 case PowerState.ON:
7 office 103 Log.Information(Resources.Attempting_to_initialize_radio);
9 office 104 if(!await InitializeRadio())
7 office 105 {
106 return;
107 }
108  
109 Log.Information(Resources.Initializing_GUI);
1 office 110 break;
111 }
112 }
113 catch(Exception exception)
114 {
115 Log.Error(exception, Resources.Failed_to_read_power_state);
116 }
117 }
118  
9 office 119 private async void quitToolStripMenuItem_Click(object sender, EventArgs e)
1 office 120 {
9 office 121 if(_bandScan != null)
122 {
123 await _bandScan.Stop();
124 _bandScan = null;
125 }
126  
1 office 127 Close();
128 }
129  
130 private void viewLogsToolStripMenuItem_Click(object sender, EventArgs e)
131 {
132 if (_viewLogsForm != null)
133 {
134 return;
135 }
136  
137 _viewLogsForm = new ViewLogsForm(this, _memorySink, _cancellationToken);
138 _viewLogsForm.Closing += ViewLogsForm_Closing;
139 _viewLogsForm.Show();
140 }
141  
142 private void ViewLogsForm_Closing(object sender, CancelEventArgs e)
143 {
144 if (_viewLogsForm == null)
145 {
146 return;
147 }
148  
149 _viewLogsForm.Closing -= ViewLogsForm_Closing;
150 _viewLogsForm.Close();
151 _viewLogsForm = null;
152 }
153  
154 private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
155 {
156 if (_aboutForm != null)
157 {
158 return;
159 }
160  
161 _aboutForm = new AboutForm(_cancellationToken);
162 _aboutForm.Closing += AboutForm_Closing;
163 _aboutForm.Show();
164 }
165  
166 private void AboutForm_Closing(object sender, CancelEventArgs e)
167 {
168 if (_aboutForm == null)
169 {
170 return;
171 }
172  
173 _aboutForm.Dispose();
174 _aboutForm = null;
175 }
176  
177 private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
178 {
179 if (_settingsForm != null)
180 {
181 return;
182 }
183  
184 _settingsForm = new SettingsForm(Configuration, _cancellationToken);
185 _settingsForm.Closing += SettingsForm_Closing;
186 _settingsForm.Show();
187 }
188  
189 private void SettingsForm_Closing(object sender, CancelEventArgs e)
190 {
191 if (_settingsForm == null)
192 {
193 return;
194 }
195  
196 if(_settingsForm.SaveOnClose)
197 {
198 // Commit the configuration.
199 _changedConfigurationContinuation.Schedule(TimeSpan.FromSeconds(1),
200 async () => {
201 await SaveConfiguration();
202  
203 Miscellaneous.LaunchOnBootSet(Configuration.LaunchOnBoot);
204  
7 office 205 _serialPort = InitializeSerialPort(Configuration);
1 office 206  
7 office 207 _catAssemblies = InitializeAssemblies(_serialPort);
208  
209 try
210 {
9 office 211 await _catAssemblies.CatWriteAsync<InformationState>("AI", new object[] { InformationState.OFF }, _cancellationToken);
212 }
213 finally
214 {
215  
216 }
217  
218 try
219 {
220 switch (await _catAssemblies.CatReadAsync<PowerState>("PS", new object[] { }, _cancellationToken))
7 office 221 {
222 case PowerState.ON:
223 Log.Information(Resources.Attempting_to_initialize_radio);
9 office 224 if (!await InitializeRadio())
7 office 225 {
226 return;
227 }
228 Log.Information(Resources.Initializing_GUI);
229 break;
230 }
231 }
232 catch (Exception exception)
233 {
234 Log.Error(exception, Resources.Failed_to_read_power_state);
235 }
236  
1 office 237 }, _cancellationToken);
238 }
239  
240 _settingsForm.Dispose();
241 _settingsForm = null;
242 }
243  
244 public async Task SaveConfiguration()
245 {
246 if (!Directory.Exists(Constants.UserApplicationDirectory))
247 {
248 Directory.CreateDirectory(Constants.UserApplicationDirectory);
249 }
250  
251 switch (await Serialization.Serialize(Configuration, Constants.ConfigurationFile, "Configuration",
252 "<!ATTLIST Configuration xmlns:xsi CDATA #IMPLIED xsi:noNamespaceSchemaLocation CDATA #IMPLIED>",
253 CancellationToken.None))
254 {
3 office 255 case SerializationSuccess<Configuration.Configuration> configuration:
1 office 256 Log.Information("Serialized configuration.");
257 break;
258 case SerializationFailure serializationFailure:
259 Log.Warning(serializationFailure.Exception.Message, "Failed to serialize configuration.");
260 break;
261 }
262 }
263  
264 public static async Task<Configuration.Configuration> LoadConfiguration()
265 {
266 if (!Directory.Exists(Constants.UserApplicationDirectory))
267 {
268 Directory.CreateDirectory(Constants.UserApplicationDirectory);
269 }
270  
271 var deserializationResult =
272 await Serialization.Deserialize<Configuration.Configuration>(Constants.ConfigurationFile,
273 Constants.ConfigurationNamespace, Constants.ConfigurationXsd, CancellationToken.None);
274  
275 switch (deserializationResult)
276 {
277 case SerializationSuccess<Configuration.Configuration> serializationSuccess:
278 return serializationSuccess.Result;
279 case SerializationFailure serializationFailure:
280 Log.Warning(serializationFailure.Exception, "Failed to load configuration.");
281 return new Configuration.Configuration();
282 default:
283 return new Configuration.Configuration();
284 }
285 }
286  
9 office 287 private async Task<bool> InitializeRadio()
1 office 288 {
289 try
290 {
9 office 291 await _catAssemblies.CatWriteAsync<InformationState>("AI", new object[] { InformationState.OFF }, _cancellationToken);
292  
7 office 293 if (!_catAssemblies.CatRead<bool>("ID", new object[] { }))
294 {
295 return false;
296 }
1 office 297 }
298 catch(Exception exception)
299 {
7 office 300 Log.Error(exception, Resources.Unable_to_initialize_radio);
301 return false;
1 office 302 }
303  
7 office 304 return true;
305 }
306  
9 office 307 private CatAssemblies InitializeAssemblies(SerialPortStream serialPort)
7 office 308 {
309 if(_catAssemblies != null)
1 office 310 {
7 office 311 _catAssemblies.Dispose();
312 _catAssemblies = null;
1 office 313 }
314  
7 office 315 return new CatAssemblies(serialPort, Configuration.Radio);
316 }
317  
9 office 318 private SerialPortStream InitializeSerialPort(Configuration.Configuration configuration)
7 office 319 {
320 if (_serialPort != null)
1 office 321 {
7 office 322 if (_serialPort.IsOpen)
323 {
324 _serialPort.Close();
325 }
326 _serialPort.Dispose();
327 _serialPort = null;
1 office 328 }
329  
7 office 330 // Set up serial connection.
9 office 331 var serialPort = new SerialPortStream(configuration.Port, configuration.Speed, configuration.DataBits, configuration.Parity, configuration.StopBits);
7 office 332 serialPort.ReadTimeout = configuration.SerialPortTimeout.Read;
333 serialPort.WriteTimeout = configuration.SerialPortTimeout.Write;
334 serialPort.Handshake = configuration.Handshake;
9 office 335 serialPort.Encoding = Encoding.ASCII;
1 office 336  
7 office 337 Log.Information($"{Resources.Initialized_serial_port} {configuration.Port} {configuration.Speed} {configuration.Parity} {configuration.DataBits} {configuration.StopBits}");
338  
339 return serialPort;
1 office 340 }
341  
342 private async void updateToolStripMenuItem_Click(object sender, EventArgs e)
343 {
344 // Manually check for updates, this will not show a ui
345 var result = await _sparkle.CheckForUpdatesQuietly();
346 if (result.Status == NetSparkleUpdater.Enums.UpdateStatus.UpdateAvailable)
347 {
348 // if update(s) are found, then we have to trigger the UI to show it gracefully
349 _sparkle.ShowUpdateNeededUI();
350 return;
351 }
352  
353 MessageBox.Show(Resources.No_updates_available_at_this_time, Resources.HamBook, MessageBoxButtons.OK,
354 MessageBoxIcon.Asterisk,
355 MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, false);
356 }
357  
9 office 358 private async void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
1 office 359 {
360 var toolStripComboBox = (ToolStripComboBox)sender;
3 office 361 if(RadioMode.TryParse(toolStripComboBox.Text, out var radioMode))
1 office 362 {
3 office 363 try
1 office 364 {
9 office 365 await _catAssemblies.CatSetAsync<RadioMode>("MD", new object[] { radioMode }, _cancellationToken);
1 office 366 }
3 office 367 catch (Exception exception)
368 {
369 Log.Error(exception, Resources.Failed_to_set_radio_mode, radioMode);
370 }
1 office 371 }
372 }
373  
374 private async void onToolStripMenuItem_Click(object sender, EventArgs e)
375 {
376 try
377 {
9 office 378 await _catAssemblies.CatSetAsync<PowerState>("PS", new object[] { PowerState.ON }, _cancellationToken);
1 office 379 }
380 catch(Exception exception)
381 {
382 Log.Error(exception, Resources.Failed_to_set_power_state);
383 }
384 }
385  
386 private async void offToolStripMenuItem_Click(object sender, EventArgs e)
387 {
388 try
389 {
9 office 390 await _catAssemblies.CatSetAsync<PowerState>("PS", new object[] { PowerState.OFF }, _cancellationToken);
1 office 391 }
392 catch(Exception exception)
393 {
394 Log.Error(exception, Resources.Failed_to_set_power_state);
395 }
396 }
397  
9 office 398 private async void toolStripComboBox2_MouseWheel(object sender, MouseEventArgs e)
1 office 399 {
5 office 400 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
1 office 401 {
7 office 402 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
5 office 403 if (int.TryParse(toolStripComboBox.Text, out var frequency))
3 office 404 {
5 office 405 switch (Math.Sign(e.Delta))
406 {
407 case -1:
408 frequency = frequency - 100;
409 break;
410 case 1:
411 frequency = frequency + 100;
412 break;
413 }
414  
415 soundPlayer.Play();
416  
417 try
418 {
9 office 419 await _catAssemblies.CatSetAsync<int>("FA", new object[] { frequency }, _cancellationToken);
5 office 420 toolStripComboBox.Text = $"{frequency}";
7 office 421  
422 Log.Information($"{Resources.Set_VFO_A_frequency} {frequency}Hz");
5 office 423 }
424 catch (Exception exception)
425 {
426 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
427 }
3 office 428 }
1 office 429 }
430 }
431  
9 office 432 private async void scrollableToolStripComboBox1_MouseWheel(object sender, MouseEventArgs e)
1 office 433 {
5 office 434 using (var soundPlayer = new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("HamBook.Effects.pot.wav")))
1 office 435 {
7 office 436 var toolStripComboBox = (ScrollableToolStripComboBox)sender;
5 office 437 if (int.TryParse(toolStripComboBox.Text, out var frequency))
3 office 438 {
5 office 439 switch (Math.Sign(e.Delta))
440 {
441 case -1:
442 frequency = frequency - 100;
443 break;
444 case 1:
445 frequency = frequency + 100;
446 break;
447 }
3 office 448  
6 office 449 soundPlayer.Play();
450  
5 office 451 try
452 {
9 office 453 await _catAssemblies.CatSetAsync<int>("FB", new object[] { frequency }, _cancellationToken);
5 office 454 toolStripComboBox.Text = $"{frequency}";
7 office 455  
456 Log.Information($"{Resources.Set_VFO_B_frequency} {frequency}Hz");
5 office 457 }
458 catch (Exception exception)
459 {
460 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
461 }
1 office 462 }
463 }
464 }
465  
9 office 466 private async void scrollableToolStripComboBox1_TextChanged(object sender, EventArgs e)
1 office 467 {
3 office 468 var toolStripComboBox = (ToolStripComboBox)sender;
469 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1 office 470 {
3 office 471 try
472 {
9 office 473 await _catAssemblies.CatSetAsync<int>("FA", new object[] { frequency }, _cancellationToken);
3 office 474 }
475 catch (Exception exception)
476 {
477 Log.Error(exception, Resources.Failed_to_set_VFO_A_frequency);
478 }
1 office 479 }
480 }
481  
9 office 482 private async void scrollableToolStripComboBox2_TextChanged(object sender, EventArgs e)
1 office 483 {
3 office 484 var toolStripComboBox = (ToolStripComboBox)sender;
485 if (int.TryParse(toolStripComboBox.Text, out var frequency))
1 office 486 {
487 try
488 {
9 office 489 await _catAssemblies.CatSetAsync<int>("FB", new object[] { frequency }, _cancellationToken);
1 office 490 }
491 catch (Exception exception)
492 {
493 Log.Error(exception, Resources.Failed_to_set_VFO_B_frequency);
494 }
3 office 495 }
496 }
497  
9 office 498 private async void toolStripMenuItem1_Click(object sender, EventArgs e)
3 office 499 {
500 if (_bandScan == null)
501 {
1 office 502 return;
503 }
504  
9 office 505 await _bandScan.Stop();
3 office 506 _bandScan = null;
1 office 507 }
3 office 508  
9 office 509 private async void scanToolStripMenuItem_Click(object sender, EventArgs e)
3 office 510 {
5 office 511 if (!(sender is ToolStripMenuItem toolStripMenuItem) ||
512 !int.TryParse(toolStripMenuItem.Tag.ToString(), out var meters))
3 office 513 {
5 office 514 return;
3 office 515 }
516  
5 office 517 if (!int.TryParse(scrollableToolStripComboBox3.Text, out var pause))
3 office 518 {
5 office 519 pause = 5;
3 office 520 }
521  
5 office 522 if(!int.TryParse(scrollableToolStripComboBox4.Text, out var step))
3 office 523 {
5 office 524 step = 5000;
3 office 525 }
526  
5 office 527 if (!Configuration.Definitions.TryGetBand(meters, out var band))
3 office 528 {
5 office 529 return;
3 office 530 }
531  
532 if (_bandScan != null)
533 {
9 office 534 await _bandScan.Stop();
535 _bandScan = null;
3 office 536 }
537  
5 office 538 _bandScan = new BandScan(_catAssemblies, band.Min, band.Max, _serialPort);
9 office 539  
5 office 540 #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
9 office 541 _bandScan.Start(step, pause, Configuration.ScanDetectPause);
5 office 542 #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
3 office 543 }
544  
9 office 545 private async void modeToolStripMenuItem_DropDownOpened(object sender, EventArgs e)
3 office 546 {
7 office 547 try
548 {
9 office 549 var mode = await _catAssemblies.CatReadAsync<RadioMode>("MD", new object[] { }, _cancellationToken);
7 office 550 toolStripComboBox1.Text = mode;
551 }
552 catch (Exception exception)
553 {
554 Log.Error(exception, Resources.Failed_to_read_radio_mode);
555 }
556  
557 try
558 {
9 office 559 var fa = await _catAssemblies.CatReadAsync<int>("FA", new object[] { }, _cancellationToken);
7 office 560 scrollableToolStripComboBox1.Text = $"{fa}";
561 }
562 catch (Exception exception)
563 {
564 Log.Error(exception, Resources.Failed_to_read_VFO_A);
565 }
566  
567 try
568 {
9 office 569 var fb = await _catAssemblies.CatReadAsync<int>("FB", new object[] { }, _cancellationToken);
7 office 570 scrollableToolStripComboBox2.Text = $"{fb}";
571 }
572 catch (Exception exception)
573 {
574 Log.Error(exception, Resources.Failed_to_read_VFO_B);
575 }
576  
3 office 577 }
10 office 578  
579 private void spectrogramToolStripMenuItem_Click(object sender, EventArgs e)
580 {
581 if (_spectrogramForm != null)
582 {
583 return;
584 }
585  
586 _spectrogramForm = new SpectrogramForm(Configuration, _cancellationToken);
587 _spectrogramForm.Closing += SpectrogramForm_Closing;
588 _spectrogramForm.Show();
589 }
590  
591 private void SpectrogramForm_Closing(object sender, CancelEventArgs e)
592 {
593 if (_spectrogramForm == null)
594 {
595 return;
596 }
597  
598 _spectrogramForm.Dispose();
599 _spectrogramForm = null;
600 }
1 office 601 }
602 }