diff --git a/QControlKit/QBrowser.cs b/QControlKit/QBrowser.cs
index faa71cc..83a4b33 100644
--- a/QControlKit/QBrowser.cs
+++ b/QControlKit/QBrowser.cs
@@ -70,9 +70,11 @@ namespace QControlKit
if (found == null)
{
- server.disconnect();
- servers.Remove(server);
Log.Information($"[qbrowser] Lost {server.name} : {server.host} : {server.port}");
+ server.disconnect();
+ Log.Information($"[qbrowser] after server disconnect()");
+
+ servers.Remove(server);
OnServerLost(server);
}
}
@@ -121,7 +123,8 @@ namespace QControlKit
public void Close()
{
- foreach(var server in servers)
+ Log.Information($"[qbrowser] Close requested");
+ foreach (var server in servers)
{
server.disconnect();
}
diff --git a/QControlKit/QClient.cs b/QControlKit/QClient.cs
index 11f9dbb..5e9d0fb 100644
--- a/QControlKit/QClient.cs
+++ b/QControlKit/QClient.cs
@@ -52,7 +52,7 @@ namespace QControlKit
public void disconnect()
{
- Log.Debug($"[client] disconnecting from {tcpClient.Address}");
+ Log.Information($"[client] disconnecting from {tcpClient.Address}");
tcpClient.Close();
}
@@ -60,7 +60,7 @@ namespace QControlKit
public void sendMessage(string address, params object[] args)
{
tcpClient.QueueForSending(new OscMessage(address, args));
- Log.Debug($"[client] send message {address} : {args}");
+ Log.Information($"[client] send message {address} : {args}");
}
private void ProcessMessage(object source, MessageEventArgs args)
@@ -97,7 +97,7 @@ namespace QControlKit
}
else
{
- Log.Warning($"[client] unhandled reply from cue: Type: {data.Type} value: {message.response}");
+ Log.Error($"[client] unhandled reply from cue: Type: {data.Type} value: {message.response}");
}
}
@@ -118,7 +118,7 @@ namespace QControlKit
}
else
{
- Log.Warning($"[client] unhandled reply message: {message.address}");
+ Log.Error($"[client] unhandled reply message: {message.address}");
}
}
else if(message.IsUpdate) {
@@ -162,12 +162,12 @@ namespace QControlKit
}
else
{
- Log.Warning($"[client] unhandled update message: {message.address}");
+ Log.Error($"[client] unhandled update message: {message.address}");
}
}
else
{
- Log.Warning($"[client] unhandled message: {message.address}");
+ Log.Error($"[client] unhandled message: {message.address}");
}
}
diff --git a/QControlKit/QControlKit.csproj b/QControlKit/QControlKit.csproj
index 1250793..1f52d5e 100644
--- a/QControlKit/QControlKit.csproj
+++ b/QControlKit/QControlKit.csproj
@@ -6,7 +6,7 @@
Joel Wetzell
1.0.0-devel
true
- 0.0.21
+ 0.0.23
QControlKit
MIT
Unofficial C# port of Figure53's QLabKit.objc
@@ -18,6 +18,7 @@
+
@@ -29,5 +30,7 @@
+
+
diff --git a/QControlKit/QCue.cs b/QControlKit/QCue.cs
index 05b48e5..c8ece0d 100644
--- a/QControlKit/QCue.cs
+++ b/QControlKit/QCue.cs
@@ -18,6 +18,7 @@ namespace QControlKit
public List childCues;
public Dictionary childCuesUIDMap;
+
public int sortIndex;
public int nestLevel;
@@ -43,32 +44,9 @@ namespace QControlKit
{
init();
this.workspace = workspace;
-
- //this breaks things???
- //it definitely is in the original but somehow the recursion is not working as I expect..
- //but cue population still works without this as child cues are populated later
-
- /*JToken children = dict[QOSCKey.Cues];
- if(children != null && children.Type == JTokenType.Array)
- {
- Log.Debug($"[cue] new cue being created with {children.Count()} childCues");
- foreach (var aChildDict in children)
- {
- string uid = (string)aChildDict[QOSCKey.UID];
- //Log.Debug($"[cue] childDict with uid: {uid} being processed");
- if (uid == null)
- continue;
- string name = dict[QOSCKey.UID].ToString();
- Log.Debug($"[cue] calling new cue from {name}");
-
- //QCue child = new QCue(aChildDict, workspace);
-
- *//*childCues.Add(child);
- childCuesUIDMap.Add(uid, child);*//*
- }
- }*/
-
updatePropertiesWithDictionary(dict);
+ workspace.fetchBasicPropertiesForCue(this);
+
}
public QCue(JToken dict, QWorkspace workspace, int nestLevel)
@@ -76,31 +54,8 @@ namespace QControlKit
init();
this.workspace = workspace;
this.nestLevel = nestLevel + 1;
- //this breaks things???
- //it definitely is in the original but somehow the recursion is not working as I expect..
- //but cue population still works without this as child cues are populated later
-
- /*JToken children = dict[QOSCKey.Cues];
- if(children != null && children.Type == JTokenType.Array)
- {
- Log.Debug($"[cue] new cue being created with {children.Count()} childCues");
- foreach (var aChildDict in children)
- {
- string uid = (string)aChildDict[QOSCKey.UID];
- //Log.Debug($"[cue] childDict with uid: {uid} being processed");
- if (uid == null)
- continue;
- string name = dict[QOSCKey.UID].ToString();
- Log.Debug($"[cue] calling new cue from {name}");
-
- //QCue child = new QCue(aChildDict, workspace);
-
- *//*childCues.Add(child);
- childCuesUIDMap.Add(uid, child);*//*
- }
- }*/
-
updatePropertiesWithDictionary(dict);
+ workspace.fetchBasicPropertiesForCue(this);
}
public void init()
@@ -244,7 +199,14 @@ namespace QControlKit
{
get
{
- return propertyForKey(QOSCKey.Parent).ToString();
+ if(propertyForKey(QOSCKey.Parent) != null)
+ {
+ return propertyForKey(QOSCKey.Parent).ToString();
+ }
+ else
+ {
+ return "";
+ }
}
}
public string playbackPositionID {
@@ -301,7 +263,14 @@ namespace QControlKit
{
get
{
- return propertyForKey(QOSCKey.ListName).ToString();
+ if(propertyForKey(QOSCKey.ListName) == null)
+ {
+ return "";
+ }
+ else
+ {
+ return propertyForKey(QOSCKey.ListName).ToString();
+ }
}
set
{
@@ -353,46 +322,39 @@ namespace QControlKit
if (workspace.connectedToQLab3 || workspace.isOlderThanVersion("4.2.0"))
return false;
- bool overridden = (bool)propertyForKey(QOSCKey.IsOverridden);
-
- if (overridden)
- return true;
foreach (var cue in cues)
{
if (cue.IsOverridden)
return true;
}
- return false;
+
+ return getBoolForKey(QOSCKey.IsOverridden);
}
}
public bool IsBroken
{
get
{
- if ((bool)propertyForKey(QOSCKey.IsBroken))
- return true;
- foreach(var cue in cues)
+ foreach (var cue in cues)
{
if (cue.IsBroken)
return true;
}
- return false;
+
+ return getBoolForKey(QOSCKey.IsBroken);
}
}
public bool IsRunning
{
get
{
- bool running = (bool)propertyForKey(QOSCKey.IsRunning);
-
- if (running)
- return true;
- foreach(var cue in cues)
+ foreach (var cue in cues)
{
if (cue.IsRunning)
return true;
}
- return false;
+
+ return getBoolForKey(QOSCKey.IsRunning);
}
}
public bool IsTailingOut
@@ -402,16 +364,13 @@ namespace QControlKit
if (workspace.connectedToQLab3)
return false;
- bool tailingOut = (bool)propertyForKey(QOSCKey.IsTailingOut);
-
- if (tailingOut)
- return true;
- foreach(var cue in cues)
+ foreach (var cue in cues)
{
if (cue.IsTailingOut)
return true;
}
- return false;
+
+ return getBoolForKey(QOSCKey.IsTailingOut);
}
}
public bool IsPanicking
@@ -421,16 +380,13 @@ namespace QControlKit
if (workspace.connectedToQLab3)
return false;
- bool panicking = (bool)propertyForKey(QOSCKey.IsPanicking);
-
- if (panicking)
- return true;
foreach (var cue in cues)
{
if (cue.IsPanicking)
return true;
}
- return false;
+
+ return getBoolForKey(QOSCKey.IsPanicking);
}
}
public bool IsGroup
@@ -571,6 +527,23 @@ namespace QControlKit
}
}
+
+ public float actionElapsed
+ {
+ get
+ {
+ object secs = propertyForKey(QOSCKey.ActionElapsed);
+ if (secs != null)
+ {
+ return float.Parse(secs.ToString());
+ }
+ else
+ {
+ return 0F;
+ }
+ }
+ }
+
public QTriggerAction secondTriggerAction
{
get
@@ -827,6 +800,32 @@ namespace QControlKit
}
return null;
}
+
+ public bool getBoolForKey(string key)
+ {
+ if (propertyForKey(key) != null)
+ {
+ object prop = propertyForKey(key);
+ //Log.Warning($"{listName} IsBroken: {propertyForKey(QOSCKey.IsBroken).ToString()} {prop.GetType().ToString()}");
+ if(prop.GetType() == typeof(Boolean)){
+ return (bool)prop;
+ }
+ else if (prop.GetType() == typeof(JValue))
+ {
+ JValue value = (JValue)prop;
+ return (bool)value.Value;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
public object propertyForKey(string key)
{
//TODO: implerment special key checks color, surfaceName, patchDescription,
@@ -996,7 +995,10 @@ namespace QControlKit
#region Event Handling
void OnCuePropertiesUpdated(List properties)
{
- Log.Debug($"[cue] <{nonEmptyName}> properties have been updated.");
+ if(parentID != null && parentID != "")
+ {
+ workspace.fetchBasicPropertiesForCue(workspace.cueWithID(parentID));
+ }
CuePropertiesUpdated?.Invoke(this, new QCuePropertiesUpdatedArgs { properties = properties });
}
#endregion
diff --git a/QControlKit/QMessage.cs b/QControlKit/QMessage.cs
index 154b17e..ce8d9de 100644
--- a/QControlKit/QMessage.cs
+++ b/QControlKit/QMessage.cs
@@ -143,5 +143,21 @@ namespace QControlKit
}
}
+ override
+ public string ToString()
+ {
+ string stringified = "";
+
+ stringified += $"\nAddress: {this.address}\nArguments: \n";
+
+
+ for(int i = 0; i");
foreach (var workspace in workspaces)
{
if (workspace.connected)
diff --git a/QControlKit/QWorkspace.cs b/QControlKit/QWorkspace.cs
index 08513dc..ca969ef 100644
--- a/QControlKit/QWorkspace.cs
+++ b/QControlKit/QWorkspace.cs
@@ -3,8 +3,6 @@ using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Timers;
-
using QControlKit.Events;
using QControlKit.Constants;
@@ -217,15 +215,13 @@ namespace QControlKit
return;
stopReceivingUpdates();
disconnectFromWorkspace();
-
- connected = false;
client.disconnect();
-
+ connected = false;
}
public void temporarilyDisconnect()
{
- //TODO
+ //TODO what does this mean?
}
#endregion
@@ -245,6 +241,7 @@ namespace QControlKit
#region Workspace Methods
public void disconnectFromWorkspace() { client.sendMessage($"{workspacePrefix}/disconnect"); }
public void startReceivingUpdates() { client.sendMessage($"{workspacePrefix}/updates", 1); }
+ public void getPropertyForActive(string prop) { client.sendMessage($"{workspacePrefix}/cue/active/{prop}"); }
public void stopReceivingUpdates() { client.sendMessage($"{workspacePrefix}/updates", 0); }
public void enableAlwaysReply() { client.sendMessage($"{workspacePrefix}/alwaysReply", 1); }
public void disableAlwaysReply() { client.sendMessage($"{workspacePrefix}/alwaysReply", 0); }
@@ -320,18 +317,48 @@ namespace QControlKit
public void fetchDefaultPropertiesForCue(QCue cue)
{
- List keys = new List { QOSCKey.UID, QOSCKey.Number, QOSCKey.Name,
- QOSCKey.ListName, QOSCKey.Type, QOSCKey.ColorName,
- QOSCKey.Flagged, QOSCKey.Armed, QOSCKey.Notes };
+ List keys = new List {
+ QOSCKey.UID,
+ QOSCKey.Number,
+ QOSCKey.Name,
+ QOSCKey.ListName,
+ QOSCKey.Type,
+ QOSCKey.ColorName,
+ QOSCKey.Flagged,
+ QOSCKey.Armed,
+ QOSCKey.IsRunning,
+ QOSCKey.IsBroken,
+ QOSCKey.Parent,
+ QOSCKey.Notes
+ };
+
fetchPropertiesForCue(cue, keys.ToArray(), false);
}
public void fetchBasicPropertiesForCue(QCue cue)
{
- List keys = new List { QOSCKey.Name, QOSCKey.ListName, QOSCKey.Number, QOSCKey.FileTarget, QOSCKey.CueTargetNumber,
- QOSCKey.HasFileTargets, QOSCKey.HasCueTargets, QOSCKey.Armed, QOSCKey.ColorName,
- QOSCKey.ContinueMode, QOSCKey.Flagged, QOSCKey.PreWait, QOSCKey.PostWait,
- QOSCKey.Duration, QOSCKey.AllowsEditingDuration, QOSCKey.Notes };
+ List keys = new List {
+ QOSCKey.Name,
+ QOSCKey.ListName,
+ QOSCKey.Number,
+ QOSCKey.FileTarget,
+ QOSCKey.CueTargetNumber,
+ QOSCKey.HasFileTargets,
+ QOSCKey.HasCueTargets,
+ QOSCKey.Armed,
+ QOSCKey.ColorName,
+ QOSCKey.ContinueMode,
+ QOSCKey.Flagged,
+ QOSCKey.PreWait,
+ QOSCKey.PostWait,
+ QOSCKey.Duration,
+ QOSCKey.AllowsEditingDuration,
+ QOSCKey.IsBroken,
+ QOSCKey.IsRunning,
+ QOSCKey.IsLoaded,
+ QOSCKey.Notes
+ };
+
if (cue.IsGroup)
keys.Add(QOSCKey.Children);
fetchPropertiesForCue(cue, keys.ToArray(), false);
@@ -502,7 +529,7 @@ namespace QControlKit
cueList.setProperty(args.cueID, QOSCKey.PlaybackPositionId, false);
}
- Log.Debug($"[workspace] cue list <{args.cueListID}> playback position changed to <{args.cueID}>");
+ Log.Information($"[workspace] cue list <{args.cueListID}> playback position changed to <{args.cueID}>");
CueListChangedPlaybackPosition?.Invoke(this, new QCueListChangedPlaybackPositionArgs { cueListID = args.cueListID, cueID = args.cueID });
}
diff --git a/QControlKit/SharpOSC/TCPClient.cs b/QControlKit/SharpOSC/TCPClient.cs
index 23119bd..2f430bf 100644
--- a/QControlKit/SharpOSC/TCPClient.cs
+++ b/QControlKit/SharpOSC/TCPClient.cs
@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Net.Sockets;
using System.Threading;
using Serilog;
+using SuperSimpleTcp;
namespace SharpOSC
{
@@ -38,32 +36,64 @@ namespace SharpOSC
private Thread sendThread;
string _address;
- TcpClient client;
byte END = 0xc0;
byte ESC = 0xdb;
byte ESC_END = 0xDC;
byte ESC_ESC = 0xDD;
+ SimpleTcpClient simpleClient;
+
public TCPClient(string address, int port)
{
_port = port;
_address = address;
+
+ simpleClient = new SimpleTcpClient(address, port);
+ simpleClient.Events.Connected += Connected;
+ simpleClient.Events.Disconnected += Disconnected;
+ simpleClient.Events.DataReceived += DataReceived;
+ simpleClient.Logger = Log.Debug;
+ }
+
+ public static string ByteArrayToString(byte[] ba)
+ {
+ return BitConverter.ToString(ba).Replace("-", "");
+ }
+
+ private void DataReceived(object sender, DataReceivedEventArgs e)
+ {
+ List messages = SlipDecode(e.Data);
+ for(int i = 0; i < messages.Count; i++)
+ {
+ OscPacket packet = OscPacket.GetPacket(messages[i]);
+ OscMessage responseMessage = (OscMessage)packet;
+ OnMessageReceived(responseMessage);
+ }
+ }
+
+ private void Disconnected(object sender, ConnectionEventArgs e)
+ {
+ Log.Debug("[tcpClient] connection to " + e.IpPort + " was disconnected");
+ }
+
+ private void Connected(object sender, ConnectionEventArgs e)
+ {
+ Log.Debug($"[tcpclient] connected to <{e.IpPort}>");
}
public bool Connect()
{
try
{
- client = new TcpClient(Address, Port);
- receivingThread = new Thread(ReceiveLoop);
- receivingThread.Start();
+ simpleClient.Connect();
sendThread = new Thread(SendLoop);
+ sendThread.IsBackground = true;
sendThread.Start();
- Log.Debug($"[tcpclient] connected to <{Address}:{Port}>");
+
return true;
}
catch (Exception e)
@@ -71,7 +101,6 @@ namespace SharpOSC
Log.Error(e.Message);
return false;
}
-
}
public void QueueForSending(OscPacket packet)
@@ -81,7 +110,7 @@ namespace SharpOSC
private void SendLoop()
{
- while (client != null && client.Connected)
+ while (simpleClient != null && simpleClient.IsConnected)
{
if(SendQueue.Count > 0)
{
@@ -94,8 +123,7 @@ namespace SharpOSC
public void Send(byte[] message)
{
byte[] slipData = SlipEncode(message);
- NetworkStream netStream = client.GetStream();
- netStream.Write(slipData.ToArray(), 0, slipData.ToArray().Length);
+ simpleClient.Send(slipData);
}
public void Send(OscPacket packet)
@@ -108,57 +136,10 @@ namespace SharpOSC
{
get
{
- if (client == null)
+ if (simpleClient == null)
return false;
else
- return client.Connected;
- }
- }
-
- public void ReceiveLoop()
- {
- while (client != null && client.Connected)
- {
- Receive();
- }
- //Log.Debug("[tcpclient] - ReceiveLoop has exited");
- }
-
- public void Receive()
- {
- Random random = new Random();
- int num = random.Next(1000);
- try
- {
- NetworkStream netStream = client.GetStream();
- netStream.ReadTimeout = 250;
- 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);
- reads += 1;
- Thread.Sleep(1);
- //Log.Debug("Thread " + num + ": Bytes read: " + bytesRead + " - " + Encoding.UTF8.GetString(buffer));
- } while (netStream.DataAvailable);
-
- //Console.WriteLine("Raw TCP In: " + System.Text.Encoding.UTF8.GetString(responseData.ToArray()));
- OscPacket packet = OscPacket.GetPacket(responseData.Skip(1).ToArray());
- OscMessage responseMessage = (OscMessage)packet;
- //watch.Stop();
- //Console.WriteLine($"TCPCLient - message receive took {watch.ElapsedMilliseconds}ms and {reads} reads");
- OnMessageReceived(responseMessage);
- }
- } catch(Exception e)
- {
- //Console.WriteLine("TCPSENDER - Receive Exception: " + e.ToString());
+ return simpleClient.IsConnected;
}
}
@@ -190,15 +171,35 @@ namespace SharpOSC
return slipData.ToArray();
}
+ public List SlipDecode(byte[] data)
+ {
+ List messages = new List();
+
+ List buffer = new List();
+ for(int i = 0; i < data.Length; i++)
+ {
+ if(data[i] == END && buffer.Count > 0)
+ {
+ messages.Add(buffer.ToArray());
+ buffer.Clear();
+ }
+ else if (data[i] != END)
+ {
+ buffer.Add(data[i]);
+ }
+ }
+ return messages;
+ }
+
public void Close()
{
- if (client != null)
+ Log.Information("[tcpclient] Close() was requested");
+ if (simpleClient != null)
{
- if (client.Connected)
+ if (simpleClient.IsConnected)
{
- Log.Debug($"[tcpClient] closing connection to {Address}");
- client.GetStream().Close();
- client.Close();
+ Log.Information($"[tcpClient] closing connection to {Address}");
+ simpleClient.Disconnect();
}
}
}
diff --git a/QControlKitXamDemo/QControlKitXamDemo.Android/Assets/materialdesignicons-webfont.ttf b/QControlKitXamDemo/QControlKitXamDemo.Android/Assets/materialdesignicons-webfont.ttf
new file mode 100644
index 0000000..522dc31
Binary files /dev/null and b/QControlKitXamDemo/QControlKitXamDemo.Android/Assets/materialdesignicons-webfont.ttf differ
diff --git a/QControlKitXamDemo/QControlKitXamDemo.Android/QControlKitXamDemo.Android.csproj b/QControlKitXamDemo/QControlKitXamDemo.Android/QControlKitXamDemo.Android.csproj
index bcdd620..9a5d8c1 100644
--- a/QControlKitXamDemo/QControlKitXamDemo.Android/QControlKitXamDemo.Android.csproj
+++ b/QControlKitXamDemo/QControlKitXamDemo.Android/QControlKitXamDemo.Android.csproj
@@ -101,6 +101,9 @@
QControlKitXamDemo
+
+
+
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/Info.plist b/QControlKitXamDemo/QControlKitXamDemo.iOS/Info.plist
index b614303..6e76ccc 100644
--- a/QControlKitXamDemo/QControlKitXamDemo.iOS/Info.plist
+++ b/QControlKitXamDemo/QControlKitXamDemo.iOS/Info.plist
@@ -40,5 +40,9 @@
NSLocalNetworkUsageDescription
Scan network for QLab instances
+ UIAppFonts
+
+ materialdesignicons-webfont.ttf
+
diff --git a/QControlKitXamDemo/QControlKitXamDemo.iOS/QControlKitXamDemo.iOS.csproj b/QControlKitXamDemo/QControlKitXamDemo.iOS/QControlKitXamDemo.iOS.csproj
index 3fe068e..fe3246f 100644
--- a/QControlKitXamDemo/QControlKitXamDemo.iOS/QControlKitXamDemo.iOS.csproj
+++ b/QControlKitXamDemo/QControlKitXamDemo.iOS/QControlKitXamDemo.iOS.csproj
@@ -133,6 +133,9 @@
+
+ 2.6.0
+
@@ -141,4 +144,7 @@
QControlKitXamDemo
+
+
+
\ No newline at end of file
diff --git a/QControlKitXamDemo/QControlKitXamDemo.iOS/Resources/materialdesignicons-webfont.ttf b/QControlKitXamDemo/QControlKitXamDemo.iOS/Resources/materialdesignicons-webfont.ttf
new file mode 100644
index 0000000..522dc31
Binary files /dev/null and b/QControlKitXamDemo/QControlKitXamDemo.iOS/Resources/materialdesignicons-webfont.ttf differ
diff --git a/QControlKitXamDemo/QControlKitXamDemo/App.xaml b/QControlKitXamDemo/QControlKitXamDemo/App.xaml
index 6dfba81..8f6f0ac 100644
--- a/QControlKitXamDemo/QControlKitXamDemo/App.xaml
+++ b/QControlKitXamDemo/QControlKitXamDemo/App.xaml
@@ -6,6 +6,52 @@
mc:Ignorable="d"
x:Class="QControlKitXamDemo.App">
+
+ Material Design Icons
+ materialdesignicons-webfont.ttf#Material Design Icons
+
+
+
+
+
+
+ 4
+ 8
+ 16
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/QControlKitXamDemo/QControlKitXamDemo/App.xaml.cs b/QControlKitXamDemo/QControlKitXamDemo/App.xaml.cs
index 2804dc9..b86146e 100644
--- a/QControlKitXamDemo/QControlKitXamDemo/App.xaml.cs
+++ b/QControlKitXamDemo/QControlKitXamDemo/App.xaml.cs
@@ -9,6 +9,8 @@ namespace QControlKitXamDemo
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
+ Current.RequestedThemeChanged += Current_RequestedThemeChanged;
+ SetAppResources();
}
protected override void OnStart()
@@ -22,5 +24,80 @@ namespace QControlKitXamDemo
protected override void OnResume()
{
}
+
+ private void Current_RequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
+ {
+ SetAppResources();
+ }
+
+ private void SetAppResources()
+ {
+
+ switch (Current.RequestedTheme)
+ {
+ case OSAppTheme.Light:
+ SetLightResources();
+ break;
+ case OSAppTheme.Dark:
+ SetDarkResources();
+ break;
+ case OSAppTheme.Unspecified:
+ //Default to Light
+ SetLightResources();
+ break;
+ default:
+ SetLightResources();
+ break;
+ }
+ }
+
+ private void SetDarkResources()
+ {
+
+ Resources["NavigationBarColor"] = Color.FromHex("#3f6dab");
+ Resources["PageBackgroundColor"] = Color.FromHex("#525252");
+
+
+ Resources["PrimaryColor"] = Color.WhiteSmoke;
+ Resources["SecondaryColor"] = Color.White;
+ Resources["PrimaryTextColor"] = Color.LightGray;
+ Resources["SecondaryTextColor"] = Color.White;
+ Resources["TertiaryTextColor"] = Color.Gray;
+ Resources["TransparentColor"] = Color.Transparent;
+
+ Resources["IconTextColor"] = Color.WhiteSmoke;
+
+ Resources["ListViewBackgroundColor"] = Color.FromHex("#363636");
+
+ Resources["ServerCellBackgroundColor"] = Color.FromHex("#363636");
+ Resources["WorkspaceCellBackgroundColor"] = Color.FromHex("#737373");
+
+ Resources["SelectedCueCellBackgroundColor"] = Color.FromHex("#737373");
+
+ }
+
+ private void SetLightResources()
+ {
+ Resources["NavigationBarColor"] = Color.FromHex("#3089ff");
+ Resources["PageBackgroundColor"] = Color.LightGray;
+
+
+ Resources["PrimaryColor"] = Color.WhiteSmoke;
+ Resources["SecondaryColor"] = Color.White;
+ Resources["PrimaryTextColor"] = Color.Black;
+ Resources["SecondaryTextColor"] = Color.White;
+ Resources["TertiaryTextColor"] = Color.Gray;
+ Resources["TransparentColor"] = Color.Transparent;
+
+ Resources["IconTextColor"] = Color.Black;
+
+ Resources["ListViewBackgroundColor"] = Color.White;
+
+ Resources["ServerCellBackgroundColor"] = Color.White;
+ Resources["WorkspaceCellBackgroundColor"] = Color.FromHex("#D8D8D8");
+
+ Resources["SelectedCueCellBackgroundColor"] = Color.FromHex("#D8D8D8");
+
+ }
}
}
diff --git a/QControlKitXamDemo/QControlKitXamDemo/CueListPage.xaml.cs b/QControlKitXamDemo/QControlKitXamDemo/CueListPage.xaml.cs
index 7b3e377..89fc60f 100644
--- a/QControlKitXamDemo/QControlKitXamDemo/CueListPage.xaml.cs
+++ b/QControlKitXamDemo/QControlKitXamDemo/CueListPage.xaml.cs
@@ -95,7 +95,7 @@ namespace QControlKitXamDemo
HorizontalOptions = LayoutOptions.StartAndExpand,
VerticalTextAlignment = TextAlignment.Center,
};
- cueLabel.SetBinding(Label.TextProperty, "name", BindingMode.OneWay);
+ cueLabel.SetBinding(Label.TextProperty, "status", BindingMode.OneWay);
var cueBackground = new Frame
{
BindingContext = qCueViewModel,
diff --git a/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml b/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml
index a258309..6e65bad 100644
--- a/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml
+++ b/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml
@@ -3,14 +3,121 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- x:Class="QControlKitXamDemo.MainPage">
+ xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
+ mc:Ignorable="d"
+ x:Class="QControlKitXamDemo.MainPage"
+ ios:Page.UseSafeArea="true"
+ BackgroundColor="{DynamicResource PageBackgroundColor}">
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml.cs b/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml.cs
index 798e341..cecd380 100644
--- a/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml.cs
+++ b/QControlKitXamDemo/QControlKitXamDemo/MainPage.xaml.cs
@@ -2,150 +2,71 @@
using System.ComponentModel;
using Xamarin.Forms;
using QControlKit;
-using System.Collections.ObjectModel;
-using System.Collections.Generic;
-using System.Linq;
-using QControlKit.Events;
-using System.Threading.Tasks;
using Serilog;
+using QControlKitXamDemo.ViewModels;
+using Acr.UserDialogs;
namespace QControlKitXamDemo
{
- // Learn more about making custom code visible in the Xamarin.Forms previewer
- // by visiting https://aka.ms/xamarinforms-previewer
- [DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
- public ObservableCollection servers = new ObservableCollection();
+ private QBrowserViewModel qBrowserViewModel;
public MainPage()
{
InitializeComponent();
- serverListView.ItemsSource = servers;
- QBrowser browser = new QBrowser();
- browser.ServerLost += Browser_ServerLost;
- browser.ServerFound += Browser_ServerFound;
- serverListView.ItemSelected += ServerListView_ItemSelected;
- Device.StartTimer(TimeSpan.FromSeconds(5), () =>
- {
- Task.Run(async () =>
- {
- Device.BeginInvokeOnMainThread(() =>
- {
- browser.ProbeForQLabInstances();
- });
-
- });
- return true;
- });
+ qBrowserViewModel = new QBrowserViewModel(new QBrowser());
+ serverListView.BindingContext = qBrowserViewModel;
+ serverListView.ItemSelected += QWorkspaceSelected;
}
- private void Browser_ServerFound(object source, QServerFoundArgs args)
+ async void QWorkspaceSelected(object sender, SelectedItemChangedEventArgs e)
{
- List serverGroups = servers.ToList();
-
- bool serverFound = false;
- foreach (var serverGroup in serverGroups)
+ if (e.SelectedItem == null)
{
-
- if (serverGroup.host == args.server.host)
- {
- serverFound = true;
-
- }
+ return;
}
- 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);
- });
- }
- }
+ qBrowserViewModel.autoUpdate = false;
+ QWorkspace selectedWorkspace = (e.SelectedItem as QWorkspaceViewModel).workspace;
+ Log.Debug($"[demo] workspace: {selectedWorkspace.nameWithoutPathExtension} has been selected");
+ ((ListView)sender).SelectedItem = null;
- private void Server_WorkspaceRemoved(object source, QServerWorkspaceChangedArgs args)
- {
- foreach (var server in servers)
+ if (selectedWorkspace.hasPasscode)
{
- if (server.host == args.server.host)
+ UserDialogs.Instance.Prompt(new PromptConfig
{
- Device.BeginInvokeOnMainThread(() =>
+ InputType = InputType.Number,
+ MaxLength = 4,
+ Title = "Workspace Requires Passcode",
+ OkText = "Connect",
+ IsCancellable = true,
+ OnTextChanged = args =>
{
- 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(() =>
+ args.IsValid = args.Value != null && !args.Value.Equals("") && args.Value.Length == 4;
+ },
+ OnAction = async (resp) =>
{
- 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)
- {
- if(e.SelectedItem != null)
- {
- QWorkspace selectedWorkspace = e.SelectedItem as QWorkspace;
- Log.Debug($"[demo] Workspace <{selectedWorkspace.nameWithoutPathExtension}> has been selected");
- if (selectedWorkspace.hasPasscode)
- {
- string passcode = await DisplayPromptAsync("Workspace has passcode", "Enter Passcode", maxLength: 4, keyboard: Keyboard.Numeric);
- if (passcode != null)
- {
-
- await Navigation.PushAsync(new CueListPage(selectedWorkspace, passcode));
+ if (resp.Ok)
+ {
+ await Navigation.PushAsync(new CueListPage(selectedWorkspace, resp.Value));
+ }
}
- }
- else
- {
- await Navigation.PushAsync(new CueListPage(selectedWorkspace));
- }
- serverListView.SelectedItem = null;
+ });
+ }
+ else
+ {
+ await Navigation.PushAsync(new CueListPage(selectedWorkspace));
}
}
- }
- public class ServerGroup : ObservableCollection{
- public string name { get; set; }
- public string host { get; set; }
- public ServerGroup(string name)
+
+ protected override void OnAppearing()
{
- this.name = name;
+ base.OnAppearing();
+ qBrowserViewModel.autoUpdate = true;
}
-
-
}
-}
+}
\ No newline at end of file
diff --git a/QControlKitXamDemo/QControlKitXamDemo/QControlKitXamDemo.csproj b/QControlKitXamDemo/QControlKitXamDemo/QControlKitXamDemo.csproj
index ffec7a3..fd63104 100644
--- a/QControlKitXamDemo/QControlKitXamDemo/QControlKitXamDemo.csproj
+++ b/QControlKitXamDemo/QControlKitXamDemo/QControlKitXamDemo.csproj
@@ -14,6 +14,7 @@
+
@@ -28,4 +29,7 @@
+
+
+
\ No newline at end of file
diff --git a/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QBrowserViewModel.cs b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QBrowserViewModel.cs
new file mode 100644
index 0000000..e5785ad
--- /dev/null
+++ b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QBrowserViewModel.cs
@@ -0,0 +1,93 @@
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms;
+
+using QControlKit;
+using QControlKit.Events;
+using System;
+using System.Threading.Tasks;
+using Serilog;
+
+namespace QControlKitXamDemo.ViewModels
+{
+ public class QBrowserViewModel : INotifyPropertyChanged
+ {
+ QBrowser browser;
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ public bool autoUpdate = false;
+ public ObservableCollection ServersGrouped { get; set; }
+ public QBrowserViewModel(QBrowser browser)
+ {
+ this.browser = browser;
+ ServersGrouped = new ObservableCollection();
+
+ this.browser.ServerFound += OnServerFound;
+ this.browser.ServerLost += OnServerLost;
+ Device.StartTimer(TimeSpan.FromSeconds(4), () =>
+ {
+ Task.Run(() =>
+ {
+ if (autoUpdate)
+ {
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ Log.Debug("[QBrowserViewModel] QBrowser probe triggered");
+ this.browser.ProbeForQLabInstances();
+ });
+ }
+ });
+ return true;
+ });
+
+ }
+
+ private void OnServerFound(object source, QServerFoundArgs args)
+ {
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ Log.Debug($"[QBrowserViewModel] adding server: {args.server.description}");
+ ServersGrouped.Add(new QServerViewModel(args.server));
+ });
+ }
+
+
+ private void OnServerLost(object source, QServerLostArgs args)
+ {
+ QServerViewModel serverToRemove = null;
+
+ foreach (QServerViewModel serverGroup in ServersGrouped)
+ {
+ if (serverGroup.host.Equals(args.server.host))
+ {
+ serverToRemove = serverGroup;
+ break;
+ }
+ }
+
+ if (serverToRemove != null)
+ {
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ Log.Debug($"[QBrowserViewModel] removing server: {args.server.description}");
+ ServersGrouped.Remove(serverToRemove);
+ });
+ }
+ }
+
+ void OnPropertyChanged([CallerMemberName] string name = "")
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
+ }
+
+ public void InitiateScan()
+ {
+ if (!autoUpdate)
+ {
+ Log.Debug("[QBrowserViewModel] Manual Scan Initiated");
+ browser.ProbeForQLabInstances();
+ }
+ }
+ }
+}
diff --git a/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QCueViewModel.cs b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QCueViewModel.cs
index 05a3b16..c73c51d 100644
--- a/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QCueViewModel.cs
+++ b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QCueViewModel.cs
@@ -5,6 +5,7 @@ using Xamarin.Forms;
using Serilog;
using QControlKit.Events;
using QControlKit.Constants;
+using System;
namespace QControlKitXamDemo.ViewModels
{
@@ -26,13 +27,19 @@ 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 for cue {name}.");
if (property.Equals(QOSCKey.Name) || property.Equals(QOSCKey.ListName))
{
OnPropertyChanged("name");
}else if (property.Equals(QOSCKey.ColorName))
{
OnPropertyChanged("color");
+ }else if (property.Equals(QOSCKey.ActionElapsed))
+ {
+ OnPropertyChanged("actionElapsed");
+ }else if (property.Equals(QOSCKey.IsBroken) || property.Equals(QOSCKey.IsRunning))
+ {
+ OnPropertyChanged("status");
}
}
}
@@ -84,6 +91,34 @@ namespace QControlKitXamDemo.ViewModels
}
}
+ public string actionElapsed
+ {
+ get
+ {
+ TimeSpan time = TimeSpan.FromSeconds(cue.actionElapsed);
+
+ return time.ToString(@"mm\:ss\:ff");
+ }
+ }
+
+ public string status
+ {
+ get
+ {
+ if (cue.IsRunning)
+ {
+ return "running";
+ }else if (cue.IsBroken)
+ {
+ return "broken";
+ }
+ else
+ {
+ return " ";
+ }
+ }
+ }
+
public bool IsSelected {
get
{
diff --git a/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QServerViewModel.cs b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QServerViewModel.cs
new file mode 100644
index 0000000..1e83cd4
--- /dev/null
+++ b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QServerViewModel.cs
@@ -0,0 +1,87 @@
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms;
+
+using QControlKit;
+using QControlKit.Events;
+
+namespace QControlKitXamDemo.ViewModels
+{
+ public class QServerViewModel : ObservableCollection, INotifyPropertyChanged
+ {
+ QServer server;
+ public new event PropertyChangedEventHandler PropertyChanged;
+ public string name
+ {
+ get => server.name;
+ set => server.name = value;
+ }
+
+ public string host => server.host;
+
+ public string version => server.version == null ? "" : $"v{server.version}";
+
+ public string GroupName => $"{name} ({host})";
+
+ public QServerViewModel(QServer server)
+ {
+ this.server = server;
+ name = this.server.name;
+ foreach (QWorkspace workspace in this.server.workspaces)
+ {
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ Add(new QWorkspaceViewModel(workspace));
+ });
+ }
+ this.server.WorkspaceAdded += Server_WorkspaceAdded;
+ this.server.WorkspaceRemoved += Server_WorkspaceRemoved;
+ this.server.ServerUpdated += OnServerUpdated;
+ }
+
+ private void Server_WorkspaceRemoved(object source, QServerWorkspaceChangedArgs args)
+ {
+ QWorkspaceViewModel workspaceToRemove = null;
+
+ foreach (QWorkspaceViewModel workspaceViewModel in this)
+ {
+ if (workspaceViewModel.workspace.uniqueID == args.workspace.uniqueID)
+ {
+ workspaceToRemove = workspaceViewModel;
+ break;
+ }
+ }
+ if (workspaceToRemove != null)
+ {
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ Remove(workspaceToRemove);
+ });
+ }
+
+ }
+
+ private void Server_WorkspaceAdded(object source, QServerWorkspaceChangedArgs args)
+ {
+ QWorkspaceViewModel workspaceViewModel = new QWorkspaceViewModel(args.workspace);
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ Add(workspaceViewModel);
+ });
+ }
+
+
+
+ private void OnServerUpdated(object source, QServerUpdatedArgs args)
+ {
+ OnPropertyChanged("GroupName");
+ OnPropertyChanged("version");
+ }
+
+ void OnPropertyChanged([CallerMemberName] string name = "")
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
+ }
+ }
+}
diff --git a/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QWorkspaceViewModel.cs b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QWorkspaceViewModel.cs
new file mode 100644
index 0000000..3a893b3
--- /dev/null
+++ b/QControlKitXamDemo/QControlKitXamDemo/ViewModels/QWorkspaceViewModel.cs
@@ -0,0 +1,17 @@
+using QControlKit;
+
+namespace QControlKitXamDemo.ViewModels
+{
+ public class QWorkspaceViewModel
+ {
+ public QWorkspace workspace;
+ public QWorkspaceViewModel(QWorkspace workspace)
+ {
+ this.workspace = workspace;
+ }
+
+ public string Name => workspace.name;
+
+ public bool HasPasscode => workspace.hasPasscode;
+ }
+}