Skip to content

Commit

Permalink
feat: openrgb sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewBabbitt97 committed Jul 13, 2024
1 parent 480124d commit 1324a77
Show file tree
Hide file tree
Showing 14 changed files with 396 additions and 1 deletion.
14 changes: 13 additions & 1 deletion ChromaControl.SDK.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ VisualStudioVersion = 17.11.35017.193
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChromaControl.SDK.Synapse", "src\ChromaControl.SDK.Synapse\ChromaControl.SDK.Synapse.csproj", "{D192C5EA-EC40-4BA9-AE43-ADA9FB4F446A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChromaControl.SDK.Synapse.Sample", "src\ChromaControl.SDK.Synapse.Sample\ChromaControl.SDK.Synapse.Sample.csproj", "{D8F00B39-3709-4157-9F87-521FDEA6041C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChromaControl.SDK.Synapse.Sample", "src\ChromaControl.SDK.Synapse.Sample\ChromaControl.SDK.Synapse.Sample.csproj", "{D8F00B39-3709-4157-9F87-521FDEA6041C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChromaControl.SDK.OpenRGB", "src\ChromaControl.SDK.OpenRGB\ChromaControl.SDK.OpenRGB.csproj", "{9542A5ED-B1B8-4E27-9AC1-B4C0565F72C1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChromaControl.SDK.OpenRGB.Sample", "src\ChromaControl.SDK.OpenRGB.Sample\ChromaControl.SDK.OpenRGB.Sample.csproj", "{ED14E023-F619-4B15-8730-5C6195CB9358}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -21,6 +25,14 @@ Global
{D8F00B39-3709-4157-9F87-521FDEA6041C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8F00B39-3709-4157-9F87-521FDEA6041C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8F00B39-3709-4157-9F87-521FDEA6041C}.Release|Any CPU.Build.0 = Release|Any CPU
{9542A5ED-B1B8-4E27-9AC1-B4C0565F72C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9542A5ED-B1B8-4E27-9AC1-B4C0565F72C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9542A5ED-B1B8-4E27-9AC1-B4C0565F72C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9542A5ED-B1B8-4E27-9AC1-B4C0565F72C1}.Release|Any CPU.Build.0 = Release|Any CPU
{ED14E023-F619-4B15-8730-5C6195CB9358}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED14E023-F619-4B15-8730-5C6195CB9358}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED14E023-F619-4B15-8730-5C6195CB9358}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED14E023-F619-4B15-8730-5C6195CB9358}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ChromaControl.SDK.OpenRGB\ChromaControl.SDK.OpenRGB.csproj" />
</ItemGroup>
</Project>
13 changes: 13 additions & 0 deletions src/ChromaControl.SDK.OpenRGB.Sample/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Licensed to the Chroma Control Contributors under one or more agreements.
// The Chroma Control Contributors licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using ChromaControl.SDK.OpenRGB.Extensions;
using ChromaControl.SDK.OpenRGB.Sample;

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddOpenRGBSDK();
builder.Services.AddHostedService<Worker>();

await builder.Build().RunAsync();
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"ChromaControl.SDK.OpenRGB.Sample": {
"commandName": "Project",
"dotnetRunMessages": true,
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
}
}
}
59 changes: 59 additions & 0 deletions src/ChromaControl.SDK.OpenRGB.Sample/Worker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Licensed to the Chroma Control Contributors under one or more agreements.
// The Chroma Control Contributors licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace ChromaControl.SDK.OpenRGB.Sample;

/// <summary>
/// The worker.
/// </summary>
public partial class Worker : IHostedService
{
private readonly ILogger<Worker> _logger;
private readonly IOpenRGBService _openRGB;

[LoggerMessage(Level = LogLevel.Information, Message = "Starting OpenRGB Service...")]
private static partial void LogStartMessage(ILogger logger);

[LoggerMessage(Level = LogLevel.Information, Message = "Stopping OpenRGB Service...")]
private static partial void LogStopMessage(ILogger logger);

/// <summary>
/// Creates a <see cref="Worker"/> instance.
/// </summary>
/// <param name="logger">The <see cref="ILogger{TCategoryName}"/>.</param>
/// <param name="openRGB">The <see cref="IOpenRGBService"/>.</param>
public Worker(ILogger<Worker> logger, IOpenRGBService openRGB)
{
_logger = logger;
_openRGB = openRGB;
}

/// <summary>
/// Starts the worker.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
/// <returns>A <see cref="Task"/> representing the worker starting.</returns>
public Task StartAsync(CancellationToken cancellationToken)
{
LogStartMessage(_logger);

_openRGB.StartService();

return Task.CompletedTask;
}

/// <summary>
/// Stops the worker.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
/// <returns>A <see cref="Task"/> representing the worker stopping.</returns>
public Task StopAsync(CancellationToken cancellationToken)
{
LogStopMessage(_logger);

_openRGB.StopService();

return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
8 changes: 8 additions & 0 deletions src/ChromaControl.SDK.OpenRGB.Sample/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
16 changes: 16 additions & 0 deletions src/ChromaControl.SDK.OpenRGB/ChromaControl.SDK.OpenRGB.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ChromaControl.Native.OpenRGB" Version="1.0.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.106">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Licensed to the Chroma Control Contributors under one or more agreements.
// The Chroma Control Contributors licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.Extensions.DependencyInjection;

namespace ChromaControl.SDK.OpenRGB.Extensions;

/// <summary>
/// Extension methods for adding the OpenRGB SDK to an <see cref="IServiceCollection" />.
/// </summary>
public static class ServiceCollectionOpenRGBExtensions
{
/// <summary>
/// Registers the OpenRGB SDK in an <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> to register with.</param>
/// <returns>The original <see cref="IServiceCollection"/>.</returns>
public static IServiceCollection AddOpenRGBSDK(this IServiceCollection services)
{
services.AddSingleton<IOpenRGBService, OpenRGBService>();

return services;
}
}
21 changes: 21 additions & 0 deletions src/ChromaControl.SDK.OpenRGB/IOpenRGBService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Licensed to the Chroma Control Contributors under one or more agreements.
// The Chroma Control Contributors licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace ChromaControl.SDK.OpenRGB;

/// <summary>
/// The OpenRGB Service.
/// </summary>
public interface IOpenRGBService
{
/// <summary>
/// Starts the OpenRGB service.
/// </summary>
void StartService();

/// <summary>
/// Stopes the OpenRGB service.
/// </summary>
void StopService();
}
93 changes: 93 additions & 0 deletions src/ChromaControl.SDK.OpenRGB/Internal/Job.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Licensed to the Chroma Control Contributors under one or more agreements.
// The Chroma Control Contributors licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.Win32.SafeHandles;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Windows.Win32;
using Windows.Win32.Security;
using Windows.Win32.System.JobObjects;

namespace ChromaControl.SDK.OpenRGB.Internal;

internal sealed class Job : IDisposable
{
private readonly SafeFileHandle _jobHandle;

public Job()
{
_jobHandle = CreateJob();

SetJobInfo(_jobHandle);
}

private static unsafe SafeFileHandle CreateJob()
{
var securityAttributes = new SECURITY_ATTRIBUTES
{
bInheritHandle = false,
lpSecurityDescriptor = IntPtr.Zero.ToPointer(),
nLength = (uint)Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES))
};

#pragma warning disable CA1416 // Validate platform compatibility
var jobHandle = PInvoke.CreateJobObject(securityAttributes, "ChromaControl.SDK.OpenRGB");
#pragma warning restore CA1416 // Validate platform compatibility

if (jobHandle.IsInvalid)
{
jobHandle.Dispose();

var lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(lastError);
}

return jobHandle;
}

private static unsafe void SetJobInfo(SafeFileHandle jobHandle)
{
var info = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
BasicLimitInformation = new()
{
LimitFlags = JOB_OBJECT_LIMIT.JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION
| JOB_OBJECT_LIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
}
};

var infoSize = (uint)Marshal.SizeOf<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>();

#pragma warning disable CA1416 // Validate platform compatibility
var setInfoResult = PInvoke.SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, &info, infoSize);
#pragma warning restore CA1416 // Validate platform compatibility

if (!setInfoResult)
{
var lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(lastError);
}
}

public void AssignProcess(Process process)
{
#pragma warning disable CA1416 // Validate platform compatibility
var assignProcessResult = PInvoke.AssignProcessToJobObject(_jobHandle, process.SafeHandle);
#pragma warning restore CA1416 // Validate platform compatibility

if (!assignProcessResult)
{
var lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(lastError);
}
}

public void Dispose()
{
_jobHandle?.Dispose();

GC.SuppressFinalize(this);
}
}
77 changes: 77 additions & 0 deletions src/ChromaControl.SDK.OpenRGB/Internal/OpenRGBManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Licensed to the Chroma Control Contributors under one or more agreements.
// The Chroma Control Contributors licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics;

namespace ChromaControl.SDK.OpenRGB.Internal;

internal sealed partial class OpenRGBManager : IDisposable
{
private static bool Is32Bit => nint.Size == 4;

private readonly Process _process = CreateProcess();
private readonly Job _job;

public OpenRGBManager()
{
_job = new();
}

public void Start()
{
_job.AssignProcess(Process.GetCurrentProcess());
_process.Start();
}

public void Stop()
{
_process.Kill();
}

public void Dispose()
{
_process.Kill();
_process.Dispose();

_job.Dispose();

GC.SuppressFinalize(this);
}

private static Process CreateProcess()
{
var process = new Process();

process.StartInfo.FileName = "cmd.exe";
process.StartInfo.UseShellExecute = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.Arguments = $"/C \"{FindExecutablePath()}\" --noautoconnect --server";

return process;
}

private static string FindExecutablePath()
{
var assembly = typeof(OpenRGBManager).Assembly;
var assemblyFilePath = assembly.Location;
var assemblyPath = Path.GetDirectoryName(assemblyFilePath) ?? throw new FileNotFoundException("Unable to find the OpenRGB executable.");
var runtimeIdentifier = Is32Bit ? "win-x86" : "win-x64";

var searchPaths = new List<string>()
{
Path.Combine(assemblyPath, "OpenRGB.exe"),
Path.Combine(assemblyPath, "runtimes", runtimeIdentifier, "native", "OpenRGB.exe")
};

foreach (var searchPath in searchPaths)
{
if (File.Exists(searchPath))
{
return searchPath;
}
}

throw new FileNotFoundException("Unable to find the OpenRGB executable.");
}
}
4 changes: 4 additions & 0 deletions src/ChromaControl.SDK.OpenRGB/NativeMethods.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
AssignProcessToJobObject
CreateJobObject
SetInformationJobObject
JOBOBJECT_EXTENDED_LIMIT_INFORMATION
Loading

0 comments on commit 1324a77

Please sign in to comment.