From fe8bd257d177fa83178175dafbaacf21449b81b8 Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Sat, 6 Jun 2020 12:12:23 -0500 Subject: [PATCH] Switch to only TCP Communication - No more UDP - Lots of random refactoring as well --- .../Classes/{Cell => Buttons}/QButton.cs | 0 .../Classes/Buttons/QLevelsButton.cs | 29 ++++ .../Classes/{Cell => Buttons}/ShadowButton.cs | 8 + .../Classes/Cell/QControlsBlock.cs | 5 +- .../Classes/Cell/QCueListCell.cs | 6 +- .../Classes/Cell/QInstanceCell.cs | 2 +- .../Classes/Cell/QLevelsCell.cs | 2 +- .../Classes/Cell/QSelectedCueCell.cs | 3 +- .../Classes/Communication/IPHelper.cs | 2 +- .../Classes/Communication/QClient.cs | 54 +++--- .../Classes/Communication/QController.cs | 24 ++- .../Classes/Communication/QFinder.cs | 2 +- .../Classes/Communication/QParser.cs | 4 +- .../Classes/Communication/QReceiver.cs | 3 +- .../Classes/Communication/QUpdater.cs | 19 ++- .../Classes/Communication/SharpOSC/Symbol.cs | 1 + .../SharpOSC/{TCPSender.cs => TCPClient.cs} | 15 +- .../Classes/Dialogs/NoWorkspacesConfig.cs | 14 ++ .../Classes/Dialogs/WorkspacePrompt.cs | 87 ++++++++++ .../Classes/QItems/NoQCueSelected.cs | 14 ++ .../Classes/{Cues => QItems}/QCue.cs | 2 +- .../Classes/{Cues => QItems}/QCueList.cs | 2 +- .../Classes/{Cues => QItems}/QDefinitions.cs | 0 .../Classes/{Cell => QItems}/QInstance.cs | 4 +- .../Classes/{Cues => QItems}/QWorkSpace.cs | 17 +- .../{Cues => QItems}/QWorkspaceInfo.cs | 2 +- .../Classes/Settings/QStorage.cs | 1 + qController.Standard/Pages/App.xaml.cs | 2 + .../Pages/ControlPage.xaml.cs | 160 ++++++------------ qController.Standard/Pages/MenuPage.xaml.cs | 4 +- .../Pages/qConnectionPage.xaml.cs | 8 +- qController.Standard/qController.csproj | 4 +- 32 files changed, 323 insertions(+), 177 deletions(-) rename qController.Standard/Classes/{Cell => Buttons}/QButton.cs (100%) create mode 100644 qController.Standard/Classes/Buttons/QLevelsButton.cs rename qController.Standard/Classes/{Cell => Buttons}/ShadowButton.cs (71%) mode change 100755 => 100644 qController.Standard/Classes/Communication/SharpOSC/Symbol.cs rename qController.Standard/Classes/Communication/SharpOSC/{TCPSender.cs => TCPClient.cs} (88%) create mode 100644 qController.Standard/Classes/Dialogs/NoWorkspacesConfig.cs create mode 100644 qController.Standard/Classes/Dialogs/WorkspacePrompt.cs create mode 100644 qController.Standard/Classes/QItems/NoQCueSelected.cs rename qController.Standard/Classes/{Cues => QItems}/QCue.cs (98%) rename qController.Standard/Classes/{Cues => QItems}/QCueList.cs (95%) rename qController.Standard/Classes/{Cues => QItems}/QDefinitions.cs (100%) rename qController.Standard/Classes/{Cell => QItems}/QInstance.cs (92%) rename qController.Standard/Classes/{Cues => QItems}/QWorkSpace.cs (91%) rename qController.Standard/Classes/{Cues => QItems}/QWorkspaceInfo.cs (90%) diff --git a/qController.Standard/Classes/Cell/QButton.cs b/qController.Standard/Classes/Buttons/QButton.cs similarity index 100% rename from qController.Standard/Classes/Cell/QButton.cs rename to qController.Standard/Classes/Buttons/QButton.cs diff --git a/qController.Standard/Classes/Buttons/QLevelsButton.cs b/qController.Standard/Classes/Buttons/QLevelsButton.cs new file mode 100644 index 0000000..fe734d3 --- /dev/null +++ b/qController.Standard/Classes/Buttons/QLevelsButton.cs @@ -0,0 +1,29 @@ +using Xamarin.Forms; +namespace qController +{ + public class QLevelsButton : ShadowButton + { + public Button button; + public QLevelsButton() + { + button = new Button + { + Text = QIcon.SLIDERS, + TextColor = Color.Black, + FontFamily = App.QFont, + FontSize = App.HeightUnit * 4, + VerticalOptions = LayoutOptions.FillAndExpand, + HorizontalOptions = LayoutOptions.FillAndExpand, + HeightRequest = App.HeightUnit * 8, + WidthRequest = App.HeightUnit * 8, + CornerRadius = (int)(App.HeightUnit * 4), + BackgroundColor = Color.LightBlue + }; + + HeightRequest = button.Height; + WidthRequest = button.Width; + CornerRadius = button.CornerRadius; + Content = button; + } + } +} diff --git a/qController.Standard/Classes/Cell/ShadowButton.cs b/qController.Standard/Classes/Buttons/ShadowButton.cs similarity index 71% rename from qController.Standard/Classes/Cell/ShadowButton.cs rename to qController.Standard/Classes/Buttons/ShadowButton.cs index 08a0a52..3114633 100644 --- a/qController.Standard/Classes/Cell/ShadowButton.cs +++ b/qController.Standard/Classes/Buttons/ShadowButton.cs @@ -16,5 +16,13 @@ namespace qController BorderColor = Color.Black; IsVisible = false; } + + public ShadowButton() + { + HasShadow = true; + BorderColor = Color.Black; + IsVisible = false; + Padding = new Thickness(0); + } } } diff --git a/qController.Standard/Classes/Cell/QControlsBlock.cs b/qController.Standard/Classes/Cell/QControlsBlock.cs index 8170f59..8b6765e 100644 --- a/qController.Standard/Classes/Cell/QControlsBlock.cs +++ b/qController.Standard/Classes/Cell/QControlsBlock.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; using Xamarin.Forms; +using qController.Communication; -namespace qController +namespace qController.Cell { public class QControlsBlock : Frame { @@ -130,7 +131,7 @@ namespace qController { string workspace_prefix = "/workspace/" + qController.qWorkspace.workspace_id; string command = workspace_prefix + ((QButton)sender).qCommand.osc; - qController.qClient.sendUDP(command); + qController.qClient.sendTCP(command); } } } diff --git a/qController.Standard/Classes/Cell/QCueListCell.cs b/qController.Standard/Classes/Cell/QCueListCell.cs index c49fa93..424b42c 100644 --- a/qController.Standard/Classes/Cell/QCueListCell.cs +++ b/qController.Standard/Classes/Cell/QCueListCell.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.ObjectModel; +using System.Collections.ObjectModel; using Xamarin.Forms; +using qController.QItems; -namespace qController +namespace qController.Cell { public class QCueListCell : Frame { diff --git a/qController.Standard/Classes/Cell/QInstanceCell.cs b/qController.Standard/Classes/Cell/QInstanceCell.cs index c4cfe5e..cb12400 100644 --- a/qController.Standard/Classes/Cell/QInstanceCell.cs +++ b/qController.Standard/Classes/Cell/QInstanceCell.cs @@ -2,7 +2,7 @@ using Xamarin.Forms; using Serilog; -namespace qController +namespace qController.Cell { public class QInstanceCell : ViewCell { diff --git a/qController.Standard/Classes/Cell/QLevelsCell.cs b/qController.Standard/Classes/Cell/QLevelsCell.cs index 344484e..1d6d04f 100644 --- a/qController.Standard/Classes/Cell/QLevelsCell.cs +++ b/qController.Standard/Classes/Cell/QLevelsCell.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Xamarin.Forms; -namespace qController +namespace qController.Cell { public class QLevelsCell : Frame { diff --git a/qController.Standard/Classes/Cell/QSelectedCueCell.cs b/qController.Standard/Classes/Cell/QSelectedCueCell.cs index 197faf6..c1a4f5d 100644 --- a/qController.Standard/Classes/Cell/QSelectedCueCell.cs +++ b/qController.Standard/Classes/Cell/QSelectedCueCell.cs @@ -1,8 +1,9 @@ using System; using Acr.UserDialogs; +using qController.QItems; using Xamarin.Forms; -namespace qController +namespace qController.Cell { public class CueEditArgs : EventArgs { diff --git a/qController.Standard/Classes/Communication/IPHelper.cs b/qController.Standard/Classes/Communication/IPHelper.cs index 7b84960..65cef36 100644 --- a/qController.Standard/Classes/Communication/IPHelper.cs +++ b/qController.Standard/Classes/Communication/IPHelper.cs @@ -2,7 +2,7 @@ //IMPLEMENT A ISREACHABLE METHOD TO BE ABLE TO DISPLAY ONLINE QINSTANCES using System.Net; -namespace qController +namespace qController.Communication { public class IPHelper { diff --git a/qController.Standard/Classes/Communication/QClient.cs b/qController.Standard/Classes/Communication/QClient.cs index d3e3a68..d0ce7eb 100644 --- a/qController.Standard/Classes/Communication/QClient.cs +++ b/qController.Standard/Classes/Communication/QClient.cs @@ -1,15 +1,15 @@ //Class used to facilitate communication with a QInstance -//Listens for incoming messages via qReceiver (UDP) and tcpSender (TCP) +//Listens for incoming messages via qReceiver (UDP) and tcpClient (TCP) //TODO: WEIRD MESSAGE PARSING RULES NEED FIXED using System; using SharpOSC; using Serilog; -namespace qController +namespace qController.Communication { public class QClient { - TCPSender tcpSender; + TCPClient tcpClient; UDPSender udpSender; public QParser qParser; public QReceiver qReceiver; @@ -21,13 +21,13 @@ namespace qController Address = address; Port = port; qParser = new QParser(); - qReceiver = new QReceiver(Port + 1); - tcpSender = new TCPSender(Address, Port); - tcpSender.Connect(); - udpSender = new UDPSender(Address, Port); + //qReceiver = new QReceiver(Port + 1); + tcpClient = new TCPClient(Address, Port); + tcpClient.Connect(); + //udpSender = new UDPSender(Address, Port); - tcpSender.MessageReceived += OnMessageReceived; - qReceiver.UpdateMessageReceived += OnMessageReceived; + tcpClient.MessageReceived += OnMessageReceived; + //qReceiver.UpdateMessageReceived += OnMessageReceived; } @@ -51,26 +51,27 @@ namespace qController ProcessUpdate(args.Message); } - public void sendUDP(string address) - { - //Log.Debug($"QCLIENT - UDP Sent with address: {address}"); - udpSender = new UDPSender(Address,Port); - udpSender.Send(new OscMessage(address)); - udpSender.Close(); - } - public void sendUDP(string address, params object[] args) - { - //Log.Debug($"QCLIENT - UDP Sent with address: {address}"); - udpSender = new UDPSender(Address, Port); - udpSender.Send(new OscMessage(address, args)); - udpSender.Close(); - } + //public void sendUDP(string address) + //{ + // //Log.Debug($"QCLIENT - UDP Sent with address: {address}"); + // udpSender = new UDPSender(Address,Port); + // udpSender.Send(new OscMessage(address)); + // udpSender.Close(); + //} + //public void sendUDP(string address, params object[] args) + //{ + // //Log.Debug($"QCLIENT - UDP Sent with address: {address}"); + // udpSender = new UDPSender(Address, Port); + // udpSender.Send(new OscMessage(address, args)); + // udpSender.Close(); + //} + public void sendTCP(string address) { //Log.Debug($"QCLIENT - TCP Sent with address: {address}"); try { - tcpSender.Send(new OscMessage(address)); + tcpClient.Send(new OscMessage(address)); } catch (Exception ex) { @@ -83,7 +84,7 @@ namespace qController //Log.Debug($"QCLIENT - TCP Sent with address: {address}"); try { - tcpSender.Send(new OscMessage(address, args)); + tcpClient.Send(new OscMessage(address, args)); } catch (Exception ex) { @@ -122,8 +123,7 @@ namespace qController public void Close() { - udpSender.Close(); - qReceiver.Close(); + tcpClient.Close(); } } } diff --git a/qController.Standard/Classes/Communication/QController.cs b/qController.Standard/Classes/Communication/QController.cs index aa26059..99b6a7f 100644 --- a/qController.Standard/Classes/Communication/QController.cs +++ b/qController.Standard/Classes/Communication/QController.cs @@ -2,10 +2,10 @@ //Contains all necessary items to facilitate communication (sending, receiving) to a QLab workspace //Also contains the local QWorkspace object which stores all the information that is used in displaying //TODO: STILL NEED TO WORK ON PASSWORD PROTECTED WORKSPACES -using System; using Serilog; +using qController.QItems; -namespace qController +namespace qController.Communication { public class QController { @@ -31,26 +31,38 @@ namespace qController { Log.Debug($"QCONTROLLER - Connect Called: {workspace_id}"); qWorkspace = new QWorkspace(workspace_id); - qClient.sendUDP("/workspace/"+workspace_id+"/connect"); + qClient.sendTCP("/workspace/"+workspace_id+"/connect"); } public void Connect(string workspace_id, string passcode) { Log.Debug($"QCONTROLLER - Connect with Passcode Called: {workspace_id}:{passcode}"); qWorkspace = new QWorkspace(workspace_id); - qClient.sendUDP("/workspace/" + workspace_id + "/connect", passcode); qClient.sendTCP("/workspace/" + workspace_id + "/connect", passcode); } + public void Connect(QWorkspace workspace) + { + if(workspace.passcode != null) + { + Connect(workspace.workspace_id, workspace.passcode); + } + else + { + Connect(workspace.workspace_id); + } + + } + public void KickOff() { - qClient.sendUDP("/workspaces"); + qClient.sendTCP("/workspaces"); } public void Disconnect() { - qClient.sendUDP("/workspace/"+qWorkspace.workspace_id+"/disconnect"); + qClient.sendTCP("/workspace/"+qWorkspace.workspace_id+"/disconnect"); } public void Resume() diff --git a/qController.Standard/Classes/Communication/QFinder.cs b/qController.Standard/Classes/Communication/QFinder.cs index 158990d..c81902a 100644 --- a/qController.Standard/Classes/Communication/QFinder.cs +++ b/qController.Standard/Classes/Communication/QFinder.cs @@ -4,7 +4,7 @@ using Serilog; using System.Collections.Generic; using Zeroconf; -namespace qController +namespace qController.Communication { public class QFinder { diff --git a/qController.Standard/Classes/Communication/QParser.cs b/qController.Standard/Classes/Communication/QParser.cs index 4175bde..cb9d479 100644 --- a/qController.Standard/Classes/Communication/QParser.cs +++ b/qController.Standard/Classes/Communication/QParser.cs @@ -3,9 +3,10 @@ using SharpOSC; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System.Collections.Generic; +using qController.QItems; using Serilog; -namespace qController +namespace qController.Communication { public class CueEventArgs : EventArgs { @@ -184,6 +185,7 @@ namespace qController } catch (Exception ex) { + Log.Debug($"QPARSER - Workspace Load Error: {ex.ToString()}"); OnWorkspaceLoadError(id); } } diff --git a/qController.Standard/Classes/Communication/QReceiver.cs b/qController.Standard/Classes/Communication/QReceiver.cs index 82ad6ac..15f0865 100644 --- a/qController.Standard/Classes/Communication/QReceiver.cs +++ b/qController.Standard/Classes/Communication/QReceiver.cs @@ -3,9 +3,8 @@ using SharpOSC; using System.Threading; using Serilog; -namespace qController +namespace qController.Communication { - public class QReceiver { public delegate void UpdateMessageReceivedHandler(object source, MessageEventArgs args); diff --git a/qController.Standard/Classes/Communication/QUpdater.cs b/qController.Standard/Classes/Communication/QUpdater.cs index 06de71e..4dbfb86 100644 --- a/qController.Standard/Classes/Communication/QUpdater.cs +++ b/qController.Standard/Classes/Communication/QUpdater.cs @@ -5,14 +5,15 @@ using Serilog; using Xamarin.Forms; using Serilog; -namespace qController +namespace qController.Communication { public class QUpdater { private bool active = true; + private bool started = false; private QController qController; - private Thread updateThread; + private Thread updateThread; public QUpdater(QController controller) { @@ -47,7 +48,15 @@ namespace qController public void Start(){ Log.Debug("QUPDATER - Start() method called"); - updateThread.Start(); + try + { + //updateThread.Start(); + Log.Debug("QUPDATER - updateThread started"); + } + catch (ThreadStateException tSe) + { + Log.Debug("QUPDATER - updateThread already started"); + } } //Attempt at a "keep alive" message @@ -67,7 +76,7 @@ namespace qController if (args.Cue.type == "Group") { //Log.Debug("QUpdater/Updated cue was group cue, sending children request"); - qController.qClient.sendUDP("/workspace/"+qController.qWorkspace.workspace_id+"/cue_id/" + args.Cue.uniqueID + "/children"); + qController.qClient.sendTCP("/workspace/"+qController.qWorkspace.workspace_id+"/cue_id/" + args.Cue.uniqueID + "/children"); } } @@ -96,7 +105,7 @@ namespace qController public void SendThump() { - qController.qClient.sendUDP("/workspace/" + qController.qWorkspace.workspace_id + "/thump"); + qController.qClient.sendTCP("/workspace/" + qController.qWorkspace.workspace_id + "/thump"); } public void Kill(){ diff --git a/qController.Standard/Classes/Communication/SharpOSC/Symbol.cs b/qController.Standard/Classes/Communication/SharpOSC/Symbol.cs old mode 100755 new mode 100644 index 209b7fa..7e4e289 --- a/qController.Standard/Classes/Communication/SharpOSC/Symbol.cs +++ b/qController.Standard/Classes/Communication/SharpOSC/Symbol.cs @@ -19,6 +19,7 @@ namespace SharpOSC this.Value = value; } + override public string ToString() { return Value; diff --git a/qController.Standard/Classes/Communication/SharpOSC/TCPSender.cs b/qController.Standard/Classes/Communication/SharpOSC/TCPClient.cs similarity index 88% rename from qController.Standard/Classes/Communication/SharpOSC/TCPSender.cs rename to qController.Standard/Classes/Communication/SharpOSC/TCPClient.cs index cbb8682..790ecfc 100644 --- a/qController.Standard/Classes/Communication/SharpOSC/TCPSender.cs +++ b/qController.Standard/Classes/Communication/SharpOSC/TCPClient.cs @@ -17,7 +17,7 @@ namespace SharpOSC } } - public class TCPSender + public class TCPClient { public int Port { @@ -41,7 +41,7 @@ namespace SharpOSC byte ESC_ESC = 0xDD; - public TCPSender(string address, int port) + public TCPClient(string address, int port) { _port = port; _address = address; @@ -50,7 +50,7 @@ namespace SharpOSC public void Connect() { client = new TcpClient(Address, Port); - Log.Debug($"TCPSender - connect called for <{Address}:{Port}>"); + Log.Debug($"TCPClient - connect called for <{Address}:{Port}>"); Thread receivingThread = new Thread(ReceiveLoop); receivingThread.Start(); } @@ -74,7 +74,7 @@ namespace SharpOSC { Receive(); } - Log.Debug("TCPSender - Receive Loop has exited for some reason"); + Log.Debug("TCPClient - Receive Loop has exited for some reason"); } public void Receive() @@ -88,19 +88,24 @@ namespace SharpOSC List responseData = new List(); if (netStream.CanRead) { + //var watch = System.Diagnostics.Stopwatch.StartNew(); byte[] buffer = new byte[256]; int bytesRead = 0; + int reads = 0; do { bytesRead = netStream.Read(buffer, 0, buffer.Length); responseData.AddRange(buffer); - Thread.Sleep(30); + reads += 1; + Thread.Sleep(1); //Log.Debug("Thread " + num + ": Bytes read: " + bytesRead + " - " + Encoding.UTF8.GetString(buffer)); } while (netStream.DataAvailable); //Log.Debug("Raw TCP In: " + System.Text.Encoding.UTF8.GetString(responseData.ToArray())); OscMessage response = (OscMessage)OscPacket.GetPacket(responseData.Skip(1).ToArray()); + //watch.Stop(); + //Log.Debug($"TCPCLient - message receive took {watch.ElapsedMilliseconds}ms and {reads} reads"); OnMessageReceived(response); } } catch(Exception e) diff --git a/qController.Standard/Classes/Dialogs/NoWorkspacesConfig.cs b/qController.Standard/Classes/Dialogs/NoWorkspacesConfig.cs new file mode 100644 index 0000000..34406f7 --- /dev/null +++ b/qController.Standard/Classes/Dialogs/NoWorkspacesConfig.cs @@ -0,0 +1,14 @@ +using System; +using Acr.UserDialogs; + +namespace qController.Dialogs +{ + public class NoWorkspacesConfig : ConfirmConfig + { + public NoWorkspacesConfig() + { + Message = "QLab doesn't have any workspaces open?"; + OkText = "Disconnect"; + } + } +} diff --git a/qController.Standard/Classes/Dialogs/WorkspacePrompt.cs b/qController.Standard/Classes/Dialogs/WorkspacePrompt.cs new file mode 100644 index 0000000..15ad08e --- /dev/null +++ b/qController.Standard/Classes/Dialogs/WorkspacePrompt.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using Acr.UserDialogs; +using qController.QItems; +using Serilog; + +namespace qController.Dialogs +{ + public class WorkspacePromptArgs : EventArgs + { + public QWorkspace SelectedWorkspace + { + get; + set; + } + } + + public class WorkspacePrompt + { + public delegate void WorkspaceSelectedHandler(object source, WorkspacePromptArgs args); + public event WorkspaceSelectedHandler WorkspaceSelected; + + public WorkspacePrompt() + { + + } + + public ActionSheetConfig getActionSheetConfigForWorkspaces(List workspaces) + { + ActionSheetConfig actionSheetConfig = new ActionSheetConfig(); + actionSheetConfig.SetTitle("Select Workspace"); + for (int i = 0; i < workspaces.Count; i++) + { + QWorkspaceInfo workspace = workspaces[i]; + actionSheetConfig.Add(workspace.displayName, new Action(() => { + Log.Debug("CONTROLPAGE - Workspace Selected " + workspace.displayName); + + + if (!workspace.hasPasscode) + { + OnWorkspaceSelected(new QWorkspace(workspace.uniqueID)); + } + else + { + promptWorkspacePasscode(workspace.uniqueID); + } + })); + } + return actionSheetConfig; + } + + + + public void promptWorkspacePasscode(string workspace_id) + { + UserDialogs.Instance.Prompt(new PromptConfig + { + InputType = InputType.Number, + MaxLength = 4, + Title = "Enter Workspace Passcode", + OkText = "Connect", + IsCancellable = true, + OnAction = (resp) => + { + if (resp.Ok) + { + OnWorkspaceSelected(new QWorkspace(workspace_id,resp.Value)); + } + else + { + OnWorkspaceSelected(null); + } + } + + }); + } + + protected virtual void OnWorkspaceSelected(QWorkspace workspace) + { + if (WorkspaceSelected != null) + WorkspaceSelected(this, new WorkspacePromptArgs() { SelectedWorkspace = workspace }); + } + + + + } +} diff --git a/qController.Standard/Classes/QItems/NoQCueSelected.cs b/qController.Standard/Classes/QItems/NoQCueSelected.cs new file mode 100644 index 0000000..ee384dd --- /dev/null +++ b/qController.Standard/Classes/QItems/NoQCueSelected.cs @@ -0,0 +1,14 @@ +using System; +namespace qController.QItems +{ + public class NoQCueSelected : QCue + { + public NoQCueSelected() + { + listName = "No Cue Selected"; + type = ""; + notes = "Workspace has loaded but no cue is selected"; + number = "!"; + } + } +} diff --git a/qController.Standard/Classes/Cues/QCue.cs b/qController.Standard/Classes/QItems/QCue.cs similarity index 98% rename from qController.Standard/Classes/Cues/QCue.cs rename to qController.Standard/Classes/QItems/QCue.cs index 38174a9..95a20d7 100644 --- a/qController.Standard/Classes/Cues/QCue.cs +++ b/qController.Standard/Classes/QItems/QCue.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace qController +namespace qController.QItems { public class QCue { diff --git a/qController.Standard/Classes/Cues/QCueList.cs b/qController.Standard/Classes/QItems/QCueList.cs similarity index 95% rename from qController.Standard/Classes/Cues/QCueList.cs rename to qController.Standard/Classes/QItems/QCueList.cs index 62a833c..60865db 100644 --- a/qController.Standard/Classes/Cues/QCueList.cs +++ b/qController.Standard/Classes/QItems/QCueList.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace qController +namespace qController.QItems { public class QCueList { diff --git a/qController.Standard/Classes/Cues/QDefinitions.cs b/qController.Standard/Classes/QItems/QDefinitions.cs similarity index 100% rename from qController.Standard/Classes/Cues/QDefinitions.cs rename to qController.Standard/Classes/QItems/QDefinitions.cs diff --git a/qController.Standard/Classes/Cell/QInstance.cs b/qController.Standard/Classes/QItems/QInstance.cs similarity index 92% rename from qController.Standard/Classes/Cell/QInstance.cs rename to qController.Standard/Classes/QItems/QInstance.cs index 6c8b519..869252c 100644 --- a/qController.Standard/Classes/Cell/QInstance.cs +++ b/qController.Standard/Classes/QItems/QInstance.cs @@ -1,8 +1,8 @@ using Xamarin.Forms; -namespace qController +namespace qController.QItems { - public class QInstance : ViewCell + public class QInstance { public string name { get; set; } public string address { get; set; } diff --git a/qController.Standard/Classes/Cues/QWorkSpace.cs b/qController.Standard/Classes/QItems/QWorkSpace.cs similarity index 91% rename from qController.Standard/Classes/Cues/QWorkSpace.cs rename to qController.Standard/Classes/QItems/QWorkSpace.cs index 6aff608..9504bfb 100644 --- a/qController.Standard/Classes/Cues/QWorkSpace.cs +++ b/qController.Standard/Classes/QItems/QWorkSpace.cs @@ -1,10 +1,8 @@ //Class pertains to the local copy of a workspace, with methods for fetching/updating information inside - -using System; using System.Collections.Generic; using Serilog; -namespace qController +namespace qController.QItems { public class QWorkspace { @@ -14,12 +12,25 @@ namespace qController public string address { get; set; } public bool IsPopulated { get; set; } + public string passcode { get; set; } + //ONLY FOR PASSING A WORKSPACE LOAD ERROR public QWorkspace(string id) { workspace_id = id; } + public QWorkspace(string id, string passcode) + { + workspace_id = id; + this.passcode = passcode; + } + + public QWorkspace() + { + + } + public QCue GetCue(string cue_id) { foreach (var cueList in data) diff --git a/qController.Standard/Classes/Cues/QWorkspaceInfo.cs b/qController.Standard/Classes/QItems/QWorkspaceInfo.cs similarity index 90% rename from qController.Standard/Classes/Cues/QWorkspaceInfo.cs rename to qController.Standard/Classes/QItems/QWorkspaceInfo.cs index 54c97c2..f9c04ee 100644 --- a/qController.Standard/Classes/Cues/QWorkspaceInfo.cs +++ b/qController.Standard/Classes/QItems/QWorkspaceInfo.cs @@ -1,5 +1,5 @@ //General information about a QLab Workspace -namespace qController +namespace qController.QItems { public class QWorkspaceInfo { diff --git a/qController.Standard/Classes/Settings/QStorage.cs b/qController.Standard/Classes/Settings/QStorage.cs index 7229baf..3191a03 100644 --- a/qController.Standard/Classes/Settings/QStorage.cs +++ b/qController.Standard/Classes/Settings/QStorage.cs @@ -1,6 +1,7 @@ using Serilog; using System.Collections.ObjectModel; using Acr.Settings; +using qController.QItems; namespace qController { diff --git a/qController.Standard/Pages/App.xaml.cs b/qController.Standard/Pages/App.xaml.cs index 2c2f686..01eddb6 100644 --- a/qController.Standard/Pages/App.xaml.cs +++ b/qController.Standard/Pages/App.xaml.cs @@ -1,6 +1,8 @@ using Acr.UserDialogs; using Xamarin.Forms; using Xamarin.Essentials; +using qController.Communication; + namespace qController { public partial class App : Application diff --git a/qController.Standard/Pages/ControlPage.xaml.cs b/qController.Standard/Pages/ControlPage.xaml.cs index 4ad5abd..2619087 100644 --- a/qController.Standard/Pages/ControlPage.xaml.cs +++ b/qController.Standard/Pages/ControlPage.xaml.cs @@ -3,6 +3,11 @@ using System.Collections.Generic; using Xamarin.Forms; using Serilog; using Acr.UserDialogs; +using qController.Dialogs; +using qController.QItems; +using qController.Cell; +using qController.Communication; + namespace qController { public partial class ControlPage : ContentPage @@ -11,8 +16,9 @@ namespace qController QSelectedCueCell qCell; QLevelsCell qLevelsCell; QCueListCell qCueListCell; - ShadowButton showLevelsButton; + QLevelsButton showLevelsButton; QControlsBlock qControlsBlock; + WorkspacePrompt workspacePrompt = new WorkspacePrompt(); public ControlPage(string name, string address) { @@ -26,16 +32,30 @@ namespace qController qController.qClient.qParser.ConnectionStatusChanged += OnConnectionStatusChanged; qController.qClient.qParser.CueInfoUpdated += OnCueUpdateReceived; qController.qClient.qParser.ChildrenUpdated += OnChildrenUpdated; + workspacePrompt.WorkspaceSelected += OnWorkspaceSelected; App.rootPage.MenuItemSelected += OnMenuItemSelected; instanceName.Text = name; - + InitGUI(); qController.KickOff(); } + private void OnWorkspaceSelected(object source, WorkspacePromptArgs args) + { + if (args.SelectedWorkspace != null) + { + qController.Connect(args.SelectedWorkspace); + } + else + { + Log.Debug("CONTROLPAGE - No Workspace selected backing out"); + Back(); + } + } + private void OnConnectionStatusChanged(object source, ConnectEventArgs args) { Log.Debug($"CONTROLPAGE - Connection Status Changed: {args.WorkspaceId} : {args.Status}"); @@ -48,13 +68,13 @@ namespace qController } else if (args.Status.Equals("badpass")) { - promptWorkspacePasscode(args.WorkspaceId); + workspacePrompt.promptWorkspacePasscode(args.WorkspaceId); } } private void WorkspaceInfoReceived(object source, WorkspaceInfoArgs args) { - if(args.WorkspaceInfo.Count > 1) + if (args.WorkspaceInfo.Count > 1) { Log.Debug("CONTROLPAGE - MULTIPLE WORKSPACES ON SELECTED COMPUTER"); PromptForWorkspace(args.WorkspaceInfo); @@ -65,51 +85,31 @@ namespace qController if (!args.WorkspaceInfo[0].hasPasscode) { qController.Connect(args.WorkspaceInfo[0].uniqueID); - + } else { - promptWorkspacePasscode(args.WorkspaceInfo[0].uniqueID); + workspacePrompt.promptWorkspacePasscode(args.WorkspaceInfo[0].uniqueID); } - } else { - UserDialogs.Instance.Confirm(new ConfirmConfig + NoWorkspacesConfig noWorkspacesConfig = new NoWorkspacesConfig(); + noWorkspacesConfig.OnAction = (resp) => { - Message = "QLab doesn't have any workspaces open?", - OkText = "Disconnect", - OnAction = (resp) => - { - if (resp) - Back(); - } - }); + if (resp) + Back(); + }; + + UserDialogs.Instance.Confirm(noWorkspacesConfig); } } private void PromptForWorkspace(List workspaces) { - ActionSheetConfig config = new ActionSheetConfig(); - config.SetTitle("Select Workspace"); - for (int i = 0; i < workspaces.Count; i++) - { - QWorkspaceInfo workspace = workspaces[i]; - config.Add(workspace.displayName, new Action(() => { - Log.Debug("CONTROLPAGE - Workspace Selected " + workspace.displayName); - if (!workspace.hasPasscode) - { - qController.Connect(workspace.uniqueID); - } - else - { - promptWorkspacePasscode(workspace.uniqueID); - } - - })); - } - UserDialogs.Instance.ActionSheet(config); + + UserDialogs.Instance.ActionSheet(workspacePrompt.getActionSheetConfigForWorkspaces(workspaces)); } private void InitGUI() @@ -121,11 +121,11 @@ namespace qController qCell = new QSelectedCueCell(); qCell.SelectedCueEdited += OnSelectedCueEdited; - + AbsoluteLayout.SetLayoutFlags(qCell, AbsoluteLayoutFlags.All); instanceName.FontSize = App.HeightUnit * 3; - + switch (Device.RuntimePlatform) { case Device.iOS: @@ -146,54 +146,41 @@ namespace qController menuButtonGesture.Tapped += ShowMenu; menuButton.GestureRecognizers.Add(menuButtonGesture); menuButton.Margin = new Thickness(App.WidthUnit * 2, 0, 0, App.WidthUnit * 2); - + sLayout.Children.Add(qCell); } private void OnSelectedCueEdited(object source, CueEditArgs args) { string address = "/workspace/" + qController.qWorkspace.workspace_id + "/cue_id/" + args.CueID + "/" + args.Property; - qController.qClient.sendUDP(address, args.NewValue); + qController.qClient.sendTCP(address, args.NewValue); } void FinishUI() { string workspace_prefix = "/workspace/" + qController.qWorkspace.workspace_id; - + qLevelsCell = new QLevelsCell(); qLevelsCell.mainSlider.ValueChanged += (sender, args) => { - qController.qClient.sendUDP(workspace_prefix + "/cue_id/" + qLevelsCell.activeCue + "/sliderLevel/0", (float)args.NewValue); + qController.qClient.sendTCP(workspace_prefix + "/cue_id/" + qLevelsCell.activeCue + "/sliderLevel/0", (float)args.NewValue); }; qLevelsCell.leftSlider.ValueChanged += (sender, args) => { - qController.qClient.sendUDP(workspace_prefix + "/cue_id/" + qLevelsCell.activeCue + "/sliderLevel/1", (float)args.NewValue); + qController.qClient.sendTCP(workspace_prefix + "/cue_id/" + qLevelsCell.activeCue + "/sliderLevel/1", (float)args.NewValue); }; qLevelsCell.rightSlider.ValueChanged += (sender, args) => { - qController.qClient.sendUDP(workspace_prefix + "/cue_id/" + qLevelsCell.activeCue + "/sliderLevel/2", (float)args.NewValue); + qController.qClient.sendTCP(workspace_prefix + "/cue_id/" + qLevelsCell.activeCue + "/sliderLevel/2", (float)args.NewValue); }; - Button showLevelsInnerButton = new Button - { - Text = QIcon.SLIDERS, - TextColor = Color.Black, - FontFamily = App.QFont, - FontSize = App.HeightUnit * 4, - VerticalOptions = LayoutOptions.FillAndExpand, - HorizontalOptions = LayoutOptions.FillAndExpand, - HeightRequest = App.HeightUnit * 8, - WidthRequest = App.HeightUnit * 8, - CornerRadius = (int)(App.HeightUnit * 4), - BackgroundColor = Color.LightBlue - }; - showLevelsInnerButton.Clicked += (s, e) => + + showLevelsButton = new QLevelsButton(); + showLevelsButton.button.Clicked += (s, e) => { qLevelsCell.IsVisible = !qLevelsCell.IsVisible; }; - - showLevelsButton = new ShadowButton(showLevelsInnerButton); qControlsBlock = new QControlsBlock(qController); AbsoluteLayout.SetLayoutFlags(qControlsBlock, AbsoluteLayoutFlags.All); @@ -205,7 +192,7 @@ namespace qController { case Device.iOS: AbsoluteLayout.SetLayoutBounds(qControlsBlock, new Rectangle(0, 0.53, 1, 0.25)); - AbsoluteLayout.SetLayoutBounds(qLevelsCell, new Rectangle(0.9,0.40,0.8,0.25)); + AbsoluteLayout.SetLayoutBounds(qLevelsCell, new Rectangle(0.9, 0.40, 0.8, 0.25)); AbsoluteLayout.SetLayoutBounds(showLevelsButton, new Rectangle(0.02, 0.34, App.HeightUnit * 8, App.HeightUnit * 8)); break; case Device.Android: @@ -222,6 +209,7 @@ namespace qController void ShowMenu(object sender, EventArgs e) { + App.MenuIsPresented = true; } @@ -257,12 +245,7 @@ namespace qController if (qCell.activeCue == null) { Device.BeginInvokeOnMainThread(() => { - QCue noSelect = new QCue(); - noSelect.listName = "No Cue Selected"; - noSelect.type = ""; - noSelect.notes = "Workspace has loaded but no cue is selected"; - noSelect.number = "!"; - qCell.UpdateSelectedCue(noSelect); + qCell.UpdateSelectedCue(new NoQCueSelected()); }); Log.Debug("CONTROLPAGE - Update Selected Cue Called because of Inital Workspace Load"); qController.qClient.UpdateSelectedCue(qController.qWorkspace.workspace_id); @@ -347,7 +330,7 @@ namespace qController { if (args.Command.Contains("/")) { - qController.qClient.sendUDP(args.Command); + qController.qClient.sendTCP(args.Command); } else if (args.Command == "disconnect") { @@ -370,36 +353,7 @@ namespace qController } } - private void promptWorkspacePasscode(string workspace_id) - { - UserDialogs.Instance.Prompt(new PromptConfig - { - InputType = InputType.Number, - MaxLength = 4, - Title = "Enter Workspace Passcode", - OkText = "Connect", - IsCancellable = true, - OnAction = (resp) => - { - if (resp.Ok) - { - qController.Connect(workspace_id, resp.Value); - } - else - { - Back(); - } - } - - }); - } - private void CloseCueList(object sender, EventArgs e) - { - CloseCueList(); - } - - private void CloseCueList() { Device.BeginInvokeOnMainThread(() => { @@ -411,19 +365,9 @@ namespace qController { OSCListItem cue = (OSCListItem)e.SelectedItem; string selectCueOSC = "/workspace/" + qController.qWorkspace.workspace_id + cue.Command; - qController.qClient.sendUDP(selectCueOSC); - CloseCueList(); + qController.qClient.sendTCP(selectCueOSC); + CloseCueList(sender,e); } - protected override bool OnBackButtonPressed() - { - qController.Kill(); - App.rootPage.MenuItemSelected -= OnMenuItemSelected; - Device.BeginInvokeOnMainThread(() => - { - App.rootPage.MenuPage.ChangeToHome(); - }); - return base.OnBackButtonPressed(); - } } } diff --git a/qController.Standard/Pages/MenuPage.xaml.cs b/qController.Standard/Pages/MenuPage.xaml.cs index bc78fbe..1d66b8a 100644 --- a/qController.Standard/Pages/MenuPage.xaml.cs +++ b/qController.Standard/Pages/MenuPage.xaml.cs @@ -1,6 +1,6 @@ -using System; -using System.Collections.ObjectModel; +using System.Collections.ObjectModel; using Xamarin.Forms; +using qController.QItems; namespace qController { diff --git a/qController.Standard/Pages/qConnectionPage.xaml.cs b/qController.Standard/Pages/qConnectionPage.xaml.cs index 5d8f376..171b9ff 100644 --- a/qController.Standard/Pages/qConnectionPage.xaml.cs +++ b/qController.Standard/Pages/qConnectionPage.xaml.cs @@ -4,6 +4,10 @@ using Acr.UserDialogs; using Zeroconf; using System.Collections.Generic; using Serilog; +using qController.QItems; +using qController.Communication; +using qController.Cell; +using Xamarin.Essentials; namespace qController { @@ -29,7 +33,7 @@ namespace qController } else if (args.Command == "feedback") { - Device.OpenUri(new Uri("mailto:jwetzell1996@gmail.com")); + Launcher.OpenAsync(new Uri("mailto:feedback@jwetzell.com?subject=qController%20feedback")); } else if(args.Command == "support") { @@ -41,7 +45,7 @@ namespace qController OnAction = (response) => { if (response) - Device.OpenUri(new Uri("https://linktr.ee/JoelWetzell")); + Launcher.OpenAsync(new Uri("https://linktr.ee/JoelWetzell")); } }); } diff --git a/qController.Standard/qController.csproj b/qController.Standard/qController.csproj index d454d40..38b5010 100644 --- a/qController.Standard/qController.csproj +++ b/qController.Standard/qController.csproj @@ -83,10 +83,12 @@ - + + +