init commit

This commit is contained in:
Vincent Maas committed 2020-08-22 12:45:14 +02:00
1 parent 4f674dafdd
commit 7b056c9dea
43 files changed
+7859

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>
</configuration>
+238
View File
@@ -0,0 +1,238 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A6005D08-70F0-44CB-A384-9219EBA84F21}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>ColorControl</RootNamespace>
<AssemblyName>ColorControl</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>false</MapFileExtensions>
<UpdateUrl>https://www.maassoft.com/downloads/ColorControl/</UpdateUrl>
<ProductName>ColorControl</ProductName>
<PublisherName>Maassoft</PublisherName>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>1.0.3.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>482C987E8C69872608C9D44751E004C5784E8540</ManifestCertificateThumbprint>
</PropertyGroup>
<PropertyGroup>
<ManifestKeyFile>ColorControl_TemporaryKey.pfx</ManifestKeyFile>
</PropertyGroup>
<PropertyGroup>
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
<PropertyGroup>
<TargetZone>LocalIntranet</TargetZone>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup>
<SignManifests>true</SignManifests>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>ColorControl_TemporaryKey.pfx</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>pngbarn.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Win32.TaskScheduler, Version=2.8.20.0, Culture=neutral, PublicKeyToken=c416bc1b32d97233, processorArchitecture=MSIL">
<HintPath>..\packages\TaskScheduler.2.8.20\lib\net452\Microsoft.Win32.TaskScheduler.dll</HintPath>
</Reference>
<Reference Include="Native, Version=0.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Native.0.1.0\lib\net35\Native.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.7.2\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="NStandard, Version=0.4.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NStandard.0.4.3\lib\net46\NStandard.dll</HintPath>
</Reference>
<Reference Include="NvAPIWrapper, Version=0.8.0.98, Culture=neutral, PublicKeyToken=310fd07b25df79b3, processorArchitecture=MSIL">
<HintPath>..\packages\NvAPIWrapper.Net.0.8.0.98\lib\net45\NvAPIWrapper.dll</HintPath>
</Reference>
<Reference Include="NWin32, Version=1.0.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NWin32.1.0.6\lib\net46\NWin32.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Runtime.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll</HintPath>
</Reference>
<Reference Include="System.ServiceModel" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Transactions" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Windows">
<HintPath>..\..\..\..\..\..\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.18362.0\Windows.winmd</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="RestartDetector.cs" />
<Compile Include="ExceptionExtensions.cs" />
<Compile Include="lgtv\App.cs" />
<Compile Include="lgtv\Channel.cs" />
<Compile Include="lgtv\ClientKeyStore.cs" />
<Compile Include="lgtv\ExternalInput.cs" />
<Compile Include="lgtv\IsConnectedDelegate.cs" />
<Compile Include="lgtv\LgTvApi.cs" />
<Compile Include="lgtv\LgTvConnection.cs" />
<Compile Include="lgtv\LgWebOsMouseService.cs" />
<Compile Include="lgtv\MessageType.cs" />
<Compile Include="lgtv\RawRequestMessage.cs" />
<Compile Include="lgtv\RequestMessage.cs" />
<Compile Include="PnpDev.cs" />
<Compile Include="TreeNodeBuilder.cs" />
<Compile Include="ColorDataConverter.cs" />
<Compile Include="Config.cs" />
<Compile Include="lgtv\LgApp.cs" />
<Compile Include="PresetBase.cs" />
<Compile Include="LgPreset.cs" />
<Compile Include="NvPreset.cs" />
<Compile Include="LgService.cs" />
<Compile Include="NvService.cs" />
<Compile Include="ScreenInterrogatory.cs" />
<Compile Include="Utils.cs" />
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="ColorControl_TemporaryKey.pfx" />
<Content Include="LgPresets.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="lgtv\README.md" />
<None Include="packages.config" />
<None Include="Properties\app.manifest" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="pngbarn.ico" />
</ItemGroup>
<ItemGroup>
<Folder Include="bin\x64\Debug\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+54
View File
@@ -0,0 +1,54 @@
using NvAPIWrapper.Display;
using NvAPIWrapper.Native.Display;
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
namespace ColorControl
{
public class ColorDataConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type>() { typeof(ColorData) }; }
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
Dictionary<string, object> result = new Dictionary<string, object>();
if (obj == null) return result;
return result;
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
var format = ColorDataFormat.RGB;
var dynamicRange = ColorDataDynamicRange.VESA;
var colorDepth = ColorDataDepth.BPC8;
var colorimetry = ColorDataColorimetry.Auto;
var selectionPolicy = ColorDataSelectionPolicy.User;
object value;
if (dictionary.TryGetValue("ColorFormat", out value))
{
format = (ColorDataFormat)Enum.ToObject(typeof(ColorDataFormat), value);
}
if (dictionary.TryGetValue("ColorDepth", out value))
{
colorDepth = (ColorDataDepth)Enum.ToObject(typeof(ColorDataDepth), value);
}
if (dictionary.TryGetValue("Colorimetry", out value))
{
colorimetry = (ColorDataColorimetry)Enum.ToObject(typeof(ColorDataColorimetry), value);
}
if (dictionary.TryGetValue("DynamicRange", out value))
{
dynamicRange = (ColorDataDynamicRange)Enum.ToObject(typeof(ColorDataDynamicRange), value);
}
if (dictionary.TryGetValue("SelectionPolicy", out value))
{
selectionPolicy = (ColorDataSelectionPolicy)Enum.ToObject(typeof(ColorDataSelectionPolicy), value);
}
return new ColorData(format, dynamicRange: dynamicRange, colorimetry: colorimetry, colorDepth: colorDepth, colorSelectionPolicy: selectionPolicy);
}
}
}
+14
View File
@@ -0,0 +1,14 @@
namespace ColorControl
{
class Config
{
public bool StartMinimized { get; set; }
public int DisplaySettingsDelay { get; set; }
public Config()
{
DisplaySettingsDelay = 1000;
}
}
}
+65
View File
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace ColorControl
{
/// <summary>
/// Extension methods for Exception class.
/// </summary>
static class ExceptionExtensions
{
/// <summary>
/// Provides full stack trace for the exception that occurred.
/// </summary>
/// <param name="exception">Exception object.</param>
/// <param name="environmentStackTrace">Environment stack trace, for pulling additional stack frames.</param>
public static string ToLogString(this Exception exception, string environmentStackTrace)
{
List<string> environmentStackTraceLines = ExceptionExtensions.GetUserStackTraceLines(environmentStackTrace);
environmentStackTraceLines.RemoveAt(0);
List<string> stackTraceLines = ExceptionExtensions.GetStackTraceLines(exception.StackTrace);
stackTraceLines.AddRange(environmentStackTraceLines);
string fullStackTrace = String.Join(Environment.NewLine, stackTraceLines);
string logMessage = exception.Message + Environment.NewLine + fullStackTrace;
return logMessage;
}
/// <summary>
/// Gets a list of stack frame lines, as strings.
/// </summary>
/// <param name="stackTrace">Stack trace string.</param>
private static List<string> GetStackTraceLines(string stackTrace)
{
return stackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToList();
}
/// <summary>
/// Gets a list of stack frame lines, as strings, only including those for which line number is known.
/// </summary>
/// <param name="fullStackTrace">Full stack trace, including external code.</param>
private static List<string> GetUserStackTraceLines(string fullStackTrace)
{
List<string> outputList = new List<string>();
Regex regex = new Regex(@"([^\)]*\)) in (.*):line (\d)*$");
List<string> stackTraceLines = ExceptionExtensions.GetStackTraceLines(fullStackTrace);
foreach (string stackTraceLine in stackTraceLines)
{
if (!regex.IsMatch(stackTraceLine))
{
continue;
}
outputList.Add(stackTraceLine);
}
return outputList;
}
}
}
+70
View File
@@ -0,0 +1,70 @@
using LgTv;
using System.Collections.Generic;
using System.Linq;
namespace ColorControl
{
class LgPreset : PresetBase
{
public string name { get; set; }
public string appId { get; set; }
public List<string> steps { get; set; }
public static List<LgApp> LgApps { get; set; }
public LgPreset()
{
steps = new List<string>();
}
public LgPreset(LgPreset preset) : this()
{
id = GetNewId();
name = preset.name + " (copy)";
appId = preset.appId;
foreach (var step in preset.steps)
{
steps.Add(step);
}
}
public LgPreset Clone()
{
var preset = new LgPreset(this);
return preset;
}
public static List<string> GetColumnNames()
{
return new List<string>() { "Name", "App|200", "Steps|400", "Shortcut" };
}
public List<string> GetDisplayValues()
{
var values = new List<string>();
values.Add(name);
var app = appId;
if (LgApps != null)
{
var item = LgApps.FirstOrDefault(x => x.appId.Equals(appId));
if (item != null)
{
app = item.title + " (" + appId + ")";
}
}
values.Add(app);
values.Add(GetStepsDisplay());
values.Add(shortcut);
return values;
}
public string GetStepsDisplay()
{
return steps.Aggregate("", (a, b) => (string.IsNullOrEmpty(a) ? "" : a + ", ") + b);
}
}
}
+1
View File
@@ -0,0 +1 @@
[{"name":"mode1","appId":"com.palm.app.settings","steps":["RIGHT:500","ENTER:1000","ENTER","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","ENTER","EXIT"],"shortcut":"","id":33675143},{"name":"mode2","appId":"com.palm.app.settings","steps":["RIGHT:500","ENTER:1000","ENTER","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","ENTER","EXIT"],"shortcut":"","id":34640832},{"name":"oledDown","appId":"com.palm.app.settings","steps":["RIGHT:500","ENTER:1000","DOWN","ENTER","ENTER","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","EXIT"],"shortcut":"","id":43332040},{"name":"oledUp","appId":"com.palm.app.settings","steps":["RIGHT:500","ENTER:1000","DOWN","ENTER","ENTER","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","EXIT"],"shortcut":"","id":54444047},{"name":"screenOff","appId":"com.palm.app.settings","steps":["RIGHT:500","DOWN","DOWN","ENTER","DOWN","DOWN","DOWN","DOWN","DOWN","ENTER"],"shortcut":"","id":20234383},{"name":"hdrCinemaHome","appId":"com.palm.app.settings","steps":["RIGHT:500","ENTER:1000","ENTER","DOWN","DOWN","ENTER","EXIT"],"shortcut":"","id":47891719},{"name":"hdrCinema","appId":"com.palm.app.settings","steps":["RIGHT:500","ENTER:1000","ENTER","DOWN","DOWN","DOWN","ENTER","EXIT"],"shortcut":"","id":28372289},{"name":"inputPC","appId":"com.webos.app.homeconnect","steps":["UP","ENTER:1000","DOWN","ENTER:1000","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","ENTER","UP","RIGHT","ENTER:1000","EXIT"],"shortcut":null,"id":54024015},{"name":"inputGameConsole","appId":"com.webos.app.homeconnect","steps":["UP","ENTER:1000","DOWN","ENTER:1000","DOWN","DOWN","DOWN","DOWN","DOWN","DOWN","ENTER","UP","RIGHT","ENTER:1000","EXIT"],"shortcut":null,"id":16454088},{"name":"oledDown (20)","appId":"com.palm.app.settings","steps":["RIGHT:500","ENTER:1000","DOWN","ENTER","ENTER","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","LEFT","EXIT"],"shortcut":"","id":-1681896321},{"name":"oledUp (20)","appId":"com.palm.app.settings","steps":["RIGHT:500","ENTER:1000","DOWN","ENTER","ENTER","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","RIGHT","EXIT"],"shortcut":"","id":-694559408},{"name":"HDMI1","appId":"com.webos.app.hdmi1","steps":[],"shortcut":"","id":40041277}]
+182
View File
@@ -0,0 +1,182 @@
using LgTv;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Windows.Data.Json;
namespace ColorControl
{
class LgService
{
public static string LgControllerExe = "LgController.exe";
public static string LgListAppsJson = "listApps.json";
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
public string FriendlyScreenName { get; private set; }
public List<PnpDev> Devices { get; private set; }
public PnpDev SelectedDevice { get; set; }
private LgTvApi _lgTvApi;
public LgService()
{
foreach (var screen in Screen.AllScreens)
{
var name = screen.DeviceFriendlyName();
if (name.Contains("LG"))
{
FriendlyScreenName = name;
}
}
RefreshDevices();
}
~LgService()
{
}
public void RefreshDevices(Action callBack = null)
{
Utils.GetPnpDevices("[LG]", Utils.PKEY_PNPX_IpAddress).ContinueWith((task) =>
{
SetDevicesTask(task);
callBack?.Invoke();
if (callBack == null && SelectedDevice != null)
{
ConnectToSelectedDevice();
}
}
);
}
private void SetDevicesTask(Task<List<PnpDev>> task)
{
Devices = task.Result;
if (Devices?.Count > 0)
{
SelectedDevice = Devices[0];
}
}
public async Task<bool> ConnectToSelectedDevice(int retries = 1)
{
try
{
DisposeConnection();
_lgTvApi = await LgTvApi.CreateLgTvApi(SelectedDevice.ipAddress, retries);
return true;
}
catch (Exception ex)
{
string logMessage = ex.ToLogString(Environment.StackTrace);
Logger.Error($"Error while connecting to {SelectedDevice.ipAddress}: {logMessage}");
return false;
}
}
public async Task<bool> ApplyPreset(LgPreset preset, bool reconnect = false)
{
if (SelectedDevice == null)
{
Logger.Debug("Cannot apply LG-preset: no device has been selected");
return false;
}
if (reconnect || _lgTvApi == null || !string.Equals(_lgTvApi.GetIpAddress(), SelectedDevice.ipAddress))
{
if (!await ConnectToSelectedDevice())
{
Logger.Debug("Cannot apply LG-preset: no connection could be made");
return false;
}
}
var hasApp = !string.IsNullOrEmpty(preset.appId);
if (hasApp)
{
await _lgTvApi.LaunchApp(preset.appId);
}
if (preset.steps.Any())
{
if (hasApp)
{
await Task.Delay(1500);
}
try
{
await ExecuteSteps(_lgTvApi, preset);
}
catch (Exception ex)
{
string logMessage = ex.ToLogString(Environment.StackTrace);
Logger.Error("Error while executing steps: " + logMessage);
return false;
}
}
return true;
}
private async Task ExecuteSteps(LgTvApi api, LgPreset preset)
{
var mouse = await api.GetMouse();
foreach (var step in preset.steps)
{
var keySpec = step.Split(':');
if (keySpec.Length == 2)
{
SendKey(mouse, keySpec[0], int.Parse(keySpec[1]));
}
else
{
SendKey(mouse, keySpec[0]);
}
}
}
private void SendKey(LgWebOsMouseService mouse, string key, int delay = 180)
{
if (key.Length == 1 && int.TryParse(key, out _))
{
key = "_" + key;
}
var button = (ButtonType)Enum.Parse(typeof(ButtonType), key);
mouse.SendButton(button);
Thread.Sleep(delay);
}
public async Task<List<LgApp>> RefreshApps(bool force = false)
{
if (SelectedDevice == null)
{
Logger.Debug("Cannot refresh apps: no device has been selected");
return null;
}
var api = await LgTvApi.CreateLgTvApi(SelectedDevice.ipAddress);
var list = await api.GetApps(force);
return list.ToList();
}
internal void DisposeConnection()
{
if (_lgTvApi != null)
{
_lgTvApi.Dispose();
_lgTvApi = null;
}
}
}
}
+971
View File
@@ -0,0 +1,971 @@
namespace ColorControl
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.tcMain = new System.Windows.Forms.TabControl();
this.tabNVIDIA = new System.Windows.Forms.TabPage();
this.btnAddModesNv = new System.Windows.Forms.Button();
this.btnNvPresetDelete = new System.Windows.Forms.Button();
this.lblError = new System.Windows.Forms.Label();
this.btnClone = new System.Windows.Forms.Button();
this.btnSetShortcut = new System.Windows.Forms.Button();
this.lblShortcut = new System.Windows.Forms.Label();
this.edtShortcut = new System.Windows.Forms.TextBox();
this.btnChange = new System.Windows.Forms.Button();
this.mnuNvPresets = new System.Windows.Forms.ContextMenuStrip(this.components);
this.miNvApply = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuNvDisplay = new System.Windows.Forms.ToolStripMenuItem();
this.miNvPrimaryDisplay = new System.Windows.Forms.ToolStripMenuItem();
this.mnuNvPresetsColorSettings = new System.Windows.Forms.ToolStripMenuItem();
this.miNvPresetColorSettings = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRefreshRate = new System.Windows.Forms.ToolStripMenuItem();
this.miRefreshRateIncluded = new System.Windows.Forms.ToolStripMenuItem();
this.miNvPresetDithering = new System.Windows.Forms.ToolStripMenuItem();
this.miNvPresetApplyDithering = new System.Windows.Forms.ToolStripMenuItem();
this.miNvPresetDitheringEnabled = new System.Windows.Forms.ToolStripMenuItem();
this.miNvHDR = new System.Windows.Forms.ToolStripMenuItem();
this.miHDRIncluded = new System.Windows.Forms.ToolStripMenuItem();
this.miToggleHDR = new System.Windows.Forms.ToolStripMenuItem();
this.miHDREnabled = new System.Windows.Forms.ToolStripMenuItem();
this.btnApply = new System.Windows.Forms.Button();
this.lvNvPresets = new System.Windows.Forms.ListView();
this.tabLG = new System.Windows.Forms.TabPage();
this.btnLgAddButton = new System.Windows.Forms.Button();
this.mnuLgButtons = new System.Windows.Forms.ContextMenuStrip(this.components);
this.label3 = new System.Windows.Forms.Label();
this.cbxLgDevices = new System.Windows.Forms.ComboBox();
this.btnLgRefreshApps = new System.Windows.Forms.Button();
this.btnAddLg = new System.Windows.Forms.Button();
this.btnDeleteLg = new System.Windows.Forms.Button();
this.cbxLgApps = new System.Windows.Forms.ComboBox();
this.label5 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.edtLgTvName = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.edtNameLg = new System.Windows.Forms.TextBox();
this.edtStepsLg = new System.Windows.Forms.TextBox();
this.lblStepsLg = new System.Windows.Forms.Label();
this.lblLgError = new System.Windows.Forms.Label();
this.btnCloneLg = new System.Windows.Forms.Button();
this.btnSetShortcutLg = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.edtShortcutLg = new System.Windows.Forms.TextBox();
this.btnApplyLg = new System.Windows.Forms.Button();
this.lvLgPresets = new System.Windows.Forms.ListView();
this.tabOptions = new System.Windows.Forms.TabPage();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.edtDelayDisplaySettings = new System.Windows.Forms.NumericUpDown();
this.label6 = new System.Windows.Forms.Label();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.chkStartMinimized = new System.Windows.Forms.CheckBox();
this.chkStartAfterLogin = new System.Windows.Forms.CheckBox();
this.tabLog = new System.Windows.Forms.TabPage();
this.edtLog = new System.Windows.Forms.TextBox();
this.tabInfo = new System.Windows.Forms.TabPage();
this.grpNVIDIAInfo = new System.Windows.Forms.GroupBox();
this.btnRefreshNVIDIAInfo = new System.Windows.Forms.Button();
this.tvNVIDIAInfo = new System.Windows.Forms.TreeView();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.lbPlugins = new System.Windows.Forms.ListBox();
this.label7 = new System.Windows.Forms.Label();
this.lblInfo = new System.Windows.Forms.Label();
this.tcMain.SuspendLayout();
this.tabNVIDIA.SuspendLayout();
this.mnuNvPresets.SuspendLayout();
this.tabLG.SuspendLayout();
this.tabOptions.SuspendLayout();
this.groupBox2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.edtDelayDisplaySettings)).BeginInit();
this.groupBox1.SuspendLayout();
this.tabLog.SuspendLayout();
this.tabInfo.SuspendLayout();
this.grpNVIDIAInfo.SuspendLayout();
this.groupBox3.SuspendLayout();
this.SuspendLayout();
//
// tcMain
//
this.tcMain.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tcMain.Controls.Add(this.tabNVIDIA);
this.tcMain.Controls.Add(this.tabLG);
this.tcMain.Controls.Add(this.tabOptions);
this.tcMain.Controls.Add(this.tabLog);
this.tcMain.Controls.Add(this.tabInfo);
this.tcMain.Location = new System.Drawing.Point(12, 12);
this.tcMain.Name = "tcMain";
this.tcMain.SelectedIndex = 0;
this.tcMain.Size = new System.Drawing.Size(849, 532);
this.tcMain.TabIndex = 3;
this.tcMain.SelectedIndexChanged += new System.EventHandler(this.tabControl1_SelectedIndexChanged);
//
// tabNVIDIA
//
this.tabNVIDIA.Controls.Add(this.btnAddModesNv);
this.tabNVIDIA.Controls.Add(this.btnNvPresetDelete);
this.tabNVIDIA.Controls.Add(this.lblError);
this.tabNVIDIA.Controls.Add(this.btnClone);
this.tabNVIDIA.Controls.Add(this.btnSetShortcut);
this.tabNVIDIA.Controls.Add(this.lblShortcut);
this.tabNVIDIA.Controls.Add(this.edtShortcut);
this.tabNVIDIA.Controls.Add(this.btnChange);
this.tabNVIDIA.Controls.Add(this.btnApply);
this.tabNVIDIA.Controls.Add(this.lvNvPresets);
this.tabNVIDIA.Location = new System.Drawing.Point(4, 22);
this.tabNVIDIA.Name = "tabNVIDIA";
this.tabNVIDIA.Padding = new System.Windows.Forms.Padding(3);
this.tabNVIDIA.Size = new System.Drawing.Size(841, 506);
this.tabNVIDIA.TabIndex = 0;
this.tabNVIDIA.Text = "NVIDIA controller";
this.tabNVIDIA.UseVisualStyleBackColor = true;
//
// btnAddModesNv
//
this.btnAddModesNv.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnAddModesNv.Location = new System.Drawing.Point(574, 477);
this.btnAddModesNv.Name = "btnAddModesNv";
this.btnAddModesNv.Size = new System.Drawing.Size(75, 23);
this.btnAddModesNv.TabIndex = 9;
this.btnAddModesNv.Text = "Add modes";
this.btnAddModesNv.UseVisualStyleBackColor = true;
this.btnAddModesNv.Click += new System.EventHandler(this.btnAddModesNv_Click);
//
// btnNvPresetDelete
//
this.btnNvPresetDelete.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnNvPresetDelete.Enabled = false;
this.btnNvPresetDelete.Location = new System.Drawing.Point(493, 477);
this.btnNvPresetDelete.Name = "btnNvPresetDelete";
this.btnNvPresetDelete.Size = new System.Drawing.Size(75, 23);
this.btnNvPresetDelete.TabIndex = 8;
this.btnNvPresetDelete.Text = "Delete";
this.btnNvPresetDelete.UseVisualStyleBackColor = true;
this.btnNvPresetDelete.Click += new System.EventHandler(this.btnNvPresetDelete_Click);
//
// lblError
//
this.lblError.AutoSize = true;
this.lblError.Location = new System.Drawing.Point(6, 6);
this.lblError.Name = "lblError";
this.lblError.Size = new System.Drawing.Size(50, 13);
this.lblError.TabIndex = 7;
this.lblError.Text = "ErrorText";
this.lblError.Visible = false;
//
// btnClone
//
this.btnClone.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnClone.Enabled = false;
this.btnClone.Location = new System.Drawing.Point(412, 477);
this.btnClone.Name = "btnClone";
this.btnClone.Size = new System.Drawing.Size(75, 23);
this.btnClone.TabIndex = 6;
this.btnClone.Text = "Clone";
this.btnClone.UseVisualStyleBackColor = true;
this.btnClone.Click += new System.EventHandler(this.btnClone_Click);
//
// btnSetShortcut
//
this.btnSetShortcut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnSetShortcut.Enabled = false;
this.btnSetShortcut.Location = new System.Drawing.Point(372, 477);
this.btnSetShortcut.Name = "btnSetShortcut";
this.btnSetShortcut.Size = new System.Drawing.Size(34, 23);
this.btnSetShortcut.TabIndex = 5;
this.btnSetShortcut.Text = "Set";
this.btnSetShortcut.UseVisualStyleBackColor = true;
this.btnSetShortcut.Click += new System.EventHandler(this.btnSetShortcut_Click);
//
// lblShortcut
//
this.lblShortcut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.lblShortcut.AutoSize = true;
this.lblShortcut.Location = new System.Drawing.Point(168, 482);
this.lblShortcut.Name = "lblShortcut";
this.lblShortcut.Size = new System.Drawing.Size(50, 13);
this.lblShortcut.TabIndex = 4;
this.lblShortcut.Text = "Shortcut:";
//
// edtShortcut
//
this.edtShortcut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.edtShortcut.Enabled = false;
this.edtShortcut.Location = new System.Drawing.Point(224, 479);
this.edtShortcut.Name = "edtShortcut";
this.edtShortcut.ReadOnly = true;
this.edtShortcut.Size = new System.Drawing.Size(142, 20);
this.edtShortcut.TabIndex = 3;
this.edtShortcut.TextChanged += new System.EventHandler(this.edtShortcut_TextChanged);
this.edtShortcut.KeyDown += new System.Windows.Forms.KeyEventHandler(this.edtShortcut_KeyDown);
this.edtShortcut.KeyUp += new System.Windows.Forms.KeyEventHandler(this.edtShortcut_KeyUp);
//
// btnChange
//
this.btnChange.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnChange.ContextMenuStrip = this.mnuNvPresets;
this.btnChange.Enabled = false;
this.btnChange.Location = new System.Drawing.Point(87, 477);
this.btnChange.Name = "btnChange";
this.btnChange.Size = new System.Drawing.Size(75, 23);
this.btnChange.TabIndex = 2;
this.btnChange.Text = "Change...";
this.btnChange.UseVisualStyleBackColor = true;
this.btnChange.Click += new System.EventHandler(this.btnChange_Click);
//
// mnuNvPresets
//
this.mnuNvPresets.ImageScalingSize = new System.Drawing.Size(20, 20);
this.mnuNvPresets.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miNvApply,
this.toolStripSeparator1,
this.mnuNvDisplay,
this.mnuNvPresetsColorSettings,
this.mnuRefreshRate,
this.miNvPresetDithering,
this.miNvHDR});
this.mnuNvPresets.Name = "mnuNvPresets";
this.mnuNvPresets.Size = new System.Drawing.Size(148, 142);
this.mnuNvPresets.Opening += new System.ComponentModel.CancelEventHandler(this.mnuNvPresets_Opening);
//
// miNvApply
//
this.miNvApply.Name = "miNvApply";
this.miNvApply.Size = new System.Drawing.Size(147, 22);
this.miNvApply.Text = "Apply";
this.miNvApply.Click += new System.EventHandler(this.miNvApply_Click);
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(144, 6);
//
// mnuNvDisplay
//
this.mnuNvDisplay.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miNvPrimaryDisplay});
this.mnuNvDisplay.Name = "mnuNvDisplay";
this.mnuNvDisplay.Size = new System.Drawing.Size(147, 22);
this.mnuNvDisplay.Text = "Display";
//
// miNvPrimaryDisplay
//
this.miNvPrimaryDisplay.Name = "miNvPrimaryDisplay";
this.miNvPrimaryDisplay.Size = new System.Drawing.Size(155, 22);
this.miNvPrimaryDisplay.Text = "Primary display";
this.miNvPrimaryDisplay.Click += new System.EventHandler(this.displayMenuItem_Click);
//
// mnuNvPresetsColorSettings
//
this.mnuNvPresetsColorSettings.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miNvPresetColorSettings});
this.mnuNvPresetsColorSettings.Name = "mnuNvPresetsColorSettings";
this.mnuNvPresetsColorSettings.Size = new System.Drawing.Size(147, 22);
this.mnuNvPresetsColorSettings.Text = "Color settings";
//
// miNvPresetColorSettings
//
this.miNvPresetColorSettings.Name = "miNvPresetColorSettings";
this.miNvPresetColorSettings.Size = new System.Drawing.Size(120, 22);
this.miNvPresetColorSettings.Text = "Included";
this.miNvPresetColorSettings.Click += new System.EventHandler(this.miNvPresetColorSettings_Click);
//
// mnuRefreshRate
//
this.mnuRefreshRate.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miRefreshRateIncluded});
this.mnuRefreshRate.Name = "mnuRefreshRate";
this.mnuRefreshRate.Size = new System.Drawing.Size(147, 22);
this.mnuRefreshRate.Text = "Refresh Rate";
//
// miRefreshRateIncluded
//
this.miRefreshRateIncluded.Name = "miRefreshRateIncluded";
this.miRefreshRateIncluded.Size = new System.Drawing.Size(120, 22);
this.miRefreshRateIncluded.Text = "Included";
this.miRefreshRateIncluded.Click += new System.EventHandler(this.includedToolStripMenuItem_Click);
//
// miNvPresetDithering
//
this.miNvPresetDithering.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miNvPresetApplyDithering,
this.miNvPresetDitheringEnabled});
this.miNvPresetDithering.Name = "miNvPresetDithering";
this.miNvPresetDithering.Size = new System.Drawing.Size(147, 22);
this.miNvPresetDithering.Text = "Dithering";
//
// miNvPresetApplyDithering
//
this.miNvPresetApplyDithering.Name = "miNvPresetApplyDithering";
this.miNvPresetApplyDithering.Size = new System.Drawing.Size(120, 22);
this.miNvPresetApplyDithering.Text = "Included";
this.miNvPresetApplyDithering.Click += new System.EventHandler(this.miNvPresetApplyDithering_Click);
//
// miNvPresetDitheringEnabled
//
this.miNvPresetDitheringEnabled.Name = "miNvPresetDitheringEnabled";
this.miNvPresetDitheringEnabled.Size = new System.Drawing.Size(120, 22);
this.miNvPresetDitheringEnabled.Text = "Enabled";
this.miNvPresetDitheringEnabled.Click += new System.EventHandler(this.miNvPresetDitheringEnabled_Click);
//
// miNvHDR
//
this.miNvHDR.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miHDRIncluded,
this.miToggleHDR,
this.miHDREnabled});
this.miNvHDR.Name = "miNvHDR";
this.miNvHDR.Size = new System.Drawing.Size(147, 22);
this.miNvHDR.Text = "HDR";
//
// miHDRIncluded
//
this.miHDRIncluded.Name = "miHDRIncluded";
this.miHDRIncluded.Size = new System.Drawing.Size(136, 22);
this.miHDRIncluded.Text = "Included";
this.miHDRIncluded.Click += new System.EventHandler(this.miHDRIncluded_Click);
//
// miToggleHDR
//
this.miToggleHDR.Name = "miToggleHDR";
this.miToggleHDR.Size = new System.Drawing.Size(136, 22);
this.miToggleHDR.Text = "Toggle HDR";
this.miToggleHDR.Click += new System.EventHandler(this.miToggleHDR_Click);
//
// miHDREnabled
//
this.miHDREnabled.Name = "miHDREnabled";
this.miHDREnabled.Size = new System.Drawing.Size(136, 22);
this.miHDREnabled.Text = "Enabled";
this.miHDREnabled.Click += new System.EventHandler(this.miHDREnabled_Click);
//
// btnApply
//
this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnApply.Enabled = false;
this.btnApply.Location = new System.Drawing.Point(6, 477);
this.btnApply.Name = "btnApply";
this.btnApply.Size = new System.Drawing.Size(75, 23);
this.btnApply.TabIndex = 1;
this.btnApply.Text = "Apply";
this.btnApply.UseVisualStyleBackColor = true;
this.btnApply.Click += new System.EventHandler(this.btnApply_Click);
//
// lvNvPresets
//
this.lvNvPresets.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lvNvPresets.ContextMenuStrip = this.mnuNvPresets;
this.lvNvPresets.FullRowSelect = true;
this.lvNvPresets.HideSelection = false;
this.lvNvPresets.Location = new System.Drawing.Point(6, 6);
this.lvNvPresets.MultiSelect = false;
this.lvNvPresets.Name = "lvNvPresets";
this.lvNvPresets.Size = new System.Drawing.Size(829, 465);
this.lvNvPresets.TabIndex = 0;
this.lvNvPresets.UseCompatibleStateImageBehavior = false;
this.lvNvPresets.View = System.Windows.Forms.View.Details;
this.lvNvPresets.SelectedIndexChanged += new System.EventHandler(this.lvNvPresets_SelectedIndexChanged);
this.lvNvPresets.DoubleClick += new System.EventHandler(this.lvNvPresets_DoubleClick);
//
// tabLG
//
this.tabLG.Controls.Add(this.btnLgAddButton);
this.tabLG.Controls.Add(this.label3);
this.tabLG.Controls.Add(this.cbxLgDevices);
this.tabLG.Controls.Add(this.btnLgRefreshApps);
this.tabLG.Controls.Add(this.btnAddLg);
this.tabLG.Controls.Add(this.btnDeleteLg);
this.tabLG.Controls.Add(this.cbxLgApps);
this.tabLG.Controls.Add(this.label5);
this.tabLG.Controls.Add(this.label4);
this.tabLG.Controls.Add(this.edtLgTvName);
this.tabLG.Controls.Add(this.label1);
this.tabLG.Controls.Add(this.edtNameLg);
this.tabLG.Controls.Add(this.edtStepsLg);
this.tabLG.Controls.Add(this.lblStepsLg);
this.tabLG.Controls.Add(this.lblLgError);
this.tabLG.Controls.Add(this.btnCloneLg);
this.tabLG.Controls.Add(this.btnSetShortcutLg);
this.tabLG.Controls.Add(this.label2);
this.tabLG.Controls.Add(this.edtShortcutLg);
this.tabLG.Controls.Add(this.btnApplyLg);
this.tabLG.Controls.Add(this.lvLgPresets);
this.tabLG.Location = new System.Drawing.Point(4, 22);
this.tabLG.Name = "tabLG";
this.tabLG.Padding = new System.Windows.Forms.Padding(3);
this.tabLG.Size = new System.Drawing.Size(841, 506);
this.tabLG.TabIndex = 1;
this.tabLG.Text = "LG controller";
this.tabLG.UseVisualStyleBackColor = true;
//
// btnLgAddButton
//
this.btnLgAddButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnLgAddButton.ContextMenuStrip = this.mnuLgButtons;
this.btnLgAddButton.Enabled = false;
this.btnLgAddButton.Location = new System.Drawing.Point(760, 460);
this.btnLgAddButton.Name = "btnLgAddButton";
this.btnLgAddButton.Size = new System.Drawing.Size(75, 23);
this.btnLgAddButton.TabIndex = 32;
this.btnLgAddButton.Text = "Add button";
this.btnLgAddButton.UseVisualStyleBackColor = true;
this.btnLgAddButton.Click += new System.EventHandler(this.btnLgAddButton_Click);
//
// mnuLgButtons
//
this.mnuLgButtons.ImageScalingSize = new System.Drawing.Size(20, 20);
this.mnuLgButtons.Name = "mnuLgButtons";
this.mnuLgButtons.Size = new System.Drawing.Size(61, 4);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(6, 10);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(44, 13);
this.label3.TabIndex = 31;
this.label3.Text = "Device:";
//
// cbxLgDevices
//
this.cbxLgDevices.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbxLgDevices.FormattingEnabled = true;
this.cbxLgDevices.Location = new System.Drawing.Point(87, 6);
this.cbxLgDevices.Name = "cbxLgDevices";
this.cbxLgDevices.Size = new System.Drawing.Size(281, 21);
this.cbxLgDevices.TabIndex = 30;
this.cbxLgDevices.SelectedIndexChanged += new System.EventHandler(this.cbxLgDevices_SelectedIndexChanged);
//
// btnLgRefreshApps
//
this.btnLgRefreshApps.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnLgRefreshApps.Location = new System.Drawing.Point(293, 407);
this.btnLgRefreshApps.Name = "btnLgRefreshApps";
this.btnLgRefreshApps.Size = new System.Drawing.Size(75, 23);
this.btnLgRefreshApps.TabIndex = 29;
this.btnLgRefreshApps.Text = "Refresh";
this.btnLgRefreshApps.UseVisualStyleBackColor = true;
this.btnLgRefreshApps.Click += new System.EventHandler(this.btnLgRefreshApps_Click);
//
// btnAddLg
//
this.btnAddLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnAddLg.Location = new System.Drawing.Point(168, 354);
this.btnAddLg.Name = "btnAddLg";
this.btnAddLg.Size = new System.Drawing.Size(75, 23);
this.btnAddLg.TabIndex = 28;
this.btnAddLg.Text = "Add";
this.btnAddLg.UseVisualStyleBackColor = true;
this.btnAddLg.Click += new System.EventHandler(this.btnAddLg_Click);
//
// btnDeleteLg
//
this.btnDeleteLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnDeleteLg.Enabled = false;
this.btnDeleteLg.Location = new System.Drawing.Point(249, 354);
this.btnDeleteLg.Name = "btnDeleteLg";
this.btnDeleteLg.Size = new System.Drawing.Size(75, 23);
this.btnDeleteLg.TabIndex = 27;
this.btnDeleteLg.Text = "Delete";
this.btnDeleteLg.UseVisualStyleBackColor = true;
this.btnDeleteLg.Click += new System.EventHandler(this.btnDeleteLg_Click);
//
// cbxLgApps
//
this.cbxLgApps.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.cbxLgApps.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbxLgApps.Enabled = false;
this.cbxLgApps.FormattingEnabled = true;
this.cbxLgApps.Location = new System.Drawing.Point(87, 409);
this.cbxLgApps.Name = "cbxLgApps";
this.cbxLgApps.Size = new System.Drawing.Size(200, 21);
this.cbxLgApps.TabIndex = 26;
//
// label5
//
this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(6, 412);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(29, 13);
this.label5.TabIndex = 25;
this.label5.Text = "App:";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(384, 10);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(110, 13);
this.label4.TabIndex = 24;
this.label4.Text = "Friendly screen name:";
//
// edtLgTvName
//
this.edtLgTvName.Enabled = false;
this.edtLgTvName.Location = new System.Drawing.Point(497, 7);
this.edtLgTvName.Name = "edtLgTvName";
this.edtLgTvName.Size = new System.Drawing.Size(142, 20);
this.edtLgTvName.TabIndex = 23;
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(6, 386);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(38, 13);
this.label1.TabIndex = 20;
this.label1.Text = "Name:";
//
// edtNameLg
//
this.edtNameLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.edtNameLg.Enabled = false;
this.edtNameLg.Location = new System.Drawing.Point(87, 383);
this.edtNameLg.Name = "edtNameLg";
this.edtNameLg.Size = new System.Drawing.Size(200, 20);
this.edtNameLg.TabIndex = 19;
//
// edtStepsLg
//
this.edtStepsLg.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.edtStepsLg.Enabled = false;
this.edtStepsLg.Location = new System.Drawing.Point(87, 462);
this.edtStepsLg.Multiline = true;
this.edtStepsLg.Name = "edtStepsLg";
this.edtStepsLg.Size = new System.Drawing.Size(667, 37);
this.edtStepsLg.TabIndex = 17;
//
// lblStepsLg
//
this.lblStepsLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.lblStepsLg.AutoSize = true;
this.lblStepsLg.Location = new System.Drawing.Point(6, 465);
this.lblStepsLg.Name = "lblStepsLg";
this.lblStepsLg.Size = new System.Drawing.Size(37, 13);
this.lblStepsLg.TabIndex = 16;
this.lblStepsLg.Text = "Steps:";
//
// lblLgError
//
this.lblLgError.AutoSize = true;
this.lblLgError.Location = new System.Drawing.Point(6, 6);
this.lblLgError.Name = "lblLgError";
this.lblLgError.Size = new System.Drawing.Size(50, 13);
this.lblLgError.TabIndex = 15;
this.lblLgError.Text = "ErrorText";
this.lblLgError.Visible = false;
//
// btnCloneLg
//
this.btnCloneLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnCloneLg.Enabled = false;
this.btnCloneLg.Location = new System.Drawing.Point(87, 354);
this.btnCloneLg.Name = "btnCloneLg";
this.btnCloneLg.Size = new System.Drawing.Size(75, 23);
this.btnCloneLg.TabIndex = 14;
this.btnCloneLg.Text = "Clone";
this.btnCloneLg.UseVisualStyleBackColor = true;
this.btnCloneLg.Click += new System.EventHandler(this.btnCloneLg_Click);
//
// btnSetShortcutLg
//
this.btnSetShortcutLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnSetShortcutLg.Enabled = false;
this.btnSetShortcutLg.Location = new System.Drawing.Point(330, 354);
this.btnSetShortcutLg.Name = "btnSetShortcutLg";
this.btnSetShortcutLg.Size = new System.Drawing.Size(75, 23);
this.btnSetShortcutLg.TabIndex = 13;
this.btnSetShortcutLg.Text = "Save";
this.btnSetShortcutLg.UseVisualStyleBackColor = true;
this.btnSetShortcutLg.Click += new System.EventHandler(this.btnSetShortcutLg_Click);
//
// label2
//
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(6, 439);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(50, 13);
this.label2.TabIndex = 12;
this.label2.Text = "Shortcut:";
//
// edtShortcutLg
//
this.edtShortcutLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.edtShortcutLg.Enabled = false;
this.edtShortcutLg.Location = new System.Drawing.Point(87, 436);
this.edtShortcutLg.Name = "edtShortcutLg";
this.edtShortcutLg.ReadOnly = true;
this.edtShortcutLg.Size = new System.Drawing.Size(200, 20);
this.edtShortcutLg.TabIndex = 11;
this.edtShortcutLg.KeyDown += new System.Windows.Forms.KeyEventHandler(this.edtShortcut_KeyDown);
this.edtShortcutLg.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.edtShortcut_KeyPress);
//
// btnApplyLg
//
this.btnApplyLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnApplyLg.Enabled = false;
this.btnApplyLg.Location = new System.Drawing.Point(6, 354);
this.btnApplyLg.Name = "btnApplyLg";
this.btnApplyLg.Size = new System.Drawing.Size(75, 23);
this.btnApplyLg.TabIndex = 9;
this.btnApplyLg.Text = "Apply";
this.btnApplyLg.UseVisualStyleBackColor = true;
this.btnApplyLg.Click += new System.EventHandler(this.btnApplyLg_Click);
//
// lvLgPresets
//
this.lvLgPresets.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lvLgPresets.FullRowSelect = true;
this.lvLgPresets.HideSelection = false;
this.lvLgPresets.Location = new System.Drawing.Point(6, 33);
this.lvLgPresets.MultiSelect = false;
this.lvLgPresets.Name = "lvLgPresets";
this.lvLgPresets.Size = new System.Drawing.Size(829, 315);
this.lvLgPresets.TabIndex = 8;
this.lvLgPresets.UseCompatibleStateImageBehavior = false;
this.lvLgPresets.View = System.Windows.Forms.View.Details;
this.lvLgPresets.SelectedIndexChanged += new System.EventHandler(this.lvLgPresets_SelectedIndexChanged);
this.lvLgPresets.DoubleClick += new System.EventHandler(this.lvLgPresets_DoubleClick);
//
// tabOptions
//
this.tabOptions.Controls.Add(this.groupBox2);
this.tabOptions.Controls.Add(this.groupBox1);
this.tabOptions.Location = new System.Drawing.Point(4, 22);
this.tabOptions.Name = "tabOptions";
this.tabOptions.Padding = new System.Windows.Forms.Padding(3);
this.tabOptions.Size = new System.Drawing.Size(841, 506);
this.tabOptions.TabIndex = 2;
this.tabOptions.Text = "Options";
this.tabOptions.UseVisualStyleBackColor = true;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.edtDelayDisplaySettings);
this.groupBox2.Controls.Add(this.label6);
this.groupBox2.Location = new System.Drawing.Point(6, 119);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(376, 107);
this.groupBox2.TabIndex = 3;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "HDR";
//
// edtDelayDisplaySettings
//
this.edtDelayDisplaySettings.Increment = new decimal(new int[] {
100,
0,
0,
0});
this.edtDelayDisplaySettings.Location = new System.Drawing.Point(296, 17);
this.edtDelayDisplaySettings.Maximum = new decimal(new int[] {
5000,
0,
0,
0});
this.edtDelayDisplaySettings.Name = "edtDelayDisplaySettings";
this.edtDelayDisplaySettings.ReadOnly = true;
this.edtDelayDisplaySettings.Size = new System.Drawing.Size(74, 20);
this.edtDelayDisplaySettings.TabIndex = 1;
this.edtDelayDisplaySettings.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
this.edtDelayDisplaySettings.ValueChanged += new System.EventHandler(this.edtDelayDisplaySettings_ValueChanged);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(6, 19);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(174, 13);
this.label6.TabIndex = 0;
this.label6.Text = "Delay opening display settings (ms):";
//
// groupBox1
//
this.groupBox1.Controls.Add(this.chkStartMinimized);
this.groupBox1.Controls.Add(this.chkStartAfterLogin);
this.groupBox1.Location = new System.Drawing.Point(6, 6);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(376, 107);
this.groupBox1.TabIndex = 2;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "General";
//
// chkStartMinimized
//
this.chkStartMinimized.AutoSize = true;
this.chkStartMinimized.Location = new System.Drawing.Point(6, 42);
this.chkStartMinimized.Name = "chkStartMinimized";
this.chkStartMinimized.Size = new System.Drawing.Size(96, 17);
this.chkStartMinimized.TabIndex = 3;
this.chkStartMinimized.Text = "Start minimized";
this.chkStartMinimized.UseVisualStyleBackColor = true;
//
// chkStartAfterLogin
//
this.chkStartAfterLogin.AutoSize = true;
this.chkStartAfterLogin.Location = new System.Drawing.Point(6, 19);
this.chkStartAfterLogin.Name = "chkStartAfterLogin";
this.chkStartAfterLogin.Size = new System.Drawing.Size(160, 17);
this.chkStartAfterLogin.TabIndex = 2;
this.chkStartAfterLogin.Text = "Automatically start after login";
this.chkStartAfterLogin.UseVisualStyleBackColor = true;
this.chkStartAfterLogin.CheckedChanged += new System.EventHandler(this.chkStartAfterLogin_CheckedChanged);
//
// tabLog
//
this.tabLog.Controls.Add(this.edtLog);
this.tabLog.Location = new System.Drawing.Point(4, 22);
this.tabLog.Name = "tabLog";
this.tabLog.Padding = new System.Windows.Forms.Padding(3);
this.tabLog.Size = new System.Drawing.Size(841, 506);
this.tabLog.TabIndex = 3;
this.tabLog.Text = "Log";
this.tabLog.UseVisualStyleBackColor = true;
//
// edtLog
//
this.edtLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.edtLog.Location = new System.Drawing.Point(6, 6);
this.edtLog.Multiline = true;
this.edtLog.Name = "edtLog";
this.edtLog.ReadOnly = true;
this.edtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.edtLog.Size = new System.Drawing.Size(832, 497);
this.edtLog.TabIndex = 0;
//
// tabInfo
//
this.tabInfo.Controls.Add(this.grpNVIDIAInfo);
this.tabInfo.Controls.Add(this.groupBox3);
this.tabInfo.Location = new System.Drawing.Point(4, 22);
this.tabInfo.Name = "tabInfo";
this.tabInfo.Padding = new System.Windows.Forms.Padding(3);
this.tabInfo.Size = new System.Drawing.Size(841, 506);
this.tabInfo.TabIndex = 4;
this.tabInfo.Text = "Info";
this.tabInfo.UseVisualStyleBackColor = true;
//
// grpNVIDIAInfo
//
this.grpNVIDIAInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.grpNVIDIAInfo.Controls.Add(this.btnRefreshNVIDIAInfo);
this.grpNVIDIAInfo.Controls.Add(this.tvNVIDIAInfo);
this.grpNVIDIAInfo.Location = new System.Drawing.Point(397, 6);
this.grpNVIDIAInfo.Name = "grpNVIDIAInfo";
this.grpNVIDIAInfo.Size = new System.Drawing.Size(440, 496);
this.grpNVIDIAInfo.TabIndex = 4;
this.grpNVIDIAInfo.TabStop = false;
this.grpNVIDIAInfo.Text = "NVIDIA info";
//
// btnRefreshNVIDIAInfo
//
this.btnRefreshNVIDIAInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnRefreshNVIDIAInfo.Location = new System.Drawing.Point(6, 467);
this.btnRefreshNVIDIAInfo.Name = "btnRefreshNVIDIAInfo";
this.btnRefreshNVIDIAInfo.Size = new System.Drawing.Size(75, 23);
this.btnRefreshNVIDIAInfo.TabIndex = 1;
this.btnRefreshNVIDIAInfo.Text = "Refresh";
this.btnRefreshNVIDIAInfo.UseVisualStyleBackColor = true;
this.btnRefreshNVIDIAInfo.Click += new System.EventHandler(this.btnRefreshNVIDIAInfo_Click);
//
// tvNVIDIAInfo
//
this.tvNVIDIAInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tvNVIDIAInfo.Location = new System.Drawing.Point(6, 19);
this.tvNVIDIAInfo.Name = "tvNVIDIAInfo";
this.tvNVIDIAInfo.Size = new System.Drawing.Size(428, 442);
this.tvNVIDIAInfo.TabIndex = 0;
//
// groupBox3
//
this.groupBox3.Controls.Add(this.lbPlugins);
this.groupBox3.Controls.Add(this.label7);
this.groupBox3.Controls.Add(this.lblInfo);
this.groupBox3.Location = new System.Drawing.Point(6, 6);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(385, 220);
this.groupBox3.TabIndex = 5;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Info";
//
// lbPlugins
//
this.lbPlugins.FormattingEnabled = true;
this.lbPlugins.HorizontalScrollbar = true;
this.lbPlugins.Location = new System.Drawing.Point(9, 67);
this.lbPlugins.Name = "lbPlugins";
this.lbPlugins.Size = new System.Drawing.Size(371, 147);
this.lbPlugins.TabIndex = 3;
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(6, 51);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(236, 13);
this.label7.TabIndex = 2;
this.label7.Text = "This app contains the following 3rd party plugins:";
//
// lblInfo
//
this.lblInfo.AutoSize = true;
this.lblInfo.Location = new System.Drawing.Point(6, 20);
this.lblInfo.Name = "lblInfo";
this.lblInfo.Size = new System.Drawing.Size(25, 13);
this.lblInfo.TabIndex = 1;
this.lblInfo.Text = "Info";
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
this.ClientSize = new System.Drawing.Size(873, 556);
this.Controls.Add(this.tcMain);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimumSize = new System.Drawing.Size(800, 398);
this.Name = "MainForm";
this.Text = "ColorControl";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed);
this.Load += new System.EventHandler(this.MainForm_Load);
this.Shown += new System.EventHandler(this.MainForm_Shown);
this.Resize += new System.EventHandler(this.MainForm_Resize);
this.tcMain.ResumeLayout(false);
this.tabNVIDIA.ResumeLayout(false);
this.tabNVIDIA.PerformLayout();
this.mnuNvPresets.ResumeLayout(false);
this.tabLG.ResumeLayout(false);
this.tabLG.PerformLayout();
this.tabOptions.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.edtDelayDisplaySettings)).EndInit();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.tabLog.ResumeLayout(false);
this.tabLog.PerformLayout();
this.tabInfo.ResumeLayout(false);
this.grpNVIDIAInfo.ResumeLayout(false);
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TabControl tcMain;
private System.Windows.Forms.TabPage tabNVIDIA;
private System.Windows.Forms.TabPage tabLG;
private System.Windows.Forms.ListView lvNvPresets;
private System.Windows.Forms.Button btnApply;
private System.Windows.Forms.Button btnChange;
private System.Windows.Forms.Button btnSetShortcut;
private System.Windows.Forms.Label lblShortcut;
private System.Windows.Forms.TextBox edtShortcut;
private System.Windows.Forms.TabPage tabOptions;
private System.Windows.Forms.Button btnClone;
private System.Windows.Forms.ContextMenuStrip mnuNvPresets;
private System.Windows.Forms.ToolStripMenuItem miNvPresetDithering;
private System.Windows.Forms.ToolStripMenuItem miNvPresetApplyDithering;
private System.Windows.Forms.ToolStripMenuItem miNvPresetDitheringEnabled;
private System.Windows.Forms.ToolStripMenuItem mnuRefreshRate;
private System.Windows.Forms.ToolStripMenuItem miRefreshRateIncluded;
private System.Windows.Forms.ToolStripMenuItem miNvHDR;
private System.Windows.Forms.ToolStripMenuItem miHDRIncluded;
private System.Windows.Forms.ToolStripMenuItem miToggleHDR;
private System.Windows.Forms.ToolStripMenuItem miHDREnabled;
private System.Windows.Forms.Label lblError;
private System.Windows.Forms.Label lblLgError;
private System.Windows.Forms.Button btnCloneLg;
private System.Windows.Forms.Button btnSetShortcutLg;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox edtShortcutLg;
private System.Windows.Forms.Button btnApplyLg;
private System.Windows.Forms.ListView lvLgPresets;
private System.Windows.Forms.TextBox edtStepsLg;
private System.Windows.Forms.Label lblStepsLg;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox edtNameLg;
private System.Windows.Forms.Button btnNvPresetDelete;
private System.Windows.Forms.Button btnAddModesNv;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox edtLgTvName;
private System.Windows.Forms.ComboBox cbxLgApps;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.ToolStripMenuItem miNvApply;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.Button btnDeleteLg;
private System.Windows.Forms.Button btnAddLg;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.CheckBox chkStartMinimized;
private System.Windows.Forms.CheckBox chkStartAfterLogin;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.NumericUpDown edtDelayDisplaySettings;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.ToolStripMenuItem mnuNvDisplay;
private System.Windows.Forms.ToolStripMenuItem miNvPrimaryDisplay;
private System.Windows.Forms.TabPage tabLog;
private System.Windows.Forms.TextBox edtLog;
private System.Windows.Forms.TabPage tabInfo;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.ListBox lbPlugins;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label lblInfo;
private System.Windows.Forms.GroupBox grpNVIDIAInfo;
private System.Windows.Forms.TreeView tvNVIDIAInfo;
private System.Windows.Forms.Button btnLgRefreshApps;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox cbxLgDevices;
private System.Windows.Forms.Button btnRefreshNVIDIAInfo;
private System.Windows.Forms.Button btnLgAddButton;
private System.Windows.Forms.ContextMenuStrip mnuLgButtons;
private System.Windows.Forms.ToolStripMenuItem mnuNvPresetsColorSettings;
private System.Windows.Forms.ToolStripMenuItem miNvPresetColorSettings;
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+186
View File
@@ -0,0 +1,186 @@
using NvAPIWrapper.Display;
using NvAPIWrapper.Native.Display;
using System;
using System.Collections.Generic;
using System.Text;
namespace ColorControl
{
class NvPreset : PresetBase
{
public bool applyColorData { get; set; }
public ColorData colorData { get; set; }
public bool applyHDR { get; set; }
public bool HDREnabled { get; set; }
public bool toggleHDR { get; set; }
public bool applyDithering { get; set; }
public bool ditheringEnabled { get; set; }
public bool applyRefreshRate { get; set; }
public uint refreshRate { get; set; }
public bool primaryDisplay { get; set; }
public string displayName { get; set; }
public NvPreset()
{
applyColorData = true;
applyDithering = false;
ditheringEnabled = true;
applyHDR = false;
HDREnabled = false;
toggleHDR = false;
applyRefreshRate = false;
refreshRate = 60;
primaryDisplay = true;
}
public NvPreset(ColorData colorData) : this()
{
id = GetNewId();
this.colorData = colorData;
}
public NvPreset(NvPreset preset): this()
{
id = GetNewId();
primaryDisplay = preset.primaryDisplay;
displayName = preset.displayName;
var colorData = preset.colorData;
this.colorData = new ColorData(colorData.ColorFormat, dynamicRange: colorData.DynamicRange, colorDepth: colorData.ColorDepth, colorSelectionPolicy: colorData.SelectionPolicy);
applyColorData = preset.applyColorData;
applyHDR = preset.applyHDR;
HDREnabled = preset.HDREnabled;
toggleHDR = preset.toggleHDR;
applyDithering = preset.applyDithering;
ditheringEnabled = preset.ditheringEnabled;
applyRefreshRate = preset.applyRefreshRate;
refreshRate = preset.refreshRate;
}
public NvPreset Clone()
{
var preset = new NvPreset(this);
return preset;
}
public static string[] GetColumnNames()
{
//return new[] { "BPC", "Format", "Dynamic range", "Toggle HDR", "Shortcut" };
return new[] { "Display|80", "Color settings (BPC, format, dyn. range, color space)|260", "Refresh rate|100", "Dithering", "HDR", "Shortcut" };
}
public List<string> GetDisplayValues()
{
var values = new List<string>();
var display = string.Format("{0}", primaryDisplay ? "Primary" : displayName);
values.Add(display);
var colorSettings = string.Format("{0}: {1}, {2}, {3}, {4}", applyColorData ? "Included" : "Excluded", colorData.ColorDepth, colorData.ColorFormat, colorData.DynamicRange, colorData.Colorimetry);
values.Add(colorSettings);
values.Add(string.Format("{0}: {1}Hz", applyRefreshRate ? "Included" : "Excluded", refreshRate));
values.Add(string.Format("{0}: {1}", applyDithering ? "Included" : "Excluded", ditheringEnabled ? "Enabled" : "Disabled"));
values.Add(string.Format("{0}: {1}", applyHDR ? "Included" : "Excluded", toggleHDR ? "Toggle" : HDREnabled ? "Enabled" : "Disabled"));
//values.Add(colorData.ColorDepth.ToString());
//values.Add(colorData.ColorFormat.ToString());
//values.Add(colorData.DynamicRange.ToString());
//values.Add(toggleHDR.ToString());
values.Add(shortcut);
return values;
}
public static List<NvPreset> GetDefaultPresets()
{
var presets = new List<NvPreset>();
presets.Add(new NvPreset(new ColorData(ColorDataFormat.Auto, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.Default, colorSelectionPolicy: ColorDataSelectionPolicy.BestQuality)));
for (var dynamicRange = ColorDataDynamicRange.VESA; dynamicRange <= ColorDataDynamicRange.CEA; dynamicRange++)
{
presets.Add(new NvPreset(new ColorData(ColorDataFormat.RGB, dynamicRange: dynamicRange, colorDepth: ColorDataDepth.BPC8, colorSelectionPolicy: ColorDataSelectionPolicy.User)));
presets.Add(new NvPreset(new ColorData(ColorDataFormat.RGB, dynamicRange: dynamicRange, colorDepth: ColorDataDepth.BPC10, colorSelectionPolicy: ColorDataSelectionPolicy.User)));
presets.Add(new NvPreset(new ColorData(ColorDataFormat.RGB, dynamicRange: dynamicRange, colorDepth: ColorDataDepth.BPC12, colorSelectionPolicy: ColorDataSelectionPolicy.User)));
}
for (var format = ColorDataFormat.YUV422; format <= ColorDataFormat.YUV420; format++)
{
presets.Add(new NvPreset(new ColorData(format, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.BPC8, colorSelectionPolicy: ColorDataSelectionPolicy.User)));
presets.Add(new NvPreset(new ColorData(format, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.BPC10, colorSelectionPolicy: ColorDataSelectionPolicy.User)));
presets.Add(new NvPreset(new ColorData(format, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.BPC12, colorSelectionPolicy: ColorDataSelectionPolicy.User)));
}
return presets;
}
public string GetTextForMenuItem()
{
var sb = new StringBuilder();
if (displayName != null)
{
sb.AppendFormat("Display: {0} / ", displayName);
}
if (applyColorData)
{
var colorSettings = string.Format("Format: {0}, {1}, {2}", colorData.ColorDepth, colorData.ColorFormat, colorData.DynamicRange);
sb.Append(colorSettings);
sb.Append(" / ");
}
if (applyRefreshRate)
{
sb.AppendFormat("{0}Hz", refreshRate);
sb.Append(" / ");
}
if (applyDithering)
{
sb.AppendFormat("Dithering: {0}", ditheringEnabled ? "Yes" : "No");
sb.Append(" / ");
}
if (applyHDR)
{
sb.AppendFormat("HDR: {0}", toggleHDR ? "Toggle" : HDREnabled ? "Enabled" : "Disabled");
sb.Append(" / ");
}
return sb.ToString(0, Math.Max(0, sb.Length - 3));
}
public static ColorData GenerateColorData(IDictionary<string, object> dictionary)
{
var format = ColorDataFormat.RGB;
var dynamicRange = ColorDataDynamicRange.VESA;
var colorDepth = ColorDataDepth.BPC8;
var colorimetry = ColorDataColorimetry.Auto;
var selectionPolicy = ColorDataSelectionPolicy.User;
object value;
if (dictionary.TryGetValue("ColorFormat", out value))
{
format = (ColorDataFormat)Enum.ToObject(typeof(ColorDataFormat), value);
}
if (dictionary.TryGetValue("ColorDepth", out value))
{
colorDepth = (ColorDataDepth)Enum.ToObject(typeof(ColorDataDepth), value);
}
if (dictionary.TryGetValue("Colorimetry", out value))
{
colorimetry = (ColorDataColorimetry)Enum.ToObject(typeof(ColorDataColorimetry), value);
}
if (dictionary.TryGetValue("DynamicRange", out value))
{
dynamicRange = (ColorDataDynamicRange)Enum.ToObject(typeof(ColorDataDynamicRange), value);
}
if (dictionary.TryGetValue("SelectionPolicy", out value))
{
selectionPolicy = (ColorDataSelectionPolicy)Enum.ToObject(typeof(ColorDataSelectionPolicy), value);
}
return new ColorData(format, dynamicRange: dynamicRange, colorimetry: colorimetry, colorDepth: colorDepth, colorSelectionPolicy: selectionPolicy);
}
}
}
+221
View File
@@ -0,0 +1,221 @@
using NvAPIWrapper;
using NvAPIWrapper.Display;
using NvAPIWrapper.Native;
using NvAPIWrapper.Native.Display;
using NvAPIWrapper.Native.Display.Structures;
using NvAPIWrapper.Native.Exceptions;
using NvAPIWrapper.Native.GPU.Structures;
using NWin32;
using NWin32.NativeTypes;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
namespace ColorControl
{
class NvService
{
const UInt32 WM_KEYDOWN = 0x0100;
const UInt32 WM_KEYUP = 0x0101;
const int VK_TAB = 0x09;
const int VK_SPACE = 0x20;
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
[DllImport(@"nvapi64", EntryPoint = @"nvapi_QueryInterface", CallingConvention = CallingConvention.Cdecl,
PreserveSig = true)]
private static extern IntPtr NvAPI64_QueryInterface(uint interfaceId);
public delegate long NvAPI_Disp_SetDitherControl(
[In] PhysicalGPUHandle physicalGpu,
[In] uint OutputId,
[In] uint state,
[In] uint bits,
[In] uint mode
);
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
private Display _currentDisplay;
public NvService()
{
NVIDIA.Initialize();
}
~NvService()
{
NVIDIA.Unload();
}
public Display GetCurrentDisplay()
{
if (_currentDisplay == null)
{
_currentDisplay = Display.GetDisplays()[0];
}
return _currentDisplay;
}
private void SetCurrentDisplay(NvPreset preset)
{
if (preset.primaryDisplay)
{
var displayId = DisplayDevice.GetGDIPrimaryDisplayDevice().DisplayId;
_currentDisplay = Display.GetDisplays().FirstOrDefault(x => x.DisplayDevice.DisplayId == displayId);
}
else
{
_currentDisplay = Display.GetDisplays().FirstOrDefault(x => x.Name.Equals(preset.displayName));
}
}
public bool ApplyPreset(NvPreset preset, Config config)
{
SetCurrentDisplay(preset);
if (preset.applyHDR)
{
if (preset.toggleHDR || preset.HDREnabled != IsHDREnabled())
{
ToggleHDR(config.DisplaySettingsDelay);
}
}
if (preset.applyRefreshRate)
{
SetRefreshRate(preset.refreshRate);
}
if (preset.applyColorData)
{
var display = GetCurrentDisplay();
//var data = new ColorData(ColorDataFormat.YUV444, ColorDataColorimetry.YCC709, ColorDataDynamicRange.Auto, ColorDataDepth.BPC8, preset.colorData.SelectionPolicy, ColorDataDesktopDepth.Default);
display.DisplayDevice.SetColorData(preset.colorData);
//var master = display.DisplayDevice.HDRColorData.MasteringDisplayData;
//var newMaster = new MasteringDisplayColorData(master.FirstColorCoordinate, master.SecondColorCoordinate, master.ThirdColorCoordinate, new ColorDataColorCoordinate(0.25f, 0.25f), 50, 0, 50, 50);
//var hdr = new HDRColorData(ColorDataHDRMode.UHDA, newMaster, ColorDataFormat.YUV444, ColorDataDynamicRange.Auto, ColorDataDepth.BPC8);
//display.DisplayDevice.SetHDRColorData(hdr);
}
if (preset.applyDithering)
{
SetDithering(preset.ditheringEnabled);
}
return true;
}
public void ToggleHDR(int delay = 1000)
{
Process.Start("ms-settings:display");
Thread.Sleep(delay);
var process = Process.GetProcessesByName("SystemSettings").FirstOrDefault();
if (process != null)
{
System.Windows.Forms.SendKeys.SendWait("{TAB}");
System.Windows.Forms.SendKeys.SendWait("{TAB}");
System.Windows.Forms.SendKeys.SendWait(" ");
System.Windows.Forms.SendKeys.SendWait("%{F4}");
}
}
public void SetDithering(bool enabled)
{
var ptr = NvAPI64_QueryInterface(0xDF0DFCDD);
if (ptr != IntPtr.Zero)
{
var delegateValue = Marshal.GetDelegateForFunctionPointer(ptr, typeof(NvAPI_Disp_SetDitherControl)) as NvAPI_Disp_SetDitherControl;
var displayDevice = GetCurrentDisplay().DisplayDevice;
var gpuHandle = displayDevice.PhysicalGPU.Handle;
var displayId = displayDevice.DisplayId;
var result = delegateValue(gpuHandle, displayId, (uint)(enabled ? 1 : 2), 1, 4);
if (result != 0)
{
Logger.Error($"Could not set dithering because NvAPI_Disp_SetDitherControl returned a non-zero return code: {result}");
}
}
}
public bool SetRefreshRate(uint refreshRate)
{
var display = GetCurrentDisplay();
var portrait = new[] { Rotate.Degree90, Rotate.Degree270 }.Contains(display.DisplayDevice.ScanOutInformation.SourceToTargetRotation);
var timing = display.DisplayDevice.CurrentTiming;
uint i = 0;
DEVMODEA devMode;
while (NativeMethods.EnumDisplaySettingsA(display.Name, i, out devMode))
{
// Also compare width with vertical and height with horizontal in case of portrait mode
if (((!portrait && devMode.dmPelsWidth == timing.HorizontalVisible && devMode.dmPelsHeight == timing.VerticalVisible) ||
(portrait && devMode.dmPelsWidth == timing.VerticalVisible && devMode.dmPelsHeight == timing.HorizontalVisible))
&& devMode.dmBitsPerPel == 32 && devMode.dmDisplayFrequency == refreshRate)
{
IntPtr bla = Marshal.AllocHGlobal(Marshal.SizeOf(devMode));
Marshal.StructureToPtr(devMode, bla, false);
var result = NativeMethods.ChangeDisplaySettingsExA(display.Name, bla, IntPtr.Zero, 0, IntPtr.Zero);
if (result != NativeConstants.DISP_CHANGE_SUCCESSFUL)
{
Logger.Error($"Could not set refreshrate {refreshRate} on display {display.Name} because ChangeDisplaySettingsExA returned a non-zero return code: {result}");
}
return result == NativeConstants.DISP_CHANGE_SUCCESSFUL;
}
i++;
}
Logger.Info($"Could not set refreshrate {refreshRate} on display {display.Name} because EnumDisplaySettings did not report it as a valid refreshrate");
return false;
}
public List<uint> GetAvailableRefreshRates(NvPreset preset = null)
{
var list = new List<uint>();
if (preset != null)
{
SetCurrentDisplay(preset);
}
var display = GetCurrentDisplay();
var portrait = new[] { Rotate.Degree90, Rotate.Degree270 }.Contains(display.DisplayDevice.ScanOutInformation.SourceToTargetRotation);
var timing = display.DisplayDevice.CurrentTiming;
uint i = 0;
DEVMODEA devMode;
while (NativeMethods.EnumDisplaySettingsA(display.Name, i, out devMode))
{
if ((!portrait && devMode.dmPelsWidth == timing.HorizontalVisible && devMode.dmPelsHeight == timing.VerticalVisible) ||
(portrait && devMode.dmPelsWidth == timing.VerticalVisible && devMode.dmPelsHeight == timing.HorizontalVisible))
{
list.Add(devMode.dmDisplayFrequency);
}
i++;
}
return list;
}
public bool IsHDREnabled()
{
var displayDevice = GetCurrentDisplay().DisplayDevice;
var hdr = displayDevice.HDRColorData;
return hdr?.HDRMode == ColorDataHDRMode.UHDA;
}
public Display[] GetDisplays()
{
return Display.GetDisplays();
}
}
}
+22
View File
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.Linq;
namespace ColorControl
{
class PnpDev
{
public string name { get; set; }
public string ipAddress { get; set; }
public PnpDev(string name, string ipAddress)
{
this.name = name;
this.ipAddress = ipAddress;
}
public override string ToString()
{
return name + " (" + ipAddress + ")";
}
}
}
+49
View File
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
namespace ColorControl
{
internal abstract class PresetBase
{
public string shortcut { get; set; }
private int _id;
public int id
{
get
{
return _id;
}
set
{
if (value == 0 || ids.Contains(value))
{
value = GetNewId();
}
else
{
ids.Add(value);
}
_id = value;
}
}
public static List<int> ids = new List<int>();
public static int GetNewId()
{
int id;
do
{
id = new Random().Next();
}
while (ids.Contains(id));
ids.Add(id);
return id;
}
}
}
+43
View File
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ColorControl
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
string mutexId = $"Global\\{typeof(MainForm).GUID}";
bool mutexCreated;
var mutex = new Mutex(true, mutexId, out mutexCreated);
try
{
if (!mutexCreated)
{
MessageBox.Show("Only one instance of this program can be active.", "ColorControl");
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
finally
{
if (mutexCreated)
{
mutex.Dispose();
}
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ColorControl")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Maassoft")]
[assembly: AssemblyProduct("ColorControl")]
[assembly: AssemblyCopyright("Copyright © Maassoft 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("a6005d08-70f0-44cb-a384-9219eba84f21")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.3.0")]
[assembly: AssemblyFileVersion("1.0.3.0")]
+71
View File
@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ColorControl.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ColorControl.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}
+117
View File
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+30
View File
@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ColorControl.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
+59
View File
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
<applicationRequestMinimum>
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
<defaultAssemblyRequest permissionSetReference="Custom" />
</applicationRequestMinimum>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 compatibility -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
-->
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>
+90
View File
@@ -0,0 +1,90 @@
using NLog;
using System;
using System.Diagnostics.Eventing.Reader;
namespace ColorControl
{
public class RestartDetector : IDisposable
{
public bool RestartDetected { get; private set; }
private EventLogWatcher watcher = null;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public RestartDetector()
{
try
{
EventLogQuery subscriptionQuery = new EventLogQuery(
"System", PathType.LogName, "*[System[Provider[@Name='USER32'] and (EventID=1074)]]");
watcher = new EventLogWatcher(subscriptionQuery);
// Make the watcher listen to the EventRecordWritten
// events. When this event happens, the callback method
// (EventLogEventRead) is called.
watcher.EventRecordWritten +=
new EventHandler<EventRecordWrittenEventArgs>(
EventLogEventRead);
// Activate the subscription
watcher.Enabled = true;
}
catch (EventLogReadingException e)
{
}
}
public void EventLogEventRead(object obj, EventRecordWrittenEventArgs arg)
{
RestartDetected = false;
try
{
Logger.Debug("Logging event: " + arg);
// Make sure there was no error reading the event.
if (arg.EventRecord != null)
{
foreach (EventProperty x in ((EventLogRecord)arg.EventRecord).Properties)
{
Logger.Debug("Event value: " + x.Value);
if (x.Value.Equals("restart"))
{
RestartDetected = true;
break;
}
}
}
//if (arg.EventRecord != null)
//{
// String[] xPathRefs = new String[1];
// xPathRefs[0] = "Event/EventData/Data";
// IEnumerable<String> xPathEnum = xPathRefs;
// EventLogPropertySelector logPropertyContext = new EventLogPropertySelector(xPathEnum);
// IList<object> logEventProps = ((EventLogRecord)arg.EventRecord).GetPropertyValues(logPropertyContext);
// string[] eventData = (string[])logEventProps[0];
// foreach (string attribute in eventData)
// {
// if (attribute.Contains("restart")) { restart = true; break; }
// }
//}
}
catch (Exception e)
{
}
}
public void Dispose()
{
// Stop listening to events
if (watcher != null)
{
watcher.Enabled = false;
watcher.Dispose();
}
}
}
}
+313
View File
@@ -0,0 +1,313 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ColorControl
{
public static class ScreenInterrogatory
{
public const int ERROR_SUCCESS = 0;
#region enums
public enum QUERY_DEVICE_CONFIG_FLAGS : uint
{
QDC_ALL_PATHS = 0x00000001,
QDC_ONLY_ACTIVE_PATHS = 0x00000002,
QDC_DATABASE_CURRENT = 0x00000004
}
public enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY : uint
{
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = 0xFFFFFFFF,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = 0x80000000,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_SCANLINE_ORDERING : uint
{
DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0,
DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_ROTATION : uint
{
DISPLAYCONFIG_ROTATION_IDENTITY = 1,
DISPLAYCONFIG_ROTATION_ROTATE90 = 2,
DISPLAYCONFIG_ROTATION_ROTATE180 = 3,
DISPLAYCONFIG_ROTATION_ROTATE270 = 4,
DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_SCALING : uint
{
DISPLAYCONFIG_SCALING_IDENTITY = 1,
DISPLAYCONFIG_SCALING_CENTERED = 2,
DISPLAYCONFIG_SCALING_STRETCHED = 3,
DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
DISPLAYCONFIG_SCALING_CUSTOM = 5,
DISPLAYCONFIG_SCALING_PREFERRED = 128,
DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_PIXELFORMAT : uint
{
DISPLAYCONFIG_PIXELFORMAT_8BPP = 1,
DISPLAYCONFIG_PIXELFORMAT_16BPP = 2,
DISPLAYCONFIG_PIXELFORMAT_24BPP = 3,
DISPLAYCONFIG_PIXELFORMAT_32BPP = 4,
DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5,
DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff
}
public enum DISPLAYCONFIG_MODE_INFO_TYPE : uint
{
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : uint
{
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF
}
#endregion
#region structs
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_SOURCE_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
public uint statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_TARGET_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
private DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
private DISPLAYCONFIG_ROTATION rotation;
private DISPLAYCONFIG_SCALING scaling;
private DISPLAYCONFIG_RATIONAL refreshRate;
private DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
public bool targetAvailable;
public uint statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_RATIONAL
{
public uint Numerator;
public uint Denominator;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_INFO
{
public DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;
public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
public uint flags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_2DREGION
{
public uint cx;
public uint cy;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO
{
public ulong pixelRate;
public DISPLAYCONFIG_RATIONAL hSyncFreq;
public DISPLAYCONFIG_RATIONAL vSyncFreq;
public DISPLAYCONFIG_2DREGION activeSize;
public DISPLAYCONFIG_2DREGION totalSize;
public uint videoStandard;
public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_TARGET_MODE
{
public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINTL
{
private int x;
private int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_SOURCE_MODE
{
public uint width;
public uint height;
public DISPLAYCONFIG_PIXELFORMAT pixelFormat;
public POINTL position;
}
[StructLayout(LayoutKind.Explicit)]
public struct DISPLAYCONFIG_MODE_INFO_UNION
{
[FieldOffset(0)]
public DISPLAYCONFIG_TARGET_MODE targetMode;
[FieldOffset(0)]
public DISPLAYCONFIG_SOURCE_MODE sourceMode;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_MODE_INFO
{
public DISPLAYCONFIG_MODE_INFO_TYPE infoType;
public uint id;
public LUID adapterId;
public DISPLAYCONFIG_MODE_INFO_UNION modeInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
{
public uint value;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_DEVICE_INFO_HEADER
{
public DISPLAYCONFIG_DEVICE_INFO_TYPE type;
public uint size;
public LUID adapterId;
public uint id;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME
{
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;
public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
public ushort edidManufactureId;
public ushort edidProductCodeId;
public uint connectorInstance;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string monitorFriendlyDeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string monitorDevicePath;
}
#endregion
#region DLL-Imports
[DllImport("user32.dll")]
public static extern int GetDisplayConfigBufferSizes(
QUERY_DEVICE_CONFIG_FLAGS flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
[DllImport("user32.dll")]
public static extern int QueryDisplayConfig(
QUERY_DEVICE_CONFIG_FLAGS flags,
ref uint numPathArrayElements, [Out] DISPLAYCONFIG_PATH_INFO[] PathInfoArray,
ref uint numModeInfoArrayElements, [Out] DISPLAYCONFIG_MODE_INFO[] ModeInfoArray,
IntPtr currentTopologyId
);
[DllImport("user32.dll")]
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName);
#endregion
private static string MonitorFriendlyName(LUID adapterId, uint targetId)
{
var deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME
{
header =
{
size = (uint)Marshal.SizeOf(typeof (DISPLAYCONFIG_TARGET_DEVICE_NAME)),
adapterId = adapterId,
id = targetId,
type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME
}
};
var error = DisplayConfigGetDeviceInfo(ref deviceName);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
return deviceName.monitorFriendlyDeviceName;
}
private static IEnumerable<string> GetAllMonitorsFriendlyNames()
{
uint pathCount, modeCount;
var error = GetDisplayConfigBufferSizes(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
var displayPaths = new DISPLAYCONFIG_PATH_INFO[pathCount];
var displayModes = new DISPLAYCONFIG_MODE_INFO[modeCount];
error = QueryDisplayConfig(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
for (var i = 0; i < modeCount; i++)
if (displayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
yield return MonitorFriendlyName(displayModes[i].adapterId, displayModes[i].id);
}
public static string DeviceFriendlyName(this Screen screen)
{
var allFriendlyNames = GetAllMonitorsFriendlyNames();
for (var index = 0; index < Screen.AllScreens.Length; index++)
if (Equals(screen, Screen.AllScreens[index]))
return allFriendlyNames.ToArray()[index];
return null;
}
}
}
+99
View File
@@ -0,0 +1,99 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Windows.Forms;
namespace ColorControl
{
public class TreeNodeBuilder
{
public string Name { get; set; }
public string Value { get; set; }
public List<TreeNode> Children { get; set; } = new List<TreeNode>();
public static TreeNode CreateTree(object obj, string text)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
var serialized = JsonConvert.SerializeObject(obj, Formatting.None,
new JsonSerializerSettings {
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Error = delegate (object sender, ErrorEventArgs args)
{
//errors.Add(args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
},
Converters = new [] { new Newtonsoft.Json.Converters.StringEnumConverter() }
});
Dictionary<string, object> dic = jss.Deserialize<Dictionary<string, object>>(serialized);
var root = new TreeNode();
root.Text = text;
BuildTree(dic, root);
return root;
}
private static void BuildTree(object item, TreeNode node)
{
if (item is KeyValuePair<string, object>)
{
KeyValuePair<string, object> kv = (KeyValuePair<string, object>)item;
TreeNode keyValueNode = new TreeNode();
keyValueNode.Name = kv.Key;
keyValueNode.Text = kv.Key + ": " + GetValueAsString(kv.Value);
node.Nodes.Add(keyValueNode);
BuildTree(kv.Value, keyValueNode);
}
else if (item is ArrayList)
{
ArrayList list = (ArrayList)item;
int index = 0;
foreach (object value in list)
{
TreeNode arrayItem = new TreeNode();
arrayItem.Name = $"[{index}]";
arrayItem.Text = $"[{index}]";
node.Nodes.Add(arrayItem);
BuildTree(value, arrayItem);
index++;
}
}
else if (item is Dictionary<string, object>)
{
Dictionary<string, object> dictionary = (Dictionary<string, object>)item;
foreach (KeyValuePair<string, object> d in dictionary)
{
BuildTree(d, node);
}
}
}
private static string GetValueAsString(object value)
{
if (value == null)
return "null";
var type = value.GetType();
if (type.IsArray)
{
return "[]";
}
if (value is ArrayList)
{
var arr = value as ArrayList;
return $"[{arr.Count}]";
}
if (type.IsGenericType)
{
return "{}";
}
return value.ToString();
}
}
}
+231
View File
@@ -0,0 +1,231 @@
using NWin32.NativeTypes;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Windows.Devices.Enumeration;
using Windows.Devices.Enumeration.Pnp;
namespace ColorControl
{
class Utils
{
[Flags]
public enum ModKeys : int
{
Alt = 1,
Control = 2,
Shift = 4,
Win = 8
}
public static string PKEY_PNPX_IpAddress = "{656a3bb3-ecc0-43fd-8477-4ae0404a96cd} 12297";
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
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;
if (!string.IsNullOrEmpty(subDir))
{
path = Path.Combine(path, subDir);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
return path;
}
public static (int mods, int key) ParseShortcut(string shortcut)
{
int mods = 0;
var key = 0;
shortcut = shortcut.Replace(",", "");
shortcut = shortcut.Replace("+", "");
shortcut = shortcut.Replace(" ", " ");
var parts = shortcut.Split(' ');
if (parts.Length > 0)
{
for (int i = 0; i + 1 < parts.Length; i++)
{
switch (parts[i])
{
case "Alt":
mods += (int)ModKeys.Alt;
break;
case "Control":
mods += (int)ModKeys.Control;
break;
case "Shift":
mods += (int)ModKeys.Shift;
break;
case "Win":
mods += (int)ModKeys.Win;
break;
}
}
var keyName = parts[parts.Length - 1];
key = (int)Enum.Parse(typeof(Keys), keyName);
}
return (mods, key);
}
public static async Task<string> GetDeviceProperty(string deviceName, string propertyName)
{
string value = null;
string name = null;
var list = await DeviceInformation.FindAllAsync("", new List<string>());
var reqs = new List<string>();
reqs.Add(propertyName);
foreach (var dev in list)
{
name = dev.Name;
if (dev.IsEnabled && dev.Name.Contains(deviceName))
{
//Debug.WriteLine(dev.Name);
//foreach (var key in dev.Properties.Keys)
//{
// Debug.WriteLine($"* {key}: {dev.Properties[key]}");
//}
var guid = dev.Properties["System.Devices.DeviceInstanceId"];
var aqs = "System.Devices.DeviceInstanceId:=\"" + guid + "\"";
var list2 = await PnpObject.FindAllAsync(PnpObjectType.Device, reqs, aqs);
foreach (var dev2 in list2)
{
foreach (var key in dev2.Properties.Keys)
{
var obj = dev2.Properties[key];
string newValue = null;
if (obj is string[])
{
var arr = obj as string[];
if (arr.Length > 0)
{
newValue = arr[0];
}
}
else
{
newValue = dev2.Properties[key].ToString();
}
if (newValue != value)
{
value = newValue;
Logger.Debug($"LG TV with name {dev.Name} found at {value}");
}
//Debug.WriteLine($"* {key}: {value}");
}
}
}
}
return value;
}
public static async Task<List<PnpDev>> GetPnpDevices(string deviceName, string propertyName)
{
var devices = new List<PnpDev>();
var list = await DeviceInformation.FindAllAsync("", new List<string>());
var reqs = new List<string>();
reqs.Add(propertyName);
foreach (var dev in list)
{
string name = dev.Name;
if (dev.IsEnabled && dev.Name.Contains(deviceName))
{
var guid = dev.Properties["System.Devices.DeviceInstanceId"];
var aqs = "System.Devices.DeviceInstanceId:=\"" + guid + "\"";
var list2 = await PnpObject.FindAllAsync(PnpObjectType.Device, reqs, aqs);
foreach (var dev2 in list2)
{
foreach (var key in dev2.Properties.Keys)
{
var obj = dev2.Properties[key];
string value = null;
if (obj is string[])
{
var arr = obj as string[];
if (arr.Length > 0)
{
value = arr[0];
}
}
else
{
value = dev2.Properties[key].ToString();
}
if (!devices.Any(x => x.name.Equals(name) && x.ipAddress.Equals(value)))
{
var device = new PnpDev(name, value);
devices.Add(device);
}
}
}
}
}
return devices;
}
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace LgTv
{
public class App
{
public string Id { get; set; }
public string LaunchPointId { get; set; }
public string Icon { get; set; }
public string Title { get; set; }
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace LgTv
{
public class Channel
{
public string Id { get; set; }
public int Number { get; set; }
public string Name { get; set; }
}
}
+28
View File
@@ -0,0 +1,28 @@
using ColorControl;
using System.IO;
namespace LgTv
{
public class ClientKeyStore
{
private string ip;
public ClientKeyStore(string ip)
{
this.ip = ip;
}
public string GetClientKey()
{
var filename = Path.Combine(Utils.GetDataPath(), ip + "_ClientKey.txt");
if (File.Exists(filename))
{
return File.ReadAllText(filename);
}
return null;
}
public void SaveClientKey(string key)
{
var filename = Path.Combine(Utils.GetDataPath(), ip + "_ClientKey.txt");
File.WriteAllText(filename, key);
}
}
}
+15
View File
@@ -0,0 +1,15 @@
namespace LgTv
{
public class ExternalInput
{
public ExternalInput(string id,string label)
{
Id = id;
Label = label;
}
public string Id { get; set; }
public string Label { get; set; }
public string Icon { get; set; }
}
}
+4
View File
@@ -0,0 +1,4 @@
namespace LgTv
{
public delegate void IsConnectedDelegate(bool status);
}
+19
View File
@@ -0,0 +1,19 @@
namespace LgTv
{
public class LgApp
{
public string title { get; set; }
public string appId { get; set; }
public LgApp(string appId, string title)
{
this.appId = appId;
this.title = title;
}
public override string ToString()
{
return title;
}
}
}
+371
View File
@@ -0,0 +1,371 @@
using ColorControl;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Storage;
namespace LgTv
{
//https://mym.hackpad.com/ep/pad/static/rLlshKkzdNj
public enum ControlButtons
{
Back,Down,Left,Right,
OK,
Exit
}
public class LgTvApi:IDisposable
{
private readonly LgTvApiCore _connection;
private LgWebOsMouseService _mouseConnection;
private readonly ClientKeyStore _keyStore;
private List<Channel> _channelList;
private List<App> _appList;
private string _ip;
private const string BEFORE_PAIR_HAND_SHAKE = "{\"type\":\"register\",\"id\":\"register_0\",\"payload\":{\"forcePairing\":false,\"pairingType\":\"PROMPT\",\"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\",\"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\"],\"signatures\":[{\"signatureVersion\":1,\"signature\":\"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw==\"}]}}}";
private const string AFTER_PAIR_HAND_SHAKE = "{\"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\",\"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\"],\"signatures\":[{\"signatureVersion\":1,\"signature\":\"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw==\"}]}}}";
public Task ControlButton(object oK)
{
// throw new NotImplementedException();
return null;
}
private string _currentPariKey;
private string webSocketUri;
public static async Task<LgTvApi> CreateLgTvApi(string ip, int retries = 1)
{
var instance = new LgTvApi(ip, new LgTvApiCore(), new ClientKeyStore(ip));
while (retries > 0)
{
var connected = await instance.Connect();
if (connected)
{
await instance.MakeHandShake();
return instance;
}
retries--;
await Task.Delay(500);
}
instance.Dispose();
return null;
}
public LgTvApi(string ip, LgTvApiCore connection, ClientKeyStore keyStore)
{
webSocketUri = "ws://" + ip + ":3000";
_ip = ip;
_connection = connection;
_keyStore = keyStore;
}
public string GetIpAddress()
{
return _ip;
}
public async Task MakeHandShake()
{
_currentPariKey = _keyStore.GetClientKey();
if (_currentPariKey != null)
{
var key = AFTER_PAIR_HAND_SHAKE.Replace("CLIENTKEYGOESHERE", _currentPariKey);
var conn = await _connection.SendCommandAsync(key);
_keyStore.SaveClientKey((string)conn.clientKey);
return;
}
dynamic result = await _connection.SendCommandAsync(BEFORE_PAIR_HAND_SHAKE);
_keyStore.SaveClientKey(result.clientKey);
}
public async Task<bool> Connect()
{
var ctx = _connection.Connect(new Uri(webSocketUri));
return await ctx;
}
public async Task<LgWebOsMouseService> GetMouse()
{
if (_mouseConnection != null) return _mouseConnection;
var requestMessage = new RequestMessage("ssap://com.webos.service.networkinput/getPointerInputSocket", new { });
var s = await _connection.SendCommandAsync(requestMessage);
var socketPath = (string)s.socketPath;
_mouseConnection = new LgWebOsMouseService(new LgTvApiCore());
await _mouseConnection.Connect(socketPath);
return _mouseConnection;
}
public async Task<IEnumerable<Channel>> ChannelList()
{
_channelList = new List<Channel>();
var requestMessage = new RequestMessage("channels", "ssap://tv/getChannelList");
var command = _connection.SendCommandAsync(requestMessage);
var res = await command;
foreach (var c in res.channelList)
{
_channelList.Add(new Channel
{
Id = c.channelId,
Name = c.channelName,
Number = int.Parse((string)c.channelNumber)
});
}
return _channelList.OrderBy(e => e.Number);
}
public async Task<Channel> GetChannel()
{
var requestMessage = new RequestMessage("channels", "ssap://tv/getCurrentChannel");
var command = _connection.SendCommandAsync(requestMessage);
var res = await command;
return new Channel() { Id = res.channelId, Name = res.channelName, Number = int.Parse(res.channelNumber) };
}
public async Task ShowToast()
{
var requestMessage = new RequestMessage("ssap://system.notifications/createToast",new {message = "Co tam u Ciebie?"});
await _connection.SendCommandAsync(requestMessage);
}
//public async Task<string> LaunchApp(string appId,Uri uri)
//{
// var url = uri.ToString();
// var requestMessage = new RequestMessage("ssap://system.launcher/launch", new { id = appId, @params={contentTarget } });
// var response = await _connection.SendCommandAsync(requestMessage);
// return (string)response.sessionId;
//}
public async Task VolumeDown()
{
var requestMessage = new RequestMessage("volumedown", "ssap://audio/volumeDown");
await _connection.SendCommandAsync(requestMessage);
}
public async Task VolumeUp()
{
var requestMessage = new RequestMessage("volumeup", "ssap://audio/volumeUp");
await _connection.SendCommandAsync(requestMessage);
}
public async Task ChannelInfo()
{
var requestMessage = new RequestMessage("programinfo", "ssap://tv/getChannelProgramInfo");
await _connection.SendCommandAsync(requestMessage);
}
public async Task SetChannel(string channelId)
{
var requestMessage = new RequestMessage("ssap://tv/openChannel", new { channelId });
await _connection.SendCommandAsync(requestMessage);
}
public async Task SetMute(bool value)
{
var requestMessage = new RequestMessage("ssap://audio/setMute", new { mute = value });
await _connection.SendCommandAsync(requestMessage);
}
public async Task ToogleMute()
{
await SetMute(!await IsMuted());
}
public async Task<bool> IsMuted()
{
var requestMessage = new RequestMessage("status", "ssap://audio/getStatus");
var command = _connection.SendCommandAsync(requestMessage);
return (bool)(await command).mute;
}
public async Task SetVolume(int value)
{
if (value >= 0 && value <= 100)
{
var requestMessage = new RequestMessage("ssap://audio/setVolume", new { volume = value });
await _connection.SendCommandAsync(requestMessage);
}
}
public async Task TurnOff()
{
await _connection.SendCommandAsync(new RequestMessage("","ssap://system/turnOff"));
}
public async Task Play()
{
await _connection.SendCommandAsync(new RequestMessage("play", "ssap://media.controls/play"));
}
public async Task Pause()
{
await _connection.SendCommandAsync(new RequestMessage("pause", "ssap://media.controls/pause"));
}
public async Task ChannelUp()
{
await _connection.SendCommandAsync(new RequestMessage("channelUp", "ssap://tv/channelUp"));
}
public async Task ChannelDown()
{
await _connection.SendCommandAsync(new RequestMessage("channelDown", "ssap://tv/channelDown"));
}
public async Task Stop()
{
await _connection.SendCommandAsync(new RequestMessage("stop", "ssap://media.controls/stop"));
}
public async Task TurnOn3D()
{
await _connection.SendCommandAsync(new RequestMessage("3d", "ssap://com.webos.service.tv.display/set3DOn"));
}
public async Task TurnOff3D()
{
await _connection.SendCommandAsync(new RequestMessage("3d", "ssap://com.webos.service.tv.display/set3DOff"));
}
public async Task<bool> IsTurnedOn3D()
{
//Response: { returnValue: true, status3D: { status: true, pattern: ’2Dto3D’ } }
var requestMessage = new RequestMessage("status3D", "ssap://com.webos.service.tv.display/get3DStatus");
var o = await _connection.SendCommandAsync(requestMessage);
return (bool)o.status3D.status;
}
public async Task<int> GetVolume()
{
// {
// "type": "response",
// "id": "status_1",
// "payload": {
// "muted": false,
// "scenario": "mastervolume_tv_speaker",
// "active": false,
// "action": "requested",
// "volume": 7,
// "returnValue": true,
// "subscribed": true
// }
// }
var requestMessage = new RequestMessage("status", "ssap://audio/getVolume");
var o = await _connection.SendCommandAsync(requestMessage);
return( (bool)o.muted) ? -1 :(int) o.volume;
}
public async Task<IEnumerable<ExternalInput>> GetInputList()
{
var requestMessage = new RequestMessage("input","ssap://tv/getExternalInputList");
var results = await _connection.SendCommandAsync(requestMessage);
var l = new List<ExternalInput>();
foreach (var result in results)
{
l.Add(new ExternalInput(result.id, result.label)
{
Icon = result.icon
});
}
return l;
}
public async Task SetInput(string id)
{
var requestMessage = new RequestMessage("ssap://tv/switchInput", new { inputId = id });
await _connection.SendCommandAsync(requestMessage);
}
public async Task<IEnumerable<App>> GetLaunchPoints()
{
_appList = new List<App>();
var requestMessage = new RequestMessage("launcher", "ssap://com.webos.applicationManager/listLaunchPoints");
var command = _connection.SendCommandAsync(requestMessage);
var res = await command;
foreach (var c in res.launchpoints)
{
_appList.Add(new App
{
Id = c.id,
LaunchPointId = c.launchPointId,
Title = c.title,
Icon = c.icon
});
}
return _appList.OrderBy(e => e.Title);
}
public async Task<IEnumerable<LgApp>> GetApps(bool force = false)
{
var appList = new List<LgApp>();
dynamic res;
var filename = Path.Combine(Utils.GetDataPath(), _ip + "_listApps.json");
if (!force && File.Exists(filename))
{
var json = File.ReadAllText(filename);
res = JToken.Parse(json);
}
else
{
var requestMessage = new RequestMessage("ssap://com.webos.applicationManager/listApps", new { });
var command = _connection.SendCommandAsync(requestMessage);
res = await command;
var json = Convert.ToString(res);
File.WriteAllText(filename, json);
}
foreach (var c in res.apps)
{
appList.Add(new LgApp((string)c.id, (string)c.title));
}
return appList.OrderBy(e => e.title);
}
public async Task<string> LaunchApp(string appId)
{
var requestMessage = new RequestMessage("ssap://system.launcher/launch", new { id = appId });
var response = await _connection.SendCommandAsync(requestMessage);
return (string)response.sessionId;
}
public async Task<string> CloseApp(string appId)
{
var requestMessage = new RequestMessage("ssap://system.launcher/close", new { id = appId });
var response = await _connection.SendCommandAsync(requestMessage);
return (string)response.sessionId;
}
public async Task<string> OpenWebBrowser(Uri uri)
{
var url = uri.ToString();
var requestMessage = new RequestMessage("ssap://system.launcher/open", new { target = url });
var response = await _connection.SendCommandAsync(requestMessage);
return (string)response.sessionId;
}
public async Task<string> LaunchYouTube(string videoId)
{
return await LaunchYouTube(new Uri($"http://www.youtube.com/tv?v={videoId}"));
}
public async Task<string> LaunchYouTube(Uri uri)
{
var url = uri.ToString();
var requestMessage = new RequestMessage("ssap://system.launcher/launch", new { id = "youtube.leanback.v4", @params = new { contentTarget = url } });
var response = await _connection.SendCommandAsync(requestMessage);
return (string)response.sessionId;
}
public void Close()
{
_connection.Close();
}
public void Dispose()
{
_connection?.Dispose();
}
}
}
+167
View File
@@ -0,0 +1,167 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.Web;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;
using Windows.Foundation;
namespace LgTv
{
public class SendMessageException : Exception
{
public SendMessageException(string message, Exception e) : base(message, e)
{
}
}
public class LgTvApiCore : IDisposable
{
private MessageWebSocket _connection;
private DataWriter _messageWriter;
private int _commandCount;
public event IsConnectedDelegate IsConnected;
private readonly ConcurrentDictionary<string, TaskCompletionSource<dynamic>> _tokens = new ConcurrentDictionary<string, TaskCompletionSource<dynamic>>();
private static void Log(RawRequestMessage message) { }
public async Task<bool> Connect(Uri uri, bool ignoreReceiver = false)
{
try
{
_commandCount = 0;
_connection = new MessageWebSocket();
_connection.Control.MessageType = SocketMessageType.Utf8;
// if(ignoreReceiver==false)
_connection.MessageReceived += Connection_MessageReceived;
_connection.Closed += Connection_Closed;
await _connection.ConnectAsync(uri);
IsConnected?.Invoke(true);
_messageWriter = new DataWriter(_connection.OutputStream);
return true;
}
catch (Exception e)
{
switch (SocketError.GetStatus(e.HResult))
{
case SocketErrorStatus.HostNotFound:
// Handle HostNotFound Error
break;
default:
// Handle Unknown Error
break;
}
return false;
}
}
public async void SendMessageAsync(string message)
{
_messageWriter.WriteString(message);
await _messageWriter.StoreAsync();
}
public Task<dynamic> SendCommandAsync(string message)
{
var obj = JsonConvert.DeserializeObject<dynamic>(message);
return SendCommandAsync((string)obj.id, message);
}
private Task<dynamic> SendCommandAsync(string id, string message)
{
try
{
var taskSource = new TaskCompletionSource<dynamic>();
_tokens.TryAdd(id, taskSource);
SendMessageAsync(message);
return taskSource.Task;
}
catch (Exception e)
{
throw new SendMessageException("Can't send message", e);
}
}
public Task<dynamic> SendCommandAsync(RequestMessage message)
{
var rawMessage = new RawRequestMessage(message, ++_commandCount);
var serialized = JsonConvert.SerializeObject(rawMessage, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
return SendCommandAsync(rawMessage.Id, serialized);
}
private void Connection_Closed(IWebSocket sender, WebSocketClosedEventArgs args)
{
MessageWebSocket webSocket = Interlocked.Exchange(ref _connection, null);
webSocket?.Dispose();
}
private void Connection_MessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args)
{
try
{
using (var dr = args.GetDataReader())
{
dr.UnicodeEncoding = UnicodeEncoding.Utf8;
var message = dr.ReadString(dr.UnconsumedBufferLength);
var obj = JsonConvert.DeserializeObject<dynamic>(message);
var id = (string)obj.id;
var type = (string)obj.type;
TaskCompletionSource<dynamic> taskCompletion;
if (type == "registered")
{
if (_tokens.TryRemove(id, out taskCompletion))
{
var key = (string)JObject.Parse(message)["payload"]["client-key"];
taskCompletion.TrySetResult(new { clientKey = key });
}
}
else
if (_tokens.TryGetValue(id, out taskCompletion))
{
if (id == "register_0") return;
if (obj.type == "error")
{
taskCompletion.SetException(new Exception(obj.error));
}
//else if (args.Cancelled)
//{
// taskSource.SetCanceled();
//}
taskCompletion.TrySetResult(obj.payload);
}
}
}
catch (Exception ex)
{
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
}
}
public void Close()
{
_connection?.Close(1, "");
}
public void Dispose()
{
_connection?.Dispose();
}
}
}
+82
View File
@@ -0,0 +1,82 @@
using NStandard;
using System;
using System.Threading.Tasks;
namespace LgTv
{
public enum ButtonType
{
HOME,
BACK,
ENTER,
EXIT,
UP,
DOWN,
LEFT,
RIGHT,
RED,
GREEN,
YELLOW,
BLUE,
_1,
_2,
_3,
_4,
_5,
_6,
_7,
_8,
_9,
_0,
POWER
}
public class LgWebOsMouseService : IDisposable
{
private readonly LgTvApiCore _connection;
public LgWebOsMouseService(LgTvApiCore connection)
{
_connection = connection;
}
public async Task<bool> Connect(string uri)
{
var ctx = _connection.Connect(new Uri(uri), ignoreReceiver: true);
return (await ctx);
}
public void SendButton(int number)
{
_connection.SendMessageAsync($"type:button\nname:{number}\n\n");
}
public void SendButton(ButtonType bt)
{
var text = bt.ToString();
if (text[0] == '_')
{
text = text.Substring(1);
}
_connection.SendMessageAsync($"type:button\nname:{text}\n\n");
}
public void Move(double dx, double dy, bool drag = false)
{
_connection.SendMessageAsync($"type:move\ndx:{dx}\ndy:{dy}\ndown:{(drag ? 1 : 0)}\n\n");
}
public void Scroll(double dx, double dy)
{
_connection.SendMessageAsync($"type:scroll\ndx:{dx}\ndy:{dy}\n\n");
}
public void Click()
{
_connection.SendMessageAsync("type:click\n\n");
}
public void Dispose()
{
_connection?.Dispose();
}
}
}
+4
View File
@@ -0,0 +1,4 @@
namespace LgTv
{
public enum MessageType { Request}
}
+30
View File
@@ -0,0 +1,30 @@
# lgtv.net
LG TV WebOS API for .NET
For now, there is only API, example app will be added in the future.
## inspiration:
* https://github.com/msloth/lgtv.js/blob/master/index.js
## references:
* https://github.com/ConnectSDK/Connect-SDK-Android-Core
* https://github.com/CODeRUS/harbour-lgremote-webos
* https://github.com/openwebos
* https://mym.hackpad.com/ep/pad/static/rLlshKkzdNj
## Usage
```C#
// Initalization
var _instance = new LgTvApi(ip,new LgTvApiCore(), new ClientKeyStore(ip));
await _instance.Connect();
await _instance.MakeHandShake();
await _instance.GetMouse();
//control
await _instance.VolumeDown();
await _instance.TurnOff();
......
(await _instance.GetMouse()).SendButton(ButtonType.RED);
(await _instance.GetMouse()).SendButton(ButtonType.LEFT);
..
```
+18
View File
@@ -0,0 +1,18 @@
namespace LgTv
{
internal class RawRequestMessage
{
public RawRequestMessage(RequestMessage rm, int commandCount)
{
var prefix = (rm.Prefix ?? "");
Id = prefix + (prefix.Length>0?"_":"") + commandCount;
Type = rm.Type??"request";
Uri = rm.Uri;
Payload = rm.Payload;
}
public string Id { get; set; }
public string Type { get; set; }
public string Uri { get; set; }
public string Payload { get; set; }
}
}
+23
View File
@@ -0,0 +1,23 @@
using Newtonsoft.Json;
namespace LgTv
{
public class RequestMessage
{
public RequestMessage(string prefix, string uri)
{
Prefix = prefix;
Uri = uri;
}
public RequestMessage(string uri,object payload)
{
Uri = uri;
Payload = JsonConvert.SerializeObject(payload);
}
public string Prefix { get; set; }
public string Type { get; set; }
public string Uri { get; set; }
public string Payload { get; set; }
}
}
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Native" version="0.1.0" targetFramework="net472" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" />
<package id="NLog" version="4.7.2" targetFramework="net472" />
<package id="NStandard" version="0.4.3" targetFramework="net472" />
<package id="NvAPIWrapper.Net" version="0.8.0.98" targetFramework="net472" />
<package id="NWin32" version="1.0.6" targetFramework="net472" />
<package id="TaskScheduler" version="2.8.20" targetFramework="net472" />
</packages>
Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB