WingMan – Blame information for rev 36

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;
36 office 8 using ProtoBuf;
5 office 9 using WingMan.Communication;
10  
14 office 11 namespace WingMan.Bindings
5 office 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  
36 office 25 SynchronizedMouseKeyBindings = new ConcurrentDictionary<string, List<string>>();
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  
36 office 34 private ConcurrentDictionary<string, List<string>> 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,
35 office 49 MqttCommunicationMessageReceivedEventArgs e)
5 office 50 {
35 office 51 if (e.Topic != "exchange")
5 office 52 return;
53  
35 office 54 using (var memoryStream = new MemoryStream())
5 office 55 {
35 office 56 await e.PayloadStream.CopyToAsync(memoryStream);
57  
5 office 58 memoryStream.Position = 0L;
59  
7 office 60 var mouseKeyBindingsExchange =
36 office 61 Serializer.Deserialize<KeyBindingExchange>(memoryStream);
5 office 62  
10 office 63 // Do not add own bindings.
64 if (string.Equals(mouseKeyBindingsExchange.Nick, MqttCommunication.Nick))
65 return;
66  
5 office 67 if (SynchronizedMouseKeyBindings.TryGetValue(mouseKeyBindingsExchange.Nick, out var mouseKeyBinding) &&
10 office 68 mouseKeyBinding.SequenceEqual(mouseKeyBindingsExchange.KeyBindings))
5 office 69 return;
70  
7 office 71 await Task.Delay(0)
72 .ContinueWith(
73 _ => OnMouseKeyBindingsSynchronized?.Invoke(sender,
10 office 74 new KeyBindingsSynchronizerEventArgs(
7 office 75 mouseKeyBindingsExchange)),
76 CancellationToken, TaskContinuationOptions.None, TaskScheduler);
10 office 77  
78 // Nick does not exist so the bindings will be added.
79 SynchronizedMouseKeyBindings.AddOrUpdate(mouseKeyBindingsExchange.Nick,
80 mouseKeyBindingsExchange.KeyBindings, (s, list) => mouseKeyBindingsExchange.KeyBindings);
5 office 81 }
82 }
83  
10 office 84 private async Task PeriodicSynchronize()
5 office 85 {
86 do
87 {
10 office 88 await Task.Delay(1000, CancellationToken);
5 office 89  
9 office 90 if (!MqttCommunication.Running)
5 office 91 continue;
92  
93 using (var memoryStream = new MemoryStream())
94 {
36 office 95 Serializer.Serialize(memoryStream,
96 new KeyBindingExchange(MqttCommunication.Nick,
97 LocalKeyBindings.Bindings.Select(binding => binding.Name).ToList()));
5 office 98  
99 memoryStream.Position = 0L;
100  
10 office 101 await MqttCommunication.Broadcast("exchange", memoryStream.ToArray());
5 office 102 }
7 office 103 } while (!CancellationToken.IsCancellationRequested);
5 office 104 }
105 }
35 office 106 }