Skip to content

Commit

Permalink
Merge branch 'feature/TouchPortalSDK'
Browse files Browse the repository at this point in the history
  • Loading branch information
oddbear committed Apr 23, 2021
2 parents 272716d + cc2787c commit 934a37e
Show file tree
Hide file tree
Showing 14 changed files with 119 additions and 385 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,119 +3,80 @@
using System.Linq;
using System.Net;
using System.Net.Sockets;
using GoXLR.Plugin.Models;
using GoXLR.Server;
using GoXLR.Server.Models;
using Microsoft.Extensions.Logging;
using TouchPortalSDK;
using TouchPortalSDK.Interfaces;
using TouchPortalSDK.Messages.Events;
using TouchPortalSDK.Messages.Models;

namespace GoXLR.Plugin.Client
{
public class TouchPortalClient
public class GoXLRPlugin : ITouchPortalEventHandler
{
private readonly ILogger<TouchPortalClient> _logger;
public string PluginId => "oddbear.touchportal.goxlr";

private readonly ITouchPortalClient _client;
private readonly GoXLRServer _server;
private readonly MessageProcessor _messageProcessor;
private readonly ILogger<GoXLRPlugin> _logger;
private readonly IReadOnlyCollection<string> _localAddresses;
public TouchPortalClient(ILogger<TouchPortalClient> logger,
GoXLRServer server,
MessageProcessor messageProcessor)

public GoXLRPlugin(ITouchPortalClientFactory clientFactory,
GoXLRServer goXLRServer,
ILogger<GoXLRPlugin> logger)
{
//Set the event handler for TouchPortal:
_client = clientFactory.Create(this);
//Set the event handler for GoXLR connected:
_server = goXLRServer;
_logger = logger;
_server = server;
_messageProcessor = messageProcessor;
_localAddresses = GetLocalAddresses();

//Set the event handler for GoXLR Clients connected:
_server.UpdateConnectedClientsEvent = UpdateClientState;
_messageProcessor.OnInfo = (infoMessage) =>
{
_logger.LogInformation("Connect Event: Plugin Connected to TouchPortal.");
UpdateClientState();
};
_messageProcessor.OnDisconnect = (exception) =>
{
_logger.LogInformation("Close Event: Plugin Disconnected from TouchPortal.");
Environment.Exit(0);
};
_messageProcessor.OnListChange = OnListChangeEventHandler;
_messageProcessor.OnActionEvent = OnActionEvent;

}

public void Init()
{
//Connecting to TouchPortal:
_messageProcessor.Connect();
_client.Connect();
}

/// <summary>
/// Updates the clients connected, and the state of the clients, ex. profiles.
/// </summary>
public void UpdateClientState()
public void OnInfoEvent(InfoEvent message)
{
if (_messageProcessor is null)
{
_logger.LogWarning("MessageProcess not Initialized, but a client was connected.");
return;
}

try
{
//Since ports are quite random, we only use the ip when connecting to the plugin.
//There is only possible (without faking it) to have one client per ip.
//Therefor this is a unique identifier that will hold between restarts.
var clients = _server.ClientData
.Select(clientData => clientData.ClientIdentifier)
.Select(identifier => identifier.ClientIpAddress)
.ToArray();

var clientChoices = new List<string> { "default" };
clientChoices.AddRange(clients);

//Update states:
_messageProcessor.UpdateState(".single.clients.state.connected", clients.FirstOrDefault() ?? "none");
_messageProcessor.UpdateState(".multiple.clients.states.count",clients.Length.ToString());

//Update choices:
_messageProcessor.UpdateChoice(".multiple.routingtable.action.change.data.clients", clientChoices.ToArray());

_messageProcessor.UpdateChoice(".multiple.profiles.action.change.data.clients", clientChoices.ToArray());
}
catch (Exception e)
{
_logger.LogError(e.ToString());
}
_logger.LogInformation("Connect Event: Plugin Connected to TouchPortal.");
UpdateClientState();
}

/// <summary>
/// Event fired when selecting a item from the dropdown in the TP Configurator.
/// Updates a second list (instanceId) with the values from the selected client name/ip.
/// </summary>
/// <param name="listChange"></param>
private void OnListChangeEventHandler(ListChangeMessage listChange)
/// <param name="message"></param>
public void OnListChangedEvent(ListChangeEvent message)
{
try
{
//Choice is changed: I can now update the next list:
_logger.LogInformation($"Choice Event: {listChange}'.");
_logger.LogInformation($"Choice Event: {message.ListId}'.");

if (string.IsNullOrWhiteSpace(listChange.InstanceId))
if (string.IsNullOrWhiteSpace(message.InstanceId))
return;

//Profiles client selected, fetch profiles for client:
if (listChange.ActionId.EndsWith(".multiple.profiles.action.change") &&
listChange.ListId.EndsWith(".multiple.profiles.action.change.data.clients"))
if (message.ActionId.EndsWith(".multiple.profiles.action.change") &&
message.ListId.EndsWith(".multiple.profiles.action.change.data.clients"))
{
var client = GetClients(listChange.Value);
var client = GetClients(message.Value);
if (client is null)
return;

var clientData = GetClients(listChange.Value);
var clientData = GetClients(message.Value);
if (clientData is null)
return;

_messageProcessor.UpdateChoice(".multiple.profiles.action.change.data.profiles", clientData.Profiles, listChange.InstanceId);
_client.ChoiceUpdate(PluginId + ".multiple.profiles.action.change.data.profiles", clientData.Profiles, message.InstanceId);
}
}
catch (Exception e)
Expand All @@ -124,24 +85,20 @@ private void OnListChangeEventHandler(ListChangeMessage listChange)
}
}

/// <summary>
/// On a button press on the Touch interface client.
/// </summary>
/// <param name="action"></param>
private void OnActionEvent(ActionMessage action)
public void OnActionEvent(ActionEvent message)
{
try
{
_logger.LogInformation($"Action Event: {action}");
_logger.LogInformation($"Action Event: {message.ActionId}");

var actionId = action.ActionId;
var actionId = message.ActionId;

//Routing change:
if (actionId.EndsWith(".routingtable.action.change"))
{
//Can be both <pluginid>.<type>.routingtable.action.change,
// where <type> is single or multiple.
RouteChange(actionId + ".data", action.Data);
RouteChange(actionId + ".data", message.Data);
}

//Profile change:
Expand All @@ -150,7 +107,7 @@ private void OnActionEvent(ActionMessage action)
{
//Can be both <pluginid>.<type>.profiles.action.change,
// where <type> is single or multiple.
ProfileChange(actionId + ".data", action.Data);
ProfileChange(actionId + ".data", message.Data);
}
}
catch (Exception e)
Expand All @@ -159,22 +116,76 @@ private void OnActionEvent(ActionMessage action)
}
}

public void OnClosedEvent(string message)
{
_logger.LogInformation("Close Event: Plugin Disconnected from TouchPortal.");
Environment.Exit(0);
}

public void OnBroadcastEvent(BroadcastEvent message)
{
//NotImplemented
}

public void OnSettingsEvent(SettingsEvent message)
{
//NotImplemented
}

public void OnUnhandledEvent(string jsonMessage)
{
//NotImplemented
}

/// <summary>
/// Updates the clients connected, and the state of the clients, ex. profiles.
/// </summary>
public void UpdateClientState()
{
try
{
//Since ports are quite random, we only use the ip when connecting to the plugin.
//There is only possible (without faking it) to have one client per ip.
//Therefor this is a unique identifier that will hold between restarts.
var clients = _server.ClientData
.Select(clientData => clientData.ClientIdentifier)
.Select(identifier => identifier.ClientIpAddress)
.ToArray();

var clientChoices = new List<string> { "default" };
clientChoices.AddRange(clients);

//Update states:
_client.StateUpdate(PluginId + ".single.clients.state.connected", clients.FirstOrDefault() ?? "none");
_client.StateUpdate(PluginId + ".multiple.clients.states.count", clients.Length.ToString());

//Update choices:
_client.ChoiceUpdate(PluginId + ".multiple.routingtable.action.change.data.clients", clientChoices.ToArray());

_client.ChoiceUpdate(PluginId + ".multiple.profiles.action.change.data.clients", clientChoices.ToArray());
}
catch (Exception e)
{
_logger.LogError(e.ToString());
}
}

/// <summary>
/// Changes a route in the GoXLR app.
/// </summary>
/// <param name="name"></param>
/// <param name="datalist"></param>
private void RouteChange(string name, ActionData[] datalist)
private void RouteChange(string name, IReadOnlyCollection<ActionDataSelected> datalist)
{
var dict = datalist
.ToDictionary(kv => kv.Id, kv => kv.Value);

dict.TryGetValue(name + ".clients", out var clientIp);

var client = GetClients(clientIp);
if(client is null)
if (client is null)
return;

var input = dict[name + ".inputs"];
var output = dict[name + ".outputs"];
var action = dict[name + ".actions"];
Expand All @@ -187,7 +198,7 @@ private void RouteChange(string name, ActionData[] datalist)
/// </summary>
/// <param name="name"></param>
/// <param name="datalist"></param>
private void ProfileChange(string name, ActionData[] datalist)
private void ProfileChange(string name, IReadOnlyCollection<ActionDataSelected> datalist)
{
var dict = datalist
.ToDictionary(kv => kv.Id, kv => kv.Value);
Expand Down Expand Up @@ -217,8 +228,8 @@ private ClientData GetClients(string clientIp)
{
//Try to use a local IP as client first:
return clients.FirstOrDefault(clientData => _localAddresses.Contains(clientData.ClientIdentifier.ClientIpAddress))
//Or just give me the first one:
?? clients.FirstOrDefault();
//Or just give me the first one:
?? clients.FirstOrDefault();
}

//Try to find a exact match:
Expand Down
Loading

0 comments on commit 934a37e

Please sign in to comment.