HamBook – Blame information for rev 12

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