HamBook – Blame information for rev 7

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