TCP Work, Log cleanup, Message parsing

This commit is contained in:
2022-11-05 13:50:27 -05:00
parent 57ca80df77
commit 2176ca4488
14 changed files with 200 additions and 158 deletions
+9 -7
View File
@@ -13,6 +13,8 @@ namespace QControlKit
{ {
public class QBrowser public class QBrowser
{ {
private ILogger _log = Log.Logger.ForContext<QBrowser>();
public ObservableCollection<QServer> servers = new ObservableCollection<QServer>(); public ObservableCollection<QServer> servers = new ObservableCollection<QServer>();
public event QServerFoundHandler ServerFound; public event QServerFoundHandler ServerFound;
@@ -26,17 +28,17 @@ namespace QControlKit
public async void ProbeForQLabInstances() public async void ProbeForQLabInstances()
{ {
Log.Debug("[qbrowser] probing for instances"); _log.Debug("probing for instances");
IReadOnlyList<IZeroconfHost> results = await IReadOnlyList<IZeroconfHost> results = await
ZeroconfResolver.ResolveAsync(QBonjour.TCPService,TimeSpan.FromSeconds(3)); ZeroconfResolver.ResolveAsync(QBonjour.TCPService,TimeSpan.FromSeconds(3));
foreach (var zeroconfHost in results) foreach (var zeroconfHost in results)
{ {
Log.Debug($"[qbrowser] found host {zeroconfHost.IPAddress}:{zeroconfHost.DisplayName}"); _log.Debug($"found host {zeroconfHost.IPAddress}:{zeroconfHost.DisplayName}");
foreach (var service in zeroconfHost.Services) foreach (var service in zeroconfHost.Services)
{ {
Log.Debug($"[qbrowser] found {service.Key}:{service.Value}"); _log.Debug($"found {service.Key}:{service.Value}");
if (service.Key.Equals(QBonjour.TCPService)) if (service.Key.Equals(QBonjour.TCPService))
{ {
@@ -44,7 +46,7 @@ namespace QControlKit
if (server == null) if (server == null)
{ {
Log.Information($"[qbrowser] Found {zeroconfHost.DisplayName} : {zeroconfHost.IPAddress} : {service.Value.Port}"); _log.Information($"Found {zeroconfHost.DisplayName} : {zeroconfHost.IPAddress} : {service.Value.Port}");
QServer serverToAdd = new QServer(zeroconfHost.IPAddress, service.Value.Port); QServer serverToAdd = new QServer(zeroconfHost.IPAddress, service.Value.Port);
serverToAdd.name = zeroconfHost.DisplayName; serverToAdd.name = zeroconfHost.DisplayName;
serverToAdd.zeroconfHost = zeroconfHost; serverToAdd.zeroconfHost = zeroconfHost;
@@ -70,9 +72,9 @@ namespace QControlKit
if (found == null) if (found == null)
{ {
Log.Information($"[qbrowser] Lost {server.name} : {server.host} : {server.port} disconnecting"); _log.Information($"Lost {server.name} : {server.host} : {server.port} disconnecting");
server.disconnect(); server.disconnect();
Log.Verbose($"[qbrowser] after server disconnect()"); _log.Verbose($"after server disconnect()");
servers.Remove(server); servers.Remove(server);
OnServerLost(server); OnServerLost(server);
} }
@@ -122,7 +124,7 @@ namespace QControlKit
public void Close() public void Close()
{ {
Log.Information($"[qbrowser] Close requested"); _log.Information($"Close requested");
foreach (var server in servers) foreach (var server in servers)
{ {
server.disconnect(); server.disconnect();
+24 -24
View File
@@ -12,6 +12,8 @@ namespace QControlKit
{ {
public class QClient public class QClient
{ {
private ILogger _log = Log.Logger.ForContext<QClient>();
TCPClient tcpClient; TCPClient tcpClient;
public event QWorkspacesUpdatedHandler WorkspacesUpdated; public event QWorkspacesUpdatedHandler WorkspacesUpdated;
@@ -35,7 +37,7 @@ namespace QControlKit
public QClient(string host, int port) public QClient(string host, int port)
{ {
tcpClient = new TCPClient(host, port); tcpClient = new TCPClient(host, port);
Log.Debug($"[client] setup connection to: <{host}:{port}>"); _log.Debug($"setup connection to: <{host}:{port}>");
tcpClient.MessageReceived += ProcessMessage; tcpClient.MessageReceived += ProcessMessage;
} }
@@ -52,15 +54,15 @@ namespace QControlKit
public void disconnect() public void disconnect()
{ {
Log.Information($"[client] disconnecting from {tcpClient.Address}"); _log.Information($"disconnecting from {tcpClient.Address}");
tcpClient.Close(); tcpClient.Close();
} }
public void sendMessage(string address, params object[] args) public void sendMessage(string address, params object[] args)
{ {
tcpClient.QueueForSending(new OscMessage(address, args)); tcpClient.Send(new OscMessage(address, args));
Log.Information($"[client] send message {address} : {args}"); _log.Debug($"send message {address} : {args}");
} }
private void ProcessMessage(object source, MessageEventArgs args) private void ProcessMessage(object source, MessageEventArgs args)
@@ -87,20 +89,19 @@ namespace QControlKit
string property = message.AddressParts.Last(); string property = message.AddressParts.Last();
if (property == null) if (property == null)
return; return;
if (property == QOSCKey.PlaybackPositionId)
{
OnCueListChangedPlaybackPosition(message.cueID, data.ToString());
return;
}
//create object manually since single value replies don't have dictionaries //create object manually since single value replies don't have dictionaries
JObject properties = new JObject(); JObject properties = new JObject();
properties.Add(property, data); properties.Add(property, data);
OnCueUpdated(message.cueID, properties); OnCueUpdated(message.cueID, properties);
if (property == QOSCKey.PlaybackPositionId)
{
OnCueListChangedPlaybackPosition(message.cueID, data.ToString());
}
} }
else else
{ {
Log.Error($"[client] unhandled reply from cue: Type: {data.Type} value: {message.response}"); _log.Error($"unhandled reply from cue: Type: {data.Type} value: {message.response}");
} }
} }
@@ -114,14 +115,14 @@ namespace QControlKit
} }
else if (message.IsConnect) else if (message.IsConnect)
{ {
if (message.response.ToString() == "ok") if (message.response.ToString().Contains("ok"))
OnWorkspaceConnected(); OnWorkspaceConnected();
else else
OnWorkspaceConnectionError(message.response.ToString()); OnWorkspaceConnectionError(message.response.ToString());
} }
else else
{ {
Log.Error($"[client] unhandled reply message: {message.address}"); _log.Error($"unhandled reply message: {message.address}");
} }
} }
else if(message.IsUpdate) { else if(message.IsUpdate) {
@@ -153,7 +154,6 @@ namespace QControlKit
else if ( message.IsPreferencesUpdate) else if ( message.IsPreferencesUpdate)
{ {
//need to do checks for 4.2 or newer //need to do checks for 4.2 or newer
string key = message.AddressParts.Last(); string key = message.AddressParts.Last();
if (key == null) if (key == null)
return; return;
@@ -165,65 +165,65 @@ namespace QControlKit
} }
else else
{ {
Log.Error($"[client] unhandled update message: {message.address}"); _log.Error($"unhandled update message: {message.address}");
} }
} }
else else
{ {
Log.Error($"[client] unhandled message: {message.address}"); _log.Error($"unhandled message: {message.address}");
} }
} }
protected virtual void OnCueUpdated(string cueID, JToken properties) protected virtual void OnCueUpdated(string cueID, JToken properties)
{ {
Log.Debug($"[client] cue updated: {cueID}"); _log.Debug($"cue updated: {cueID}");
CueUpdated?.Invoke(this, new QCueUpdatedArgs { cueID = cueID, data = properties }); CueUpdated?.Invoke(this, new QCueUpdatedArgs { cueID = cueID, data = properties });
} }
protected virtual void OnCueNeedsUpdated(string cueID) protected virtual void OnCueNeedsUpdated(string cueID)
{ {
Log.Debug($"[client] cue needs updated: {cueID}"); _log.Debug($"cue needs updated: {cueID}");
CueNeedsUpdated?.Invoke(this, new QCueNeedsUpdatedArgs { cueID = cueID }); CueNeedsUpdated?.Invoke(this, new QCueNeedsUpdatedArgs { cueID = cueID });
} }
protected virtual void OnCueListsUpdated(JToken response) protected virtual void OnCueListsUpdated(JToken response)
{ {
Log.Debug($"[client] Cue Lists Updated"); _log.Debug($"Cue Lists Updated");
CueListsUpdated?.Invoke(this, new QCueListsUpdatedArgs { data = response }); CueListsUpdated?.Invoke(this, new QCueListsUpdatedArgs { data = response });
} }
protected virtual void OnCueListChangedPlaybackPosition(string cueListID, string cueID) protected virtual void OnCueListChangedPlaybackPosition(string cueListID, string cueID)
{ {
Log.Debug($"[client] CueList <{cueListID}> Playback Position Changed to <{cueID}>"); _log.Debug($"CueList <{cueListID}> Playback Position Changed to <{cueID}>");
CueListChangedPlaybackPosition?.Invoke(this, new QCueListChangedPlaybackPositionArgs { cueListID = cueListID, cueID = cueID }); CueListChangedPlaybackPosition?.Invoke(this, new QCueListChangedPlaybackPositionArgs { cueListID = cueListID, cueID = cueID });
} }
protected virtual void OnWorkspaceUpdated() protected virtual void OnWorkspaceUpdated()
{ {
//Log.Debug($"[client] Workspace Updated"); _log.Debug($"Workspace Updated");
WorkspaceUpdated?.Invoke(this, new QWorkspaceUpdatedArgs()); WorkspaceUpdated?.Invoke(this, new QWorkspaceUpdatedArgs());
} }
protected virtual void OnWorkspaceSettingsUpdated(string settingsType) protected virtual void OnWorkspaceSettingsUpdated(string settingsType)
{ {
Log.Debug($"[client] Workspace Settings Updated"); _log.Debug($"Workspace Settings Updated");
WorkspaceSettingsUpdated?.Invoke(this, new QWorkspaceSettingsUpdatedArgs { settingsType = settingsType }); WorkspaceSettingsUpdated?.Invoke(this, new QWorkspaceSettingsUpdatedArgs { settingsType = settingsType });
} }
protected virtual void OnWorkspaceLightDashboardUpdated() protected virtual void OnWorkspaceLightDashboardUpdated()
{ {
Log.Debug($"[client] Workspace Light Dashboard Updated"); _log.Debug($"Workspace Light Dashboard Updated");
WorkspaceLightDashboardUpdated?.Invoke(this, new QWorkspaceLightDashboardUpdatedArgs()); WorkspaceLightDashboardUpdated?.Invoke(this, new QWorkspaceLightDashboardUpdatedArgs());
} }
protected virtual void OnQLabPreferencesUpdated(string key) protected virtual void OnQLabPreferencesUpdated(string key)
{ {
Log.Debug($"[client] QLab Preferences Updated"); _log.Debug($"QLab Preferences Updated");
QLabPreferencesUpdated?.Invoke(this, new QQLabPreferencesUpdatedArgs { key = key }); QLabPreferencesUpdated?.Invoke(this, new QQLabPreferencesUpdatedArgs { key = key });
} }
protected virtual void OnWorkspaceDisconnected() protected virtual void OnWorkspaceDisconnected()
{ {
Log.Debug($"[client] Workspace Disconnected"); _log.Debug($"Workspace Disconnected");
WorkspaceDisconnected?.Invoke(this, new QWorkspaceDisconnectedArgs()); WorkspaceDisconnected?.Invoke(this, new QWorkspaceDisconnectedArgs());
} }
+2 -1
View File
@@ -17,7 +17,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Serilog" Version="2.12.0" /> <PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="SuperSimpleTcp" Version="3.0.0.2" /> <PackageReference Include="SuperSimpleTcp" Version="3.0.5" />
<PackageReference Include="Zeroconf" Version="3.5.11" /> <PackageReference Include="Zeroconf" Version="3.5.11" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -32,5 +32,6 @@
<None Remove="SharpOSC\" /> <None Remove="SharpOSC\" />
<None Remove="SimpleTCP" /> <None Remove="SimpleTCP" />
<None Remove="SuperSimpleTcp" /> <None Remove="SuperSimpleTcp" />
<None Remove="WatsonTcp" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+20 -8
View File
@@ -12,6 +12,7 @@ namespace QControlKit
{ {
public class QCue : IComparable public class QCue : IComparable
{ {
private ILogger _log = Log.Logger.ForContext<QCue>();
public QWorkspace workspace; public QWorkspace workspace;
public Dictionary<string, object> cueData; public Dictionary<string, object> cueData;
@@ -162,7 +163,7 @@ namespace QControlKit
QCue cue = childCuesUIDMap[aUid]; QCue cue = childCuesUIDMap[aUid];
//Log.Debug($"Removing Child Cue From {listName} : {cue.uid} + {cue.listName}"); //_log.Debug($"Removing Child Cue From {listName} : {cue.uid} + {cue.listName}");
childCues.Remove(cue); childCues.Remove(cue);
childCuesUIDMap.Remove(aUid); childCuesUIDMap.Remove(aUid);
} }
@@ -639,6 +640,8 @@ namespace QControlKit
{ {
bool cueUpdated = false; bool cueUpdated = false;
_log.Verbose($"updatePropertiesWithDictionary() Called for cue");
//TODO: pretty sure this is done //TODO: pretty sure this is done
JObject dictObj = (JObject)dict; JObject dictObj = (JObject)dict;
List<string> propertiesUpdated = new List<string>(); List<string> propertiesUpdated = new List<string>();
@@ -647,14 +650,14 @@ namespace QControlKit
JToken value = obj.Value; JToken value = obj.Value;
if (obj.Key.Equals(QOSCKey.Cues)) if (obj.Key.Equals(QOSCKey.Cues))
{ {
//Log.Debug($"Cues OSC Key found in update message...updating child cues"); //_log.Debug($"Cues OSC Key found in update message...updating child cues");
if (value.Type != JTokenType.Array) if (value.Type != JTokenType.Array)
continue; continue;
updateChildCuesWithPropertiesArray(value, false); updateChildCuesWithPropertiesArray(value, false);
} }
else if(obj.Key.Equals(QOSCKey.Children) && IsGroup) else if(obj.Key.Equals(QOSCKey.Children) && IsGroup)
{ {
//Log.Debug($"Children OSC Key found in update message for {uid} ...updating child and removing deleted ones."); //_log.Debug($"Children OSC Key found in update message for {uid} ...updating child and removing deleted ones.");
if (value.Type != JTokenType.Array) if (value.Type != JTokenType.Array)
continue; continue;
updateChildCuesWithPropertiesArray(value, true); updateChildCuesWithPropertiesArray(value, true);
@@ -668,7 +671,7 @@ namespace QControlKit
{ {
cueUpdated = true; cueUpdated = true;
propertiesUpdated.Add(obj.Key); propertiesUpdated.Add(obj.Key);
//Log.Debug($"[cue] cue property {obj.Key} updated with {obj.Value}"); //_log.Debug($"cue property {obj.Key} updated with {obj.Value}");
} }
} }
} }
@@ -803,7 +806,7 @@ namespace QControlKit
if (propertyForKey(key) != null) if (propertyForKey(key) != null)
{ {
object prop = propertyForKey(key); object prop = propertyForKey(key);
//Log.Warning($"{listName} IsBroken: {propertyForKey(QOSCKey.IsBroken).ToString()} {prop.GetType().ToString()}"); //_log.Warning($"{listName} IsBroken: {propertyForKey(QOSCKey.IsBroken).ToString()} {prop.GetType().ToString()}");
if(prop.GetType() == typeof(Boolean)){ if(prop.GetType() == typeof(Boolean)){
return (bool)prop; return (bool)prop;
} }
@@ -893,7 +896,7 @@ namespace QControlKit
} }
else if (key.Equals(QOSCKey.Children)) else if (key.Equals(QOSCKey.Children))
{ {
Log.Debug($"Children Cues property updated for: {this.displayName} : {this.uid}"); _log.Debug($"Children Cues property updated for: {this.displayName} : {this.uid}");
} }
else if(key.Equals(QOSCKey.PlaybackPositionId)) else if(key.Equals(QOSCKey.PlaybackPositionId))
{ {
@@ -992,9 +995,18 @@ namespace QControlKit
#region Event Handling #region Event Handling
void OnCuePropertiesUpdated(List<string> properties) void OnCuePropertiesUpdated(List<string> properties)
{ {
_log.Verbose("OnCuePropertiesUpdated");
if(parentID != null && parentID != "") if(parentID != null && parentID != "")
{ {
workspace.fetchBasicPropertiesForCue(workspace.cueWithID(parentID)); QCue parentCue = workspace.cueWithID(parentID);
if(parentCue != null)
{
workspace.fetchBasicPropertiesForCue(workspace.cueWithID(parentID));
}
else
{
_log.Verbose($"parent cue with id: {parentID} can't be found this could be a problem");
}
} }
CuePropertiesUpdated?.Invoke(this, new QCuePropertiesUpdatedArgs { properties = properties }); CuePropertiesUpdated?.Invoke(this, new QCuePropertiesUpdatedArgs { properties = properties });
} }
@@ -1011,7 +1023,7 @@ namespace QControlKit
{ {
string indent = new string(' ', level*2); string indent = new string(' ', level*2);
Log.Information($"{indent}\u00b7{displayName} - {uid}"); _log.Information($"{indent}\u00b7{displayName} - {uid}");
if (IsGroup) if (IsGroup)
{ {
level++; level++;
+11 -6
View File
@@ -10,11 +10,13 @@ namespace QControlKit
{ {
public class QServer public class QServer
{ {
private ILogger _log = Log.Logger.ForContext<QServer>();
public event QServerUpdatedHandler ServerUpdated; public event QServerUpdatedHandler ServerUpdated;
public event QServerWorkspaceAddedHandler WorkspaceAdded; public event QServerWorkspaceAddedHandler WorkspaceAdded;
public event QServerWorkspaceRemovedHandler WorkspaceRemoved; public event QServerWorkspaceRemovedHandler WorkspaceRemoved;
private QClient client; private QClient _client;
public string host { get; set; } public string host { get; set; }
public int port { get; set; } public int port { get; set; }
@@ -28,18 +30,21 @@ namespace QControlKit
this.host = host; this.host = host;
this.port = port; this.port = port;
client = new QClient(host, port); _client = new QClient(host, port);
client.WorkspacesUpdated += OnServerWorkspacesUpdated; client.WorkspacesUpdated += OnServerWorkspacesUpdated;
if (!client.connect()) if (!client.connect())
{ {
Log.Error($"[server] unable to connect to QLab Server: {host}:{port}"); _log.Error($"unable to connect to QLab Server: {host}:{port}");
} }
} }
public string description { get { return $"{name} - {host} - {port}"; } } public string description { get { return $"{name} - {host} - {port}"; } }
public QClient client {
get { return _client; }
}
public void refreshWorkspaces() public void refreshWorkspaces()
{ {
client.sendMessage("/workspaces"); client.sendMessage("/workspaces");
@@ -111,12 +116,12 @@ namespace QControlKit
public void disconnect() public void disconnect()
{ {
Log.Information($"[server] disconnect requested for server <{name}>"); _log.Information($"disconnect requested for server <{name}>");
foreach (var workspace in workspaces) foreach (var workspace in workspaces)
{ {
if (workspace.connected) if (workspace.connected)
{ {
Log.Debug($"[server] Closing workspace <{workspace.name}> still connected to {name}"); _log.Debug($"Closing workspace <{workspace.name}> still connected to {name}");
workspace.disconnect(); workspace.disconnect();
} }
} }
+27 -15
View File
@@ -10,6 +10,7 @@ namespace QControlKit
{ {
public class QWorkspace: IEquatable<QWorkspace> public class QWorkspace: IEquatable<QWorkspace>
{ {
private ILogger _log = Log.Logger.ForContext<QWorkspace>();
private QServer server; private QServer server;
private QClient client; private QClient client;
@@ -64,7 +65,7 @@ namespace QControlKit
updateWithWorkspaceInfo(workspaceInfo); updateWithWorkspaceInfo(workspaceInfo);
client = new QClient(server.host, server.port); client = server.client;
client.WorkspaceConnected += OnWorkspaceConnected; client.WorkspaceConnected += OnWorkspaceConnected;
client.WorkspaceConnectionError += OnWorkspaceConnectionError; client.WorkspaceConnectionError += OnWorkspaceConnectionError;
@@ -75,7 +76,7 @@ namespace QControlKit
client.CueUpdated += OnCueUpdated; client.CueUpdated += OnCueUpdated;
this.server = server; this.server = server;
Log.Debug($"[workspace] <{name}> on <{server.name}> initialized."); _log.Debug($"<{name}> on <{server.name}> initialized.");
} }
//updateWithDictionary //updateWithDictionary
@@ -164,18 +165,18 @@ namespace QControlKit
public void connect(string passcode = null) public void connect(string passcode = null)
{ {
Log.Information($"[workspace] connecting to <{name}> @ {this.server.host}:{this.server.port}"); _log.Information($"connecting to <{name}> @ {this.server.host}:{this.server.port}");
if(hasPasscode && passcode == null) if(hasPasscode && passcode == null)
{ {
Log.Error($"[workspace] *** workspace <{name}> requires a passcode but none was supplied."); _log.Error($"*** workspace <{name}> requires a passcode but none was supplied.");
OnWorkspaceConnectionError(this, new QWorkspaceConnectionErrorArgs { status = QConnectionStatus.BadPass }); OnWorkspaceConnectionError(this, new QWorkspaceConnectionErrorArgs { status = QConnectionStatus.BadPass });
return; return;
} }
if (!client.connect()) if (!client.connect())
{ {
Log.Error($"[workspace] *** couldn't connect to server client is not connected."); _log.Error($"*** couldn't connect to server client is not connected.");
OnWorkspaceConnectionError(this, new QWorkspaceConnectionErrorArgs { status = QConnectionStatus.Error }); OnWorkspaceConnectionError(this, new QWorkspaceConnectionErrorArgs { status = QConnectionStatus.Error });
return; return;
} }
@@ -210,7 +211,7 @@ namespace QControlKit
public void disconnect() public void disconnect()
{ {
Log.Information($"[workspace] disconnecting from <{name}>"); _log.Information($"disconnecting from <{name}>");
if (!connected) if (!connected)
return; return;
stopReceivingUpdates(); stopReceivingUpdates();
@@ -417,11 +418,11 @@ namespace QControlKit
{ {
//clear passcode if there was one set in the connect() method //clear passcode if there was one set in the connect() method
this.passcode = null; this.passcode = null;
Log.Error($"[workspace] *** Password for workspace <{name}> was incorrect!"); _log.Error($"*** Password for workspace <{name}> was incorrect!");
} }
else else
{ {
Log.Error($"[workspace] *** Unable to connect to workspace: <{name}> on server: <{server.name}>"); _log.Error($"*** Unable to connect to workspace: <{name}> on server: <{server.name}>");
} }
WorkspaceConnectionError?.Invoke(this, new QWorkspaceConnectionErrorArgs { status = args.status }); WorkspaceConnectionError?.Invoke(this, new QWorkspaceConnectionErrorArgs { status = args.status });
@@ -429,7 +430,7 @@ namespace QControlKit
private void OnWorkspaceConnected(object source, QWorkspaceConnectedArgs args) private void OnWorkspaceConnected(object source, QWorkspaceConnectedArgs args)
{ {
Log.Information($"[workspace] Connection to <{name}> successful, finishing things up."); _log.Information($"Connection to <{name}> successful, finishing things up.");
WorkspaceConnected?.Invoke(this, new QWorkspaceConnectedArgs()); WorkspaceConnected?.Invoke(this, new QWorkspaceConnectedArgs());
finishConnection(); finishConnection();
} }
@@ -437,7 +438,7 @@ namespace QControlKit
private void OnWorkspaceDisconnected(object source, QWorkspaceDisconnectedArgs args) private void OnWorkspaceDisconnected(object source, QWorkspaceDisconnectedArgs args)
{ {
//this might not be called with TCP? //this might not be called with TCP?
Log.Warning($"[workspace] *** Workspace has indicated it is disconnecting"); _log.Warning($"*** Workspace has indicated it is disconnecting");
WorkspaceDisconnected?.Invoke(this, new QWorkspaceDisconnectedArgs()); WorkspaceDisconnected?.Invoke(this, new QWorkspaceDisconnectedArgs());
} }
@@ -506,7 +507,7 @@ namespace QControlKit
//add Event handled? use CueUpdated one? //add Event handled? use CueUpdated one?
} }
Log.Debug($"[workspace] cueLists finished processing. root updated? {rootCueUpdated}"); _log.Debug($"cueLists finished processing. root updated? {rootCueUpdated}");
OnWorkspaceUpdated(); OnWorkspaceUpdated();
@@ -524,7 +525,7 @@ namespace QControlKit
cueList.setProperty(args.cueID, QOSCKey.PlaybackPositionId, false); cueList.setProperty(args.cueID, QOSCKey.PlaybackPositionId, false);
} }
Log.Information($"[workspace] cue list <{args.cueListID}> playback position changed to <{args.cueID}>"); _log.Information($"cue list <{args.cueListID}> playback position changed to <{args.cueID}>");
CueListChangedPlaybackPosition?.Invoke(this, new QCueListChangedPlaybackPositionArgs { cueListID = args.cueListID, cueID = args.cueID }); CueListChangedPlaybackPosition?.Invoke(this, new QCueListChangedPlaybackPositionArgs { cueListID = args.cueListID, cueID = args.cueID });
} }
@@ -538,7 +539,7 @@ namespace QControlKit
{ {
if (args.cueID.Equals(QIdentifiers.RootCueUpdate)) if (args.cueID.Equals(QIdentifiers.RootCueUpdate))
{ {
Log.Debug("[workspace] root cue update requested, updating all cue lists"); _log.Debug("root cue update requested, updating all cue lists");
foreach (var cuelist in this.cueLists) foreach (var cuelist in this.cueLists)
{ {
if (!cuelist.uid.Equals(QIdentifiers.ActiveCues)) if (!cuelist.uid.Equals(QIdentifiers.ActiveCues))
@@ -560,10 +561,21 @@ namespace QControlKit
private void OnCueUpdated(object source, QCueUpdatedArgs args) private void OnCueUpdated(object source, QCueUpdatedArgs args)
{ {
_log.Verbose($"OnCueUpdated: {args.cueID}");
QCue cue = cueWithID(args.cueID); QCue cue = cueWithID(args.cueID);
if (cue == null || cue.ignoreUpdates)
if(cue == null)
{
_log.Error($"Could not find cue to update, this is likely a problem.");
return; return;
}
if (cue.ignoreUpdates)
{
_log.Verbose($"Skipping updatePropertiesWithDictionary for cue: {args.cueID} because of ignoreUpdates setting");
return;
}
cue.updatePropertiesWithDictionary(args.data); cue.updatePropertiesWithDictionary(args.data);
} }
@@ -578,7 +590,7 @@ namespace QControlKit
#region Printing #region Printing
public void Print() public void Print()
{ {
Log.Information($"[workspace] {name}"); _log.Information($"{name}");
foreach (var cueList in root.cues) foreach (var cueList in root.cues)
{ {
cueList.Print(); cueList.Print();
+1
View File
@@ -26,6 +26,7 @@ namespace SharpOSC
buffer.Add(data[i]); buffer.Add(data[i]);
} }
} }
return messages; return messages;
} }
+66 -87
View File
@@ -5,6 +5,7 @@ using System.Text;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;
using Serilog; using Serilog;
using SuperSimpleTcp;
namespace SharpOSC namespace SharpOSC
{ {
@@ -19,6 +20,8 @@ namespace SharpOSC
public class TCPClient public class TCPClient
{ {
private ILogger _log = Log.Logger.ForContext<TCPClient>();
public int Port public int Port
{ {
get { return _port; } get { return _port; }
@@ -32,18 +35,10 @@ namespace SharpOSC
public delegate void MessageReceivedHandler(object source, MessageEventArgs args); public delegate void MessageReceivedHandler(object source, MessageEventArgs args);
public event MessageReceivedHandler MessageReceived; public event MessageReceivedHandler MessageReceived;
private Queue<OscPacket> SendQueue = new Queue<OscPacket>();
private Thread receivingThread;
private Thread sendThread;
string _address; string _address;
TcpClient client;
byte END = 0xc0; SimpleTcpClient tcpClient;
byte ESC = 0xdb;
byte ESC_END = 0xDC;
byte ESC_ESC = 0xDD;
public TCPClient(string address, int port) public TCPClient(string address, int port)
@@ -54,48 +49,81 @@ namespace SharpOSC
public bool Connect() public bool Connect()
{ {
try try
{ {
client = new TcpClient(Address, Port); tcpClient = new SimpleTcpClient(Address, Port);
receivingThread = new Thread(ReceiveLoop); tcpClient.Events.Connected += ClientConnected;
receivingThread.Start(); tcpClient.Events.DataReceived += DataReceived;
tcpClient.Events.Disconnected += ClientDisconneted;
sendThread = new Thread(SendLoop); tcpClient.Logger += TCPLog;
sendThread.Start(); tcpClient.Connect();
Log.Debug($"[tcpclient] connected to <{Address}:{Port}>");
return true; return true;
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error(e.Message); _log.Error(e.Message);
return false; return false;
} }
} }
public void QueueForSending(OscPacket packet) private void TCPLog(string obj)
{ {
SendQueue.Enqueue(packet); _log.Verbose($"{obj}");
} }
private void SendLoop() private void ClientDisconneted(object sender, ConnectionEventArgs e)
{ {
while (client != null && client.Connected) _log.Verbose($"{e.IpPort} client disconnected: {e.Reason}");
Close();
}
private void DataReceived(object sender, DataReceivedEventArgs e)
{
_log.Verbose($"Raw Data Received contents: {Encoding.UTF8.GetString(e.Data.Array, 0, e.Data.Count)}");
_log.Verbose($"Raw Data Received size: {e.Data.Count}");
List<byte[]> messages = SlipFrame.Decode(e.Data.Array);
_log.Verbose($"Slip decoded {messages.Count} osc messages");
foreach (var message in messages)
{ {
if (SendQueue.Count > 0) _log.Verbose($"Raw message contents: {Encoding.UTF8.GetString(message, 0, message.Length)}");
try
{
OscPacket packet = OscPacket.GetPacket(message);
OscMessage responseMessage = (OscMessage)packet;
if (packet == null)
{
_log.Error("packet is null");
}
if (responseMessage == null)
{
_log.Error("responeMessage is null");
}
_log.Debug($"OSC Message Received: {responseMessage.Address}");
OnMessageReceived(responseMessage);
_log.Debug($"After OnMessageReceived Event");
}
catch (Exception ex)
{ {
OscPacket packet = SendQueue.Dequeue(); _log.Error($"Exception parsing OSC message: {ex.ToString()}");
Send(packet);
} }
} }
} }
private void ClientConnected(object sender, ConnectionEventArgs e)
{
_log.Debug($"connected to <{Address}:{Port}>");
}
public void Send(byte[] message) public void Send(byte[] message)
{ {
byte[] slipData = SlipFrame.Encode(message); byte[] slipData = SlipFrame.Encode(message);
NetworkStream netStream = client.GetStream(); tcpClient.Send(slipData.ToArray());
netStream.Write(slipData.ToArray(), 0, slipData.ToArray().Length);
} }
public void Send(OscPacket packet) public void Send(OscPacket packet)
@@ -108,74 +136,25 @@ namespace SharpOSC
{ {
get get
{ {
if (client == null) if (tcpClient == null)
return false; return false;
else else
return client.Connected; return tcpClient.IsConnected;
}
}
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<byte> responseData = new List<byte>();
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()));
List<byte[]> messages = SlipFrame.Decode(responseData.ToArray());
foreach(var message in messages)
{
OscPacket packet = OscPacket.GetPacket(message);
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());
} }
} }
public void Close() public void Close()
{ {
if (client != null) if (tcpClient != null)
{ {
if (client.Connected) tcpClient.Events.Connected -= ClientConnected;
tcpClient.Events.DataReceived -= DataReceived;
tcpClient.Events.Disconnected -= ClientDisconneted;
if (tcpClient.IsConnected)
{ {
Log.Debug($"[tcpClient] closing connection to {Address}"); _log.Debug($"closing connection to {Address}");
client.GetStream().Close(); tcpClient.Disconnect();
client.Close(); tcpClient.Dispose();
} }
} }
} }
@@ -5,6 +5,8 @@ using System.Linq;
using Foundation; using Foundation;
using UIKit; using UIKit;
using Serilog; using Serilog;
using Serilog.Events;
namespace QControlKitXamDemo.iOS namespace QControlKitXamDemo.iOS
{ {
// The UIApplicationDelegate for the application. This class is responsible for launching the // The UIApplicationDelegate for the application. This class is responsible for launching the
@@ -23,7 +25,7 @@ namespace QControlKitXamDemo.iOS
public override bool FinishedLaunching(UIApplication app, NSDictionary options) public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{ {
global::Xamarin.Forms.Forms.Init(); global::Xamarin.Forms.Forms.Init();
Log.Logger = new LoggerConfiguration().WriteTo.NSLog().MinimumLevel.Verbose().CreateLogger(); Log.Logger = new LoggerConfiguration().WriteTo.NSLog(outputTemplate: "[{Level}] ({SourceContext}) {Message}{NewLine}{Exception}").MinimumLevel.Verbose().CreateLogger();
LoadApplication(new App()); LoadApplication(new App());
return base.FinishedLaunching(app, options); return base.FinishedLaunching(app, options);
@@ -7,6 +7,7 @@ using Xamarin.Forms;
using QControlKit.Events; using QControlKit.Events;
using QControlKit.Constants; using QControlKit.Constants;
using Serilog;
namespace QControlKitXamDemo namespace QControlKitXamDemo
{ {
@@ -64,6 +65,18 @@ namespace QControlKitXamDemo
}); });
} }
void updateCuePropertes(QCue cue)
{
cue.workspace.fetchDefaultPropertiesForCue(cue);
if (cue.cues.Count > 0)
{
foreach (QCue childCue in cue.cues)
{
childCue.workspace.fetchDefaultPropertiesForCue(childCue);
}
}
}
void Workspace_WorkspaceUpdated(object source, QWorkspaceUpdatedArgs args) void Workspace_WorkspaceUpdated(object source, QWorkspaceUpdatedArgs args)
{ {
if(connectedWorkspace.cueLists.Count > 0) if(connectedWorkspace.cueLists.Count > 0)
@@ -71,6 +84,7 @@ namespace QControlKitXamDemo
List<Task> cueAddTasks = new List<Task>(); List<Task> cueAddTasks = new List<Task>();
foreach(var aCue in connectedWorkspace.cueLists) foreach(var aCue in connectedWorkspace.cueLists)
{ {
updateCuePropertes(aCue);
Grid cueGrid = cueToGrid(aCue); Grid cueGrid = cueToGrid(aCue);
cueGridDict.Add(aCue.uid, cueGrid); cueGridDict.Add(aCue.uid, cueGrid);
MainThread.InvokeOnMainThreadAsync(() => MainThread.InvokeOnMainThreadAsync(() =>
@@ -95,7 +109,7 @@ namespace QControlKitXamDemo
HorizontalOptions = LayoutOptions.StartAndExpand, HorizontalOptions = LayoutOptions.StartAndExpand,
VerticalTextAlignment = TextAlignment.Center, VerticalTextAlignment = TextAlignment.Center,
}; };
cueLabel.SetBinding(Label.TextProperty, "status", BindingMode.OneWay); cueLabel.SetBinding(Label.TextProperty, "name", BindingMode.OneWay);
var cueBackground = new Frame var cueBackground = new Frame
{ {
BindingContext = qCueViewModel, BindingContext = qCueViewModel,
@@ -30,7 +30,7 @@ namespace QControlKitXamDemo
qBrowserViewModel.autoUpdate = false; qBrowserViewModel.autoUpdate = false;
QWorkspace selectedWorkspace = (e.SelectedItem as QWorkspaceViewModel).workspace; QWorkspace selectedWorkspace = (e.SelectedItem as QWorkspaceViewModel).workspace;
Log.Debug($"[demo] workspace: {selectedWorkspace.nameWithoutPathExtension} has been selected"); Log.Debug($"workspace: {selectedWorkspace.nameWithoutPathExtension} has been selected");
((ListView)sender).SelectedItem = null; ((ListView)sender).SelectedItem = null;
if (selectedWorkspace.hasPasscode) if (selectedWorkspace.hasPasscode)
@@ -13,11 +13,15 @@ namespace QControlKitXamDemo.ViewModels
{ {
public class QBrowserViewModel : INotifyPropertyChanged public class QBrowserViewModel : INotifyPropertyChanged
{ {
private ILogger _log = Log.Logger.ForContext<QBrowserViewModel>();
QBrowser browser; QBrowser browser;
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
public bool autoUpdate = false; public bool autoUpdate = false;
public ObservableCollection<QServerViewModel> ServersGrouped { get; set; } public ObservableCollection<QServerViewModel> ServersGrouped { get; set; }
bool connected = false;
public QBrowserViewModel(QBrowser browser) public QBrowserViewModel(QBrowser browser)
{ {
this.browser = browser; this.browser = browser;
@@ -31,9 +35,10 @@ namespace QControlKitXamDemo.ViewModels
{ {
if (autoUpdate) if (autoUpdate)
{ {
_log.Verbose($"Auto Update is enabled running probe");
Device.BeginInvokeOnMainThread(() => Device.BeginInvokeOnMainThread(() =>
{ {
Log.Debug("[QBrowserViewModel] QBrowser probe triggered"); _log.Debug("QBrowser probe triggered");
this.browser.ProbeForQLabInstances(); this.browser.ProbeForQLabInstances();
}); });
} }
@@ -47,7 +52,7 @@ namespace QControlKitXamDemo.ViewModels
{ {
Device.BeginInvokeOnMainThread(() => Device.BeginInvokeOnMainThread(() =>
{ {
Log.Debug($"[QBrowserViewModel] adding server: {args.server.description}"); _log.Debug($"adding server: {args.server.description}");
ServersGrouped.Add(new QServerViewModel(args.server)); ServersGrouped.Add(new QServerViewModel(args.server));
}); });
} }
@@ -70,7 +75,7 @@ namespace QControlKitXamDemo.ViewModels
{ {
Device.BeginInvokeOnMainThread(() => Device.BeginInvokeOnMainThread(() =>
{ {
Log.Debug($"[QBrowserViewModel] removing server: {args.server.description}"); _log.Debug($"removing server: {args.server.description}");
ServersGrouped.Remove(serverToRemove); ServersGrouped.Remove(serverToRemove);
}); });
} }
@@ -85,7 +90,7 @@ namespace QControlKitXamDemo.ViewModels
{ {
if (!autoUpdate) if (!autoUpdate)
{ {
Log.Debug("[QBrowserViewModel] Manual Scan Initiated"); _log.Debug("Manual Scan Initiated");
browser.ProbeForQLabInstances(); browser.ProbeForQLabInstances();
} }
} }
@@ -11,6 +11,8 @@ namespace QControlKitXamDemo.ViewModels
{ {
public class QCueViewModel : INotifyPropertyChanged public class QCueViewModel : INotifyPropertyChanged
{ {
private ILogger _log = Log.Logger.ForContext<QCueViewModel>();
QCue cue; QCue cue;
bool isSelected = false; bool isSelected = false;
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
@@ -18,16 +20,20 @@ namespace QControlKitXamDemo.ViewModels
public QCueViewModel(QCue cue, bool checkPlayback) public QCueViewModel(QCue cue, bool checkPlayback)
{ {
this.cue = cue; this.cue = cue;
if(checkPlayback) if (checkPlayback)
{
this.cue.workspace.CueListChangedPlaybackPosition += Workspace_CueListChangedPlaybackPosition; this.cue.workspace.CueListChangedPlaybackPosition += Workspace_CueListChangedPlaybackPosition;
}
this.cue.CuePropertiesUpdated += OnCuePropertiesUpdated; this.cue.CuePropertiesUpdated += OnCuePropertiesUpdated;
} }
private void OnCuePropertiesUpdated(object source, QCuePropertiesUpdatedArgs args) private void OnCuePropertiesUpdated(object source, QCuePropertiesUpdatedArgs args)
{ {
foreach(var property in args.properties) _log.Debug($"properties updated from cue");
foreach (var property in args.properties)
{ {
Log.Debug($"[cueviewmodel] property <{property}> has been updated for cue {name}."); _log.Debug($"property <{property}> has been updated for cue {name}.");
if (property.Equals(QOSCKey.Name) || property.Equals(QOSCKey.ListName)) if (property.Equals(QOSCKey.Name) || property.Equals(QOSCKey.ListName))
{ {
OnPropertyChanged("name"); OnPropertyChanged("name");
@@ -5,11 +5,14 @@ using Xamarin.Forms;
using QControlKit; using QControlKit;
using QControlKit.Events; using QControlKit.Events;
using Serilog;
namespace QControlKitXamDemo.ViewModels namespace QControlKitXamDemo.ViewModels
{ {
public class QServerViewModel : ObservableCollection<QWorkspaceViewModel>, INotifyPropertyChanged public class QServerViewModel : ObservableCollection<QWorkspaceViewModel>, INotifyPropertyChanged
{ {
private ILogger _log = Log.Logger.ForContext<QServerViewModel>();
QServer server; QServer server;
public new event PropertyChangedEventHandler PropertyChanged; public new event PropertyChangedEventHandler PropertyChanged;
public string name public string name