diff --git a/QControlKit/Events/QEventArgs.cs b/QControlKit/Events/QEventArgs.cs index 8c07890..a07c661 100644 --- a/QControlKit/Events/QEventArgs.cs +++ b/QControlKit/Events/QEventArgs.cs @@ -9,6 +9,17 @@ namespace QControlKit.Events public QServer server { get; set; } } + public class QServerWorkspaceChangedArgs : EventArgs + { + public QServer server { get; set; } + public QWorkspace workspace { get; set; } + } + + public class QServerLostArgs : EventArgs + { + public QServer server { get; set; } + } + public class QServerUpdatedArgs : EventArgs { public QServer server { get; set; } diff --git a/QControlKit/Events/QEventHandlers.cs b/QControlKit/Events/QEventHandlers.cs index 5547688..2b17d19 100644 --- a/QControlKit/Events/QEventHandlers.cs +++ b/QControlKit/Events/QEventHandlers.cs @@ -1,7 +1,10 @@ namespace QControlKit.Events { public delegate void QServerFoundHandler(object source, QServerFoundArgs args); + public delegate void QServerLostHandler(object source, QServerLostArgs args); public delegate void QServerUpdatedHandler(object source, QServerUpdatedArgs args); + public delegate void QServerWorkspaceAddedHandler(object source, QServerWorkspaceChangedArgs args); + public delegate void QServerWorkspaceRemovedHandler(object source, QServerWorkspaceChangedArgs args); public delegate void QWorkspacesUpdatedHandler(object source, QWorkspacesUpdatedArgs args); diff --git a/QControlKit/QBrowser.cs b/QControlKit/QBrowser.cs index 769592c..b98a94c 100644 --- a/QControlKit/QBrowser.cs +++ b/QControlKit/QBrowser.cs @@ -5,61 +5,79 @@ using Serilog; using QControlKit.Constants; using QControlKit.Events; +using System; +using System.Collections.Generic; +using System.Linq; namespace QControlKit { public class QBrowser { - - ZeroconfResolver.ResolverListener zeroconfTCPBrowser; - public ObservableCollection servers = new ObservableCollection(); public event QServerFoundHandler ServerFound; + public event QServerLostHandler ServerLost; public event QServerUpdatedHandler ServerUpdatedWorkspaces; public QBrowser() { - zeroconfTCPBrowser = ZeroconfResolver.CreateListener(QBonjour.TCPService); - zeroconfTCPBrowser.ServiceFound += ZeroconfHostFound; - zeroconfTCPBrowser.ServiceLost += ZeroconfHostLost; + ProbeForQLabInstances(); } - private void ZeroconfHostLost(object sender, IZeroconfHost e) + public async void ProbeForQLabInstances() { - Log.Information($"[browser] Lost {e.DisplayName} : {e.IPAddress}"); + IReadOnlyList results = await + ZeroconfResolver.ResolveAsync(QBonjour.TCPService,TimeSpan.FromSeconds(3)); - } - - private void ZeroconfHostFound(object sender, IZeroconfHost e) - { - - - foreach(var service in e.Services) + foreach (var zeroconfHost in results) { - if (service.Key.Equals(QBonjour.TCPService)) + foreach (var service in zeroconfHost.Services) { - Log.Information($"Found {e.DisplayName} : {e.IPAddress} : {service.Value.Port}"); - - QServer server = serverForAddress(e.IPAddress); - - if(server == null) + if (service.Key.Equals(QBonjour.TCPService)) { - QServer serverToAdd = new QServer(e.IPAddress, service.Value.Port); - serverToAdd.name = e.DisplayName; - serverToAdd.zeroconfHost = e; - servers.Add(serverToAdd); - serverToAdd.refreshWorkspaces(); - serverToAdd.ServerUpdated += OnServerUpdatedWorkspace; - OnServerFound(serverToAdd); - } - else - { - server.name = e.DisplayName; + + QServer server = serverForAddress(zeroconfHost.IPAddress); + + if (server == null) + { + Log.Information($"[qbrowser] Found {zeroconfHost.DisplayName} : {zeroconfHost.IPAddress} : {service.Value.Port}"); + QServer serverToAdd = new QServer(zeroconfHost.IPAddress, service.Value.Port); + serverToAdd.name = zeroconfHost.DisplayName; + serverToAdd.zeroconfHost = zeroconfHost; + servers.Add(serverToAdd); + serverToAdd.refreshWorkspaces(); + serverToAdd.ServerUpdated += OnServerUpdatedWorkspace; + OnServerFound(serverToAdd); + } + else + { + server.name = zeroconfHost.DisplayName; + server.refreshWorkspaces(); + } } } } + List qServers = servers.ToList(); + + foreach(var server in qServers) + { + bool serverToBeRemoved = true; + foreach(var zeroconfHost in results){ + QServer existingServer = serverForAddress(zeroconfHost.IPAddress); + if(server != null) + { + serverToBeRemoved = false; + } + } + if (serverToBeRemoved) + { + server.disconnect(); + servers.Remove(server); + Log.Information($"[qbrowser] Lost {server.name} : {server.host} : {server.port}"); + OnServerLost(server); + } + } } public QServer serverForAddress(string address) @@ -93,6 +111,11 @@ namespace QControlKit ServerFound?.Invoke(this, new QServerFoundArgs { server = server }); } + protected virtual void OnServerLost(QServer server) + { + ServerLost?.Invoke(this, new QServerLostArgs { server = server }); + } + protected virtual void OnServerUpdatedWorkspace(object source, QServerUpdatedArgs args) { ServerUpdatedWorkspaces?.Invoke(this, args); @@ -104,7 +127,6 @@ namespace QControlKit { server.disconnect(); } - zeroconfTCPBrowser.Dispose(); } } } \ No newline at end of file diff --git a/QControlKit/QControlKit.csproj b/QControlKit/QControlKit.csproj index 4423484..b83e4f2 100644 --- a/QControlKit/QControlKit.csproj +++ b/QControlKit/QControlKit.csproj @@ -6,7 +6,7 @@ Joel Wetzell 1.0.0-devel true - 0.0.6 + 0.0.11 QControlKit diff --git a/QControlKit/QServer.cs b/QControlKit/QServer.cs index 1445766..fd63698 100644 --- a/QControlKit/QServer.cs +++ b/QControlKit/QServer.cs @@ -3,12 +3,16 @@ using System.Collections.Generic; using Zeroconf; using QControlKit.Events; +using System.Collections.ObjectModel; +using System.Linq; namespace QControlKit { public class QServer { public event QServerUpdatedHandler ServerUpdated; + public event QServerWorkspaceAddedHandler WorkspaceAdded; + public event QServerWorkspaceRemovedHandler WorkspaceRemoved; private QClient client; @@ -17,7 +21,7 @@ namespace QControlKit public string name { get; set; } public string version { get; set; } public IZeroconfHost zeroconfHost; - public List workspaces = new List(); + public ObservableCollection workspaces = new ObservableCollection(); public QServer(string host, int port) { @@ -61,14 +65,44 @@ namespace QControlKit { QWorkspace workspaceToAdd = new QWorkspace(workspace, this); workspaces.Add(workspaceToAdd); + OnServerAddedWorkspace(workspaceToAdd); //set server version to the version of first workspace found...kind of hacky but eh if (version == null) version = workspaceToAdd.version; } } + List tempWorkspaces = workspaces.ToList(); + for(int i = 0;i< tempWorkspaces.Count;i++) + { + QWorkspace workspace = workspaces[i]; + bool toBeRemoved = true; + foreach (var foundWorkspace in args.Workspaces) + { + if(workspace.uniqueID == foundWorkspace.uniqueID) + { + toBeRemoved = false; + } + } + if (toBeRemoved) + { + workspace.disconnect(); + workspaces.Remove(workspace); + OnServerRemovedWorkspace(workspace); + } + } OnServerUpdated(this); } + protected virtual void OnServerAddedWorkspace(QWorkspace workspace) + { + WorkspaceAdded?.Invoke(this, new QServerWorkspaceChangedArgs { server = this, workspace = workspace }); + } + + protected virtual void OnServerRemovedWorkspace(QWorkspace workspace) + { + WorkspaceRemoved?.Invoke(this, new QServerWorkspaceChangedArgs { server = this, workspace = workspace }); + } + protected virtual void OnServerUpdated(QServer server) { ServerUpdated?.Invoke(this, new QServerUpdatedArgs { server = server }); diff --git a/QControlKit/QWorkspace.cs b/QControlKit/QWorkspace.cs index 025e734..a870e4b 100644 --- a/QControlKit/QWorkspace.cs +++ b/QControlKit/QWorkspace.cs @@ -11,7 +11,7 @@ using QControlKit.Constants; namespace QControlKit { - public class QWorkspace + public class QWorkspace: IEquatable { private QServer server; @@ -216,6 +216,8 @@ namespace QControlKit public void disconnect() { Log.Information($"[workspace] disconnecting from <{name}>"); + if (!connected) + return; if (heartbeatTimer != null) stopHeartbeat(); stopReceivingUpdates(); @@ -578,6 +580,25 @@ namespace QControlKit cueList.Print(); } } + #endregion + + public override bool Equals(object obj) + { + if (obj == null) return false; + QWorkspace objAsPart = obj as QWorkspace; + if (objAsPart == null) return false; + else return Equals(objAsPart); + } + + public override int GetHashCode() + { + return this.uniqueID.GetHashCode(); + } + + public bool Equals(QWorkspace other) + { + return this.uniqueID.Equals(other.uniqueID); + } } } diff --git a/QControlKitXamDemo/QControlKitXamDemo.Android/QControlKitXamDemo.Android.csproj b/QControlKitXamDemo/QControlKitXamDemo.Android/QControlKitXamDemo.Android.csproj index d25aa83..efc5bf2 100644 --- a/QControlKitXamDemo/QControlKitXamDemo.Android/QControlKitXamDemo.Android.csproj +++ b/QControlKitXamDemo/QControlKitXamDemo.Android/QControlKitXamDemo.Android.csproj @@ -56,8 +56,8 @@ 0.2.0.64 - - + + diff --git a/QControlKitXamDemo/QControlKitXamDemo.iOS/AppDelegate.cs b/QControlKitXamDemo/QControlKitXamDemo.iOS/AppDelegate.cs index fc3ccfd..7b9b1e7 100644 --- a/QControlKitXamDemo/QControlKitXamDemo.iOS/AppDelegate.cs +++ b/QControlKitXamDemo/QControlKitXamDemo.iOS/AppDelegate.cs @@ -23,7 +23,7 @@ namespace QControlKitXamDemo.iOS public override bool FinishedLaunching(UIApplication app, NSDictionary options) { global::Xamarin.Forms.Forms.Init(); - Log.Logger = new LoggerConfiguration().WriteTo.NSLog().MinimumLevel.Debug().CreateLogger(); + Log.Logger = new LoggerConfiguration().WriteTo.NSLog().MinimumLevel.Information().CreateLogger(); LoadApplication(new App()); return base.FinishedLaunching(app, options); diff --git a/QControlKitXamDemo/QControlKitXamDemo.iOS/QControlKitXamDemo.iOS.csproj b/QControlKitXamDemo/QControlKitXamDemo.iOS/QControlKitXamDemo.iOS.csproj index b9a6166..c90bd5d 100644 --- a/QControlKitXamDemo/QControlKitXamDemo.iOS/QControlKitXamDemo.iOS.csproj +++ b/QControlKitXamDemo/QControlKitXamDemo.iOS/QControlKitXamDemo.iOS.csproj @@ -61,6 +61,7 @@ ARM64 iPhone Developer Entitlements.plist + SdkOnly @@ -129,8 +130,8 @@ 0.2.0.64 - - + + diff --git a/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml.cs b/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml.cs index 03db4a2..db7a143 100644 --- a/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml.cs +++ b/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml.cs @@ -4,8 +4,9 @@ using Xamarin.Forms; using QControlKit; using System.Collections.ObjectModel; using System.Collections.Generic; - +using System.Linq; using QControlKit.Events; +using System.Threading.Tasks; namespace QControlKitXamDemo { @@ -20,9 +21,91 @@ namespace QControlKitXamDemo InitializeComponent(); serverListView.ItemsSource = servers; QBrowser browser = new QBrowser(); - browser.ServerUpdatedWorkspaces += Browser_ServerUpdatedWorkspaces; + browser.ServerLost += Browser_ServerLost; + browser.ServerFound += Browser_ServerFound; serverListView.ItemSelected += ServerListView_ItemSelected; + Device.StartTimer(TimeSpan.FromSeconds(5), () => + { + Task.Run(async () => + { + browser.ProbeForQLabInstances(); + }); + return true; + }); + + } + + private void Browser_ServerFound(object source, QServerFoundArgs args) + { + List serverGroups = servers.ToList(); + + bool serverFound = false; + foreach (var serverGroup in serverGroups) + { + + if (serverGroup.host == args.server.host) + { + serverFound = true; + + } + } + + if (!serverFound) + { + Device.BeginInvokeOnMainThread(() => + { + ServerGroup serverGroup = new ServerGroup(args.server.name); + args.server.WorkspaceAdded += Server_WorkspaceAdded; + args.server.WorkspaceRemoved += Server_WorkspaceRemoved; + serverGroup.host = args.server.host; + servers.Add(serverGroup); + }); + } + } + + private void Server_WorkspaceRemoved(object source, QServerWorkspaceChangedArgs args) + { + foreach (var server in servers) + { + if (server.host == args.server.host) + { + Device.BeginInvokeOnMainThread(() => + { + server.Remove(args.workspace); + }); + } + } + } + + private void Server_WorkspaceAdded(object source, QServerWorkspaceChangedArgs args) + { + foreach(var server in servers) + { + if(server.host == args.server.host) + { + Device.BeginInvokeOnMainThread(() => + { + server.Add(args.workspace); + }); + } + } + } + + private void Browser_ServerLost(object source, QServerLostArgs args) + { + + List serverGroups = servers.ToList(); + foreach(var serverGroup in serverGroups) + { + if(serverGroup.host == args.server.host) + { + Device.BeginInvokeOnMainThread(() => + { + servers.Remove(serverGroup); + }); + } + } } async void ServerListView_ItemSelected(object sender, SelectedItemChangedEventArgs e) @@ -48,26 +131,16 @@ namespace QControlKitXamDemo serverListView.SelectedItem = null; } } - - private void Browser_ServerUpdatedWorkspaces(object source, QServerUpdatedArgs args) - { - ServerGroup serverGroup = new ServerGroup(args.server.name); - serverGroup.AddRange(args.server.workspaces); - - Device.BeginInvokeOnMainThread(() => - { - servers.Add(serverGroup); - - }); - } } - public class ServerGroup : List{ + public class ServerGroup : ObservableCollection{ public string name { get; set; } - + public string host { get; set; } public ServerGroup(string name) { this.name = name; } + + } } diff --git a/QControlKitXamDemo/QControlKitXamDemo/QControlKitXamDemo.csproj b/QControlKitXamDemo/QControlKitXamDemo/QControlKitXamDemo.csproj index 4928ee6..a162908 100644 --- a/QControlKitXamDemo/QControlKitXamDemo/QControlKitXamDemo.csproj +++ b/QControlKitXamDemo/QControlKitXamDemo/QControlKitXamDemo.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QCueViewModel.cs b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QCueViewModel.cs index 87d7ab0..05a3b16 100644 --- a/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QCueViewModel.cs +++ b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QCueViewModel.cs @@ -2,7 +2,7 @@ using System.ComponentModel; using System.Runtime.CompilerServices; using Xamarin.Forms; - +using Serilog; using QControlKit.Events; using QControlKit.Constants; @@ -26,7 +26,7 @@ namespace QControlKitXamDemo.ViewModels { foreach(var property in args.properties) { - //Log.Debug($"[cueviewmodel] property <{property}> has been updated."); + Log.Debug($"[cueviewmodel] property <{property}> has been updated."); if (property.Equals(QOSCKey.Name) || property.Equals(QOSCKey.ListName)) { OnPropertyChanged("name");