HamBook – Blame information for rev 9

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