HamBook – Blame information for rev 13

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