diff --git a/.run/Build & Install - Linux.run.xml b/.run/Build & Install - Linux.run.xml
new file mode 100644
index 0000000..ba0f97d
--- /dev/null
+++ b/.run/Build & Install - Linux.run.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Build & Install - Windows.run.xml b/.run/Build & Install - Windows.run.xml
new file mode 100644
index 0000000..8b0e2ce
--- /dev/null
+++ b/.run/Build & Install - Windows.run.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FaderSyncPlugin/GoXLR/UtilitySingleton.cs b/FaderSyncPlugin/GoXLR/UtilitySingleton.cs
index 4def558..c4d3c17 100644
--- a/FaderSyncPlugin/GoXLR/UtilitySingleton.cs
+++ b/FaderSyncPlugin/GoXLR/UtilitySingleton.cs
@@ -8,7 +8,7 @@ public static class UtilitySingleton
private static readonly Logger Log = new Logger(typeof(Plugin), Module.Name);
private static Utility? _utility;
- private static Thread? _connectionThread = null;
+ private static Thread? _connectionThread;
private static async void Connect()
{
@@ -17,7 +17,7 @@ private static async void Connect()
if (_utility.IsConnectionAlive())
{
- Log.Info($"Connected to GoXLR Utility v{_utility.Status?["config"]?["daemon_version"]}");
+ Log.Info($"Connected to GoXLR Utility v{_utility.Status["config"]?["daemon_version"]}");
}
else
{
@@ -30,7 +30,7 @@ public static Utility GetInstance()
_utility ??= new Utility();
if (_utility.IsConnectionAlive()) return _utility;
- _utility.OnException += (sender, exception) =>
+ _utility.OnException += (_, exception) =>
{
Log.Error($"Something internally went wrong in the GoXLR Utility API Client: {exception.Message}");
};
diff --git a/FaderSyncPlugin/Module.cs b/FaderSyncPlugin/Module.cs
index 8e868a0..fdeebdc 100644
--- a/FaderSyncPlugin/Module.cs
+++ b/FaderSyncPlugin/Module.cs
@@ -4,9 +4,9 @@ namespace FaderSync;
public static class Module
{
- public static readonly string Name = Assembly.GetExecutingAssembly()?.GetName()?.Name!;
+ public static readonly string Name = Assembly.GetExecutingAssembly().GetName().Name!;
- public static readonly string Version = Assembly.GetExecutingAssembly()?
- .GetCustomAttribute()?.InformationalVersion!
+ public static readonly string Version = Assembly.GetExecutingAssembly()
+ .GetCustomAttribute()?.InformationalVersion
.Split('+')[0]!; // remove commit hash
}
\ No newline at end of file
diff --git a/FaderSyncPlugin/OBS/GoXlrChannelSyncFilter.cs b/FaderSyncPlugin/OBS/GoXlrChannelSyncFilter.cs
index 57d880e..9b7f174 100644
--- a/FaderSyncPlugin/OBS/GoXlrChannelSyncFilter.cs
+++ b/FaderSyncPlugin/OBS/GoXlrChannelSyncFilter.cs
@@ -90,7 +90,7 @@ private static unsafe void Tick(void* data, float seconds)
var channelName = Marshal.PtrToStringUTF8((IntPtr)context->ChannelName);
var target = Obs.obs_filter_get_parent(context->Source);
- var systemVolume = utility.Status?["mixers"]?[deviceSerial ?? ""]?["levels"]?["volumes"]?[channelName ?? ""]?
+ var systemVolume = utility.Status["mixers"]?[deviceSerial ?? ""]?["levels"]?["volumes"]?[channelName ?? ""]?
.GetValue() ?? 0;
// Ok, the GoXLR seems to decrease the volume by 1dB for every (on average) 4.85 volume steps, it
@@ -106,12 +106,12 @@ private static unsafe void Tick(void* data, float seconds)
utilityBase += count * 0.115f;
}
- // Now we convert this into a OBS value...
+ // Now we convert this into an OBS value...
var obsVolume = (float)Math.Pow(10, -utilityBase / 20f);
// check if channel is muted
var isMuted = false;
- var faderStatus = (JsonObject)utility.Status?["mixers"]?[deviceSerial ?? ""]?["fader_status"];
+ var faderStatus = (JsonObject?)utility.Status["mixers"]?[deviceSerial ?? ""]?["fader_status"];
if (faderStatus != null)
foreach (var faderEntry in faderStatus)
{
@@ -134,7 +134,7 @@ private static unsafe void Tick(void* data, float seconds)
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static unsafe void GetDefaults(obs_data* settings)
{
- // Todo: implement
+ // do nothing
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
@@ -186,7 +186,7 @@ private static unsafe void GetDefaults(obs_data* settings)
sChannelLineOutId = "LineOut"u8.ToArray()
)
{
- // Create the Serial Dropdown..
+ // Create the Serial Dropdown...
var deviceList = ObsProperties.obs_properties_add_list(properties, (sbyte*)sDeviceSerialId, (sbyte*)sDeviceSerialDescription,
obs_combo_type.OBS_COMBO_TYPE_LIST, obs_combo_format.OBS_COMBO_FORMAT_STRING);
@@ -206,9 +206,9 @@ private static unsafe void GetDefaults(obs_data* settings)
ObsProperties.obs_property_list_add_string(channelList, (sbyte*)sChannelMicMonitor, (sbyte*)sChannelMicMonitorId);
ObsProperties.obs_property_list_add_string(channelList, (sbyte*)sChannelLineOut, (sbyte*)sChannelLineOutId);
- // Before we Proceed, we need to fetch a list of the available GoXLRs on the System..
+ // Before we Proceed, we need to fetch a list of the available GoXLRs on the System...
var utility = UtilitySingleton.GetInstance();
- var mixers = (JsonObject)utility.Status?["mixers"];
+ var mixers = (JsonObject?)utility.Status["mixers"];
var locatedDevices = new ArrayList();
var forcedSerial = false;
@@ -222,9 +222,9 @@ private static unsafe void GetDefaults(obs_data* settings)
// Get an initial count of devices which we'll use for stuff later!
var locatedDeviceCount = locatedDevices.Count;
- // If the user has perviously configured a GoXLR but it's not currently attached to the Utility, we need to
+ // If the user has previously configured a GoXLR, but it's not currently attached to the Utility, we need to
// force the serial into the list to prevent arbitrary device switching later on. We'll also flag this as a
- // forced entry so we can appropriately label it.
+ // forced entry, so we can appropriately label it.
if (serial != "" && !locatedDevices.Contains(serial)) {
locatedDevices.Add(serial);
forcedSerial = true;
@@ -232,12 +232,12 @@ private static unsafe void GetDefaults(obs_data* settings)
if (locatedDevices.Count == 0) {
// We're in some kind of error state. Either the utility connection is broken or there are no GoXLRs attached, and the
- // user hasn't previously defined a GoXLR. In this case we'll forcably add the 'Error' serial to the list so we can
+ // user hasn't previously defined a GoXLR. In this case we'll forcibly add the 'Error' serial to the list, so we can
// display the problem to the user in the drop-down.
locatedDevices.Add(deviceSerialError);
}
- // Start filling out the list..
+ // Start filling out the list...
foreach (var located in locatedDevices) {
fixed (byte* sSerial = Encoding.UTF8.GetBytes((string)located)) {
if (located.Equals(deviceSerialError) && mixers == null) {
@@ -254,8 +254,8 @@ private static unsafe void GetDefaults(obs_data* settings)
// Has this device been forced into the located list due to it being disconnected?
if (forcedSerial && located.Equals(serial)) {
- // We can do a *LOT* better than this and potentially check WHY it's disconnected..
- title = String.Format("{0} - Disconnected", located);
+ // We can do a *LOT* better than this and potentially check WHY it's disconnected...
+ title = $"{located} - Disconnected";
}
fixed(byte* sTitle = Encoding.UTF8.GetBytes(title)) {
ObsProperties.obs_property_list_add_string(deviceList, (sbyte*)sTitle, (sbyte*)sSerial);
@@ -283,6 +283,7 @@ public static unsafe void Update(void* data, obs_data* settings)
}
}
+#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
private unsafe struct FilterContext
{
public obs_source* Source;
@@ -292,4 +293,5 @@ private unsafe struct FilterContext
public sbyte* DeviceSerial;
public sbyte* ChannelName;
}
+#pragma warning restore CS0649 // Field is never assigned to, and will always have its default value
}
\ No newline at end of file
diff --git a/FaderSyncPlugin/OBS/Logger.cs b/FaderSyncPlugin/OBS/Logger.cs
index 9095b5a..cde85de 100644
--- a/FaderSyncPlugin/OBS/Logger.cs
+++ b/FaderSyncPlugin/OBS/Logger.cs
@@ -10,10 +10,10 @@ public class Logger
public enum LogLevel
{
- ERROR = ObsBase.LOG_ERROR,
- WARNING = ObsBase.LOG_WARNING,
- INFO = ObsBase.LOG_INFO,
- DEBUG = ObsBase.LOG_DEBUG,
+ Error = ObsBase.LOG_ERROR,
+ Warning = ObsBase.LOG_WARNING,
+ Info = ObsBase.LOG_INFO,
+ Debug = ObsBase.LOG_DEBUG,
}
private static unsafe void Log(LogLevel level, string text)
@@ -40,8 +40,8 @@ public Logger(MemberInfo loggerClass)
_className = loggerClass.Name;
}
- public void Error(string message) => Log(LogLevel.ERROR, $"<{_className}> {message}");
- public void Warning(string message) => Log(LogLevel.WARNING, $"<{_className}> {message}");
- public void Info(string message) => Log(LogLevel.INFO, $"<{_className}> {message}");
- public void Debug(string message) => Log(LogLevel.DEBUG, $"<{_className}> {message}");
+ public void Error(string message) => Log(LogLevel.Error, $"<{_className}> {message}");
+ public void Warning(string message) => Log(LogLevel.Warning, $"<{_className}> {message}");
+ public void Info(string message) => Log(LogLevel.Info, $"<{_className}> {message}");
+ public void Debug(string message) => Log(LogLevel.Debug, $"<{_className}> {message}");
}
\ No newline at end of file
diff --git a/FaderSyncPlugin/OBS/Plugin.cs b/FaderSyncPlugin/OBS/Plugin.cs
index cfb45e2..7b495a1 100644
--- a/FaderSyncPlugin/OBS/Plugin.cs
+++ b/FaderSyncPlugin/OBS/Plugin.cs
@@ -1,5 +1,4 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
+using System.Runtime.InteropServices;
using FaderSync.GoXLR;
using ObsInterop;
@@ -13,7 +12,7 @@ public static class Plugin
CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
public static unsafe void obs_module_set_pointer(obs_module* obsModulePointer)
{
-
+ // do nothing, needs to exist for OBS to load
}
[UnmanagedCallersOnly(EntryPoint = "obs_module_ver",
@@ -29,7 +28,7 @@ public static uint obs_module_ver()
[UnmanagedCallersOnly(EntryPoint = "obs_module_load",
CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
- public static unsafe bool obs_module_load()
+ public static bool obs_module_load()
{
Log.Info($"Loading {Module.Name} v{Module.Version}");
@@ -62,14 +61,14 @@ public static void obs_module_unload()
CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
public static unsafe void obs_module_set_locale(char* locale)
{
-
+ // TODO: add locale support
}
[UnmanagedCallersOnly(EntryPoint = "obs_module_free_locale",
CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
- public static unsafe void obs_module_free_locale()
+ public static void obs_module_free_locale()
{
-
+ // do nothing, needs to exist for OBS to load
}
}
}
\ No newline at end of file
diff --git a/UtilityClient/Native/SocketClient.cs b/UtilityClient/Native/SocketClient.cs
index a2a4164..40cffb3 100644
--- a/UtilityClient/Native/SocketClient.cs
+++ b/UtilityClient/Native/SocketClient.cs
@@ -1,7 +1,7 @@
using System.IO.Pipes;
using System.Text;
-namespace GoXLRUtilityClient.client;
+namespace GoXLRUtilityClient.Native;
public class SocketClient : IDisposable
{
@@ -41,7 +41,7 @@ public string ReadMessage()
// read message length
byte[] lengthBytes;
try { lengthBytes = _reader.ReadBytes(4); }
- catch (IOException) { return null; }
+ catch (IOException) { return ""; }
if (BitConverter.IsLittleEndian) Array.Reverse(lengthBytes);
var messageLength = BitConverter.ToUInt32(lengthBytes);
@@ -65,6 +65,5 @@ public void Dispose()
_reader.Dispose();
_writer.Dispose();
- _client.Dispose();
}
}
\ No newline at end of file
diff --git a/UtilityClient/Native/WebsocketClient.cs b/UtilityClient/Native/WebsocketClient.cs
index 01fdbf9..e4ad5a3 100644
--- a/UtilityClient/Native/WebsocketClient.cs
+++ b/UtilityClient/Native/WebsocketClient.cs
@@ -1,17 +1,17 @@
using System.Net.WebSockets;
using System.Text;
-namespace GoXLRUtilityClient.client;
+namespace GoXLRUtilityClient.Native;
public class WebsocketClient : IDisposable
{
private ClientWebSocket _client = new();
private CancellationTokenSource _cancellationTokenSource = new();
- private Task _receiveMessageTask;
- private Task _connectionTask;
+ private Task? _receiveMessageTask;
+ private Task? _connectionTask;
- private bool _isConnected = false;
+ private bool _isConnected;
public event EventHandler? OnConnected;
public event EventHandler? OnDisconnected;
@@ -31,7 +31,7 @@ private async Task ReceiveMessageTask()
continue;
}
- WebSocketReceiveResult result = null;
+ WebSocketReceiveResult? result = null;
try
{
result = await _client.ReceiveAsync(new ArraySegment(buffer),
@@ -54,11 +54,10 @@ private async Task ReceiveMessageTask()
{
var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
this.OnMessage?.Invoke(this, message);
- break;
}
else
{
- memoryStream.Write(buffer, 0, result.Count);
+ await memoryStream.WriteAsync(buffer, 0, result.Count);
if (result.EndOfMessage)
{
var message = Encoding.UTF8.GetString(memoryStream.GetBuffer(), 0, (int)memoryStream.Position);
@@ -73,12 +72,11 @@ private async Task ReceiveMessageTask()
hasReceivedCloseMessage = true;
// If the server initiates the close handshake, handle it
- Task.Run(DisconnectAsync);
+ await Task.Run(DisconnectAsync);
break;
- case WebSocketMessageType.Binary:
default:
- // This wont occur with the Utility, but we need to trigger DisconnectAsync to perform tidying up!
+ // This won't occur with the Utility, but we need to trigger DisconnectAsync to perform tidying up!
await _client.CloseAsync(WebSocketCloseStatus.ProtocolError, "Only Text is supported.", CancellationToken.None);
this.OnDisconnected?.Invoke(this, "Connection closed because server tried to send binary or invalid message.");
break;
@@ -100,10 +98,7 @@ private async Task ConnectionTask()
case WebSocketState.Aborted:
case WebSocketState.Closed:
// Trigger an internal disconnect to clean resources.
- Task.Run(DisconnectAsync);
- break;
-
- default:
+ await Task.Run(DisconnectAsync);
break;
}
@@ -121,7 +116,7 @@ public async Task ConnectAsync(string uri)
return await this.ConnectAsync(new Uri(uri));
}
- public async Task ConnectAsync(Uri uri)
+ protected async Task ConnectAsync(Uri uri)
{
this._receiveMessageTask = ReceiveMessageTask();
this._connectionTask = ConnectionTask();
@@ -129,7 +124,7 @@ public async Task ConnectAsync(Uri uri)
return this._client.State == WebSocketState.Open;
}
- public async Task DisconnectAsync()
+ protected async Task DisconnectAsync()
{
// Only attempt to close the socket if it's not already closed
if (this._client.State != WebSocketState.Aborted && this._client.State != WebSocketState.Closed) {
@@ -137,8 +132,8 @@ public async Task DisconnectAsync()
}
this.OnDisconnected?.Invoke(this, "Connection closed.");
- this._cancellationTokenSource.Cancel();
- var shutdownSuccessful = Task.WaitAll(new[] { this._receiveMessageTask, this._connectionTask },
+ await _cancellationTokenSource.CancelAsync();
+ var shutdownSuccessful = Task.WaitAll(new[] { this._receiveMessageTask!, this._connectionTask! },
TimeSpan.FromSeconds(5));
if (!shutdownSuccessful)
{
@@ -146,8 +141,8 @@ public async Task DisconnectAsync()
return;
}
- this._receiveMessageTask.Dispose();
- this._connectionTask.Dispose();
+ this._receiveMessageTask!.Dispose();
+ this._connectionTask!.Dispose();
// Dispose of, and create a new client / Token for future connections
this._client.Dispose();
@@ -159,7 +154,7 @@ public async Task DisconnectAsync()
this._isConnected = false;
}
- public async Task SendMessage(string message)
+ protected async Task SendMessage(string message)
{
await this._client.SendAsync(
new ArraySegment(Encoding.UTF8.GetBytes(message)),
@@ -172,7 +167,7 @@ public void Dispose()
{
this._cancellationTokenSource.Cancel();
- var shutdownSuccessful = Task.WaitAll(new[] { this._receiveMessageTask, this._connectionTask },
+ var shutdownSuccessful = Task.WaitAll(new[] { this._receiveMessageTask!, this._connectionTask! },
TimeSpan.FromSeconds(5));
if (!shutdownSuccessful)
{
@@ -182,7 +177,7 @@ public void Dispose()
this._cancellationTokenSource.Dispose();
this._client.Dispose();
- this._receiveMessageTask.Dispose();
- this._connectionTask.Dispose();
+ this._receiveMessageTask!.Dispose();
+ this._connectionTask!.Dispose();
}
}
\ No newline at end of file
diff --git a/UtilityClient/Utility.cs b/UtilityClient/Utility.cs
index 0d3d7a8..50404be 100644
--- a/UtilityClient/Utility.cs
+++ b/UtilityClient/Utility.cs
@@ -1,6 +1,6 @@
using System.Text.Json;
using System.Text.Json.Nodes;
-using GoXLRUtilityClient.client;
+using GoXLRUtilityClient.Native;
using Json.Patch;
namespace GoXLRUtilityClient;
@@ -13,23 +13,23 @@ public class Utility : WebsocketClient
public JsonNode Status;
- public Utility() : base()
+ public Utility()
{
this.Status = JsonNode.Parse("{}")!;
// basic message handler
- base.OnMessage += (object? sender, string message) =>
+ OnMessage += (_, message) =>
{
try
{
var jsonNode = JsonNode.Parse(message);
// test if message is valid
- if (jsonNode!["id"] == null || jsonNode!["data"] == null) return;
+ if (jsonNode!["id"] == null || jsonNode["data"] == null) return;
- var isPatchMessage = jsonNode!["data"]!["Patch"] != null;
- var id = jsonNode!["id"]!.GetValue();
- var data = jsonNode!["data"]!;
+ var isPatchMessage = jsonNode["data"]!["Patch"] != null;
+ var id = jsonNode["id"]!.GetValue();
+ var data = jsonNode["data"]!;
this.OnMessageReceived?.Invoke(this, new MessageData(id, data, isPatchMessage));
@@ -37,7 +37,7 @@ public Utility() : base()
if (isPatchMessage)
{
var patchString = data["Patch"]!.ToJsonString();
- var patch = JsonSerializer.Deserialize(patchString);
+ var patch = JsonSerializer.Deserialize(patchString); // FIXME: can break functionality when AOT compiling
var resultResult = patch?.Apply(this.Status);
this.Status = resultResult!.Result!;
}
@@ -48,7 +48,7 @@ public Utility() : base()
} // nothing
};
- base.OnDisconnected += async (object? sender, string message) => {
+ OnDisconnected += (_, message) => {
Console.WriteLine("Disconnected from Host: {0}", message);
// Reset the status, so Upstream code knows we're not connected.
@@ -90,7 +90,7 @@ void TempMessageHandler(object? _, MessageData message)
}
}
- public new async Task ConnectAsync()
+ public async Task ConnectAsync()
{
String pipeName = OperatingSystem.IsWindows() ? "@goxlr.socket" : "/tmp/goxlr.socket";
SocketClient socketClient = new SocketClient(pipeName);
@@ -127,8 +127,8 @@ void TempMessageHandler(object? _, MessageData message)
// request status
var statusRequest = JsonNode.Parse("{}");
statusRequest!["id"] = requestId;
- statusRequest!["data"] = "GetStatus";
- await base.SendMessage(statusRequest.ToJsonString());
+ statusRequest["data"] = "GetStatus";
+ await SendMessage(statusRequest.ToJsonString());
var result = await this.AwaitResponse(requestId);
if (result != null) this.Status = result["Status"]!;