mirror of
https://github.com/Maassoft/ColorControl.git
synced 2026-10-19 23:31:13 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0d3bb4682 | ||
|
|
8cb427f0b0 |
No files matched your search
+70
-23
@@ -1,7 +1,10 @@
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.UI.Pages.Generic;
|
||||
using ColorControl.UI.Services;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||
using NStandard;
|
||||
using System.Net;
|
||||
|
||||
namespace ColorControl.UI;
|
||||
@@ -9,17 +12,15 @@ namespace ColorControl.UI;
|
||||
public static class Blazor
|
||||
{
|
||||
private static WebApplication? CurrentApplication;
|
||||
private static int Port;
|
||||
private static bool AllowRemoteConnections;
|
||||
|
||||
public static bool IsRunning(Config config) => CurrentApplication != null && Port == config.UiPort && AllowRemoteConnections == config.UiAllowRemoteConnections;
|
||||
public static CustomComponentBase? CurrentComponent { get; private set; }
|
||||
|
||||
public static async Task Start(Config config)
|
||||
public static async Task Start(string[] args)
|
||||
{
|
||||
if (IsRunning(config))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var mutexId = args.GetValueOrDefault(0);
|
||||
var useDarkMode = args.GetValueOrDefault(1) == "True";
|
||||
var uiPort = Utils.ParseInt(args.GetValueOrDefault(2));
|
||||
var allowRemoteConnections = args.GetValueOrDefault(3) == "True";
|
||||
|
||||
await Stop();
|
||||
|
||||
@@ -29,7 +30,7 @@ public static class Blazor
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents();
|
||||
|
||||
builder.Services.AddSingleton<AppState>(new AppState { SelectedTheme = config.UseDarkMode ? "dark" : "light" });
|
||||
builder.Services.AddSingleton(new AppState { SelectedTheme = useDarkMode ? "dark" : "light" });
|
||||
builder.Services.AddTransient<RpcUiClientService>();
|
||||
builder.Services.AddTransient<JSHelper>();
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
@@ -37,11 +38,11 @@ public static class Blazor
|
||||
|
||||
builder.Services.Configure<HostOptions>(opts => opts.ShutdownTimeout = TimeSpan.FromSeconds(3));
|
||||
|
||||
var listenPort = config.UiPort > 0 ? config.UiPort : 0;
|
||||
var listenPort = uiPort > 0 ? uiPort : 0;
|
||||
|
||||
builder.WebHost.ConfigureKestrel(options =>
|
||||
{
|
||||
if (config.UiAllowRemoteConnections)
|
||||
if (allowRemoteConnections)
|
||||
{
|
||||
options.ListenAnyIP(listenPort);
|
||||
}
|
||||
@@ -51,6 +52,8 @@ public static class Blazor
|
||||
}
|
||||
});
|
||||
|
||||
builder.WebHost.UseStaticWebAssets();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
@@ -61,17 +64,56 @@ public static class Blazor
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
||||
//app.UseHttpsRedirection();
|
||||
|
||||
app.UseStaticFiles();
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.MapStaticAssets();
|
||||
//app.UsePathBase("/");
|
||||
|
||||
app.MapRazorComponents<Components.App>()
|
||||
.AddInteractiveServerRenderMode();
|
||||
|
||||
CurrentApplication = app;
|
||||
Port = config.UiPort;
|
||||
AllowRemoteConnections = config.UiAllowRemoteConnections;
|
||||
|
||||
var _ = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(500);
|
||||
|
||||
var port = GetCurrentPort();
|
||||
|
||||
if (port == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var rpcServer = app.Services.GetRequiredService<RpcUiClientService>();
|
||||
|
||||
await rpcServer.CallAsync<bool>("OptionsService", "SetCurrentUiSettings", port, allowRemoteConnections);
|
||||
|
||||
if (!mutexId.IsNullOrWhiteSpace())
|
||||
{
|
||||
Console.WriteLine("Waiting for mutex: " + mutexId);
|
||||
var mutex = new Mutex(false, mutexId, out var createdNew);
|
||||
if (createdNew)
|
||||
{
|
||||
Console.WriteLine("Mutex was created, skipping.");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
mutex.WaitOne();
|
||||
Console.WriteLine("Waiting done.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Wait completed: " + ex.Message);
|
||||
}
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
await app.RunAsync();
|
||||
}
|
||||
@@ -85,14 +127,7 @@ public static class Blazor
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetCurrentUrl()
|
||||
{
|
||||
var port = GetCurrentPort();
|
||||
|
||||
return $"http://localhost:{port}";
|
||||
}
|
||||
|
||||
public static int GetCurrentPort()
|
||||
public static int GetCurrentPort(Config? config = null)
|
||||
{
|
||||
if (CurrentApplication == null)
|
||||
{
|
||||
@@ -115,4 +150,16 @@ public static class Blazor
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void SetCurrentComponent(CustomComponentBase? customComponentBase)
|
||||
{
|
||||
CurrentComponent = customComponentBase;
|
||||
}
|
||||
|
||||
public static void ClearCurrentComponent(CustomComponentBase customComponentBase)
|
||||
{
|
||||
if (CurrentComponent == customComponentBase)
|
||||
{
|
||||
CurrentComponent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<OutputType>Library</OutputType>
|
||||
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
|
||||
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.3.4" />
|
||||
<PackageReference Include="NLog" Version="6.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@using ColorControl.Shared.Common
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.UI.Pages.Generic
|
||||
@using ColorControl.UI.Services
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
@@ -9,6 +10,7 @@
|
||||
@inject NavigationManager _navigationManager
|
||||
@inject NotificationService _notificationService
|
||||
@inject ProtectedSessionStorage _sessionStorage
|
||||
@inject JSHelper _jsHelper
|
||||
|
||||
@implements IDisposable
|
||||
@attribute [StreamRendering]
|
||||
@@ -20,19 +22,26 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<base href="/" />
|
||||
<ResourcePreloader />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="app.css" />
|
||||
<link rel="stylesheet" href="ColorControl.UI.styles.css" />
|
||||
<ImportMap />
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
|
||||
<HeadOutlet />
|
||||
<HeadOutlet @rendermode="InteractiveServer" />
|
||||
<script>
|
||||
addEventListener('focus', (event) => {
|
||||
var isModalShown = document.getElementsByClassName("modal show").length > 0;
|
||||
DotNet.invokeMethodAsync("ColorControl.UI", "RefreshSummary", isModalShown);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<Routes />
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
<Routes @rendermode="InteractiveServer" />
|
||||
<script src="@Assets["_framework/blazor.web.js"]"></script>
|
||||
<NotificationsComponent></NotificationsComponent>
|
||||
</body>
|
||||
|
||||
@@ -59,4 +68,13 @@
|
||||
{
|
||||
AppState.OnChange -= StateHasChanged;
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public static async Task RefreshSummary(bool isModalShown)
|
||||
{
|
||||
if (Blazor.CurrentComponent is SummaryComponentBase summaryComponent && !isModalShown)
|
||||
{
|
||||
await summaryComponent.RefreshExternal();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,12 @@
|
||||
@using ColorControl.Shared.Common
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.AMD
|
||||
@using ColorControl.UI.Pages.Generic
|
||||
@using ColorControl.UI.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Generics
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
@inherits SummaryComponentBase
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -144,6 +146,13 @@ else
|
||||
private PresetOrder PresetOrder;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await Refresh();
|
||||
}
|
||||
|
||||
protected override async Task Refresh()
|
||||
{
|
||||
await RefreshPresets();
|
||||
DisplayPresets = await _rpcClientService.CallAsync<List<AmdPreset>>("AmdService", "GetDisplayPresets");
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
@using ColorControl.Shared.Contracts.DisplayInfo
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Generics
|
||||
@using ColorControl.UI.Pages.Generic
|
||||
@using ColorControl.UI.Services
|
||||
@inherits SummaryComponentBase
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -190,7 +192,15 @@ else
|
||||
|
||||
private FieldDefinition AskHdrAssociationField = new FieldDefinition { Label = "Associate as HDR profile", FieldType = FieldType.CheckBox, Value = false };
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await Refresh();
|
||||
}
|
||||
|
||||
protected override async Task Refresh()
|
||||
{
|
||||
await RefreshDisplays();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
@using ColorControl.Shared.Contracts.Game
|
||||
@using ColorControl.UI.Services
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace ColorControl.UI.Pages.Generic;
|
||||
|
||||
public abstract class CustomComponentBase : ComponentBase, IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
Blazor.ClearCurrentComponent(this);
|
||||
}
|
||||
|
||||
protected override Task OnInitializedAsync()
|
||||
{
|
||||
Blazor.SetCurrentComponent(this);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -44,9 +44,9 @@
|
||||
try
|
||||
{
|
||||
var options = new RpcUiClientOptions
|
||||
{
|
||||
Timeout = 60000
|
||||
};
|
||||
{
|
||||
Timeout = 60000
|
||||
};
|
||||
|
||||
var result = await _rpcClientService.CallWithOptionsAsync<string>("GameService", "SelectPath", options);
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace ColorControl.UI.Pages.Generic;
|
||||
|
||||
public abstract class SummaryComponentBase : CustomComponentBase
|
||||
{
|
||||
protected abstract Task Refresh();
|
||||
|
||||
public async Task RefreshExternal()
|
||||
{
|
||||
await Refresh();
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
@@ -7,16 +7,20 @@
|
||||
|
||||
@if (Triggers != null)
|
||||
{
|
||||
if (!Triggers.Any())
|
||||
if (Triggers.Count < 2)
|
||||
{
|
||||
<div>
|
||||
<label class="form-label">No triggers found. Click to add:</label>
|
||||
<label class="form-label">Add trigger:</label>
|
||||
<button class="btn btn-primary btn-sm" type="button" @onclick="() => Triggers.Add(new PresetTrigger())">Add</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
foreach (var trigger in Triggers)
|
||||
{
|
||||
<div class="clearfix">
|
||||
<label class="form-label">Trigger @(Triggers.IndexOf(trigger) + 1)</label>
|
||||
<button class="btn btn-danger btn-sm float-end" type="button" @onclick="() => Triggers.Remove(trigger)">Remove</button>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="triggerType">Trigger type</label>
|
||||
<select class="form-select" id="triggerType" @bind="trigger.Trigger">
|
||||
@@ -26,7 +30,7 @@
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<FlagsInput Label="Conditions" Value="@((uint)trigger.Conditions)" Labels="ConditionLabels" Col="6" ValueChanged="ConditionsChanged"></FlagsInput>
|
||||
<FlagsInput Label="Conditions" Value="@((uint)trigger.Conditions)" Labels="ConditionLabels" Col="6" ValueChanged="value => ConditionsChanged(value, trigger)"></FlagsInput>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="includedProcesses">Included processes</label>
|
||||
<input class="form-control" type="text" @bind="trigger.IncludedProcessesAsString" />
|
||||
@@ -40,6 +44,11 @@
|
||||
<input class="form-control" type="text" @bind="trigger.ConnectedDisplaysRegex"
|
||||
title="The preset will be executed only if the supplied Regular Expression matches the device name of at least one of the displays that are connected at the moment the trigger is fired." />
|
||||
</div>
|
||||
|
||||
@if (Triggers.IndexOf(trigger) < Triggers.Count - 1)
|
||||
{
|
||||
<div class="border-bottom mb-2"></div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,14 +58,8 @@
|
||||
|
||||
private List<string> ConditionLabels = Utils.GetDescriptions<PresetConditionType>(fromValue: 1).ToList();
|
||||
|
||||
public void ConditionsChanged(uint value)
|
||||
public void ConditionsChanged(uint value, PresetTrigger trigger)
|
||||
{
|
||||
if (Triggers == null || !Triggers.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var trigger = Triggers.First();
|
||||
trigger.Conditions = (PresetConditionType)value;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.LG
|
||||
@using ColorControl.UI.Services
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using ColorControl.Shared.Common
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
|
||||
@@ -154,6 +154,10 @@
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkUseSecureConnection" @bind="Device.Options.UseSecureConnection">
|
||||
<label class="form-check-label" for="checkUseSecureConnection">Use secure connection</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkUseNewHandshake" @bind="Device.Options.UseNewHandshake">
|
||||
<label class="form-check-label" for="checkUseNewHandshake">Enable webOS 26 compatibility</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
@using ColorControl.Shared.Contracts.LG
|
||||
@using ColorControl.UI.Services
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
@using static ColorControl.UI.Components.Pages.Generic.StepsInput<ColorControl.Shared.Contracts.LG.LgPreset>
|
||||
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Contracts.LG
|
||||
@using ColorControl.UI.Components.Pages.RemoteControl
|
||||
@using ColorControl.UI.Pages.Generic
|
||||
@using ColorControl.UI.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Generics
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
@inherits SummaryComponentBase
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -239,6 +241,13 @@ else
|
||||
private List<LgPreset> RcPresets = [LgPresets.InStartPreset, LgPresets.EzAdjustPreset];
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await Refresh();
|
||||
}
|
||||
|
||||
protected override async Task Refresh()
|
||||
{
|
||||
Config = await _rpcClientService.CallAsync<LgServiceConfigDto>("LgService", "GetConfig");
|
||||
await RefreshPresets();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.UI.Services;
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Services;
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Services;
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.UI.Services;
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common;
|
||||
@using static ColorControl.Shared.Common.NestedItemsBuilder
|
||||
|
||||
|
||||
@@ -45,50 +45,62 @@
|
||||
}
|
||||
<div class="accordion accordion-flush" id="presetAccordion">
|
||||
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem; visibility: hidden" type="checkbox">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#displaySettings">
|
||||
Display
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="displaySettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem; visibility: hidden" type="checkbox">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#displaySettings">
|
||||
Display
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="displaySettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.primaryDisplay" id="primaryDisplay">
|
||||
<label class="form-check-label" for="primaryDisplay">
|
||||
Primary display
|
||||
</label>
|
||||
</div>
|
||||
@if (displayPresets != null)
|
||||
}
|
||||
@if (displayPresets != null)
|
||||
{
|
||||
if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="mode">Display</label>
|
||||
<select class="form-select" id="mode" @bind="Preset.DisplayId" disabled="@(Preset.primaryDisplay)">
|
||||
<select class="form-select" id="mode" @bind="Preset.DisplayId" disabled="@Preset.primaryDisplay">
|
||||
@foreach (var display in displayPresets)
|
||||
{
|
||||
<option value="@display.DisplayId">@display.displayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.DisplayConfig.IsPrimary" id="setAsPrimaryDisplay" disabled="@(Preset.primaryDisplay)">
|
||||
<label class="form-check-label" for="setAsPrimaryDisplay">
|
||||
Set display as primary display
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.DisplayConfig.IsPrimary" id="setAsPrimaryDisplay" disabled="@(Preset.IsDisplayPreset && displayPresets.Count == 1)">
|
||||
<label class="form-check-label" for="setAsPrimaryDisplay">
|
||||
Set display as primary display
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="connectivity">Connectivity</label>
|
||||
<select class="form-select" id="scaling" @bind="Preset.DisplayConfig.Connectivity">
|
||||
@foreach (var connectivity in Enum.GetValues<Shared.Contracts.DisplayConnectivity>())
|
||||
{
|
||||
<option value="@connectivity.ToString()">@connectivity.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (resolutions != null)
|
||||
{
|
||||
@@ -745,7 +757,7 @@
|
||||
|
||||
ApplyImmediately = false;
|
||||
|
||||
Preset = PresetParam == null ? null : PresetParam.CloneWithId();
|
||||
Preset = PresetParam?.CloneWithId();
|
||||
|
||||
displayPresets = await _rpcClientService.CallAsync<List<NvPreset>>("NvService", "GetDisplayPresets");
|
||||
if (Preset?.IsDisplayPreset == true)
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.UI.Pages.Generic
|
||||
@using ColorControl.UI.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Generics
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
@inherits SummaryComponentBase
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -276,6 +278,13 @@ else
|
||||
private PresetOrder PresetOrder;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await Refresh();
|
||||
}
|
||||
|
||||
protected override async Task Refresh()
|
||||
{
|
||||
NvConfig = await _rpcClientService.CallAsync<NvServiceConfig>("NvService", "GetConfig");
|
||||
await RefreshPresets();
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
@using ColorControl.Shared.Contracts.Base
|
||||
@using ColorControl.Shared.Contracts.RemoteControl
|
||||
@using ColorControl.UI.Services
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
@using System.Globalization
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
@using ColorControl.Shared.Contracts.Samsung
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Services
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
@using ColorControl.Shared.Contracts.Samsung
|
||||
@using ColorControl.UI.Services
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
@using static ColorControl.UI.Components.Pages.Generic.StepsInput<ColorControl.Shared.Contracts.Samsung.SamsungPreset>
|
||||
|
||||
|
||||
@@ -102,8 +102,8 @@
|
||||
SecondaryAction = FactoryMenuSecondStepEnterWithoutExecute;
|
||||
Fields =
|
||||
[
|
||||
AddField("Service Menu - Advanced", null, FieldType.Label, "If the service menu opened and you want to access the Advanced settings, click 'Next >' or click 'Skip' to skip"),
|
||||
AddField("Advanced Unlock Type", AdvancedUnlockType.TV, subLabel: "Select the desired unlock type for the Advanced section. If the target is a TV choose TV, otherwise choose Monitor")
|
||||
AddField("Service Menu - Advanced", null, FieldType.Label, "If the service menu opened and you want to access the Advanced settings, click 'Next >' or click 'Skip' to skip. You can also manually enter the unlock codes 0098 (for TV's) and 0038 (for monitors) while the 'Advanced' item is highlighted."),
|
||||
AddField("Advanced Unlock Type", AdvancedUnlockType.TV, subLabel: "Select the desired unlock type for the Advanced section. If the target is a TV choose TV, otherwise choose Monitor")
|
||||
];
|
||||
|
||||
StateHasChanged();
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Contracts.Samsung
|
||||
@using ColorControl.UI.Components.Pages.RemoteControl
|
||||
@using ColorControl.UI.Pages.Generic
|
||||
@using ColorControl.UI.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Generics
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
@inherits SummaryComponentBase
|
||||
|
||||
@rendermode Constants.RenderMode
|
||||
|
||||
@@ -220,6 +222,13 @@ else
|
||||
private PresetOrder PresetOrder;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await Refresh();
|
||||
}
|
||||
|
||||
protected override async Task Refresh()
|
||||
{
|
||||
Config = await _rpcClientService.CallAsync<SamsungServiceConfigDto>("SamsungService", "GetConfig");
|
||||
await RefreshPresets();
|
||||
|
||||
@@ -12,7 +12,5 @@ public static class Constants
|
||||
public const string Light = "light";
|
||||
public const string Dark = "dark";
|
||||
|
||||
|
||||
public static IComponentRenderMode RenderMode = new InteractiveServerRenderMode(prerender: false);
|
||||
|
||||
}
|
||||
+16
-28
@@ -1,32 +1,20 @@
|
||||
//using ColorControl.UI;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.UI;
|
||||
using ColorControl.UI.Services;
|
||||
using System.Diagnostics;
|
||||
|
||||
//Blazor.Start();
|
||||
var arguments = args;
|
||||
|
||||
//var builder = WebApplication.CreateBuilder(args);
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
var rpcServer = new RpcUiClientService(null);
|
||||
var options = new RpcUiClientOptions
|
||||
{
|
||||
Timeout = 10000
|
||||
};
|
||||
|
||||
//// Add services to the container.
|
||||
//builder.Services.AddRazorComponents()
|
||||
// .AddInteractiveServerComponents();
|
||||
var config = await rpcServer.CallWithOptionsAsync<Config>("OptionsService", "GetConfig", options);
|
||||
arguments = ["", config.UseDarkMode.ToString(), config.UiPort.ToString(), config.UiAllowRemoteConnections.ToString()];
|
||||
}
|
||||
|
||||
//builder.Services.AddSingleton<AppState>();
|
||||
//builder.Services.AddSingleton<OptionsService>();
|
||||
|
||||
//var app = builder.Build();
|
||||
|
||||
//// Configure the HTTP request pipeline.
|
||||
//if (!app.Environment.IsDevelopment())
|
||||
//{
|
||||
// app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
// // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
// app.UseHsts();
|
||||
//}
|
||||
|
||||
//app.UseHttpsRedirection();
|
||||
|
||||
//app.UseStaticFiles();
|
||||
//app.UseAntiforgery();
|
||||
|
||||
//app.MapRazorComponents<App>()
|
||||
// .AddInteractiveServerRenderMode();
|
||||
|
||||
//app.Run();
|
||||
await Blazor.Start(arguments);
|
||||
@@ -1,13 +1,5 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:31433",
|
||||
"sslPort": 44330
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
@@ -26,13 +18,6 @@
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,11 @@ public class JSHelper(IJSRuntime jsRuntime)
|
||||
await InvokeVoidAsync("CloseModal", id);
|
||||
}
|
||||
|
||||
public async Task<bool> IsModalShown()
|
||||
{
|
||||
return await InvokeAsync<bool>("IsModalShown");
|
||||
}
|
||||
|
||||
public async Task ShowToast(string id)
|
||||
{
|
||||
await InvokeVoidAsync("ShowToast", id);
|
||||
|
||||
@@ -10,7 +10,7 @@ public class RpcUiClientOptions
|
||||
public int Timeout { get; set; } = PipeUtils.DefaultTimeout;
|
||||
}
|
||||
|
||||
public class RpcUiClientService(NotificationService notificationService)
|
||||
public class RpcUiClientService(NotificationService? notificationService)
|
||||
{
|
||||
public string? LastErrorMessage { get; private set; }
|
||||
|
||||
@@ -46,7 +46,7 @@ public class RpcUiClientService(NotificationService notificationService)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result?.ErrorMessages.Count > 0)
|
||||
if (result?.ErrorMessages.Count > 0 && notificationService != null)
|
||||
{
|
||||
await notificationService.SendNotificationDirect(new NotificationDto(result.ErrorMessages.First(), Constants.Danger));
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public class RpcUiClientService(NotificationService notificationService)
|
||||
|
||||
if (resultJson == null)
|
||||
{
|
||||
notificationService.SendNotification(new NotificationDto("Unknown communication error", Constants.Danger));
|
||||
notificationService?.SendNotification(new NotificationDto("Unknown communication error", Constants.Danger));
|
||||
|
||||
return default;
|
||||
}
|
||||
@@ -85,7 +85,10 @@ public class RpcUiClientService(NotificationService notificationService)
|
||||
{
|
||||
LastErrorMessage = resultMessage?.ErrorMessage ?? "Unknown communication error";
|
||||
|
||||
await notificationService.SendNotificationDirect(new NotificationDto(LastErrorMessage, Constants.Danger));
|
||||
if (notificationService != null)
|
||||
{
|
||||
await notificationService.SendNotificationDirect(new NotificationDto(LastErrorMessage, Constants.Danger));
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
@@ -26,4 +26,8 @@ export function GetElementClassName(elementId) {
|
||||
|
||||
export function NavigateTo(uri, timeout = 0) {
|
||||
setTimeout(() => window.location = uri, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
export function IsModalShown() {
|
||||
return document.getElementsByClassName("modal show").length > 0;
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.32014.148
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorControl", "ColorControl\ColorControl.csproj", "{A6005D08-70F0-44CB-A384-9219EBA84F21}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nspector", "Nspector\Nspector.csproj", "{76797290-48F5-4A82-86C3-FAD25DAE4500}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvAPIWrapper", "NvAPIWrapper\NvAPIWrapper.csproj", "{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "novideo_srgb", "novideo_srgb\novideo_srgb.csproj", "{A6A97834-7BE1-474A-B92F-A512DB1D5186}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NLogViewer", "NLogViewer\NLogViewer.csproj", "{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LittleCms", "LittleCms\LittleCms.csproj", "{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MHC2Gen", "MHC2Gen\MHC2Gen.csproj", "{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorControl.UI", "ColorControl.UI\ColorControl.UI.csproj", "{85EA3079-BB73-4CE5-A72F-E56906187051}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|x64.Build.0 = Release|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Release|x64.Build.0 = Release|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Debug|x64.Build.0 = Debug|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Release|Any CPU.Build.0 = Release|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Release|x64.ActiveCfg = Release|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Release|x64.Build.0 = Release|x64
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {34BA158F-AE57-4A7B-A372-11FEFBBC1F98}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,17 @@
|
||||
<Solution>
|
||||
<Configurations>
|
||||
<Platform Name="Any CPU" />
|
||||
<Platform Name="x64" />
|
||||
</Configurations>
|
||||
<Project Path="ColorControl.UI/ColorControl.UI.csproj" />
|
||||
<Project Path="ColorControl/ColorControl.csproj" />
|
||||
<Project Path="LittleCms/LittleCms.csproj" />
|
||||
<Project Path="MHC2Gen/MHC2Gen.csproj">
|
||||
<Platform Project="x64" />
|
||||
</Project>
|
||||
<Project Path="NLogViewer/NLogViewer.csproj" />
|
||||
<Project Path="novideo_srgb/novideo_srgb.csproj" />
|
||||
<Project Path="Nspector/Nspector.csproj" />
|
||||
<Project Path="NvAPIWrapper/NvAPIWrapper.csproj" />
|
||||
<Project Path="Shared/Shared.csproj" />
|
||||
</Solution>
|
||||
@@ -0,0 +1,111 @@
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.Services;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ColorControl;
|
||||
|
||||
public static class BlazorUiManager
|
||||
{
|
||||
private const string ImageName = "ColorControl.UI.exe";
|
||||
private const string ProcessName = "ColorControl.UI";
|
||||
private const bool DebugUi = true;
|
||||
|
||||
private static bool FirsTime = true;
|
||||
private static Mutex UiMutex;
|
||||
private static string MutexId;
|
||||
|
||||
public static bool IsRunning(Config config)
|
||||
{
|
||||
return Process.GetProcessesByName(ProcessName).Length > 0 &&
|
||||
(config.UiPort == 0 || config.CurrentUiPort == config.UiPort) &&
|
||||
config.CurrentUiAllowRemoteConnections == config.UiAllowRemoteConnections;
|
||||
}
|
||||
|
||||
public static async Task<bool> Start(Config config)
|
||||
{
|
||||
if ((!FirsTime || Debugger.IsAttached && DebugUi) && IsRunning(config))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FirsTime = false;
|
||||
|
||||
await Stop();
|
||||
|
||||
var uiExe = Path.Combine(Environment.CurrentDirectory, ImageName);
|
||||
if (!File.Exists(uiExe))
|
||||
{
|
||||
uiExe = Path.Combine(Environment.CurrentDirectory.Replace("ColorControl\\bin", "ColorControl.UI\\bin"), ImageName);
|
||||
|
||||
if (!File.Exists(uiExe))
|
||||
{
|
||||
throw new InvalidOperationException("UI executable not found");
|
||||
}
|
||||
}
|
||||
|
||||
MutexId = $"Global\\{ProcessName}_{Guid.NewGuid()}";
|
||||
Utils.ExecuteOnMainThread(() =>
|
||||
{
|
||||
UiMutex = new Mutex(false, MutexId);
|
||||
UiMutex.WaitOne();
|
||||
});
|
||||
|
||||
var windowStyle = ProcessWindowStyle.Hidden;
|
||||
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
windowStyle = ProcessWindowStyle.Normal;
|
||||
}
|
||||
|
||||
var processStartInfo = new ProcessStartInfo(uiExe, [MutexId, config.UseDarkMode.ToString(), config.UiPort.ToString(), config.UiAllowRemoteConnections.ToString()])
|
||||
{
|
||||
WindowStyle = windowStyle
|
||||
};
|
||||
|
||||
Process.Start(processStartInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async Task Stop()
|
||||
{
|
||||
if (UiMutex != null)
|
||||
{
|
||||
Utils.ExecuteOnMainThread(() =>
|
||||
{
|
||||
UiMutex.ReleaseMutex();
|
||||
UiMutex.Close();
|
||||
UiMutex = null;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var processes = Process.GetProcessesByName(ProcessName);
|
||||
|
||||
if (processes.Length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var winApi = Program.ServiceProvider.GetRequiredService<WinApiAdminService>();
|
||||
winApi.StopProcessByName(ProcessName);
|
||||
}
|
||||
|
||||
public static string GetCurrentUrl(Config config)
|
||||
{
|
||||
var port = GetCurrentPort(config);
|
||||
|
||||
return $"http://localhost:{port}";
|
||||
}
|
||||
|
||||
public static int GetCurrentPort(Config config = null)
|
||||
{
|
||||
return config?.CurrentUiPort ?? -1;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
@@ -11,8 +11,8 @@
|
||||
<PublisherName>Maassoft</PublisherName>
|
||||
<Company>Maassoft</Company>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>10.4.0.0</ApplicationVersion>
|
||||
<Version>10.4.0.0</Version>
|
||||
<ApplicationVersion>11.0.0.0</ApplicationVersion>
|
||||
<Version>11.0.0.0</Version>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>false</BootstrapperEnabled>
|
||||
@@ -72,6 +72,7 @@
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Resources\LgRemotes.json" />
|
||||
<EmbeddedResource Include="Resources\LG_register_legacy.json" />
|
||||
<EmbeddedResource Include="Resources\LG_register.json" />
|
||||
<EmbeddedResource Include="Resources\RC_coords.txt" />
|
||||
<EmbeddedResource Include="Resources\LG_remote.jpg" />
|
||||
@@ -96,16 +97,14 @@
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="9.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.3.4" />
|
||||
<PackageReference Include="NStandard" Version="0.83.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.7" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3912.50" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="NLog" Version="6.1.2" />
|
||||
<PackageReference Include="NStandard" Version="0.110.7" />
|
||||
<PackageReference Include="NWin32" Version="1.2.8" />
|
||||
<PackageReference Include="System.Management" Version="9.0.0" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.11.0" />
|
||||
<PackageReference Include="System.Management" Version="10.0.7" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.12.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="XForms\ColorProfileWindow.xaml">
|
||||
|
||||
@@ -199,6 +199,11 @@ namespace LgTv
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
throw new InvalidOperationException("Empty response received. Assuming connection closed.");
|
||||
}
|
||||
|
||||
var obj = JsonConvert.DeserializeObject<dynamic>(message);
|
||||
var id = (string)obj.id;
|
||||
var type = (string)obj.type;
|
||||
@@ -217,7 +222,7 @@ namespace LgTv
|
||||
{
|
||||
if (id == "register_0")
|
||||
{
|
||||
//taskCompletion.TrySetResult(obj.payload);
|
||||
//taskCompletion.TrySetResult(null);
|
||||
return;
|
||||
}
|
||||
if (obj.type == "error")
|
||||
|
||||
@@ -177,6 +177,8 @@ internal class MainWorker
|
||||
|
||||
private void StartScreenSaver()
|
||||
{
|
||||
//NativeMethods.SendMessageW(-1, NativeConstants.WM_SYSCOMMAND, NativeConstants.SC_MONITORPOWER, (int)WinApi.MonitorState.OFF);
|
||||
|
||||
var screenSaver = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "scrnsave.scr");
|
||||
Process.Start("explorer.exe", screenSaver);
|
||||
}
|
||||
|
||||
+29
-22
@@ -12,7 +12,6 @@ using ColorControl.Shared.Forms;
|
||||
using ColorControl.Shared.Native;
|
||||
using ColorControl.Shared.Services;
|
||||
using ColorControl.Svc;
|
||||
using ColorControl.UI;
|
||||
using ColorControl.XForms;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
@@ -44,6 +43,7 @@ namespace ColorControl
|
||||
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
private static Mutex _mutex;
|
||||
public static string MutexId;
|
||||
public static MainForm _mainForm;
|
||||
private static LoggingRule _loggingRule;
|
||||
|
||||
@@ -96,11 +96,11 @@ namespace ColorControl
|
||||
Logger.Debug($"Result of setting SetHighDpiMode: {result}");
|
||||
}
|
||||
|
||||
var mutexId = $"Global\\{typeof(MainForm).GUID}";
|
||||
MutexId = $"Global\\{typeof(MainForm).GUID}";
|
||||
|
||||
var startUpParams = StartUpParams.Parse(args);
|
||||
|
||||
AppContext = new GlobalContext(Config, startUpParams, DataDir, _loggingRule, null, startTime, mutexId);
|
||||
AppContext = new GlobalContext(Config, startUpParams, DataDir, _loggingRule, null, startTime, MutexId);
|
||||
|
||||
var host = CreateHostBuilder().Build();
|
||||
ServiceProvider = host.Services;
|
||||
@@ -168,6 +168,8 @@ namespace ColorControl
|
||||
var winApiAdminService = ServiceProvider.GetRequiredService<WinApiAdminService>();
|
||||
winApiAdminService.StopService();
|
||||
}
|
||||
|
||||
await BlazorUiManager.Stop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -233,31 +235,43 @@ namespace ColorControl
|
||||
|
||||
public static async Task OpenNewUi()
|
||||
{
|
||||
if (await StartUiServer())
|
||||
{
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
var winApi = AppContext.ServiceProvider.GetRequiredService<WinApiAdminService>();
|
||||
|
||||
winApi.StartProcess(Blazor.GetCurrentUrl());
|
||||
await OpenNewUi(false);
|
||||
}
|
||||
|
||||
public static async Task OpenNewUiEmbedded()
|
||||
{
|
||||
await OpenNewUi(true);
|
||||
}
|
||||
|
||||
public static async Task OpenNewUi(bool embedded)
|
||||
{
|
||||
if (await StartUiServer())
|
||||
{
|
||||
await Task.Delay(500);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
BrowserWindow.CreateAndShow(Blazor.GetCurrentUrl());
|
||||
if (BlazorUiManager.GetCurrentPort(Config) <= 0)
|
||||
{
|
||||
await OpenMainForm();
|
||||
return;
|
||||
}
|
||||
|
||||
if (embedded)
|
||||
{
|
||||
BrowserWindow.CreateAndShow(BlazorUiManager.GetCurrentUrl(Config));
|
||||
}
|
||||
else
|
||||
{
|
||||
var winApi = AppContext.ServiceProvider.GetRequiredService<WinApiAdminService>();
|
||||
winApi.StartProcess(BlazorUiManager.GetCurrentUrl(Config));
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<bool> StartOrStopUiServer()
|
||||
{
|
||||
if (Config.UiType == UiType.WinForms)
|
||||
{
|
||||
var _ = Task.Run(() => UI.Blazor.Stop());
|
||||
var _ = Task.Run(() => BlazorUiManager.Stop());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -266,11 +280,6 @@ namespace ColorControl
|
||||
|
||||
public static async Task<bool> StartUiServer()
|
||||
{
|
||||
if (UI.Blazor.IsRunning(Config))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var backgroundService = ServiceProvider.GetRequiredService<ColorControlBackgroundService>();
|
||||
|
||||
if (backgroundService.PipeName != PipeUtils.MainPipe)
|
||||
@@ -280,9 +289,7 @@ namespace ColorControl
|
||||
await backgroundService.StartAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
var _ = Task.Run(() => UI.Blazor.Start(Config));
|
||||
|
||||
return true;
|
||||
return await BlazorUiManager.Start(Config);
|
||||
}
|
||||
|
||||
private static void InitLogger(bool runAsService, bool runElevated)
|
||||
|
||||
@@ -1,77 +1,69 @@
|
||||
{
|
||||
"type":"register",
|
||||
"id":"register_0",
|
||||
"payload":{
|
||||
"forcePairing":false,
|
||||
"pairingType":"PROMPT",
|
||||
"client-key":"CLIENTKEYGOESHERE",
|
||||
"manifest":{
|
||||
"manifestVersion":1,
|
||||
"appVersion":"1.1",
|
||||
"signed":{
|
||||
"created":"20140509",
|
||||
"appId":"com.lge.test",
|
||||
"vendorId":"com.lge",
|
||||
"localizedAppNames":{
|
||||
"":"LG Remote App",
|
||||
"ko-KR":"리모컨 앱",
|
||||
"zxx-XX":"ЛГ Rэмotэ AПП"
|
||||
},
|
||||
"localizedVendorNames":{
|
||||
"":"LG Electronics"
|
||||
},
|
||||
"permissions":[
|
||||
"TEST_SECURE",
|
||||
"CONTROL_INPUT_TEXT",
|
||||
"CONTROL_MOUSE_AND_KEYBOARD",
|
||||
"READ_INSTALLED_APPS",
|
||||
"READ_LGE_SDX",
|
||||
"READ_NOTIFICATIONS",
|
||||
"SEARCH",
|
||||
"WRITE_SETTINGS",
|
||||
"WRITE_NOTIFICATION_ALERT",
|
||||
"CONTROL_POWER",
|
||||
"READ_CURRENT_CHANNEL",
|
||||
"READ_RUNNING_APPS",
|
||||
"READ_UPDATE_INFO",
|
||||
"UPDATE_FROM_REMOTE_APP",
|
||||
"READ_LGE_TV_INPUT_EVENTS",
|
||||
"READ_TV_CURRENT_TIME"
|
||||
],
|
||||
"serial":"2f930e2d2cfe083771f68e4fe7bb07"
|
||||
},
|
||||
"permissions":[
|
||||
"LAUNCH",
|
||||
"LAUNCH_WEBAPP",
|
||||
"APP_TO_APP",
|
||||
"CLOSE",
|
||||
"TEST_OPEN",
|
||||
"TEST_PROTECTED",
|
||||
"CONTROL_AUDIO",
|
||||
"CONTROL_DISPLAY",
|
||||
"CONTROL_INPUT_JOYSTICK",
|
||||
"CONTROL_INPUT_MEDIA_RECORDING",
|
||||
"CONTROL_INPUT_MEDIA_PLAYBACK",
|
||||
"CONTROL_INPUT_TV",
|
||||
"CONTROL_POWER",
|
||||
"CONTROL_TV_SCREEN",
|
||||
"READ_APP_STATUS",
|
||||
"READ_CURRENT_CHANNEL",
|
||||
"READ_INPUT_DEVICE_LIST",
|
||||
"READ_NETWORK_STATE",
|
||||
"READ_RUNNING_APPS",
|
||||
"READ_TV_CHANNEL_LIST",
|
||||
"WRITE_NOTIFICATION_TOAST",
|
||||
"READ_POWER_STATE",
|
||||
"READ_COUNTRY_INFO",
|
||||
"READ_SETTINGS"
|
||||
],
|
||||
"signatures":[
|
||||
{
|
||||
"signatureVersion":1,
|
||||
"signature":"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw=="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"type": "register",
|
||||
"id": "register_0",
|
||||
"payload": {
|
||||
"forcePairing": false,
|
||||
"pairingType": "PROMPT",
|
||||
"client-key": "CLIENTKEYGOESHERE",
|
||||
"manifest": {
|
||||
"manifestVersion": 1,
|
||||
"appVersion": "1.0",
|
||||
"signed": {
|
||||
"appId": "com.colorcontrol.app",
|
||||
"created": "20260426",
|
||||
"localizedAppNames": {
|
||||
"": "ColorControl"
|
||||
},
|
||||
"localizedVendorNames": {
|
||||
"": "ColorControl"
|
||||
},
|
||||
"permissions": [
|
||||
"CONTROL_POWER",
|
||||
"READ_POWER_STATE",
|
||||
"READ_CURRENT_CHANNEL",
|
||||
"READ_RUNNING_APPS",
|
||||
"READ_NETWORK_STATE",
|
||||
"READ_INPUT_DEVICE_LIST",
|
||||
"READ_TV_CHANNEL_LIST",
|
||||
"READ_SETTINGS",
|
||||
"READ_COUNTRY_INFO",
|
||||
"WRITE_NOTIFICATION_TOAST",
|
||||
"CONTROL_AUDIO",
|
||||
"CONTROL_DISPLAY",
|
||||
"CONTROL_INPUT_JOYSTICK",
|
||||
"CONTROL_INPUT_MEDIA_PLAYBACK",
|
||||
"CONTROL_INPUT_TV",
|
||||
"CONTROL_TV_SCREEN",
|
||||
"LAUNCH",
|
||||
"LAUNCH_WEBAPP",
|
||||
"APP_TO_APP",
|
||||
"CLOSE"
|
||||
],
|
||||
"serial": "colorcontrol-webos26"
|
||||
},
|
||||
"permissions": [
|
||||
"LAUNCH",
|
||||
"LAUNCH_WEBAPP",
|
||||
"APP_TO_APP",
|
||||
"CLOSE",
|
||||
"CONTROL_AUDIO",
|
||||
"CONTROL_DISPLAY",
|
||||
"CONTROL_INPUT_JOYSTICK",
|
||||
"CONTROL_INPUT_MEDIA_PLAYBACK",
|
||||
"CONTROL_INPUT_TV",
|
||||
"CONTROL_POWER",
|
||||
"CONTROL_TV_SCREEN",
|
||||
"READ_APP_STATUS",
|
||||
"READ_CURRENT_CHANNEL",
|
||||
"READ_INPUT_DEVICE_LIST",
|
||||
"READ_NETWORK_STATE",
|
||||
"READ_RUNNING_APPS",
|
||||
"READ_TV_CHANNEL_LIST",
|
||||
"WRITE_NOTIFICATION_TOAST",
|
||||
"READ_POWER_STATE",
|
||||
"READ_COUNTRY_INFO",
|
||||
"READ_SETTINGS"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"type":"register",
|
||||
"id":"register_0",
|
||||
"payload":{
|
||||
"forcePairing":false,
|
||||
"pairingType":"PROMPT",
|
||||
"client-key":"CLIENTKEYGOESHERE",
|
||||
"manifest":{
|
||||
"manifestVersion":1,
|
||||
"appVersion":"1.1",
|
||||
"signed":{
|
||||
"created":"20140509",
|
||||
"appId":"com.lge.test",
|
||||
"vendorId":"com.lge",
|
||||
"localizedAppNames":{
|
||||
"":"LG Remote App",
|
||||
"ko-KR":"리모컨 앱",
|
||||
"zxx-XX":"ЛГ Rэмotэ AПП"
|
||||
},
|
||||
"localizedVendorNames":{
|
||||
"":"LG Electronics"
|
||||
},
|
||||
"permissions":[
|
||||
"TEST_SECURE",
|
||||
"CONTROL_INPUT_TEXT",
|
||||
"CONTROL_MOUSE_AND_KEYBOARD",
|
||||
"READ_INSTALLED_APPS",
|
||||
"READ_LGE_SDX",
|
||||
"READ_NOTIFICATIONS",
|
||||
"SEARCH",
|
||||
"WRITE_SETTINGS",
|
||||
"WRITE_NOTIFICATION_ALERT",
|
||||
"CONTROL_POWER",
|
||||
"READ_CURRENT_CHANNEL",
|
||||
"READ_RUNNING_APPS",
|
||||
"READ_UPDATE_INFO",
|
||||
"UPDATE_FROM_REMOTE_APP",
|
||||
"READ_LGE_TV_INPUT_EVENTS",
|
||||
"READ_TV_CURRENT_TIME"
|
||||
],
|
||||
"serial":"2f930e2d2cfe083771f68e4fe7bb07"
|
||||
},
|
||||
"permissions":[
|
||||
"LAUNCH",
|
||||
"LAUNCH_WEBAPP",
|
||||
"APP_TO_APP",
|
||||
"CLOSE",
|
||||
"TEST_OPEN",
|
||||
"TEST_PROTECTED",
|
||||
"CONTROL_AUDIO",
|
||||
"CONTROL_DISPLAY",
|
||||
"CONTROL_INPUT_JOYSTICK",
|
||||
"CONTROL_INPUT_MEDIA_RECORDING",
|
||||
"CONTROL_INPUT_MEDIA_PLAYBACK",
|
||||
"CONTROL_INPUT_TV",
|
||||
"CONTROL_POWER",
|
||||
"CONTROL_TV_SCREEN",
|
||||
"READ_APP_STATUS",
|
||||
"READ_CURRENT_CHANNEL",
|
||||
"READ_INPUT_DEVICE_LIST",
|
||||
"READ_NETWORK_STATE",
|
||||
"READ_RUNNING_APPS",
|
||||
"READ_TV_CHANNEL_LIST",
|
||||
"WRITE_NOTIFICATION_TOAST",
|
||||
"READ_POWER_STATE",
|
||||
"READ_COUNTRY_INFO",
|
||||
"READ_SETTINGS"
|
||||
],
|
||||
"signatures":[
|
||||
{
|
||||
"signatureVersion":1,
|
||||
"signature":"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw=="
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,6 +91,11 @@ abstract class GraphicsService<T> : ServiceBase<T> where T : PresetBase, new()
|
||||
currentDisplayConfig.Rotation = displayConfig.Rotation;
|
||||
}
|
||||
|
||||
if (displayConfig.Connectivity != DisplayConnectivity.Unchanged)
|
||||
{
|
||||
currentDisplayConfig.Connectivity = displayConfig.Connectivity;
|
||||
}
|
||||
|
||||
return CCD.SetDisplayConfig(displayName, currentDisplayConfig, updateRegistry);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.EventDispatcher;
|
||||
using ColorControl.Shared.Services;
|
||||
using ColorControl.UI;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -35,7 +34,7 @@ public class OptionsService
|
||||
public Config GetConfig()
|
||||
{
|
||||
_globalContext.Config.AutoStart = _winApiService.TaskExists(Program.TS_TASKNAME);
|
||||
_globalContext.Config.CurrentUiPort = Blazor.GetCurrentPort();
|
||||
_globalContext.Config.CurrentUiPort = BlazorUiManager.GetCurrentPort(Program.Config);
|
||||
|
||||
return _globalContext.Config;
|
||||
}
|
||||
@@ -51,6 +50,14 @@ public class OptionsService
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SetCurrentUiSettings(int port, bool allowRemoteConnections)
|
||||
{
|
||||
_globalContext.Config.CurrentUiPort = port;
|
||||
_globalContext.Config.CurrentUiAllowRemoteConnections = allowRemoteConnections;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SaveSettings()
|
||||
{
|
||||
_serviceManager.Save();
|
||||
|
||||
@@ -12,212 +12,212 @@ namespace ColorControl.Services.Common;
|
||||
|
||||
public class UpdateManager
|
||||
{
|
||||
private readonly GlobalContext _globalContext;
|
||||
private readonly ServiceManager _serviceManager;
|
||||
private readonly NotifyIconManager _notifyIconManager;
|
||||
private readonly WinApiService _winApiService;
|
||||
private readonly WinApiAdminService _winApiAdminService;
|
||||
private readonly Config _config;
|
||||
private readonly GlobalContext _globalContext;
|
||||
private readonly ServiceManager _serviceManager;
|
||||
private readonly NotifyIconManager _notifyIconManager;
|
||||
private readonly WinApiService _winApiService;
|
||||
private readonly WinApiAdminService _winApiAdminService;
|
||||
private readonly Config _config;
|
||||
|
||||
public UpdateManager(GlobalContext globalContext, ServiceManager serviceManager, NotifyIconManager notifyIconManager, WinApiService winApiService, WinApiAdminService winApiAdminService)
|
||||
{
|
||||
_globalContext = globalContext;
|
||||
_serviceManager = serviceManager;
|
||||
_notifyIconManager = notifyIconManager;
|
||||
_winApiService = winApiService;
|
||||
_winApiAdminService = winApiAdminService;
|
||||
_config = globalContext.Config;
|
||||
}
|
||||
public UpdateManager(GlobalContext globalContext, ServiceManager serviceManager, NotifyIconManager notifyIconManager, WinApiService winApiService, WinApiAdminService winApiAdminService)
|
||||
{
|
||||
_globalContext = globalContext;
|
||||
_serviceManager = serviceManager;
|
||||
_notifyIconManager = notifyIconManager;
|
||||
_winApiService = winApiService;
|
||||
_winApiAdminService = winApiAdminService;
|
||||
_config = globalContext.Config;
|
||||
}
|
||||
|
||||
private void trayIconBalloonTip_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (_globalContext.UpdateInfo?.HtmlUrl != null)
|
||||
{
|
||||
_winApiAdminService.StartProcess(_globalContext.UpdateInfo?.HtmlUrl);
|
||||
}
|
||||
}
|
||||
private void trayIconBalloonTip_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (_globalContext.UpdateInfo?.HtmlUrl != null)
|
||||
{
|
||||
_winApiAdminService.StartProcess(_globalContext.UpdateInfo?.HtmlUrl);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CheckForUpdatesAndInstall()
|
||||
{
|
||||
var updateInfo = await CheckForUpdates();
|
||||
public async Task CheckForUpdatesAndInstall()
|
||||
{
|
||||
var updateInfo = await CheckForUpdates();
|
||||
|
||||
if (!updateInfo.UpdateAvailable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!updateInfo.UpdateAvailable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_notifyIconManager.NotifyIcon.BalloonTipClicked += trayIconBalloonTip_Clicked;
|
||||
var newVersion = updateInfo.NewVersionNumber;
|
||||
_notifyIconManager.NotifyIcon.BalloonTipClicked += trayIconBalloonTip_Clicked;
|
||||
var newVersion = updateInfo.NewVersionNumber;
|
||||
|
||||
if (!string.IsNullOrEmpty(updateInfo.DownloadUrl) && _winApiService.IsServiceRunning())
|
||||
{
|
||||
if (_config.AutoInstallUpdates)
|
||||
{
|
||||
await InstallUpdate();
|
||||
if (!string.IsNullOrEmpty(updateInfo.DownloadUrl) && _winApiService.IsServiceRunning())
|
||||
{
|
||||
if (_config.AutoInstallUpdates)
|
||||
{
|
||||
await InstallUpdate();
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_notifyIconManager.NotifyIcon.Visible)
|
||||
{
|
||||
_notifyIconManager.NotifyIcon.ShowBalloonTip(5000, "Update available", $"Version {newVersion} is available. Click on the Update-button to update", ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageForms.InfoOk($"New version {newVersion} is available. Click on the Update-button to update", "Update available", $"https://github.com/Maassoft/ColorControl/releases/tag/v{newVersion}");
|
||||
}
|
||||
if (_notifyIconManager.NotifyIcon.Visible)
|
||||
{
|
||||
_notifyIconManager.NotifyIcon.ShowBalloonTip(5000, "Update available", $"Version {newVersion} is available. Click on the Update-button to update", ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageForms.InfoOk($"New version {newVersion} is available. Click on the Update-button to update", "Update available", $"https://github.com/Maassoft/ColorControl/releases/tag/v{newVersion}");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_notifyIconManager.NotifyIcon.Visible)
|
||||
{
|
||||
_notifyIconManager.NotifyIcon.ShowBalloonTip(5000, "Update available", $"Version {newVersion} is available. Click to open the GitHub page", ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageForms.InfoOk($"New version {newVersion} is available. Click on the Help-button to open the GitHub page.", "Update available", $"https://github.com/Maassoft/ColorControl/releases/tag/v{newVersion}");
|
||||
}
|
||||
}
|
||||
if (_notifyIconManager.NotifyIcon.Visible)
|
||||
{
|
||||
_notifyIconManager.NotifyIcon.ShowBalloonTip(5000, "Update available", $"Version {newVersion} is available. Click to open the GitHub page", ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageForms.InfoOk($"New version {newVersion} is available. Click on the Help-button to open the GitHub page.", "Update available", $"https://github.com/Maassoft/ColorControl/releases/tag/v{newVersion}");
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateAvailable() => _globalContext.UpdateInfo?.UpdateAvailable == true;
|
||||
public bool UpdateAvailable() => _globalContext.UpdateInfo?.UpdateAvailable == true;
|
||||
|
||||
public async Task<UpdateInfoDto> CheckForUpdates()
|
||||
{
|
||||
if (_globalContext.UpdateInfo != null)
|
||||
{
|
||||
return _globalContext.UpdateInfo;
|
||||
}
|
||||
public async Task<UpdateInfoDto> CheckForUpdates()
|
||||
{
|
||||
if (_globalContext.UpdateInfo != null)
|
||||
{
|
||||
return _globalContext.UpdateInfo;
|
||||
}
|
||||
|
||||
//if (Debugger.IsAttached)
|
||||
//{
|
||||
// return _globalContext.UpdateInfo = new UpdateInfoDto
|
||||
// {
|
||||
// UpdateAvailable = true,
|
||||
// NewVersionNumber = "10.0.0.2",
|
||||
// DownloadUrl = "http://testurl"
|
||||
// };
|
||||
//}
|
||||
//if (Debugger.IsAttached)
|
||||
//{
|
||||
// return _globalContext.UpdateInfo = new UpdateInfoDto
|
||||
// {
|
||||
// UpdateAvailable = true,
|
||||
// NewVersionNumber = "10.0.0.2",
|
||||
// DownloadUrl = "http://testurl"
|
||||
// };
|
||||
//}
|
||||
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
return new UpdateInfoDto();
|
||||
}
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
return new UpdateInfoDto();
|
||||
}
|
||||
|
||||
var json = await Utils.GetRestJsonAsync("https://api.github.com/repos/maassoft/colorcontrol/releases/latest");
|
||||
var json = await Utils.GetRestJsonAsync("https://api.github.com/repos/maassoft/colorcontrol/releases/latest");
|
||||
|
||||
if (json == null)
|
||||
{
|
||||
return new UpdateInfoDto();
|
||||
}
|
||||
if (json == null)
|
||||
{
|
||||
return new UpdateInfoDto();
|
||||
}
|
||||
|
||||
_globalContext.UpdateInfo = GetUpdateInfo(json);
|
||||
_globalContext.UpdateInfo = GetUpdateInfo(json);
|
||||
|
||||
return _globalContext.UpdateInfo;
|
||||
}
|
||||
return _globalContext.UpdateInfo;
|
||||
}
|
||||
|
||||
private static UpdateInfoDto GetUpdateInfo(dynamic json)
|
||||
{
|
||||
var updateInfo = new UpdateInfoDto();
|
||||
private static UpdateInfoDto GetUpdateInfo(dynamic json)
|
||||
{
|
||||
var updateInfo = new UpdateInfoDto();
|
||||
|
||||
if (json?.tag_name == null)
|
||||
{
|
||||
return updateInfo;
|
||||
}
|
||||
if (json?.tag_name == null)
|
||||
{
|
||||
return updateInfo;
|
||||
}
|
||||
|
||||
var currentVersion = Application.ProductVersion;
|
||||
var cvParts = currentVersion.Split(".");
|
||||
var currentVersion = Application.ProductVersion;
|
||||
var cvParts = currentVersion.Split(".");
|
||||
|
||||
var newVersion = (string)json.tag_name.Value.Substring(1);
|
||||
var nvParts = newVersion.Split(".");
|
||||
var newVersion = (string)json.tag_name.Value.Substring(1);
|
||||
var nvParts = newVersion.Split(".");
|
||||
|
||||
bool CompareVersions()
|
||||
{
|
||||
var result = true;
|
||||
var aNumberIsLarger = false;
|
||||
bool CompareVersions()
|
||||
{
|
||||
var result = true;
|
||||
var aNumberIsLarger = false;
|
||||
|
||||
for (var i = 0; i < nvParts.Length; i++)
|
||||
{
|
||||
var part = Utils.ParseInt(nvParts[i]);
|
||||
var cvPart = Utils.ParseInt(cvParts[i]);
|
||||
for (var i = 0; i < nvParts.Length; i++)
|
||||
{
|
||||
var part = Utils.ParseInt(nvParts[i]);
|
||||
var cvPart = Utils.ParseInt(cvParts[i]);
|
||||
|
||||
if (part > cvPart)
|
||||
{
|
||||
aNumberIsLarger = true;
|
||||
break;
|
||||
}
|
||||
if (part > cvPart)
|
||||
{
|
||||
aNumberIsLarger = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (part == cvPart)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (part == cvPart)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return result && aNumberIsLarger;
|
||||
}
|
||||
return result && aNumberIsLarger;
|
||||
}
|
||||
|
||||
updateInfo.NewVersionNumber = newVersion;
|
||||
updateInfo.UpdateAvailable = nvParts.Length != cvParts.Length || CompareVersions();
|
||||
updateInfo.NewVersionNumber = newVersion;
|
||||
updateInfo.UpdateAvailable = nvParts.Length != cvParts.Length || CompareVersions();
|
||||
|
||||
updateInfo.HtmlUrl = json.html_url.Value;
|
||||
updateInfo.HtmlUrl = json.html_url.Value;
|
||||
|
||||
if (json.assets != null)
|
||||
{
|
||||
var asset = json.assets[0];
|
||||
updateInfo.DownloadUrl = asset.browser_download_url.Value;
|
||||
}
|
||||
if (json.assets != null)
|
||||
{
|
||||
var asset = json.assets[0];
|
||||
updateInfo.DownloadUrl = asset.browser_download_url.Value;
|
||||
}
|
||||
|
||||
return updateInfo;
|
||||
}
|
||||
return updateInfo;
|
||||
}
|
||||
|
||||
public async Task<bool> InstallUpdate()
|
||||
{
|
||||
if (_globalContext.UpdateInfo?.DownloadUrl == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public async Task<bool> InstallUpdate()
|
||||
{
|
||||
if (_globalContext.UpdateInfo?.DownloadUrl == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
return true;
|
||||
}
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
return true;
|
||||
}
|
||||
|
||||
var message = new SvcInstallUpdateMessage
|
||||
{
|
||||
DownloadUrl = _globalContext.UpdateInfo?.DownloadUrl,
|
||||
ClientPath = new FileInfo(Application.ExecutablePath).Directory.FullName
|
||||
};
|
||||
var message = new SvcInstallUpdateMessage
|
||||
{
|
||||
DownloadUrl = _globalContext.UpdateInfo?.DownloadUrl,
|
||||
ClientPath = new FileInfo(Application.ExecutablePath).Directory.FullName
|
||||
};
|
||||
|
||||
var result = await PipeUtils.SendMessageAsync(message, 30000);
|
||||
var result = await PipeUtils.SendMessageAsync(message, 30000);
|
||||
|
||||
if (result != null && !result.Result)
|
||||
{
|
||||
if (Program.IsMainFormOpened())
|
||||
{
|
||||
MessageForms.ErrorOk($"Error while updating: {result.ErrorMessage}");
|
||||
}
|
||||
if (result != null && !result.Result)
|
||||
{
|
||||
if (Program.IsMainFormOpened())
|
||||
{
|
||||
MessageForms.ErrorOk($"Error while updating: {result.ErrorMessage}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
await PipeUtils.SendMessageAsync(SvcMessageType.RestartAfterUpdate);
|
||||
await PipeUtils.SendMessageAsync(SvcMessageType.RestartAfterUpdate);
|
||||
|
||||
if (Program.IsMainFormOpened() && MessageForms.QuestionYesNo("Update installed successfully. Do you want to restart the application?") == DialogResult.Yes)
|
||||
{
|
||||
Program.Restart();
|
||||
}
|
||||
if (Program.IsMainFormOpened() && MessageForms.QuestionYesNo("Update installed successfully. Do you want to restart the application?") == DialogResult.Yes)
|
||||
{
|
||||
Program.Restart();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Task<bool> RestartAfterUpdate()
|
||||
{
|
||||
Program.Restart();
|
||||
public Task<bool> RestartAfterUpdate()
|
||||
{
|
||||
Program.Restart();
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
@@ -337,7 +337,7 @@ namespace ColorControl.Services.GameLauncher
|
||||
|
||||
public string SelectPath()
|
||||
{
|
||||
var fileInfo = Utils.SelectFile();
|
||||
var fileInfo = Utils.SelectFileFromNonUiThread(_globalContext.SynchronizationContext);
|
||||
|
||||
if (fileInfo == null)
|
||||
{
|
||||
|
||||
@@ -107,6 +107,8 @@ namespace ColorControl.Services.LG
|
||||
|
||||
public bool UseSecureConnection { get; set; } = true;
|
||||
|
||||
public bool UseNewHandshake { get; set; }
|
||||
|
||||
private List<string> _actionsForGameBar;
|
||||
|
||||
public List<string> ActionsOnGameBar
|
||||
@@ -311,6 +313,7 @@ namespace ColorControl.Services.LG
|
||||
private void UpdateOptions(LgDeviceOptions options)
|
||||
{
|
||||
UseSecureConnection = options.UseSecureConnection;
|
||||
UseNewHandshake = options.UseNewHandshake;
|
||||
TurnScreenOffOnScreenSaver = options.TurnScreenOffOnScreenSaver;
|
||||
TurnScreenOnAfterScreenSaver = options.TurnScreenOnAfterScreenSaver;
|
||||
ScreenSaverMinimalDuration = options.ScreenSaverMinimalDuration;
|
||||
@@ -501,7 +504,7 @@ namespace ColorControl.Services.LG
|
||||
try
|
||||
{
|
||||
await DisposeConnection();
|
||||
_lgTvApi = await LgTvApi.CreateLgTvApi(IpAddress, retries, UseSecureConnection);
|
||||
_lgTvApi = await LgTvApi.CreateLgTvApi(IpAddress, retries, UseSecureConnection, UseNewHandshake);
|
||||
|
||||
//Test();
|
||||
//_lgTvApi.Test3();
|
||||
|
||||
+7
-7
@@ -179,7 +179,7 @@
|
||||
lblLgPresetConnectedDisplaysRegex.Location = new System.Drawing.Point(475, 404);
|
||||
lblLgPresetConnectedDisplaysRegex.Margin = new System.Windows.Forms.Padding(6, 0, 6, 0);
|
||||
lblLgPresetConnectedDisplaysRegex.Name = "lblLgPresetConnectedDisplaysRegex";
|
||||
lblLgPresetConnectedDisplaysRegex.Size = new System.Drawing.Size(149, 15);
|
||||
lblLgPresetConnectedDisplaysRegex.Size = new System.Drawing.Size(148, 15);
|
||||
lblLgPresetConnectedDisplaysRegex.TabIndex = 67;
|
||||
lblLgPresetConnectedDisplaysRegex.Text = "Connected Displays Regex:";
|
||||
//
|
||||
@@ -330,7 +330,7 @@
|
||||
lblLgPresetExcludedProcesses.Location = new System.Drawing.Point(475, 370);
|
||||
lblLgPresetExcludedProcesses.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblLgPresetExcludedProcesses.Name = "lblLgPresetExcludedProcesses";
|
||||
lblLgPresetExcludedProcesses.Size = new System.Drawing.Size(112, 15);
|
||||
lblLgPresetExcludedProcesses.Size = new System.Drawing.Size(111, 15);
|
||||
lblLgPresetExcludedProcesses.TabIndex = 52;
|
||||
lblLgPresetExcludedProcesses.Text = "Excluded processes:";
|
||||
//
|
||||
@@ -395,7 +395,7 @@
|
||||
lblLgPresetTrigger.Location = new System.Drawing.Point(475, 277);
|
||||
lblLgPresetTrigger.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblLgPresetTrigger.Name = "lblLgPresetTrigger";
|
||||
lblLgPresetTrigger.Size = new System.Drawing.Size(46, 15);
|
||||
lblLgPresetTrigger.Size = new System.Drawing.Size(47, 15);
|
||||
lblLgPresetTrigger.TabIndex = 45;
|
||||
lblLgPresetTrigger.Text = "Trigger:";
|
||||
//
|
||||
@@ -834,7 +834,7 @@
|
||||
clbLgPower.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
clbLgPower.ColumnWidth = 240;
|
||||
clbLgPower.FormattingEnabled = true;
|
||||
clbLgPower.Items.AddRange(new object[] { "Power on after startup", "Power on after resume from standby", "Power off on shutdown", "Power off on standby", "Power off when screensaver activates", "Power on when screensaver deactivates", "Power on even after manual power off", "Allow triggers to be fired for this device", "Use Windows power settings to power on", "Use Windows power settings to power off", "Power off when locking the pc", "Power on when unlocking the pc", "Use secure connection" });
|
||||
clbLgPower.Items.AddRange(new object[] { "Power on after startup", "Power on after resume from standby", "Power off on shutdown", "Power off on standby", "Power off when screensaver activates", "Power on when screensaver deactivates", "Power on even after manual power off", "Allow triggers to be fired for this device", "Use Windows power settings to power on", "Use Windows power settings to power off", "Power off when locking the pc", "Power on when unlocking the pc", "Use secure connection", "Enable webOS 26 compatibility" });
|
||||
clbLgPower.Location = new System.Drawing.Point(6, 70);
|
||||
clbLgPower.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
clbLgPower.MultiColumn = true;
|
||||
@@ -860,19 +860,19 @@
|
||||
mnuLgSettings.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
mnuLgSettings.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miTestPowerOffOn, miNvSettings });
|
||||
mnuLgSettings.Name = "mnuLgButtons";
|
||||
mnuLgSettings.Size = new System.Drawing.Size(168, 48);
|
||||
mnuLgSettings.Size = new System.Drawing.Size(169, 48);
|
||||
//
|
||||
// miTestPowerOffOn
|
||||
//
|
||||
miTestPowerOffOn.Name = "miTestPowerOffOn";
|
||||
miTestPowerOffOn.Size = new System.Drawing.Size(167, 22);
|
||||
miTestPowerOffOn.Size = new System.Drawing.Size(168, 22);
|
||||
miTestPowerOffOn.Text = "Test power off/on";
|
||||
miTestPowerOffOn.Click += miTestPowerOffOn_Click;
|
||||
//
|
||||
// miNvSettings
|
||||
//
|
||||
miNvSettings.Name = "miNvSettings";
|
||||
miNvSettings.Size = new System.Drawing.Size(167, 22);
|
||||
miNvSettings.Size = new System.Drawing.Size(168, 22);
|
||||
miNvSettings.Text = "Settings";
|
||||
miNvSettings.Click += miNvSettings_Click;
|
||||
//
|
||||
|
||||
@@ -321,11 +321,11 @@ namespace ColorControl.Services.LG
|
||||
|
||||
FormUtils.BuildComboBox(cbxLgPresetTrigger, PresetTriggerType.Reserved5);
|
||||
|
||||
if (!string.IsNullOrEmpty(_lgTabMessage))
|
||||
{
|
||||
MessageForms.WarningOk(_lgTabMessage);
|
||||
_lgTabMessage = null;
|
||||
}
|
||||
//if (!string.IsNullOrEmpty(_lgTabMessage))
|
||||
//{
|
||||
// MessageForms.WarningOk(_lgTabMessage);
|
||||
// _lgTabMessage = null;
|
||||
//}
|
||||
}
|
||||
|
||||
private void FillLgDevices()
|
||||
@@ -349,16 +349,7 @@ namespace ColorControl.Services.LG
|
||||
|
||||
if (!devices.Any())
|
||||
{
|
||||
var message = "It seems there's no LG TV available! Please make sure it's connected to the same network as this PC.";
|
||||
|
||||
if (Visible /*tcMain.SelectedTab == tabLG*/)
|
||||
{
|
||||
MessageForms.WarningOk(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lgTabMessage = message;
|
||||
}
|
||||
_lgTabMessage = "It seems there's no LG TV available! Please make sure it's connected to the same network as this PC.";
|
||||
}
|
||||
|
||||
if (cbxLgApps.Items.Count == 0 && device != null)
|
||||
@@ -396,6 +387,7 @@ namespace ColorControl.Services.LG
|
||||
clbLgPower.SetItemChecked(10, device?.PowerOffAfterSessionLock ?? false);
|
||||
clbLgPower.SetItemChecked(11, device?.PowerOnAfterSessionUnlock ?? false);
|
||||
clbLgPower.SetItemChecked(12, device?.UseSecureConnection ?? false);
|
||||
clbLgPower.SetItemChecked(13, device?.UseNewHandshake ?? false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -674,6 +666,7 @@ You can also activate this option by using the Expert-button and selecting Wake-
|
||||
device.PowerOffAfterSessionLock = clbLgPower.GetItemChecked(10);
|
||||
device.PowerOnAfterSessionUnlock = clbLgPower.GetItemChecked(11);
|
||||
device.UseSecureConnection = clbLgPower.GetItemChecked(12);
|
||||
device.UseNewHandshake = clbLgPower.GetItemChecked(13);
|
||||
|
||||
if (e.Index == 12)
|
||||
{
|
||||
|
||||
@@ -1174,7 +1174,8 @@ namespace ColorControl.Services.LG
|
||||
TriggersEnabled = d.TriggersEnabled,
|
||||
TurnScreenOffOnScreenSaver = d.TurnScreenOffOnScreenSaver,
|
||||
TurnScreenOnAfterScreenSaver = d.TurnScreenOnAfterScreenSaver,
|
||||
UseSecureConnection = d.UseSecureConnection
|
||||
UseSecureConnection = d.UseSecureConnection,
|
||||
UseNewHandshake = d.UseNewHandshake,
|
||||
},
|
||||
IsConnected = d.IsConnected(),
|
||||
IsSelected = d == SelectedDevice
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
public string DisplayId { get; private set; }
|
||||
public string DisplayId { get; set; }
|
||||
|
||||
public NvDisplayInfo(Display display, List<string> values, string infoLine, string name = null)
|
||||
{
|
||||
|
||||
@@ -1214,7 +1214,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
|
||||
if (preset.IsDisplayPreset)
|
||||
{
|
||||
_nvService.SetHDRState(preset.Display, !_nvService.IsHDREnabled());
|
||||
_nvService.SetHDRState(preset.Display, !NvService.IsHDREnabled(preset.Display));
|
||||
|
||||
UpdateDisplayInfoItems();
|
||||
return;
|
||||
|
||||
@@ -235,7 +235,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
}
|
||||
}
|
||||
|
||||
public Display GetCurrentDisplay(bool checkDisplays = true)
|
||||
public Display GetCurrentDisplay(bool checkDisplays = true, bool useFirstIfNoneSet = true)
|
||||
{
|
||||
if (checkDisplays && !HasDisplaysAttached())
|
||||
{
|
||||
@@ -243,7 +243,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_currentDisplay == null)
|
||||
if (_currentDisplay == null && useFirstIfNoneSet)
|
||||
{
|
||||
_currentDisplay = Display.GetDisplays()[0];
|
||||
}
|
||||
@@ -396,7 +396,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
|
||||
var display = await WaitForDisplayAsync(preset);
|
||||
|
||||
if (display == null)
|
||||
if (display == null && preset.DisplayConfig.Connectivity != DisplayConnectivity.Enabled)
|
||||
{
|
||||
var error = $"Cannot apply preset {preset.IdOrName} because the associated display is not active/found";
|
||||
|
||||
@@ -405,6 +405,9 @@ namespace ColorControl.Services.NVIDIA
|
||||
return GenericBoolResult.FromError(error);
|
||||
}
|
||||
|
||||
//ReadDDC(display);
|
||||
//WriteDDC(display, 0, 0);
|
||||
|
||||
if (preset.DdcSettings.ApplyDdc)
|
||||
{
|
||||
var ddcResult = await ApplyDdcSettings(display, preset.DdcSettings);
|
||||
@@ -414,7 +417,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
}
|
||||
}
|
||||
|
||||
var hdrEnabled = IsHDREnabled();
|
||||
var hdrEnabled = IsHDREnabled(display);
|
||||
|
||||
var newHdrEnabled = preset.applyHDR && (preset.HDREnabled || (preset.toggleHDR && !hdrEnabled));
|
||||
var applyHdr = preset.applyHDR && (preset.toggleHDR || preset.HDREnabled != hdrEnabled);
|
||||
@@ -427,11 +430,14 @@ namespace ColorControl.Services.NVIDIA
|
||||
if ((preset.DisplayConfig.ApplyRefreshRate && preset.DisplayConfig.RefreshRate.MilliValue < timing.Extra.FrequencyInMillihertz) ||
|
||||
(preset.DisplayConfig.ApplyResolution && preset.DisplayConfig.Resolution.ActiveWidth < timing.HorizontalVisible))
|
||||
{
|
||||
SetMode(preset.DisplayConfig, true);
|
||||
SetMode(preset.DisplayConfig, true, displayId: preset.DisplayId);
|
||||
}
|
||||
}
|
||||
|
||||
SetColorData(display, preset.colorData);
|
||||
if (!SetColorData(display, preset.colorData))
|
||||
{
|
||||
result.AddError("Could not apply color settings");
|
||||
}
|
||||
}
|
||||
|
||||
if (preset.applyHDR)
|
||||
@@ -457,9 +463,9 @@ namespace ColorControl.Services.NVIDIA
|
||||
}
|
||||
}
|
||||
|
||||
if (preset.DisplayConfig.ApplyRefreshRate || preset.DisplayConfig.ApplyResolution)
|
||||
if (preset.DisplayConfig.ApplyRefreshRate || preset.DisplayConfig.ApplyResolution || preset.DisplayConfig.IsPrimary != null || preset.DisplayConfig.Connectivity != DisplayConnectivity.Unchanged)
|
||||
{
|
||||
if (!SetMode(preset.DisplayConfig, true))
|
||||
if (!SetMode(preset.DisplayConfig, true, displayId: preset.DisplayId))
|
||||
{
|
||||
result.AddError(WinError.GetMessage());
|
||||
}
|
||||
@@ -531,6 +537,8 @@ namespace ColorControl.Services.NVIDIA
|
||||
PresetApplied();
|
||||
GetDisplayInfos(false);
|
||||
|
||||
_currentDisplay = null;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1068,15 +1076,15 @@ namespace ColorControl.Services.NVIDIA
|
||||
return SetMode(display.Name, resolution, refreshRate, updateRegistry);
|
||||
}
|
||||
|
||||
public bool SetMode(DisplayConfig displayConfig, bool updateRegistry = false, NvPreset preset = null)
|
||||
public bool SetMode(DisplayConfig displayConfig, bool updateRegistry = false, NvPreset preset = null, string displayId = null)
|
||||
{
|
||||
var display = preset == null ? GetCurrentDisplay() : GetPresetDisplay(preset);
|
||||
if (display == null)
|
||||
var display = preset == null ? GetCurrentDisplay(useFirstIfNoneSet: false) : GetPresetDisplay(preset);
|
||||
if (display == null && displayId == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return SetMode(display.Name, displayConfig, updateRegistry);
|
||||
return SetMode(display?.Name ?? displayId, displayConfig, updateRegistry);
|
||||
}
|
||||
|
||||
public List<Rational> GetAvailableRefreshRatesV2(NvPreset preset = null)
|
||||
@@ -1141,9 +1149,8 @@ namespace ColorControl.Services.NVIDIA
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsHDREnabled(Display currentDisplay = null)
|
||||
public static bool IsHDREnabled(Display display)
|
||||
{
|
||||
var display = currentDisplay ?? GetCurrentDisplay();
|
||||
if (display == null)
|
||||
{
|
||||
return false;
|
||||
@@ -1325,29 +1332,54 @@ namespace ColorControl.Services.NVIDIA
|
||||
CCD.SetDisplayDefaultColorProfile(display.Name, name, _globalContext.Config.SetMinTmlAndMaxTml, IsHDREnabled(display));
|
||||
}
|
||||
|
||||
//public void WriteDDC(Display display, byte vcpCode, uint value)
|
||||
//{
|
||||
// if (display == null)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
public void ReadDDC(Display display)
|
||||
{
|
||||
if (display == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// byte i2cDeviceAddr = 0x37;
|
||||
byte i2cDeviceAddr = 0x37;
|
||||
|
||||
// //short value = 8704;
|
||||
//short value = 8704;
|
||||
|
||||
// //var data = new byte[] { 0x84, 0x03, 0x10, 0x00, 0x64, 0xDD };
|
||||
// //var data = new byte[] { 0x84, 0x03, 0x15, 0x00, 0x2D, 0xDD };
|
||||
// var value1 = (byte)(value >> 8);
|
||||
// var value2 = (byte)(value & 0xFF);
|
||||
// var data = new byte[] { 0x84, 0x03, vcpCode, value1, value2, 0xDD };
|
||||
//var data = new byte[] { 0x84, 0x03, 0x10, 0x00, 0x64, 0xDD };
|
||||
//var data = new byte[] { 0x84, 0x03, 0x15, 0x00, 0x2D, 0xDD };
|
||||
|
||||
// I2CInfoV3.FillDDCCIChecksum((byte)(i2cDeviceAddr << 1), [0x51], data);
|
||||
var info = new I2CInfoV2(display.Output.OutputId, true, i2cDeviceAddr, [0x51], 256);
|
||||
|
||||
// var info = new I2CInfoV2(display.Output.OutputId, true, i2cDeviceAddr, [0x51], data);
|
||||
var data = display.DisplayDevice.PhysicalGPU.ReadI2C(info);
|
||||
|
||||
// display.DisplayDevice.PhysicalGPU.WriteI2C(info);
|
||||
//}
|
||||
File.WriteAllBytes($"d:\\ddc\\lg_data.dat", data);
|
||||
}
|
||||
|
||||
public void WriteDDC(Display display, byte vcpCode, uint value)
|
||||
{
|
||||
if (display == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Switch input
|
||||
vcpCode = 0xF4;
|
||||
value = 0x91;
|
||||
|
||||
byte i2cDeviceAddr = 0x37;
|
||||
|
||||
//short value = 8704;
|
||||
|
||||
//var data = new byte[] { 0x84, 0x03, 0x10, 0x00, 0x64, 0xDD };
|
||||
//var data = new byte[] { 0x84, 0x03, 0x15, 0x00, 0x2D, 0xDD };
|
||||
var value1 = (byte)(value >> 8);
|
||||
var value2 = (byte)(value & 0xFF);
|
||||
var data = new byte[] { 0x84, 0x03, vcpCode, value1, value2, 0xDD };
|
||||
|
||||
I2CInfoV3.FillDDCCIChecksum((byte)(i2cDeviceAddr << 1), [0x50], data);
|
||||
|
||||
var info = new I2CInfoV2(display.Output.OutputId, true, i2cDeviceAddr, [0x50], data);
|
||||
|
||||
display.DisplayDevice.PhysicalGPU.WriteI2C(info);
|
||||
}
|
||||
|
||||
public GenericResult<VcpInfo> GetVcpInfo(string displayId, byte vcpCode)
|
||||
{
|
||||
@@ -1518,6 +1550,16 @@ namespace ColorControl.Services.NVIDIA
|
||||
list.Add(displayInfo);
|
||||
}
|
||||
|
||||
//foreach (var display in WindowsDisplayAPI.UnAttachedDisplay.GetUnAttachedDisplays())
|
||||
//{
|
||||
// var displayInfo = new NvDisplayInfo(null, null, null, display.DeviceName)
|
||||
// {
|
||||
// DisplayId = CCD.GetDisplayIdByPath(display.DevicePath)
|
||||
// };
|
||||
|
||||
// list.Add(displayInfo);
|
||||
//}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -1537,6 +1579,12 @@ namespace ColorControl.Services.NVIDIA
|
||||
foreach (var displayInfo in displayInfos)
|
||||
{
|
||||
var preset = GetPresetForDisplay(displayInfo, true, displayInfos.Count());
|
||||
|
||||
if (preset == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var values = preset.GetDisplayValues(_globalContext.Config);
|
||||
|
||||
displayInfo.Values = values;
|
||||
@@ -1574,8 +1622,11 @@ namespace ColorControl.Services.NVIDIA
|
||||
foreach (var displayInfo in displayInfos)
|
||||
{
|
||||
var preset = GetPresetForDisplay(displayInfo, true, displayInfos.Count());
|
||||
preset.MonitorConnectionType = preset?.Display?.DisplayDevice?.ConnectionType ?? NvAPIWrapper.Native.GPU.MonitorConnectionType.Unknown;
|
||||
list.Add(preset);
|
||||
if (preset != null)
|
||||
{
|
||||
preset.MonitorConnectionType = preset?.Display?.DisplayDevice?.ConnectionType ?? NvAPIWrapper.Native.GPU.MonitorConnectionType.Unknown;
|
||||
list.Add(preset);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -1604,6 +1655,11 @@ namespace ColorControl.Services.NVIDIA
|
||||
|
||||
var display = displayInfo.Display;
|
||||
|
||||
if (display == null)
|
||||
{
|
||||
return new NvPreset { displayName = displayInfo.Name, DisplayId = displayInfo.DisplayId };
|
||||
}
|
||||
|
||||
var isPrimaryDisplay = displayCount == 1 || display.DisplayDevice.DisplayId == DisplayDevice.GetGDIPrimaryDisplayDevice()?.DisplayId;
|
||||
var preset = new NvPreset { Display = display, IsDisplayPreset = true, applyColorData = false, primaryDisplay = isPrimaryDisplay };
|
||||
|
||||
|
||||
@@ -813,7 +813,7 @@ namespace ColorControl.Services.Samsung
|
||||
new FieldDefinition
|
||||
{
|
||||
Label = "Service Menu - Advanced",
|
||||
SubLabel = "If the service menu opened and you want to access the Advanced settings, click 'Next >' or click 'X' to skip",
|
||||
SubLabel = "If the service menu opened and you want to access the Advanced settings, manually navigate to 'Advanced' first and then click 'Next >' or click 'X' to skip. You can also manually enter the unlock codes 0098 (for TV's) and 0038 (for monitors) while the 'Advanced' item is highlighted.",
|
||||
FieldType = FieldType.Label
|
||||
} }, okButtonText: "Next >");
|
||||
|
||||
|
||||
@@ -328,11 +328,11 @@ namespace ColorControl.Services.Samsung
|
||||
|
||||
FormUtils.BuildComboBox(cbxSamsungPresetTrigger, PresetTriggerType.Reserved5);
|
||||
|
||||
if (!string.IsNullOrEmpty(_tabMessage))
|
||||
{
|
||||
MessageForms.WarningOk(_tabMessage);
|
||||
_tabMessage = null;
|
||||
}
|
||||
//if (!string.IsNullOrEmpty(_tabMessage))
|
||||
//{
|
||||
// MessageForms.WarningOk(_tabMessage);
|
||||
// _tabMessage = null;
|
||||
//}
|
||||
}
|
||||
|
||||
private void FillSamsungDevices()
|
||||
@@ -361,16 +361,7 @@ namespace ColorControl.Services.Samsung
|
||||
|
||||
if (!devices.Any())
|
||||
{
|
||||
var message = "It seems there's no Samsung TV available! Please make sure it's connected to the same network as this PC.";
|
||||
|
||||
if (Visible)
|
||||
{
|
||||
MessageForms.WarningOk(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tabMessage = message;
|
||||
}
|
||||
_tabMessage = "It seems there's no Samsung TV available! Please make sure it's connected to the same network as this PC.";
|
||||
}
|
||||
|
||||
//if (cbxSamsungApps.Items.Count == 0 && device != null)
|
||||
|
||||
@@ -88,9 +88,19 @@ namespace ColorControl.Svc
|
||||
{
|
||||
Logger.Error(ex, $"Error while handling message: {message}");
|
||||
|
||||
var result = SvcResultMessage.FromResult(false, ex.Message);
|
||||
var resultJson = JsonConvert.SerializeObject(result);
|
||||
ss.WriteString(resultJson);
|
||||
if (!ex.Message.Contains("Pipe is broken"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = SvcResultMessage.FromResult(false, ex.Message);
|
||||
var resultJson = JsonConvert.SerializeObject(result);
|
||||
ss.WriteString(resultJson);
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
Logger.Error(ex2, $"Error while sending error message: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pipeServer.Close();
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
d:DesignHeight="720" d:DesignWidth="1280" Loaded="Window_Loaded">
|
||||
<DockPanel>
|
||||
<wv2:WebView2 Name="webView" DefaultBackgroundColor="#212529"
|
||||
Source="{Binding Url}" NavigationStarting="webView_NavigationStarting"/>
|
||||
Source="{Binding Url}" NavigationStarting="webView_NavigationStarting" NavigationCompleted="webView_NavigationCompleted"/>
|
||||
</DockPanel>
|
||||
</src:BaseWindow>
|
||||
@@ -1,6 +1,5 @@
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.XForms;
|
||||
using ColorControl.UI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
@@ -46,16 +45,22 @@ public partial class BrowserWindow : BaseWindow
|
||||
|
||||
var reload = _window != null && _window._currentUrl != url;
|
||||
|
||||
//if (reload && _window != null)
|
||||
//{
|
||||
// _window.Close();
|
||||
// _window = null;
|
||||
//}
|
||||
|
||||
_window ??= Program.ServiceProvider.GetRequiredService<BrowserWindow>();
|
||||
_window.Url = url;
|
||||
_window._currentUrl = url;
|
||||
if (reload)
|
||||
{
|
||||
_window.webView.Source = new Uri(url);
|
||||
}
|
||||
|
||||
if (show)
|
||||
{
|
||||
_window.Url = url;
|
||||
_window._currentUrl = url;
|
||||
if (reload)
|
||||
{
|
||||
_window.webView.Source = new Uri(url);
|
||||
}
|
||||
_window.WindowState = WindowState.Normal;
|
||||
_window.Show();
|
||||
_window.Topmost = true;
|
||||
@@ -112,11 +117,23 @@ public partial class BrowserWindow : BaseWindow
|
||||
{
|
||||
e.Cancel = true;
|
||||
|
||||
var port = Blazor.GetCurrentPort();
|
||||
var port = BlazorUiManager.GetCurrentPort(Program.Config);
|
||||
|
||||
var newUrl = e.Uri.Replace(":0/", $":{port}/");
|
||||
|
||||
CreateAndShow(newUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private void webView_NavigationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs e)
|
||||
{
|
||||
if (e.WebErrorStatus > 0)
|
||||
{
|
||||
var port = BlazorUiManager.GetCurrentPort(Program.Config);
|
||||
|
||||
var newUrl = $"http://localhost:{port}";
|
||||
|
||||
CreateAndShow(newUrl, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,306 +17,310 @@ namespace ColorControl.XForms;
|
||||
|
||||
public class CustomDisplay
|
||||
{
|
||||
public Display Display { get; set; }
|
||||
public Display Display { get; set; }
|
||||
|
||||
public string DisplayName => Display.DisplayName;
|
||||
public string DevicePath => Display.DevicePath;
|
||||
public bool IsHDRSupportedAndEnabled()
|
||||
{
|
||||
var advancedColor = CCD.GetAdvancedColorSupportedAndEnabled(DisplayName);
|
||||
public string DisplayName => Display.DisplayName;
|
||||
public string DevicePath => Display.DevicePath;
|
||||
public bool IsHDRSupportedAndEnabled()
|
||||
{
|
||||
var advancedColor = CCD.GetAdvancedColorSupportedAndEnabled(DisplayName);
|
||||
|
||||
return advancedColor.isSupported && advancedColor.isEnabled;
|
||||
}
|
||||
return advancedColor.isSupported && advancedColor.isEnabled;
|
||||
}
|
||||
|
||||
public CustomDisplay(Display display)
|
||||
{
|
||||
Display = display;
|
||||
}
|
||||
public CustomDisplay(Display display)
|
||||
{
|
||||
Display = display;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{CCD.GetDisplayInfo(Display.DisplayName)} on {Display.Adapter.DeviceName}";
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{CCD.GetDisplayInfo(Display.DisplayName)} on {Display.Adapter.DeviceName}";
|
||||
}
|
||||
}
|
||||
|
||||
public class ColorPointModel : BaseViewModel
|
||||
{
|
||||
private double _x;
|
||||
public double X { get => _x; set { _x = value; OnPropertyChanged(); } }
|
||||
private double _x;
|
||||
public double X { get => _x; set { _x = value; OnPropertyChanged(); } }
|
||||
|
||||
private double _y;
|
||||
public double Y { get => _y; set { _y = value; OnPropertyChanged(); } }
|
||||
private double _y;
|
||||
public double Y { get => _y; set { _y = value; OnPropertyChanged(); } }
|
||||
|
||||
public ColorPointModel()
|
||||
{
|
||||
public ColorPointModel()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public ColorPointModel(CIExy coord)
|
||||
{
|
||||
X = coord.x;
|
||||
Y = coord.y;
|
||||
}
|
||||
public ColorPointModel(CIExy coord)
|
||||
{
|
||||
X = coord.x;
|
||||
Y = coord.y;
|
||||
}
|
||||
}
|
||||
|
||||
internal class ColorProfileViewModel : BaseViewModel
|
||||
{
|
||||
[StringLength(30)]
|
||||
public string Description { get; set; }
|
||||
[StringLength(30)]
|
||||
public string Description { get; set; }
|
||||
|
||||
public ColorPointModel RedPoint { get; set; } = new ColorPointModel(RgbPrimaries.sRGB.Red);
|
||||
public ColorPointModel GreenPoint { get; set; } = new ColorPointModel(RgbPrimaries.sRGB.Green);
|
||||
public ColorPointModel BluePoint { get; set; } = new ColorPointModel(RgbPrimaries.sRGB.Blue);
|
||||
public ColorPointModel WhitePoint { get; set; } = new ColorPointModel(RgbPrimaries.sRGB.White);
|
||||
public Dictionary<DisplayPrimariesSource, string> PrimariesSources { get; } = Utils.EnumToDictionary<DisplayPrimariesSource>();
|
||||
public DisplayPrimariesSource PrimariesSource { get; set; } = DisplayPrimariesSource.EDID;
|
||||
public Dictionary<ColorGamut, string> ColorGamuts { get; } = Utils.EnumToDictionary<ColorGamut>();
|
||||
public ColorGamut ColorGamut { get; set; } = ColorGamut.Native;
|
||||
public Dictionary<SDRTransferFunction, string> SDRTransferFunctions { get; } = Utils.EnumToDictionary<SDRTransferFunction>();
|
||||
public SDRTransferFunction SDRTransferFunction { get; set; } = SDRTransferFunction.PurePower;
|
||||
[Range(0.1, 10)]
|
||||
public double CustomGamma { get; set; } = 2.20;
|
||||
[Range(0, 10)]
|
||||
public double MinCLL { get; set; } = 0;
|
||||
[Range(11, 10000)]
|
||||
public double MaxCLL { get; set; } = 1000;
|
||||
[Range(0, 10)]
|
||||
public double BlackLuminance { get; set; } = 0;
|
||||
[Range(11, 10000)]
|
||||
public double WhiteLuminance { get; set; } = 1000;
|
||||
[Range(0, 10)]
|
||||
public double SDRMinBrightness { get; set; } = 0;
|
||||
[Range(11, 10000)]
|
||||
public double SDRMaxBrightness { get; set; } = 100;
|
||||
[Range(-50, 50)]
|
||||
public double SDRBrightnessBoost { get; set; }
|
||||
public ColorPointModel RedPoint { get; set; } = new ColorPointModel(RgbPrimaries.sRGB.Red);
|
||||
public ColorPointModel GreenPoint { get; set; } = new ColorPointModel(RgbPrimaries.sRGB.Green);
|
||||
public ColorPointModel BluePoint { get; set; } = new ColorPointModel(RgbPrimaries.sRGB.Blue);
|
||||
public ColorPointModel WhitePoint { get; set; } = new ColorPointModel(RgbPrimaries.sRGB.White);
|
||||
public Dictionary<DisplayPrimariesSource, string> PrimariesSources { get; } = Utils.EnumToDictionary<DisplayPrimariesSource>();
|
||||
public DisplayPrimariesSource PrimariesSource { get; set; } = DisplayPrimariesSource.EDID;
|
||||
public Dictionary<ColorGamut, string> ColorGamuts { get; } = Utils.EnumToDictionary<ColorGamut>();
|
||||
public ColorGamut ColorGamut { get; set; } = ColorGamut.Native;
|
||||
public Dictionary<SDRTransferFunction, string> SDRTransferFunctions { get; } = Utils.EnumToDictionary<SDRTransferFunction>();
|
||||
public SDRTransferFunction SDRTransferFunction { get; set; } = SDRTransferFunction.PurePower;
|
||||
[Range(0.1, 10)]
|
||||
public double CustomGamma { get; set; } = 2.20;
|
||||
[Range(0, 10)]
|
||||
public double MinCLL { get; set; } = 0;
|
||||
[Range(11, 10000)]
|
||||
public double MaxCLL { get; set; } = 1000;
|
||||
[Range(0, 10)]
|
||||
public double BlackLuminance { get; set; } = 0;
|
||||
[Range(11, 10000)]
|
||||
public double WhiteLuminance { get; set; } = 1000;
|
||||
[Range(0, 10)]
|
||||
public double SDRMinBrightness { get; set; } = 0;
|
||||
[Range(11, 10000)]
|
||||
public double SDRMaxBrightness { get; set; } = 100;
|
||||
[Range(-50, 50)]
|
||||
public double SDRBrightnessBoost { get; set; }
|
||||
[Range(-200, 200)]
|
||||
public double ShadowDetailBoost { get; set; } = 0;
|
||||
[Range(0, 100)]
|
||||
public double ShadowDetailRange { get; set; } = 0;
|
||||
|
||||
public CustomDisplay SelectedDisplay { get; set; }
|
||||
public IEnumerable<CustomDisplay> Displays { get; set; }
|
||||
public CustomDisplay SelectedDisplay { get; set; }
|
||||
public IEnumerable<CustomDisplay> Displays { get; set; }
|
||||
|
||||
public string SelectedDisplayName => SelectedDisplay?.DisplayName;
|
||||
public string SelectedDisplayName => SelectedDisplay?.DisplayName;
|
||||
|
||||
public ObservableCollection<string> ExistingProfiles { get; set; }
|
||||
public string SelectedExistingProfile { get; set; } = CreateANewProfile;
|
||||
public string NewProfileName { get; set; }
|
||||
public string ProfileName => SelectedExistingProfile == CreateANewProfile ? NewProfileName : SelectedExistingProfile;
|
||||
public bool IsHDR { get; set; } = true;
|
||||
public Dictionary<SaveOption, string> SaveOptions { get; } = Utils.EnumToDictionary<SaveOption>();
|
||||
public SaveOption SaveOption { get; set; } = SaveOption.InstallAndSetAsDefault;
|
||||
public ObservableCollection<string> ExistingProfiles { get; set; }
|
||||
public string SelectedExistingProfile { get; set; } = CreateANewProfile;
|
||||
public string NewProfileName { get; set; }
|
||||
public string ProfileName => SelectedExistingProfile == CreateANewProfile ? NewProfileName : SelectedExistingProfile;
|
||||
public bool IsHDR { get; set; } = true;
|
||||
public Dictionary<SaveOption, string> SaveOptions { get; } = Utils.EnumToDictionary<SaveOption>();
|
||||
public SaveOption SaveOption { get; set; } = SaveOption.InstallAndSetAsDefault;
|
||||
|
||||
public bool SDRSettingsEnabled { get; set; }
|
||||
public Visibility VisibilityHDRSettings => IsHDR ? Visibility.Visible : Visibility.Collapsed;
|
||||
public bool IsLoadEnabled { get; set; }
|
||||
public bool SetMinMaxTml { get; set; } = true;
|
||||
public bool PrimariesEnabled { get; set; } = true;
|
||||
public bool SDRSettingsEnabled { get; set; }
|
||||
public Visibility VisibilityHDRSettings => IsHDR ? Visibility.Visible : Visibility.Collapsed;
|
||||
public bool IsLoadEnabled { get; set; }
|
||||
public bool SetMinMaxTml { get; set; } = true;
|
||||
public bool PrimariesEnabled { get; set; } = true;
|
||||
|
||||
[Range(400, 10000)]
|
||||
public double ToneMappingFromLuminance { get; set; } = 400;
|
||||
[Range(400, 10000)]
|
||||
public double ToneMappingToLuminance { get; set; } = 400;
|
||||
[Range(400, 10000)]
|
||||
public double ToneMappingFromLuminance { get; set; } = 400;
|
||||
[Range(400, 10000)]
|
||||
public double ToneMappingToLuminance { get; set; } = 400;
|
||||
|
||||
|
||||
public bool ToneMappingSettingsEnabled { get; set; }
|
||||
public bool ToneMappingSettingsEnabled { get; set; }
|
||||
|
||||
public bool BrightnessBoostSettingsEnabled { get; set; }
|
||||
public bool BrightnessBoostSettingsEnabled { get; set; }
|
||||
|
||||
[Range(.04, 25)]
|
||||
public double HdrBrightnessMultiplier { get; set; } = 1;
|
||||
[Range(.04, 25)]
|
||||
public double HdrBrightnessMultiplier { get; set; } = 1;
|
||||
|
||||
[Range(.04, 25)]
|
||||
public double HdrGammaMultiplier { get; set; } = 1;
|
||||
[Range(.04, 25)]
|
||||
public double HdrGammaMultiplier { get; set; } = 1;
|
||||
|
||||
public override string this[string columnName]
|
||||
{
|
||||
get
|
||||
{
|
||||
var baseResult = base[columnName];
|
||||
public override string this[string columnName]
|
||||
{
|
||||
get
|
||||
{
|
||||
var baseResult = base[columnName];
|
||||
|
||||
if (columnName == nameof(SelectedDisplay))
|
||||
{
|
||||
UpdateDisplay();
|
||||
}
|
||||
else if (columnName == nameof(SDRTransferFunction))
|
||||
{
|
||||
if (SDRTransferFunction == SDRTransferFunction.PurePower)
|
||||
{
|
||||
SDRSettingsEnabled = true;
|
||||
ToneMappingSettingsEnabled = false;
|
||||
BrightnessBoostSettingsEnabled = true;
|
||||
OnPropertyChanged(nameof(SDRSettingsEnabled));
|
||||
OnPropertyChanged(nameof(ToneMappingSettingsEnabled));
|
||||
OnPropertyChanged(nameof(BrightnessBoostSettingsEnabled));
|
||||
}
|
||||
else if (SDRTransferFunction == SDRTransferFunction.ToneMappedPiecewise)
|
||||
{
|
||||
if (columnName == nameof(SelectedDisplay))
|
||||
{
|
||||
UpdateDisplay();
|
||||
}
|
||||
else if (columnName == nameof(SDRTransferFunction))
|
||||
{
|
||||
if (SDRTransferFunction == SDRTransferFunction.PurePower)
|
||||
{
|
||||
SDRSettingsEnabled = true;
|
||||
ToneMappingSettingsEnabled = false;
|
||||
BrightnessBoostSettingsEnabled = true;
|
||||
OnPropertyChanged(nameof(SDRSettingsEnabled));
|
||||
OnPropertyChanged(nameof(ToneMappingSettingsEnabled));
|
||||
OnPropertyChanged(nameof(BrightnessBoostSettingsEnabled));
|
||||
}
|
||||
else if (SDRTransferFunction == SDRTransferFunction.ToneMappedPiecewise)
|
||||
{
|
||||
|
||||
ToneMappingSettingsEnabled = true;
|
||||
SDRSettingsEnabled = false;
|
||||
BrightnessBoostSettingsEnabled = false;
|
||||
OnPropertyChanged(nameof(ToneMappingSettingsEnabled));
|
||||
OnPropertyChanged(nameof(SDRSettingsEnabled));
|
||||
OnPropertyChanged(nameof(BrightnessBoostSettingsEnabled));
|
||||
}
|
||||
else
|
||||
{
|
||||
ToneMappingSettingsEnabled = false;
|
||||
SDRSettingsEnabled = false;
|
||||
BrightnessBoostSettingsEnabled = true;
|
||||
OnPropertyChanged(nameof(ToneMappingSettingsEnabled));
|
||||
OnPropertyChanged(nameof(SDRSettingsEnabled));
|
||||
OnPropertyChanged(nameof(BrightnessBoostSettingsEnabled));
|
||||
}
|
||||
ToneMappingSettingsEnabled = true;
|
||||
SDRSettingsEnabled = false;
|
||||
BrightnessBoostSettingsEnabled = false;
|
||||
OnPropertyChanged(nameof(ToneMappingSettingsEnabled));
|
||||
OnPropertyChanged(nameof(SDRSettingsEnabled));
|
||||
OnPropertyChanged(nameof(BrightnessBoostSettingsEnabled));
|
||||
}
|
||||
else
|
||||
{
|
||||
ToneMappingSettingsEnabled = false;
|
||||
SDRSettingsEnabled = false;
|
||||
BrightnessBoostSettingsEnabled = true;
|
||||
OnPropertyChanged(nameof(ToneMappingSettingsEnabled));
|
||||
OnPropertyChanged(nameof(SDRSettingsEnabled));
|
||||
OnPropertyChanged(nameof(BrightnessBoostSettingsEnabled));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if (columnName == nameof(SelectedExistingProfile))
|
||||
{
|
||||
IsLoadEnabled = SelectedExistingProfile != CreateANewProfile;
|
||||
OnPropertyChanged(nameof(IsLoadEnabled));
|
||||
}
|
||||
else if (columnName == nameof(PrimariesSource))
|
||||
{
|
||||
PrimariesEnabled = PrimariesSource == DisplayPrimariesSource.Custom;
|
||||
OnPropertyChanged(nameof(PrimariesEnabled));
|
||||
UpdateDisplay();
|
||||
}
|
||||
}
|
||||
else if (columnName == nameof(SelectedExistingProfile))
|
||||
{
|
||||
IsLoadEnabled = SelectedExistingProfile != CreateANewProfile;
|
||||
OnPropertyChanged(nameof(IsLoadEnabled));
|
||||
}
|
||||
else if (columnName == nameof(PrimariesSource))
|
||||
{
|
||||
PrimariesEnabled = PrimariesSource == DisplayPrimariesSource.Custom;
|
||||
OnPropertyChanged(nameof(PrimariesEnabled));
|
||||
UpdateDisplay();
|
||||
}
|
||||
|
||||
return baseResult;
|
||||
}
|
||||
}
|
||||
return baseResult;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool PreValidate()
|
||||
{
|
||||
return base.PreValidate() && Displays.Any();
|
||||
}
|
||||
public override bool PreValidate()
|
||||
{
|
||||
return base.PreValidate() && Displays.Any();
|
||||
}
|
||||
|
||||
public const string CreateANewProfile = "<create a new profile>";
|
||||
public const string CreateANewProfile = "<create a new profile>";
|
||||
|
||||
public ColorProfileViewModel(bool isHDR = true)
|
||||
{
|
||||
IsHDR = isHDR;
|
||||
public ColorProfileViewModel(bool isHDR = true)
|
||||
{
|
||||
IsHDR = isHDR;
|
||||
|
||||
RefreshDisplays();
|
||||
RefreshDisplays();
|
||||
|
||||
ExistingProfiles = new ObservableCollection<string> { CreateANewProfile };
|
||||
NewProfileName = $"CC_{(isHDR ? "HDR" : "SDR")}_profile_{DateTime.Now:yyyyMMddHHmmss}.icm";
|
||||
Description = $"CC_{(isHDR ? "HDR" : "SDR")}";
|
||||
ExistingProfiles = new ObservableCollection<string> { CreateANewProfile };
|
||||
NewProfileName = $"CC_{(isHDR ? "HDR" : "SDR")}_profile_{DateTime.Now:yyyyMMddHHmmss}.icm";
|
||||
Description = $"CC_{(isHDR ? "HDR" : "SDR")}";
|
||||
|
||||
if (Displays.Any())
|
||||
{
|
||||
SelectedDisplay = Displays.First();
|
||||
if (Displays.Any())
|
||||
{
|
||||
SelectedDisplay = Displays.First();
|
||||
|
||||
UpdateDisplay();
|
||||
}
|
||||
}
|
||||
UpdateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshDisplays()
|
||||
{
|
||||
Displays = Display.GetDisplays().Select(d => new CustomDisplay(d))
|
||||
.Where(d => IsHDR == d.IsHDRSupportedAndEnabled())
|
||||
.ToList();
|
||||
}
|
||||
public void RefreshDisplays()
|
||||
{
|
||||
Displays = Display.GetDisplays().Select(d => new CustomDisplay(d))
|
||||
.Where(d => IsHDR == d.IsHDRSupportedAndEnabled())
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
foreach (var property in GetType().GetProperties().Where(p => !new[] { "Display", "PrimariesSource" }.Any(s => p.Name.Contains(s))))
|
||||
{
|
||||
OnPropertyChanged(property.Name);
|
||||
}
|
||||
}
|
||||
public void Update()
|
||||
{
|
||||
foreach (var property in GetType().GetProperties().Where(p => !new[] { "Display", "PrimariesSource" }.Any(s => p.Name.Contains(s))))
|
||||
{
|
||||
OnPropertyChanged(property.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDisplay()
|
||||
{
|
||||
if (SelectedDisplay == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
private void UpdateDisplay()
|
||||
{
|
||||
if (SelectedDisplay == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var colorParams = CCD.GetColorParams(SelectedDisplay.DisplayName);
|
||||
var colorParams = CCD.GetColorParams(SelectedDisplay.DisplayName);
|
||||
|
||||
if (colorParams.MaxLuminance > 0)
|
||||
{
|
||||
if (PrimariesSource == DisplayPrimariesSource.Windows)
|
||||
{
|
||||
var divider = colorParams.RedPointX <= 1 << 10 ? 1 << 10 : 1 << 20;
|
||||
if (colorParams.MaxLuminance > 0)
|
||||
{
|
||||
if (PrimariesSource == DisplayPrimariesSource.Windows)
|
||||
{
|
||||
var divider = colorParams.RedPointX <= 1 << 10 ? 1 << 10 : 1 << 20;
|
||||
|
||||
RedPoint.X = (double)colorParams.RedPointX / divider;
|
||||
RedPoint.Y = (double)colorParams.RedPointY / divider;
|
||||
GreenPoint.X = (double)colorParams.GreenPointX / divider;
|
||||
GreenPoint.Y = (double)colorParams.GreenPointY / divider;
|
||||
BluePoint.X = (double)colorParams.BluePointX / divider;
|
||||
BluePoint.Y = (double)colorParams.BluePointY / divider;
|
||||
WhitePoint.X = (double)colorParams.WhitePointX / divider;
|
||||
WhitePoint.Y = (double)colorParams.WhitePointY / divider;
|
||||
}
|
||||
RedPoint.X = (double)colorParams.RedPointX / divider;
|
||||
RedPoint.Y = (double)colorParams.RedPointY / divider;
|
||||
GreenPoint.X = (double)colorParams.GreenPointX / divider;
|
||||
GreenPoint.Y = (double)colorParams.GreenPointY / divider;
|
||||
BluePoint.X = (double)colorParams.BluePointX / divider;
|
||||
BluePoint.Y = (double)colorParams.BluePointY / divider;
|
||||
WhitePoint.X = (double)colorParams.WhitePointX / divider;
|
||||
WhitePoint.Y = (double)colorParams.WhitePointY / divider;
|
||||
}
|
||||
|
||||
WhiteLuminance = (double)colorParams.MaxLuminance / 10000;
|
||||
OnPropertyChanged(nameof(WhiteLuminance));
|
||||
BlackLuminance = (double)colorParams.MinLuminance / 10000;
|
||||
OnPropertyChanged(nameof(BlackLuminance));
|
||||
MinCLL = BlackLuminance;
|
||||
OnPropertyChanged(nameof(MinCLL));
|
||||
MaxCLL = WhiteLuminance;
|
||||
OnPropertyChanged(nameof(MaxCLL));
|
||||
}
|
||||
WhiteLuminance = (double)colorParams.MaxLuminance / 10000;
|
||||
OnPropertyChanged(nameof(WhiteLuminance));
|
||||
BlackLuminance = (double)colorParams.MinLuminance / 10000;
|
||||
OnPropertyChanged(nameof(BlackLuminance));
|
||||
MinCLL = BlackLuminance;
|
||||
OnPropertyChanged(nameof(MinCLL));
|
||||
MaxCLL = WhiteLuminance;
|
||||
OnPropertyChanged(nameof(MaxCLL));
|
||||
}
|
||||
|
||||
if (PrimariesSource == DisplayPrimariesSource.EDID)
|
||||
{
|
||||
GetEDID();
|
||||
}
|
||||
if (PrimariesSource == DisplayPrimariesSource.EDID)
|
||||
{
|
||||
GetEDID();
|
||||
}
|
||||
|
||||
if (!CCD.GetUsePerUserDisplayProfiles(SelectedDisplay.DisplayName))
|
||||
{
|
||||
if (MessageForms.QuestionYesNo("To be able to select/activate a color profile, user specific settings have to be enabled. Do you want to enable this?") == DialogResult.Yes)
|
||||
{
|
||||
CCD.SetUsePerUserDisplayProfiles(SelectedDisplay.DisplayName, true);
|
||||
}
|
||||
}
|
||||
if (!CCD.GetUsePerUserDisplayProfiles(SelectedDisplay.DisplayName))
|
||||
{
|
||||
if (MessageForms.QuestionYesNo("To be able to select/activate a color profile, user specific settings have to be enabled. Do you want to enable this?") == DialogResult.Yes)
|
||||
{
|
||||
CCD.SetUsePerUserDisplayProfiles(SelectedDisplay.DisplayName, true);
|
||||
}
|
||||
}
|
||||
|
||||
ExistingProfiles = new ObservableCollection<string> { CreateANewProfile };
|
||||
ExistingProfiles = new ObservableCollection<string> { CreateANewProfile };
|
||||
|
||||
var profiles = CCD.GetDisplayColorProfiles(SelectedDisplay.DisplayName);
|
||||
var profiles = CCD.GetDisplayColorProfiles(SelectedDisplay.DisplayName);
|
||||
|
||||
foreach (var profile in profiles)
|
||||
{
|
||||
ExistingProfiles.Add(profile);
|
||||
}
|
||||
}
|
||||
foreach (var profile in profiles)
|
||||
{
|
||||
ExistingProfiles.Add(profile);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetEDID()
|
||||
{
|
||||
if (SelectedDisplay == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
private void GetEDID()
|
||||
{
|
||||
if (SelectedDisplay == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var path = SelectedDisplay.DevicePath;
|
||||
var path = SelectedDisplay.DevicePath;
|
||||
|
||||
var edid = ColorProfileService.GetEDIDInternal(path);
|
||||
var primaries = edid?.DisplayParameters?.ChromaticityCoordinates;
|
||||
var edid = ColorProfileService.GetEDIDInternal(path);
|
||||
var primaries = edid?.DisplayParameters?.ChromaticityCoordinates;
|
||||
|
||||
if (primaries == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (primaries == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RedPoint.X = primaries.RedX;
|
||||
RedPoint.Y = primaries.RedY;
|
||||
GreenPoint.X = primaries.GreenX;
|
||||
GreenPoint.Y = primaries.GreenY;
|
||||
BluePoint.X = primaries.BlueX;
|
||||
BluePoint.Y = primaries.BlueY;
|
||||
WhitePoint.X = primaries.WhiteX;
|
||||
WhitePoint.Y = primaries.WhiteY;
|
||||
}
|
||||
RedPoint.X = primaries.RedX;
|
||||
RedPoint.Y = primaries.RedY;
|
||||
GreenPoint.X = primaries.GreenX;
|
||||
GreenPoint.Y = primaries.GreenY;
|
||||
BluePoint.X = primaries.BlueX;
|
||||
BluePoint.Y = primaries.BlueY;
|
||||
WhitePoint.X = primaries.WhiteX;
|
||||
WhitePoint.Y = primaries.WhiteY;
|
||||
}
|
||||
|
||||
internal RgbPrimaries GetDevicePrimaries()
|
||||
{
|
||||
return new RgbPrimaries(
|
||||
new CIExy { x = RedPoint.X, y = RedPoint.Y },
|
||||
new CIExy { x = GreenPoint.X, y = GreenPoint.Y },
|
||||
new CIExy { x = BluePoint.X, y = BluePoint.Y },
|
||||
new CIExy { x = WhitePoint.X, y = WhitePoint.Y });
|
||||
}
|
||||
internal RgbPrimaries GetDevicePrimaries()
|
||||
{
|
||||
return new RgbPrimaries(
|
||||
new CIExy { x = RedPoint.X, y = RedPoint.Y },
|
||||
new CIExy { x = GreenPoint.X, y = GreenPoint.Y },
|
||||
new CIExy { x = BluePoint.X, y = BluePoint.Y },
|
||||
new CIExy { x = WhitePoint.X, y = WhitePoint.Y });
|
||||
}
|
||||
}
|
||||
@@ -52,8 +52,8 @@
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Left" Margin="412,236,0,0" TextWrapping="Wrap" Text="{Binding WhiteLuminance, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" VerticalAlignment="Top" Width="120" Name="tbMaxLuminance" Height="18" InputScope="Number"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<GroupBox Header="Advanced HDR Settings" Padding="6" Height="199" Width="734" HorizontalAlignment="Left" Visibility="{Binding VisibilityHDRSettings}">
|
||||
<Grid Height="150">
|
||||
<GroupBox Header="Advanced HDR Settings" Padding="6" Height="216" Width="734" HorizontalAlignment="Left" Visibility="{Binding VisibilityHDRSettings}">
|
||||
<Grid Height="187" VerticalAlignment="Top">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="179*"/>
|
||||
<ColumnDefinition Width="735*"/>
|
||||
@@ -74,11 +74,15 @@
|
||||
<Label Content="HDR Luminance to convert (nits):" HorizontalAlignment="Left" Margin="194,94,0,0" VerticalAlignment="Top" Width="211" Height="26" Grid.Column="1"/>
|
||||
<TextBox IsEnabled="{Binding ToneMappingSettingsEnabled}" Grid.Column="1" HorizontalAlignment="Left" Margin="405,98,0,0" TextWrapping="Wrap" Text="{Binding ToneMappingToLuminance, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" VerticalAlignment="Top" Width="120" x:Name="tbNitsTo" Height="18" InputScope="Number"/>
|
||||
|
||||
<Label Content="Brightness multiplier:" HorizontalAlignment="Left" Margin="-5,120,0,4" Width="208" Grid.ColumnSpan="2"/>
|
||||
<Label Content="Brightness multiplier:" HorizontalAlignment="Left" Margin="-5,120,0,4" Width="208" Grid.ColumnSpan="2" VerticalAlignment="Top"/>
|
||||
<TextBox IsEnabled="{Binding ToneMappingSettingsEnabled}" Grid.Column="1" HorizontalAlignment="Left" Margin="69,128,0,0" TextWrapping="Wrap" Text="{Binding HdrBrightnessMultiplier, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" VerticalAlignment="Top" Width="120" x:Name="tbhdrbrightness" Height="18" InputScope="Number"/>
|
||||
|
||||
<Label Content="Gamma multiplier:" HorizontalAlignment="Left" Margin="194,124,0,0" Width="211" Grid.Column="1"/>
|
||||
<Label Content="Gamma multiplier:" HorizontalAlignment="Left" Margin="194,124,0,0" Width="211" Grid.Column="1" VerticalAlignment="Top"/>
|
||||
<TextBox IsEnabled="{Binding ToneMappingSettingsEnabled}" Grid.Column="1" HorizontalAlignment="Left" Margin="405,128,0,0" TextWrapping="Wrap" Text="{Binding HdrGammaMultiplier, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" VerticalAlignment="Top" Width="120" x:Name="tbhdrgamma" Height="18" InputScope="Number"/>
|
||||
<Label Content="Shadow detail boost (%):" HorizontalAlignment="Left" Margin="-5,148,0,0" Width="208" Grid.ColumnSpan="2" VerticalAlignment="Top"/>
|
||||
<TextBox IsEnabled="{Binding BrightnessBoostSettingsEnabled}" Grid.Column="1" HorizontalAlignment="Left" Margin="69,156,0,0" TextWrapping="Wrap" Text="{Binding ShadowDetailBoost, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" VerticalAlignment="Top" Width="120" x:Name="tbShadowDetailBoost" Height="18" InputScope="Number"/>
|
||||
<Label Content="Shadow detail range (%):" HorizontalAlignment="Left" Margin="194,152,0,0" Width="211" Grid.Column="1" VerticalAlignment="Top"/>
|
||||
<TextBox IsEnabled="{Binding BrightnessBoostSettingsEnabled}" Grid.Column="1" HorizontalAlignment="Left" Margin="405,156,0,0" TextWrapping="Wrap" Text="{Binding ShadowDetailRange, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" VerticalAlignment="Top" Width="120" x:Name="tbShadowDetailRange" Height="18" InputScope="Number"/>
|
||||
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
@@ -94,7 +98,7 @@
|
||||
<TextBox Grid.Column="1" HorizontalAlignment="Left" Margin="400,10,0,0" TextWrapping="Wrap" Text="{Binding MaxCLL, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" VerticalAlignment="Top" Width="120" x:Name="tbMinLuminance_Copy1" Height="18" InputScope="Number"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<GroupBox DockPanel.Dock="Right" Margin="0,0,0,0" Header="Generate Options" Padding="6" Height="225" Width="733" HorizontalAlignment="Left">
|
||||
<GroupBox DockPanel.Dock="Right" Margin="0,0,0,0" Header="Generate Options" Padding="6" Height="227" Width="733" HorizontalAlignment="Left">
|
||||
<Grid Height="194" Margin="-2,0,2,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="8*"/>
|
||||
|
||||
@@ -113,6 +113,8 @@ namespace ColorControl.XForms
|
||||
SDRMaxBrightness = _viewModel.SDRMaxBrightness,
|
||||
SDRTransferFunction = _viewModel.SDRTransferFunction,
|
||||
SDRBrightnessBoost = _viewModel.SDRBrightnessBoost,
|
||||
ShadowDetailBoost = _viewModel.ShadowDetailBoost,
|
||||
ShadowDetailRange = _viewModel.ShadowDetailRange,
|
||||
ColorGamut = _viewModel.ColorGamut,
|
||||
Gamma = _viewModel.CustomGamma,
|
||||
DevicePrimaries = _viewModel.GetDevicePrimaries(),
|
||||
@@ -208,6 +210,8 @@ namespace ColorControl.XForms
|
||||
_viewModel.SDRMinBrightness = profileProperties.SDRMinBrightness;
|
||||
_viewModel.SDRMaxBrightness = profileProperties.SDRMaxBrightness;
|
||||
_viewModel.SDRBrightnessBoost = profileProperties.SDRBrightnessBoost;
|
||||
_viewModel.ShadowDetailBoost = profileProperties.ShadowDetailBoost;
|
||||
_viewModel.ShadowDetailRange = profileProperties.ShadowDetailRange;
|
||||
_viewModel.MinCLL = profileProperties.MinCLL;
|
||||
_viewModel.MaxCLL = profileProperties.MaxCLL;
|
||||
|
||||
|
||||
@@ -24,19 +24,21 @@ namespace LgTv
|
||||
private string _ip;
|
||||
private string _currentPairKey;
|
||||
private string webSocketUri;
|
||||
private string _registerJson;
|
||||
|
||||
protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public static async Task<LgTvApi> CreateLgTvApi(string ip, int retries = 1, bool useSecureWs = true)
|
||||
public static async Task<LgTvApi> CreateLgTvApi(string ip, int retries = 1, bool useSecureWs = true, bool useNewHandshake = false)
|
||||
{
|
||||
var instance = new LgTvApi(ip, useSecureWs);
|
||||
var instance = new LgTvApi(ip, useSecureWs, useNewHandshake);
|
||||
|
||||
return await instance.Connect(retries);
|
||||
}
|
||||
|
||||
private LgTvApi(string ip, bool useSecureWs)
|
||||
private LgTvApi(string ip, bool useSecureWs, bool useNewHandshake)
|
||||
{
|
||||
webSocketUri = useSecureWs ? $"wss://{ip}:3001" : $"ws://{ip}:3000";
|
||||
_registerJson = Utils.GetResourceFile(useNewHandshake ? "LG_register.json" : "LG_register_legacy.json");
|
||||
_ip = ip;
|
||||
_connection = new LgTvApiCoreCws();
|
||||
_keyStore = new ClientKeyStore(ip);
|
||||
@@ -68,26 +70,43 @@ namespace LgTv
|
||||
return _ip;
|
||||
}
|
||||
|
||||
public async Task MakeHandShake()
|
||||
public async Task<bool> MakeHandShake()
|
||||
{
|
||||
var registerJson = Utils.GetResourceFile("LG_register.json");
|
||||
|
||||
_currentPairKey = _keyStore.GetClientKey();
|
||||
if (!string.IsNullOrWhiteSpace(_currentPairKey) && !_currentPairKey.All(k => k == '\0') && _keyStore.HasValidHandShake(registerJson))
|
||||
if (!string.IsNullOrWhiteSpace(_currentPairKey) && !_currentPairKey.All(k => k == '\0') && _keyStore.HasValidHandShake(_registerJson))
|
||||
{
|
||||
var key = registerJson.Replace("CLIENTKEYGOESHERE", _currentPairKey);
|
||||
var conn = await _connection.SendCommandAsync(key);
|
||||
_keyStore.SaveClientKey((string)conn.clientKey);
|
||||
return;
|
||||
var key = _registerJson.Replace("CLIENTKEYGOESHERE", _currentPairKey);
|
||||
try
|
||||
{
|
||||
var conn = await _connection.SendCommandAsync(key);
|
||||
ArgumentNullException.ThrowIfNull(conn);
|
||||
_keyStore.SaveClientKey((string)conn.clientKey);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Re-register below
|
||||
}
|
||||
}
|
||||
|
||||
var registerJsonRemovedKey = registerJson.Replace("CLIENTKEYGOESHERE", string.Empty);
|
||||
dynamic result = await _connection.SendCommandAsync(registerJsonRemovedKey);
|
||||
_keyStore.SaveClientKey(result.clientKey);
|
||||
_keyStore.SaveHandShake(registerJson);
|
||||
var registerJsonRemovedKey = _registerJson.Replace("CLIENTKEYGOESHERE", string.Empty);
|
||||
try
|
||||
{
|
||||
var result = await _connection.SendCommandAsync(registerJsonRemovedKey);
|
||||
if (result?.clientKey == null)
|
||||
{
|
||||
throw new InvalidOperationException("No valid client key received");
|
||||
}
|
||||
_keyStore.SaveClientKey(result.clientKey);
|
||||
_keyStore.SaveHandShake(_registerJson);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> Connect()
|
||||
{
|
||||
var ctx = _connection.Connect(new Uri(webSocketUri));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace MHC2Gen
|
||||
var value = (double)i / lutSizeDiv;
|
||||
|
||||
value = ApplyGain(gain, value, i, lutSizeDiv);
|
||||
value = ApplyShadowDetailBoost(shadowDetailBoost, shadowDetailRange, value, i);
|
||||
value = ApplyShadowDetailBoost(shadowDetailBoost, shadowDetailRange, value, i, false);
|
||||
|
||||
RegammaLUT[c, i] = value * amplifier;
|
||||
}
|
||||
@@ -140,14 +140,14 @@ namespace MHC2Gen
|
||||
return value;
|
||||
}
|
||||
|
||||
public static double ApplyShadowDetailBoost(double boost, double range, double value, int lutIndex)
|
||||
public static double ApplyShadowDetailBoost(double boost, double range, double value, int lutIndex, bool piecewiseAverage = true)
|
||||
{
|
||||
if (boost != 0 && lutIndex < range)
|
||||
{
|
||||
var correctedBoost = (boost * (range - lutIndex)) / range;
|
||||
|
||||
// Average between sSRGB and Piecewise gamma
|
||||
if (true)
|
||||
// Average between sRGB and Piecewise gamma
|
||||
if (piecewiseAverage)
|
||||
{
|
||||
var piecewiseValue = (double)lutIndex / 1023;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>x64</Platforms>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<RootNamespace>DJ</RootNamespace>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
@@ -18,8 +18,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.3.4" />
|
||||
<PackageReference Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageReference Include="NLog" Version="6.1.2" />
|
||||
<PackageReference Include="System.Reactive" Version="6.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -13,10 +13,6 @@
|
||||
<PathMap Condition="'$(Configuration)' == 'Release'">$(MSBuildThisFileDirectory)=.\</PathMap>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Resources.Extensions" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -7776,23 +7776,23 @@
|
||||
<HexValue>0x00000000</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Enabled (Low Quality) (0x06)</UserfriendlyName>
|
||||
<UserfriendlyName>Enabled via driver (No Debanding) (0x06)</UserfriendlyName>
|
||||
<HexValue>0x00000006</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Enabled (Medium Quality) (0x0A)</UserfriendlyName>
|
||||
<UserfriendlyName>Enabled via driver (Medium Debanding) (0x0A)</UserfriendlyName>
|
||||
<HexValue>0x0000000A</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Enabled (VeryHigh Quality) (0x02)</UserfriendlyName>
|
||||
<UserfriendlyName>Enabled via driver (VeryHigh Debanding) (0x02)</UserfriendlyName>
|
||||
<HexValue>0x00000002</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Enable + Indicator (0x03)</UserfriendlyName>
|
||||
<UserfriendlyName>Enabled + Indicator (VeryHigh) (0x03)</UserfriendlyName>
|
||||
<HexValue>0x00000003</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Enable + Indicator + Debug (0x23)</UserfriendlyName>
|
||||
<UserfriendlyName>Enabled + Indicator + Debug (VeryHigh) (0x23)</UserfriendlyName>
|
||||
<HexValue>0x00000023</HexValue>
|
||||
</CustomSettingValue>
|
||||
</SettingValues>
|
||||
@@ -7906,6 +7906,26 @@
|
||||
<GroupName>8 - Extra</GroupName>
|
||||
<MinRequiredDriverVersion>0</MinRequiredDriverVersion>
|
||||
<SettingValues>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>N/A</UserfriendlyName>
|
||||
<HexValue>0x00000000</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset A</UserfriendlyName>
|
||||
<HexValue>0x00000001</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset B</UserfriendlyName>
|
||||
<HexValue>0x00000002</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset C</UserfriendlyName>
|
||||
<HexValue>0x00000003</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset D</UserfriendlyName>
|
||||
<HexValue>0x00000004</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset E</UserfriendlyName>
|
||||
<HexValue>0x00000005</HexValue>
|
||||
@@ -7914,6 +7934,18 @@
|
||||
<UserfriendlyName>Preset F</UserfriendlyName>
|
||||
<HexValue>0x00000006</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset G (unused)</UserfriendlyName>
|
||||
<HexValue>0x00000007</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset H (unused)</UserfriendlyName>
|
||||
<HexValue>0x00000008</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset I (unused)</UserfriendlyName>
|
||||
<HexValue>0x00000009</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset J</UserfriendlyName>
|
||||
<HexValue>0x0000000A</HexValue>
|
||||
@@ -7922,6 +7954,103 @@
|
||||
<UserfriendlyName>Preset K</UserfriendlyName>
|
||||
<HexValue>0x0000000B</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset L</UserfriendlyName>
|
||||
<HexValue>0x0000000C</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset M</UserfriendlyName>
|
||||
<HexValue>0x0000000D</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset N (unused)</UserfriendlyName>
|
||||
<HexValue>0x0000000E</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset O (unused)</UserfriendlyName>
|
||||
<HexValue>0x0000000F</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Always use latest</UserfriendlyName>
|
||||
<HexValue>0x00FFFFFF</HexValue>
|
||||
</CustomSettingValue>
|
||||
</SettingValues>
|
||||
<SettingMasks/>
|
||||
</CustomSetting>
|
||||
<CustomSetting>
|
||||
<UserfriendlyName>DLSS-RR - Forced Preset Letter</UserfriendlyName>
|
||||
<HexSettingID>0x10E41DF7</HexSettingID>
|
||||
<GroupName>5 - Common</GroupName>
|
||||
<MinRequiredDriverVersion>0</MinRequiredDriverVersion>
|
||||
<SettingValues>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>N/A</UserfriendlyName>
|
||||
<HexValue>0x00000000</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset A</UserfriendlyName>
|
||||
<HexValue>0x00000001</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset B</UserfriendlyName>
|
||||
<HexValue>0x00000002</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset C</UserfriendlyName>
|
||||
<HexValue>0x00000003</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset D</UserfriendlyName>
|
||||
<HexValue>0x00000004</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset E</UserfriendlyName>
|
||||
<HexValue>0x00000005</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset F (unused)</UserfriendlyName>
|
||||
<HexValue>0x00000006</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset G (unused)</UserfriendlyName>
|
||||
<HexValue>0x00000007</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset H (unused)</UserfriendlyName>
|
||||
<HexValue>0x00000008</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset I (unused)</UserfriendlyName>
|
||||
<HexValue>0x00000009</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset J (unused)</UserfriendlyName>
|
||||
<HexValue>0x0000000A</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset K (unused)</UserfriendlyName>
|
||||
<HexValue>0x0000000B</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset L (unused)</UserfriendlyName>
|
||||
<HexValue>0x0000000C</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset M (unused)</UserfriendlyName>
|
||||
<HexValue>0x0000000D</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset N (unused)</UserfriendlyName>
|
||||
<HexValue>0x0000000E</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Preset O (unused)</UserfriendlyName>
|
||||
<HexValue>0x0000000F</HexValue>
|
||||
</CustomSettingValue>
|
||||
<CustomSettingValue>
|
||||
<UserfriendlyName>Always use latest</UserfriendlyName>
|
||||
<HexValue>0x00FFFFFF</HexValue>
|
||||
</CustomSettingValue>
|
||||
</SettingValues>
|
||||
<SettingMasks/>
|
||||
</CustomSetting>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<Version>0.8.1.106</Version>
|
||||
<Company>falahati.net</Company>
|
||||
<Description>NvAPIWrapper is a .Net wrapper for NVIDIA public API</Description>
|
||||
|
||||
@@ -5,8 +5,8 @@ Easily change NVIDIA and AMD display settings, control LG and Samsung tv's, Game
|
||||
|
||||
Just extract the .zip file in a folder of your preference. Run ColorControl.exe to start the application.
|
||||
Requires .NET 9 with the following runtimes:
|
||||
* .NET Desktop Runtime 9
|
||||
* .NET ASP.NET Core Runtime 9
|
||||
* .NET Desktop Runtime 10
|
||||
* .NET ASP.NET Core Runtime 10
|
||||
|
||||
ColorControl stores its settings in the following folder:
|
||||
* C:\Users\username\AppData\Roaming\Maassoft\ColorControl
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace ColorControl.Shared.Common
|
||||
public DateTime StartTime { get; private set; }
|
||||
public string MutexId { get; private set; }
|
||||
public nint MainHandle { get; set; }
|
||||
public int MainThreadId { get; private set; }
|
||||
public IServiceProvider ServiceProvider { get; set; }
|
||||
|
||||
public string ApplicationTitle { get; private set; }
|
||||
@@ -37,6 +38,7 @@ namespace ColorControl.Shared.Common
|
||||
ServiceProvider = serviceProvider;
|
||||
StartTime = startTime;
|
||||
MutexId = mutexId;
|
||||
MainThreadId = Environment.CurrentManagedThreadId;
|
||||
|
||||
CurrentContext = this;
|
||||
|
||||
|
||||
+62
-47
@@ -50,46 +50,6 @@ These methods are available:
|
||||
|
||||
The best and suggested method to provide this is via a Windows Service. Only when installing the service a User Account Control window may popup.";
|
||||
|
||||
public static Bitmap SubPixelShift(Bitmap bitmap)
|
||||
{
|
||||
Bitmap bitmap2 = (Bitmap)bitmap.Clone();
|
||||
|
||||
int shift = -1;
|
||||
bool shiftRed = true;
|
||||
bool shiftGreen = true;
|
||||
bool shiftBlue = false;
|
||||
|
||||
for (int i = 0; i < bitmap.Width; i++)
|
||||
{
|
||||
for (int j = 0; j < bitmap.Height; j++)
|
||||
{
|
||||
Color pixel = bitmap.GetPixel(i, j);
|
||||
|
||||
if (shift > 0 && i < bitmap.Width - shift)
|
||||
{
|
||||
Color pixel2 = bitmap2.GetPixel(i + shift, j);
|
||||
|
||||
Color pixel3 = Color.FromArgb(shiftRed ? pixel.R : pixel2.R, shiftGreen ? pixel.G : pixel2.G, shiftBlue ? pixel.B : pixel2.B);
|
||||
|
||||
bitmap2.SetPixel(i + shift, j, pixel3);
|
||||
|
||||
}
|
||||
else if (i + shift >= 0)
|
||||
{
|
||||
Color pixel2 = bitmap2.GetPixel(i + shift, j);
|
||||
|
||||
Color pixel3 = Color.FromArgb(shiftRed ? pixel.R : pixel2.R, shiftGreen ? pixel.G : pixel2.G, shiftBlue ? pixel.B : pixel2.B);
|
||||
|
||||
bitmap2.SetPixel(i + shift, j, pixel3);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap2;
|
||||
//bitmap2.Save("d:\\ss_shifted.bmp");
|
||||
}
|
||||
|
||||
public static string GetDataPath(string subDir = "")
|
||||
{
|
||||
var path = Directory.GetParent(Application.UserAppDataPath).FullName;
|
||||
@@ -465,22 +425,77 @@ The best and suggested method to provide this is via a Windows Service. Only whe
|
||||
|
||||
public static FileInfo SelectFile(string ext = "*.exe", string filter = "Application EXE Name|*.exe|Application Absolute Path|*.exe")
|
||||
{
|
||||
var openDialog = new System.Windows.Forms.OpenFileDialog();
|
||||
openDialog.DefaultExt = ext;
|
||||
openDialog.Filter = filter;
|
||||
var openDialog = new OpenFileDialog
|
||||
{
|
||||
DefaultExt = ext,
|
||||
Filter = filter
|
||||
};
|
||||
|
||||
if (openDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
return new FileInfo(openDialog.FileName);
|
||||
//if (openDialog.FilterIndex == 2)
|
||||
// applicationName = openDialog.FileName;
|
||||
|
||||
//return applicationName;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static FileInfo SelectFileFromNonUiThread(SynchronizationContext synchronizationContext, string ext = "*.exe", string filter = "Application EXE Name|*.exe|Application Absolute Path|*.exe")
|
||||
{
|
||||
var completionSource = new TaskCompletionSource<FileInfo>();
|
||||
|
||||
var workerThread = new Thread(() =>
|
||||
{
|
||||
// Post back to the main thread
|
||||
synchronizationContext?.Post(_ =>
|
||||
{
|
||||
var openDialog = new OpenFileDialog
|
||||
{
|
||||
DefaultExt = ext,
|
||||
Filter = filter
|
||||
};
|
||||
|
||||
if (openDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
completionSource.SetResult(new FileInfo(openDialog.FileName));
|
||||
}
|
||||
else
|
||||
{
|
||||
completionSource.SetResult(null);
|
||||
}
|
||||
}, null);
|
||||
});
|
||||
|
||||
workerThread.Start();
|
||||
|
||||
completionSource.Task.Wait();
|
||||
return completionSource.Task.Result;
|
||||
}
|
||||
|
||||
public static void ExecuteOnMainThread(Action action)
|
||||
{
|
||||
if (GlobalContext.CurrentContext.MainThreadId == Environment.CurrentManagedThreadId)
|
||||
{
|
||||
action();
|
||||
return;
|
||||
}
|
||||
|
||||
var completionSource = new TaskCompletionSource();
|
||||
|
||||
var workerThread = new Thread(() =>
|
||||
{
|
||||
// Post back to the main thread
|
||||
GlobalContext.CurrentContext.SynchronizationContext?.Post(_ =>
|
||||
{
|
||||
action();
|
||||
completionSource.SetResult();
|
||||
}, null);
|
||||
});
|
||||
|
||||
workerThread.Start();
|
||||
|
||||
completionSource.Task.Wait();
|
||||
}
|
||||
|
||||
public static bool NormEquals(this string str1, string str2)
|
||||
{
|
||||
return str1.Trim().Replace(" ", string.Empty).Equals(str2.Trim().Replace(" ", string.Empty), StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
@@ -61,9 +61,11 @@ namespace ColorControl.Shared.Contracts
|
||||
public bool DisableErrorPopupWhenApplyingPreset { get; set; }
|
||||
public UiType UiType { get; set; }
|
||||
public int UiPort { get; set; }
|
||||
public bool UiAllowRemoteConnections { get; set; }
|
||||
[JsonIgnore]
|
||||
public int CurrentUiPort { get; set; }
|
||||
public bool UiAllowRemoteConnections { get; set; }
|
||||
[JsonIgnore]
|
||||
public bool CurrentUiAllowRemoteConnections { get; set; }
|
||||
|
||||
public Config()
|
||||
{
|
||||
@@ -83,7 +85,7 @@ namespace ColorControl.Shared.Contracts
|
||||
ElevationMethod = ElevationMethod.None;
|
||||
ElevationMethodAsked = false;
|
||||
ProcessMonitorPollingInterval = 1000;
|
||||
UiType = UiType.WebEmbedded;
|
||||
UiType = UiType.WinForms;
|
||||
UiPort = 0; // Let .NET decide
|
||||
UiAllowRemoteConnections = false;
|
||||
LgPresetsSortState = new ListViewSortState();
|
||||
|
||||
@@ -12,6 +12,7 @@ public class DisplayConfig
|
||||
public DisplayConfigScaling Scaling { get; set; }
|
||||
public DisplayConfigRotation Rotation { get; set; }
|
||||
public bool? IsPrimary { get; set; }
|
||||
public DisplayConnectivity Connectivity { get; set; }
|
||||
|
||||
public DisplayConfig()
|
||||
{
|
||||
@@ -30,6 +31,7 @@ public class DisplayConfig
|
||||
Scaling = displayConfig.Scaling;
|
||||
Rotation = displayConfig.Rotation;
|
||||
IsPrimary = displayConfig.IsPrimary;
|
||||
Connectivity = displayConfig.Connectivity;
|
||||
}
|
||||
|
||||
public string GetResolutionDesc()
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ColorControl.Shared.Contracts;
|
||||
|
||||
public enum DisplayConnectivity
|
||||
{
|
||||
Unchanged = 0,
|
||||
Enabled = 1,
|
||||
Disabled = 2
|
||||
}
|
||||
@@ -21,5 +21,5 @@ public class LgDeviceOptions
|
||||
public int HDMIPortNumber { get; set; }
|
||||
|
||||
public bool UseSecureConnection { get; set; } = true;
|
||||
}
|
||||
|
||||
public bool UseNewHandshake { get; set; }
|
||||
}
|
||||
@@ -149,7 +149,8 @@ namespace ColorControl.Shared.Contracts.NVIDIA
|
||||
applyDithering = keepChanges && applyDithering || (ditheringEnabled != currentSettings.ditheringEnabled || ditheringMode != currentSettings.ditheringMode || ditheringBits != currentSettings.ditheringBits);
|
||||
applyHDR = keepChanges && applyHDR || (HDREnabled != currentSettings.HDREnabled || toggleHDR || SDRBrightness != currentSettings.SDRBrightness || HdrSettings.OutputMode != currentSettings.HdrSettings.OutputMode);
|
||||
DisplayConfig.ApplyResolution = keepChanges && DisplayConfig.ApplyResolution || (DisplayConfig.Resolution.IsDifferent(currentSettings.DisplayConfig.Resolution) ||
|
||||
DisplayConfig.Scaling != currentSettings.DisplayConfig.Scaling || DisplayConfig.Rotation != currentSettings.DisplayConfig.Rotation || DisplayConfig.IsPrimary != null && DisplayConfig.IsPrimary != currentSettings.DisplayConfig.IsPrimary);
|
||||
DisplayConfig.Scaling != currentSettings.DisplayConfig.Scaling || DisplayConfig.Rotation != currentSettings.DisplayConfig.Rotation || DisplayConfig.IsPrimary != null && DisplayConfig.IsPrimary != currentSettings.DisplayConfig.IsPrimary ||
|
||||
DisplayConfig.Connectivity != DisplayConnectivity.Unchanged);
|
||||
DisplayConfig.ApplyRefreshRate = keepChanges && DisplayConfig.ApplyRefreshRate || !DisplayConfig.RefreshRate.Equals(currentSettings.DisplayConfig.RefreshRate);
|
||||
applyOther = keepChanges && applyOther || (scaling != currentSettings.scaling || ColorProfileSettings.ProfileName != currentSettings.ColorProfileSettings.ProfileName);
|
||||
applyDriverSettings = keepChanges && applyDriverSettings || driverSettings.Any(s => !currentSettings.driverSettings.Any(o => o.Key == s.Key && o.Value == s.Value));
|
||||
@@ -216,11 +217,8 @@ namespace ColorControl.Shared.Contracts.NVIDIA
|
||||
|
||||
MonitorConnectionType = preset.MonitorConnectionType;
|
||||
|
||||
var trigger = preset.Triggers.FirstOrDefault();
|
||||
if (trigger != null)
|
||||
{
|
||||
UpdateTrigger(trigger.Trigger, trigger.Conditions, trigger.IncludedProcessesAsString, trigger.ExcludedProcessesAsString, trigger.ConnectedDisplaysRegex);
|
||||
}
|
||||
UpdateTriggers(preset.Triggers);
|
||||
|
||||
Steps.Clear();
|
||||
Steps.AddRange(preset.Steps);
|
||||
}
|
||||
|
||||
@@ -166,6 +166,19 @@ public class PresetTrigger
|
||||
{
|
||||
return processes.Contains("*") ? "all processes" : string.Join(", ", processes);
|
||||
}
|
||||
|
||||
internal void Update(PresetTrigger updatedTrigger)
|
||||
{
|
||||
Trigger = updatedTrigger.Trigger;
|
||||
Conditions = updatedTrigger.Conditions;
|
||||
|
||||
IncludedProcesses ??= [];
|
||||
ExcludedProcesses ??= [];
|
||||
Utils.ParseWords(IncludedProcesses, updatedTrigger.IncludedProcessesAsString);
|
||||
Utils.ParseWords(ExcludedProcesses, updatedTrigger.ExcludedProcessesAsString);
|
||||
|
||||
ConnectedDisplaysRegex = updatedTrigger.ConnectedDisplaysRegex;
|
||||
}
|
||||
}
|
||||
|
||||
public class PresetTriggerContext
|
||||
@@ -282,16 +295,20 @@ public abstract class PresetBase
|
||||
trigger.ConnectedDisplaysRegex = connectedDisplaysRegex;
|
||||
}
|
||||
|
||||
public PresetTrigger AddTrigger()
|
||||
public void UpdateTriggers(List<PresetTrigger> updatedTriggers)
|
||||
{
|
||||
if (!Triggers.Any())
|
||||
{
|
||||
Triggers.Add(new PresetTrigger());
|
||||
}
|
||||
Triggers.Clear();
|
||||
|
||||
return Triggers.First();
|
||||
foreach (var updatedTrigger in updatedTriggers)
|
||||
{
|
||||
var newTrigger = new PresetTrigger();
|
||||
newTrigger.Update(updatedTrigger);
|
||||
|
||||
Triggers.Add(newTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetSteps(List<string> steps)
|
||||
{
|
||||
Steps = steps;
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
public static class SamsungFactoryMenuPresets
|
||||
{
|
||||
public static readonly SamsungPreset Preset1 = new("ServiceMenuStep1", null, ["KEY_INFO", "KEY_FACTORY:2000"]);
|
||||
public static readonly SamsungPreset PresetAdvanced = new("ServiceMenuAdvanced", null, ["KEY_UP", "KEY_0", "KEY_0", "KEY_9", "KEY_8"]);
|
||||
public static readonly SamsungPreset PresetAdvancedMonitor = new("ServiceMenuAdvancedMonitor", null, ["KEY_UP", "KEY_0", "KEY_0", "KEY_3", "KEY_8"]);
|
||||
public static readonly SamsungPreset Exit = new("ServiceMenuStep3", null, ["KEY_FACTORY:1500", "KEY_FACTORY"]);
|
||||
public static readonly SamsungPreset Preset1 = new("ServiceMenuStep1", null, ["KEY_INFO:600", "KEY_FACTORY:3000"]);
|
||||
public static readonly SamsungPreset PresetAdvanced = new("ServiceMenuAdvanced", null, ["KEY_0:800", "KEY_0:800", "KEY_9:800", "KEY_8:800"]);
|
||||
public static readonly SamsungPreset PresetAdvancedMonitor = new("ServiceMenuAdvancedMonitor", null, ["KEY_0:800", "KEY_0:800", "KEY_3:800", "KEY_8:800"]);
|
||||
public static readonly SamsungPreset Exit = new("ServiceMenuStep3", null, ["KEY_FACTORY:2500", "KEY_FACTORY"]);
|
||||
public static readonly SamsungPreset KeyFactory = new("ServiceMenuKeyFactory", null, ["KEY_FACTORY"]);
|
||||
}
|
||||
|
||||
public static class SamsungHospitalityMenuPresets
|
||||
{
|
||||
public static readonly SamsungPreset Preset1 = new("ServiceMenuStep1", null, ["KEY_MUTE:600", "KEY_1:600", "KEY_1:600", "KEY_9:600", "KEY_ENTER:2000"]);
|
||||
public static readonly SamsungPreset Preset2 = new("ServiceMenuStep2", null, ["KEY_1", "KEY_2", "KEY_3", "KEY_4", "KEY_UP"]);
|
||||
public static readonly SamsungPreset Preset1 = new("ServiceMenuStep1", null, ["KEY_MUTE:800", "KEY_1:800", "KEY_1:800", "KEY_9:800", "KEY_ENTER:3000"]);
|
||||
public static readonly SamsungPreset Preset2 = new("ServiceMenuStep2", null, ["KEY_1:800", "KEY_2:800", "KEY_3:800", "KEY_4:800", "KEY_UP"]);
|
||||
public static readonly SamsungPreset Preset3 = new("ServiceMenuStep3", null, ["KEY_VOLUP:5100:Press", "KEY_VOLUP:500:Release"]);
|
||||
}
|
||||
|
||||
|
||||
+69
-8
@@ -175,6 +175,49 @@ namespace ColorControl.Shared.Native
|
||||
var sourceIndex = pathsArray[pathIndex].sourceInfo.modeInfoIdx;
|
||||
var targetIndex = pathsArray[pathIndex].targetInfo.modeInfoIdx;
|
||||
|
||||
if (displayConfig.Connectivity == DisplayConnectivity.Disabled)
|
||||
{
|
||||
var newPaths = pathsArray.Where((p, i) => i != pathIndex).ToArray();
|
||||
var newModes = modesArray.Where((m, i) => i != sourceIndex && i != targetIndex).ToArray();
|
||||
|
||||
for (var i = 0; i < newPaths.Length; i++)
|
||||
{
|
||||
var sourceDiff = 0U;
|
||||
var targetDiff = 0U;
|
||||
|
||||
if (newPaths[i].sourceInfo.modeInfoIdx > sourceIndex)
|
||||
{
|
||||
sourceDiff++;
|
||||
}
|
||||
if (newPaths[i].sourceInfo.modeInfoIdx > targetIndex)
|
||||
{
|
||||
sourceDiff++;
|
||||
}
|
||||
if (newPaths[i].targetInfo.modeInfoIdx > sourceIndex)
|
||||
{
|
||||
targetDiff++;
|
||||
}
|
||||
if (newPaths[i].targetInfo.modeInfoIdx > targetIndex)
|
||||
{
|
||||
targetDiff++;
|
||||
}
|
||||
|
||||
newPaths[i].sourceInfo.modeInfoIdx -= sourceDiff;
|
||||
newPaths[i].targetInfo.modeInfoIdx -= targetDiff;
|
||||
}
|
||||
|
||||
var flags = SdcFlags.Apply | SdcFlags.UseSuppliedDisplayConfig | SdcFlags.AllowChanges;
|
||||
|
||||
if (updateRegistry)
|
||||
{
|
||||
flags |= SdcFlags.SaveToDatabase;
|
||||
}
|
||||
|
||||
err = NativeMethods.SetDisplayConfig(pathCount - 1, newPaths, modeCount - 2, newModes, flags);
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
var resolution = displayConfig.Resolution;
|
||||
var refreshRate = displayConfig.RefreshRate;
|
||||
|
||||
@@ -322,7 +365,6 @@ namespace ColorControl.Shared.Native
|
||||
return NativeMethods.UninstallColorProfileW(null, name, true);
|
||||
}
|
||||
|
||||
|
||||
private static bool MinRequiredVersion = true;
|
||||
|
||||
public static bool AddDisplayColorProfile(string displayName, string profileName, bool setAsDefault = true, bool isHdrColorProfile = false)
|
||||
@@ -1061,6 +1103,31 @@ namespace ColorControl.Shared.Native
|
||||
return true;
|
||||
}
|
||||
|
||||
if (displayName.StartsWith("\\\\"))
|
||||
{
|
||||
return MatchDisplayNameByDeviceName(path, displayName);
|
||||
}
|
||||
|
||||
// get display name
|
||||
var info = new DISPLAYCONFIG_TARGET_DEVICE_NAME();
|
||||
info.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
|
||||
info.header.size = Marshal.SizeOf<DISPLAYCONFIG_TARGET_DEVICE_NAME>();
|
||||
info.header.adapterId = path.targetInfo.adapterId;
|
||||
info.header.id = path.targetInfo.id;
|
||||
|
||||
var err = NativeMethods.DisplayConfigGetDeviceInfo(ref info);
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var deviceName = CCD.GetDisplayIdByPath(info.monitorDevicePath);
|
||||
|
||||
return deviceName == displayName;
|
||||
}
|
||||
|
||||
private static bool MatchDisplayNameByDeviceName(DisplayConfigPathInfo path, string deviceName)
|
||||
{
|
||||
// get display name
|
||||
var info = new DISPLAYCONFIG_SOURCE_DEVICE_NAME();
|
||||
info.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||
@@ -1074,13 +1141,7 @@ namespace ColorControl.Shared.Native
|
||||
return false;
|
||||
}
|
||||
|
||||
var deviceName = info.viewGdiDeviceName;
|
||||
if (!EqualDisplayNames(deviceName, displayName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return EqualDisplayNames(deviceName, info.viewGdiDeviceName);
|
||||
}
|
||||
|
||||
private static uint GetSDRWhiteLevelForDisplayConfig(DisplayConfigModeInfo displayConfigModeInfo)
|
||||
|
||||
@@ -166,6 +166,29 @@ namespace ColorControl.Shared.Services
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool StopProcessByName(string name)
|
||||
{
|
||||
if (!_winApiService.IsAdministrator())
|
||||
{
|
||||
return _rpcService.Call<bool>(nameof(StopProcessByName), name);
|
||||
}
|
||||
|
||||
var processes = Process.GetProcessesByName(name);
|
||||
var result = false;
|
||||
|
||||
foreach (var item in processes)
|
||||
{
|
||||
try
|
||||
{
|
||||
item.Kill();
|
||||
result = true;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool SetProcessAffinity(int processId, uint affinityMask)
|
||||
{
|
||||
if (!_winApiService.IsAdministrator())
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
<UseWPF>true</UseWPF>
|
||||
@@ -25,15 +25,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.3.4" />
|
||||
<PackageReference Include="NStandard" Version="0.83.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.7" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="NLog" Version="6.1.2" />
|
||||
<PackageReference Include="NStandard" Version="0.110.7" />
|
||||
<PackageReference Include="NWin32" Version="1.2.8" />
|
||||
<PackageReference Include="System.Management" Version="9.0.0" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.11.0" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="4.0.4" />
|
||||
<PackageReference Include="System.Management" Version="10.0.7" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.12.2" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="5.0.4" />
|
||||
<PackageReference Include="RawInput.Sharp" Version="0.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace novideo_srgb
|
||||
|
||||
try
|
||||
{
|
||||
var hdrActive = hdrPaths.Contains(path);
|
||||
var hdrActive = hdrPaths?.Contains(path) == true;
|
||||
|
||||
var settings = config?.FirstOrDefault(x => (string?)x.Attribute("path") == path);
|
||||
MonitorData monitor;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<TargetFramework>net10.0-windows</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
@@ -16,13 +16,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.3.4" />
|
||||
<PackageReference Include="System.Resources.Extensions" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="6.1.2" />
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.2.14" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="EDIDParser" Version="1.2.5.4" />
|
||||
<PackageReference Include="WindowsDisplayAPI" Version="1.3.0.13" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in new issue
Block a user