WingMan – Blame information for rev 10

Subversion Repositories:
Rev:
Rev Author Line No. Line
10 office 1 using System;
2 using System.Collections.Concurrent;
5 office 3 using System.Collections.Generic;
4 using System.IO;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using MQTTnet;
9 using WingMan.Communication;
10  
11 namespace WingMan.MouseKey
12 {
10 office 13 public class KeyBindingsSynchronizer : IDisposable
5 office 14 {
10 office 15 public delegate void MouseKeyBindingsSynchronized(object sender, KeyBindingsSynchronizerEventArgs e);
5 office 16  
10 office 17 public KeyBindingsSynchronizer(LocalKeyBindings localKeyBindings, MqttCommunication mqttCommunication,
7 office 18 TaskScheduler taskScheduler, CancellationToken cancellationToken)
5 office 19 {
10 office 20 LocalKeyBindings = localKeyBindings;
9 office 21 MqttCommunication = mqttCommunication;
7 office 22 CancellationToken = cancellationToken;
23 TaskScheduler = taskScheduler;
5 office 24  
10 office 25 SynchronizedMouseKeyBindings = new ConcurrentDictionary<string, List<KeyBinding>>();
5 office 26  
10 office 27 MqttCommunication.OnMessageReceived += MqttCommunicationOnMessageReceived;
5 office 28  
10 office 29 Task.Run(PeriodicSynchronize, CancellationToken);
5 office 30 }
31  
10 office 32 private LocalKeyBindings LocalKeyBindings { get; }
7 office 33  
10 office 34 private ConcurrentDictionary<string, List<KeyBinding>> SynchronizedMouseKeyBindings { get; }
7 office 35  
9 office 36 private MqttCommunication MqttCommunication { get; }
7 office 37  
38 private CancellationToken CancellationToken { get; }
39 private TaskScheduler TaskScheduler { get; }
10 office 40  
41 public void Dispose()
42 {
43 MqttCommunication.OnMessageReceived -= MqttCommunicationOnMessageReceived;
44 }
45  
7 office 46 public event MouseKeyBindingsSynchronized OnMouseKeyBindingsSynchronized;
47  
10 office 48 private async void MqttCommunicationOnMessageReceived(object sender,
7 office 49 MqttApplicationMessageReceivedEventArgs e)
5 office 50 {
51 if (e.ApplicationMessage.Topic != "exchange")
52 return;
53  
54 using (var memoryStream = new MemoryStream(e.ApplicationMessage.Payload))
55 {
56 memoryStream.Position = 0L;
57  
7 office 58 var mouseKeyBindingsExchange =
10 office 59 (KeyBindingExchange) KeyBindingExchange.XmlSerializer.Deserialize(memoryStream);
5 office 60  
10 office 61 // Do not add own bindings.
62 if (string.Equals(mouseKeyBindingsExchange.Nick, MqttCommunication.Nick))
63 return;
64  
5 office 65 if (SynchronizedMouseKeyBindings.TryGetValue(mouseKeyBindingsExchange.Nick, out var mouseKeyBinding) &&
10 office 66 mouseKeyBinding.SequenceEqual(mouseKeyBindingsExchange.KeyBindings))
5 office 67 return;
68  
7 office 69 await Task.Delay(0)
70 .ContinueWith(
71 _ => OnMouseKeyBindingsSynchronized?.Invoke(sender,
10 office 72 new KeyBindingsSynchronizerEventArgs(
7 office 73 mouseKeyBindingsExchange)),
74 CancellationToken, TaskContinuationOptions.None, TaskScheduler);
10 office 75  
76 // Nick does not exist so the bindings will be added.
77 SynchronizedMouseKeyBindings.AddOrUpdate(mouseKeyBindingsExchange.Nick,
78 mouseKeyBindingsExchange.KeyBindings, (s, list) => mouseKeyBindingsExchange.KeyBindings);
5 office 79 }
80 }
81  
10 office 82 private async Task PeriodicSynchronize()
5 office 83 {
84 do
85 {
10 office 86 await Task.Delay(1000, CancellationToken);
5 office 87  
9 office 88 if (!MqttCommunication.Running)
5 office 89 continue;
90  
91 using (var memoryStream = new MemoryStream())
92 {
10 office 93 KeyBindingExchange.XmlSerializer.Serialize(memoryStream,
94 new KeyBindingExchange(MqttCommunication.Nick, LocalKeyBindings.Bindings));
5 office 95  
96 memoryStream.Position = 0L;
97  
10 office 98 await MqttCommunication.Broadcast("exchange", memoryStream.ToArray());
5 office 99 }
7 office 100 } while (!CancellationToken.IsCancellationRequested);
5 office 101 }
102 }
103 }