WingMan – Blame information for rev 35

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