mirror of
https://github.com/Maassoft/ColorControl.git
synced 2026-10-22 00:22:18 -05:00
add samsung service, fix some issues
This commit is contained in:
1 parent
97b931f433
commit
3d7abd991c
35 files changed
+4362
-87
No files matched your search
@@ -62,6 +62,9 @@
|
||||
<Compile Update="Services\NVIDIA\NvPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Services\Samsung\SamsungPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Resources\LG_register.json" />
|
||||
<EmbeddedResource Include="Resources\RC_coords.txt" />
|
||||
<EmbeddedResource Include="Resources\LG_remote.jpg" />
|
||||
@@ -105,6 +108,11 @@
|
||||
<ProjectReference Include="..\Nspector\Nspector.csproj" />
|
||||
<ProjectReference Include="..\NvAPIWrapper\NvAPIWrapper.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Services\Samsung\SamsungPanel.resx">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
|
||||
@@ -388,6 +388,22 @@ The best and suggested method to provide this is via a Windows Service. Only whe
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void SetBrightness(IntPtr handle)
|
||||
{
|
||||
var displays = Windows.Graphics.Display.DisplayServices.FindAll();
|
||||
|
||||
var folderPicker = new Windows.Storage.Pickers.FolderPicker();
|
||||
|
||||
// Initialize the folder picker with the window handle (HWND).
|
||||
WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, handle);
|
||||
|
||||
folderPicker.FileTypeFilter.Add("*");
|
||||
var folder = folderPicker.PickSingleFolderAsync().GetAwaiter();
|
||||
|
||||
//var info = Windows.Graphics.Display.DisplayInformation.GetForCurrentView();
|
||||
//var colorInfo = info.GetAdvancedColorInfo();
|
||||
}
|
||||
|
||||
public static async Task<List<PnpDev>> GetPnpDevices(string deviceName)
|
||||
{
|
||||
var devices = new List<PnpDev>();
|
||||
@@ -698,13 +714,24 @@ The best and suggested method to provide this is via a Windows Service. Only whe
|
||||
if (!WinApi.AttachConsole(-1))
|
||||
{
|
||||
WinApi.AllocConsole();
|
||||
|
||||
SetConsoleWriter();
|
||||
|
||||
return true;
|
||||
}
|
||||
ConsoleOpened = true;
|
||||
|
||||
SetConsoleWriter();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void SetConsoleWriter()
|
||||
{
|
||||
var writer = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true };
|
||||
Console.SetOut(writer);
|
||||
}
|
||||
|
||||
public static bool CloseConsole()
|
||||
{
|
||||
if (!ConsoleOpened)
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace ColorControl
|
||||
public bool UseDedicatedElevatedProcess { get; set; }
|
||||
public ElevationMethod ElevationMethod { get; set; }
|
||||
public bool ElevationMethodAsked { get; set; }
|
||||
public int ProcessMonitorPollingInterval { get; set; }
|
||||
public List<Module> Modules { get; set; }
|
||||
|
||||
public Config()
|
||||
@@ -59,6 +60,7 @@ namespace ColorControl
|
||||
UseDedicatedElevatedProcess = false;
|
||||
ElevationMethod = ElevationMethod.None;
|
||||
ElevationMethodAsked = false;
|
||||
ProcessMonitorPollingInterval = 1000;
|
||||
LgPresetsSortState = new ListViewSortState();
|
||||
NvPresetsSortState = new ListViewSortState();
|
||||
AmdPresetsSortState = new ListViewSortState();
|
||||
|
||||
@@ -680,6 +680,18 @@ namespace ColorControl.Forms
|
||||
sortState.SortOrder = sorter.Order;
|
||||
sortState.SortIndex = sorter.SortColumn;
|
||||
}
|
||||
|
||||
public static void UpdateShortcutTextBox(TextBox edtShortcut, PresetBase preset)
|
||||
{
|
||||
if (preset == null || string.IsNullOrEmpty(edtShortcut.Text))
|
||||
{
|
||||
edtShortcut.ForeColor = CurrentForeColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
//edtShortcutLg.ForeColor = ShortCutExists(text, preset.id) ? Color.Red : SystemColors.WindowText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class EnumComboBoxItem
|
||||
|
||||
Generated
+19
-3
@@ -70,6 +70,7 @@
|
||||
label7 = new System.Windows.Forms.Label();
|
||||
lblInfo = new System.Windows.Forms.Label();
|
||||
btnUpdate = new System.Windows.Forms.Button();
|
||||
btnOptionsAdvanced = new System.Windows.Forms.Button();
|
||||
tcMain.SuspendLayout();
|
||||
tabOptions.SuspendLayout();
|
||||
grpOptionsModules.SuspendLayout();
|
||||
@@ -113,7 +114,7 @@
|
||||
//
|
||||
grpOptionsModules.Controls.Add(label1);
|
||||
grpOptionsModules.Controls.Add(chkModules);
|
||||
grpOptionsModules.Location = new System.Drawing.Point(7, 210);
|
||||
grpOptionsModules.Location = new System.Drawing.Point(11, 223);
|
||||
grpOptionsModules.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpOptionsModules.Name = "grpOptionsModules";
|
||||
grpOptionsModules.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
@@ -134,8 +135,10 @@
|
||||
//
|
||||
// chkModules
|
||||
//
|
||||
chkModules.ColumnWidth = 200;
|
||||
chkModules.FormattingEnabled = true;
|
||||
chkModules.Location = new System.Drawing.Point(7, 40);
|
||||
chkModules.MultiColumn = true;
|
||||
chkModules.Name = "chkModules";
|
||||
chkModules.Size = new System.Drawing.Size(507, 76);
|
||||
chkModules.TabIndex = 0;
|
||||
@@ -148,7 +151,7 @@
|
||||
grpMiscellaneousOptions.Controls.Add(edtBlankScreenSaverShortcut);
|
||||
grpMiscellaneousOptions.Controls.Add(lblFixChromeFontsDescription);
|
||||
grpMiscellaneousOptions.Controls.Add(chkFixChromeFonts);
|
||||
grpMiscellaneousOptions.Location = new System.Drawing.Point(7, 347);
|
||||
grpMiscellaneousOptions.Location = new System.Drawing.Point(11, 360);
|
||||
grpMiscellaneousOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpMiscellaneousOptions.Name = "grpMiscellaneousOptions";
|
||||
grpMiscellaneousOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
@@ -213,6 +216,7 @@
|
||||
//
|
||||
// grpGeneralOptions
|
||||
//
|
||||
grpGeneralOptions.Controls.Add(btnOptionsAdvanced);
|
||||
grpGeneralOptions.Controls.Add(chkOptionsUseDarkMode);
|
||||
grpGeneralOptions.Controls.Add(chkAutoInstallUpdates);
|
||||
grpGeneralOptions.Controls.Add(btnStartStopService);
|
||||
@@ -232,7 +236,7 @@
|
||||
grpGeneralOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpGeneralOptions.Name = "grpGeneralOptions";
|
||||
grpGeneralOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpGeneralOptions.Size = new System.Drawing.Size(522, 197);
|
||||
grpGeneralOptions.Size = new System.Drawing.Size(522, 210);
|
||||
grpGeneralOptions.TabIndex = 2;
|
||||
grpGeneralOptions.TabStop = false;
|
||||
grpGeneralOptions.Text = "General";
|
||||
@@ -587,6 +591,17 @@
|
||||
btnUpdate.Visible = false;
|
||||
btnUpdate.Click += btnUpdate_Click;
|
||||
//
|
||||
// btnOptionsAdvanced
|
||||
//
|
||||
btnOptionsAdvanced.Location = new System.Drawing.Point(7, 172);
|
||||
btnOptionsAdvanced.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnOptionsAdvanced.Name = "btnOptionsAdvanced";
|
||||
btnOptionsAdvanced.Size = new System.Drawing.Size(88, 27);
|
||||
btnOptionsAdvanced.TabIndex = 11;
|
||||
btnOptionsAdvanced.Text = "Advanced...";
|
||||
btnOptionsAdvanced.UseVisualStyleBackColor = true;
|
||||
btnOptionsAdvanced.Click += btnOptionsAdvanced_Click;
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
@@ -670,6 +685,7 @@
|
||||
private System.Windows.Forms.CheckedListBox chkModules;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.CheckBox chkOptionsUseDarkMode;
|
||||
private System.Windows.Forms.Button btnOptionsAdvanced;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using ColorControl.Services.EventDispatcher;
|
||||
using ColorControl.Services.GameLauncher;
|
||||
using ColorControl.Services.LG;
|
||||
using ColorControl.Services.NVIDIA;
|
||||
using ColorControl.Services.Samsung;
|
||||
using ColorControl.Svc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NLog;
|
||||
@@ -47,11 +48,13 @@ namespace ColorControl
|
||||
private bool _setVisibleCalled = false;
|
||||
|
||||
private LgPanel _lgPanel;
|
||||
private SamsungPanel _samsungPanel;
|
||||
|
||||
private ToolStripMenuItem _nvTrayMenu;
|
||||
private ToolStripMenuItem _novideoTrayMenu;
|
||||
private ToolStripMenuItem _amdTrayMenu;
|
||||
private ToolStripMenuItem _lgTrayMenu;
|
||||
private ToolStripMenuItem _samsungTrayMenu;
|
||||
private ToolStripMenuItem _gameTrayMenu;
|
||||
|
||||
private StartUpParams StartUpParams { get; }
|
||||
@@ -94,6 +97,7 @@ namespace ColorControl
|
||||
_novideoTrayMenu = new ToolStripMenuItem("Novideo sRGB");
|
||||
_amdTrayMenu = new ToolStripMenuItem("AMD presets");
|
||||
_lgTrayMenu = new ToolStripMenuItem("LG presets");
|
||||
_samsungTrayMenu = new ToolStripMenuItem("Samsung presets");
|
||||
_gameTrayMenu = new ToolStripMenuItem("Game Launcher");
|
||||
_trayIcon = new NotifyIcon()
|
||||
{
|
||||
@@ -108,6 +112,7 @@ namespace ColorControl
|
||||
_novideoTrayMenu,
|
||||
_amdTrayMenu,
|
||||
_lgTrayMenu,
|
||||
_samsungTrayMenu,
|
||||
_gameTrayMenu,
|
||||
new ToolStripSeparator(),
|
||||
new ToolStripMenuItem("Open", null, OpenForm),
|
||||
@@ -163,6 +168,7 @@ namespace ColorControl
|
||||
_modules.Add("AMD controller", InitAmdService);
|
||||
_modules.Add("LG controller", InitLgService);
|
||||
_modules.Add("Game launcher", InitGameService);
|
||||
_modules.Add("Samsung controller", InitSamsungService);
|
||||
|
||||
foreach (var keyValue in _modules)
|
||||
{
|
||||
@@ -347,6 +353,31 @@ namespace ColorControl
|
||||
}
|
||||
}
|
||||
|
||||
private UserControl InitSamsungService()
|
||||
{
|
||||
try
|
||||
{
|
||||
_serviceManager.SamsungService = Program.ServiceProvider.GetRequiredService<SamsungService>();
|
||||
|
||||
//_serviceManager.SamsungService.Init();
|
||||
|
||||
_samsungPanel = new SamsungPanel(_serviceManager.SamsungService, _serviceManager.NvService, _serviceManager.AmdService, Handle);
|
||||
_samsungPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
|
||||
_samsungPanel.Init();
|
||||
|
||||
InitShortcut(SamsungPanel.SHORTCUTID_SAMSUNGQA, _serviceManager.SamsungService.Config.QuickAccessShortcut, _serviceManager.SamsungService.ToggleQuickAccessForm);
|
||||
|
||||
return _samsungPanel;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error("Error initializing SamsungService: " + e.ToLogString());
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void TestKey()
|
||||
{
|
||||
BeginInvoke(async () =>
|
||||
@@ -499,6 +530,12 @@ namespace ColorControl
|
||||
{
|
||||
_lgPanel?.ApplyLgPreset(lgPreset);
|
||||
}
|
||||
|
||||
var samsungPreset = _serviceManager.SamsungService?.GetPresets().FirstOrDefault(x => x.id == id);
|
||||
if (samsungPreset != null)
|
||||
{
|
||||
_samsungPanel?.ApplyPreset(samsungPreset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m.Msg == NativeConstants.WM_QUERYENDSESSION)
|
||||
@@ -873,6 +910,16 @@ NOTE: installing the service may cause a User Account Control popup.");
|
||||
UpdateTrayMenu(_lgTrayMenu, presets, TrayMenuItemLg_Click);
|
||||
}
|
||||
|
||||
_samsungTrayMenu.Visible = _serviceManager.SamsungService != null;
|
||||
if (_samsungTrayMenu.Visible)
|
||||
{
|
||||
var presets = _serviceManager.SamsungService.GetPresets().Where(x => x.Steps.Any());
|
||||
|
||||
_samsungTrayMenu.DropDownItems.Clear();
|
||||
|
||||
UpdateTrayMenu(_samsungTrayMenu, presets, TrayMenuItemSamsung_Click);
|
||||
}
|
||||
|
||||
_gameTrayMenu.Visible = _serviceManager.GameService != null;
|
||||
if (_gameTrayMenu.Visible)
|
||||
{
|
||||
@@ -892,6 +939,14 @@ NOTE: installing the service may cause a User Account Control popup.");
|
||||
await _lgPanel?.ApplyLgPreset(preset);
|
||||
}
|
||||
|
||||
private async void TrayMenuItemSamsung_Click(object sender, EventArgs e)
|
||||
{
|
||||
var item = sender as ToolStripMenuItem;
|
||||
var preset = (SamsungPreset)item.Tag;
|
||||
|
||||
await _samsungPanel?.ApplyPreset(preset);
|
||||
}
|
||||
|
||||
private void LoadLog()
|
||||
{
|
||||
var logType = cbxLogType.SelectedIndex;
|
||||
@@ -1311,13 +1366,20 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
|
||||
LoadLog();
|
||||
}
|
||||
|
||||
private void MainForm_Click(object sender, EventArgs e)
|
||||
private async void MainForm_Click(object sender, EventArgs e)
|
||||
{
|
||||
//_powerEventDispatcher.SendEvent(PowerEventDispatcher.Event_Shutdown);
|
||||
//PipeUtils.SendMessage(SvcMessageType.RestartAfterUpdate);
|
||||
//Program.Restart();
|
||||
//Environment.Exit(0);
|
||||
//InstallUpdate("");
|
||||
//await Test();
|
||||
|
||||
//Utils.SetBrightness(Handle);
|
||||
}
|
||||
|
||||
private async Task Test()
|
||||
{
|
||||
}
|
||||
|
||||
private void SetTheme(bool toDark)
|
||||
@@ -1417,5 +1479,27 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
|
||||
|
||||
SetTheme(_config.UseDarkMode);
|
||||
}
|
||||
|
||||
private void btnOptionsAdvanced_Click(object sender, EventArgs e)
|
||||
{
|
||||
var processPollingIntervalField = new MessageForms.FieldDefinition
|
||||
{
|
||||
FieldType = MessageForms.FieldType.Numeric,
|
||||
Label = "Polling interval of process monitor (milliseconds).",
|
||||
SubLabel = "Decreasing this delay may execute triggered presets sooner but can cause a higher CPU load",
|
||||
MinValue = 50,
|
||||
MaxValue = 5000,
|
||||
Value = _config.ProcessMonitorPollingInterval
|
||||
};
|
||||
|
||||
var values = MessageForms.ShowDialog("Advanced settings", new[] { processPollingIntervalField });
|
||||
|
||||
if (values?.Any() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_config.ProcessMonitorPollingInterval = processPollingIntervalField.ValueAsInt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,64 @@
|
||||
<root>
|
||||
<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
|
||||
+190
-25
@@ -8,6 +8,8 @@ namespace ColorControl
|
||||
// This class takes care of wrapping "Connecting and Configuring Displays(CCD) Win32 API"
|
||||
internal static class CCD
|
||||
{
|
||||
private static bool? IsHDRActive = null;
|
||||
|
||||
public enum DisplayTopology
|
||||
{
|
||||
Internal,
|
||||
@@ -59,7 +61,7 @@ namespace ColorControl
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetHDRState(bool enabled, string displayName = null)
|
||||
public static void SetHDRState(bool enabled, string displayName = null, float? SDRWhiteLevelInNits = null)
|
||||
{
|
||||
uint pathCount, modeCount;
|
||||
|
||||
@@ -76,21 +78,7 @@ namespace ColorControl
|
||||
{
|
||||
foreach (var path in pathsArray)
|
||||
{
|
||||
// get display name
|
||||
var info = new DISPLAYCONFIG_SOURCE_DEVICE_NAME();
|
||||
info.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||
info.header.size = Marshal.SizeOf<DISPLAYCONFIG_SOURCE_DEVICE_NAME>();
|
||||
info.header.adapterId = path.sourceInfo.adapterId;
|
||||
info.header.id = path.sourceInfo.id;
|
||||
|
||||
err = NativeMethods.DisplayConfigGetDeviceInfo(ref info);
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var deviceName = info.viewGdiDeviceName;
|
||||
if (displayName != null && !EqualDisplayNames(deviceName, displayName))
|
||||
if (!MatchDisplayNames(path, displayName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -98,12 +86,12 @@ namespace ColorControl
|
||||
var setpacket = new DISPLAYCONFIG_SET_ADVANCED_COLOR_INFO();
|
||||
setpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
setpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE;
|
||||
setpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_SET_ADVANCED_COLOR_INFO>(); ;
|
||||
setpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_SET_ADVANCED_COLOR_INFO>();
|
||||
|
||||
var requestpacket = new DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO();
|
||||
requestpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
requestpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
|
||||
requestpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO>(); ;
|
||||
requestpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO>();
|
||||
|
||||
for (int i = 0; i < modeCount; i++)
|
||||
{
|
||||
@@ -114,26 +102,189 @@ namespace ColorControl
|
||||
requestpacket.header.adapterId = modesArray[i].adapterId;
|
||||
requestpacket.header.id = modesArray[i].id;
|
||||
|
||||
if (NativeMethods.DisplayConfigGetDeviceInfo(ref requestpacket) == NativeConstants.ERROR_SUCCESS)
|
||||
if (NativeMethods.DisplayConfigGetDeviceInfo(ref requestpacket) == NativeConstants.ERROR_SUCCESS && requestpacket.advancedColorSupported)
|
||||
{
|
||||
if (requestpacket.advancedColorSupported)
|
||||
{
|
||||
setpacket.enableAdvancedColor = enabled ? 1U : 0;
|
||||
NativeMethods.DisplayConfigSetDeviceInfo(ref setpacket);
|
||||
}
|
||||
setpacket.enableAdvancedColor = enabled ? 1U : 0;
|
||||
NativeMethods.DisplayConfigSetDeviceInfo(ref setpacket);
|
||||
|
||||
IsHDRActive = enabled;
|
||||
|
||||
//if (enabled && SDRWhiteLevelInNits.HasValue)
|
||||
//{
|
||||
// SetSDRWhiteLevel(modesArray[i], SDRWhiteLevelInNits.Value);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetSDRWhiteLevel(float SDRWhiteLevelInNits, string displayName = null)
|
||||
{
|
||||
uint pathCount, modeCount;
|
||||
|
||||
var err = NativeMethods.GetDisplayConfigBufferSizes(QueryDisplayFlags.OnlyActivePaths, out pathCount, out modeCount);
|
||||
if (err == NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
var pathsArray = new DisplayConfigPathInfo[pathCount];
|
||||
var modesArray = new DisplayConfigModeInfo[modeCount];
|
||||
|
||||
DisplayConfigTopologyId displayTopology;
|
||||
|
||||
err = NativeMethods.QueryDisplayConfig(QueryDisplayFlags.DatabaseCurrent, ref pathCount, pathsArray, ref modeCount, modesArray, out displayTopology);
|
||||
if (err == NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
foreach (var path in pathsArray)
|
||||
{
|
||||
if (!MatchDisplayNames(path, displayName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var requestpacket = new DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO();
|
||||
requestpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
requestpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
|
||||
requestpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO>();
|
||||
|
||||
for (int i = 0; i < modeCount; i++)
|
||||
{
|
||||
if (modesArray[i].infoType == DisplayConfigModeInfoType.Target)
|
||||
{
|
||||
requestpacket.header.adapterId = modesArray[i].adapterId;
|
||||
requestpacket.header.id = modesArray[i].id;
|
||||
|
||||
err = NativeMethods.DisplayConfigGetDeviceInfo(ref requestpacket);
|
||||
|
||||
if (err == NativeConstants.ERROR_SUCCESS && requestpacket.advancedColorSupported)
|
||||
{
|
||||
SetSDRWhiteLevel(modesArray[i], SDRWhiteLevelInNits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsHDREnabled(string displayName = null)
|
||||
{
|
||||
if (IsHDRActive.HasValue)
|
||||
{
|
||||
return IsHDRActive.Value;
|
||||
}
|
||||
|
||||
uint pathCount, modeCount;
|
||||
|
||||
var err = NativeMethods.GetDisplayConfigBufferSizes(QueryDisplayFlags.OnlyActivePaths, out pathCount, out modeCount);
|
||||
if (err == NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
var pathsArray = new DisplayConfigPathInfo[pathCount];
|
||||
var modesArray = new DisplayConfigModeInfo[modeCount];
|
||||
|
||||
err = NativeMethods.QueryDisplayConfig(QueryDisplayFlags.DatabaseCurrent, ref pathCount, pathsArray, ref modeCount, modesArray, out _);
|
||||
if (err == NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
foreach (var path in pathsArray)
|
||||
{
|
||||
if (!MatchDisplayNames(path, displayName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var requestpacket = new DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO();
|
||||
requestpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
requestpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
|
||||
requestpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO>();
|
||||
|
||||
for (int i = 0; i < modeCount; i++)
|
||||
{
|
||||
if (modesArray[i].infoType == DisplayConfigModeInfoType.Target)
|
||||
{
|
||||
requestpacket.header.adapterId = modesArray[i].adapterId;
|
||||
requestpacket.header.id = modesArray[i].id;
|
||||
|
||||
err = NativeMethods.DisplayConfigGetDeviceInfo(ref requestpacket);
|
||||
|
||||
IsHDRActive = err == NativeConstants.ERROR_SUCCESS && requestpacket.advancedColorEnabled;
|
||||
|
||||
return IsHDRActive.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool MatchDisplayNames(DisplayConfigPathInfo path, string displayName)
|
||||
{
|
||||
if (displayName == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// get display name
|
||||
var info = new DISPLAYCONFIG_SOURCE_DEVICE_NAME();
|
||||
info.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||
info.header.size = Marshal.SizeOf<DISPLAYCONFIG_SOURCE_DEVICE_NAME>();
|
||||
info.header.adapterId = path.sourceInfo.adapterId;
|
||||
info.header.id = path.sourceInfo.id;
|
||||
|
||||
var err = NativeMethods.DisplayConfigGetDeviceInfo(ref info);
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var deviceName = info.viewGdiDeviceName;
|
||||
if (!EqualDisplayNames(deviceName, displayName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void SetSDRWhiteLevel(DisplayConfigModeInfo displayConfigModeInfo, float value)
|
||||
{
|
||||
var setpacket = new DISPLAYCONFIG_SDR_WHITE_LEVEL();
|
||||
setpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
setpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_SET_SDR_WHITE_LEVEL;
|
||||
setpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_SDR_WHITE_LEVEL>();
|
||||
|
||||
var requestpacket = new DISPLAYCONFIG_SDR_WHITE_LEVEL();
|
||||
requestpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
requestpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
|
||||
requestpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_SDR_WHITE_LEVEL>();
|
||||
requestpacket.header.adapterId = displayConfigModeInfo.adapterId;
|
||||
requestpacket.header.id = displayConfigModeInfo.id;
|
||||
|
||||
var error = NativeMethods.DisplayConfigGetDeviceInfo(ref requestpacket);
|
||||
|
||||
if (error == NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
setpacket.header.adapterId = displayConfigModeInfo.adapterId;
|
||||
setpacket.header.id = displayConfigModeInfo.id;
|
||||
setpacket.SDRWhiteLevel = 2000;
|
||||
|
||||
error = NativeMethods.DisplayConfigSetDeviceInfo(ref setpacket);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static bool EqualDisplayNames(string displayName1, string displayName2)
|
||||
{
|
||||
displayName1 = displayName1.Replace("\\", string.Empty);
|
||||
@@ -162,6 +313,7 @@ namespace ColorControl
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO = 9,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE = 10,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL = 11,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_SDR_WHITE_LEVEL = 12,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
@@ -506,6 +658,13 @@ namespace ColorControl
|
||||
public uint enableAdvancedColor;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct DISPLAYCONFIG_SDR_WHITE_LEVEL
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
|
||||
public uint SDRWhiteLevel;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
|
||||
{
|
||||
@@ -559,6 +718,12 @@ namespace ColorControl
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SOURCE_DEVICE_NAME requestPacket);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SDR_WHITE_LEVEL requestPacket);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern int DisplayConfigSetDeviceInfo(ref DISPLAYCONFIG_SDR_WHITE_LEVEL setPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using ColorControl.Services.EventDispatcher;
|
||||
using ColorControl.Services.GameLauncher;
|
||||
using ColorControl.Services.LG;
|
||||
using ColorControl.Services.NVIDIA;
|
||||
using ColorControl.Services.Samsung;
|
||||
using ColorControl.Svc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
@@ -290,6 +291,7 @@ namespace ColorControl
|
||||
Console.WriteLine("--nvpreset <preset name or id>: execute NVIDIA-preset");
|
||||
Console.WriteLine("--amdpreset <preset name or id>: execute AMD-preset");
|
||||
Console.WriteLine("--lgpreset <preset name> : execute LG-preset");
|
||||
Console.WriteLine("--sampreset <preset name> : execute Samsung-preset");
|
||||
Console.WriteLine("--help : displays this help info");
|
||||
Console.WriteLine("Options:");
|
||||
Console.WriteLine("--nogui: starts command from the command line and will not open GUI (is forced when GUI is already running)");
|
||||
@@ -309,6 +311,18 @@ namespace ColorControl
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (startUpParams.ExecuteSamsungPreset)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine($"Executing Samsung-preset '{startUpParams.SamsungPresetName}'...");
|
||||
await SamsungService.ExecutePresetAsync(startUpParams.SamsungPresetName);
|
||||
|
||||
Console.WriteLine("Done.");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (startUpParams.ExecuteNvidiaPreset)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
@@ -358,10 +372,12 @@ namespace ColorControl
|
||||
services.RegisterSharedServices();
|
||||
services.AddSingleton<LgService>();
|
||||
services.AddSingleton<GameService>();
|
||||
services.AddSingleton<SamsungService>();
|
||||
services.AddSingleton<PowerEventDispatcher>();
|
||||
services.AddSingleton<ProcessEventDispatcher>();
|
||||
services.AddSingleton<MainForm>();
|
||||
services.AddSingleton<ServiceManager>();
|
||||
services.AddSingleton<RestartDetector>();
|
||||
});
|
||||
}
|
||||
private static async Task RunService(string[] args)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"profiles": {
|
||||
"ColorControl": {
|
||||
"commandName": "Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,14 +268,7 @@ namespace ColorControl.Services.AMD
|
||||
|
||||
var preset = GetSelectedAmdPreset();
|
||||
|
||||
if (preset == null || string.IsNullOrEmpty(text))
|
||||
{
|
||||
edtAmdShortcut.ForeColor = SystemColors.WindowText;
|
||||
}
|
||||
else
|
||||
{
|
||||
// edtAmdShortcut.ForeColor = ShortCutExists(text, preset.id) ? Color.Red : SystemColors.WindowText;
|
||||
}
|
||||
FormUtils.UpdateShortcutTextBox(edtAmdShortcut, preset);
|
||||
}
|
||||
|
||||
private void btnSetAmdShortcut_Click(object sender, EventArgs e)
|
||||
|
||||
@@ -3,6 +3,7 @@ using ColorControl.Services.AMD;
|
||||
using ColorControl.Services.GameLauncher;
|
||||
using ColorControl.Services.LG;
|
||||
using ColorControl.Services.NVIDIA;
|
||||
using ColorControl.Services.Samsung;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -15,6 +16,7 @@ namespace ColorControl.Services.Common
|
||||
internal LgService LgService { get; set; }
|
||||
internal AmdService AmdService { get; set; }
|
||||
internal GameService GameService { get; set; }
|
||||
internal SamsungService SamsungService { get; set; }
|
||||
|
||||
public async Task<bool> HandleExternalServiceAsync(string serviceName, string[] parameters)
|
||||
{
|
||||
@@ -58,6 +60,7 @@ namespace ColorControl.Services.Common
|
||||
AmdService?.GlobalSave();
|
||||
LgService?.GlobalSave();
|
||||
GameService?.GlobalSave();
|
||||
SamsungService?.GlobalSave();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using ColorControl.Common;
|
||||
using ColorControl.Forms;
|
||||
using ColorControl.Services.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@@ -31,9 +32,12 @@ namespace ColorControl.Services.EventDispatcher
|
||||
protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
private ProcessChangedEventArgs MonitorContext { get; set; }
|
||||
private AppContextProvider _appContextProvider { get; }
|
||||
|
||||
public ProcessEventDispatcher()
|
||||
public ProcessEventDispatcher(AppContextProvider appContextProvider)
|
||||
{
|
||||
_appContextProvider = appContextProvider;
|
||||
|
||||
IsRunning = true;
|
||||
|
||||
//Task.Run(async () => await CheckProcesses());
|
||||
@@ -53,7 +57,7 @@ namespace ColorControl.Services.EventDispatcher
|
||||
|
||||
while (IsRunning)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
await Task.Delay(_appContextProvider.GetAppContext().Config.ProcessMonitorPollingInterval);
|
||||
|
||||
if (!HasHandlers(Event_ProcessChanged))
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ColorControl.Services.GameLauncher
|
||||
{
|
||||
class GameService : ServiceBase<GamePreset>
|
||||
{
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
//private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public override string ServiceName => "Game";
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ using NStandard;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
@@ -724,14 +723,7 @@ You can also activate this option by using the Expert-button and selecting Wake-
|
||||
|
||||
var preset = GetSelectedLgPreset();
|
||||
|
||||
if (preset == null || string.IsNullOrEmpty(text))
|
||||
{
|
||||
edtShortcutLg.ForeColor = SystemColors.WindowText;
|
||||
}
|
||||
else
|
||||
{
|
||||
//edtShortcutLg.ForeColor = ShortCutExists(text, preset.id) ? Color.Red : SystemColors.WindowText;
|
||||
}
|
||||
FormUtils.UpdateShortcutTextBox(edtShortcutLg, preset);
|
||||
}
|
||||
|
||||
private async void btnLgAddDevice_Click(object sender, EventArgs e)
|
||||
@@ -747,7 +739,7 @@ You can also activate this option by using the Expert-button and selecting Wake-
|
||||
Enabled = false;
|
||||
try
|
||||
{
|
||||
await device.TestConnection();
|
||||
result = await device.TestConnection();
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -1185,7 +1177,7 @@ Do you want to continue?";
|
||||
new()
|
||||
{
|
||||
FieldType = MessageForms.FieldType.Numeric,
|
||||
Label = "Delay when shutting down/restarting PC (milli seconds).",
|
||||
Label = "Delay when shutting down/restarting PC (milliseconds).",
|
||||
SubLabel = "This delay may prevent the tv from powering off when restarting the pc.",
|
||||
MinValue = 0,
|
||||
MaxValue = 5000,
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace ColorControl.Services.LG
|
||||
private RestartDetector _restartDetector;
|
||||
private SynchronizationContext _syncContext;
|
||||
|
||||
public LgService(AppContextProvider appContextProvider, PowerEventDispatcher powerEventDispatcher, SessionSwitchDispatcher sessionSwitchDispatcher, ProcessEventDispatcher processEventDispatcher, ServiceManager serviceManager) : base(appContextProvider)
|
||||
public LgService(AppContextProvider appContextProvider, PowerEventDispatcher powerEventDispatcher, SessionSwitchDispatcher sessionSwitchDispatcher, ProcessEventDispatcher processEventDispatcher, ServiceManager serviceManager, RestartDetector restartDetector) : base(appContextProvider)
|
||||
{
|
||||
_allowPowerOn = appContextProvider.GetAppContext().StartUpParams.RunningFromScheduledTask;
|
||||
_powerEventDispatcher = powerEventDispatcher;
|
||||
@@ -84,7 +84,7 @@ namespace ColorControl.Services.LG
|
||||
_serviceManager = serviceManager;
|
||||
LgPreset.LgApps = _lgApps;
|
||||
|
||||
_restartDetector = new RestartDetector();
|
||||
_restartDetector = restartDetector;
|
||||
_syncContext = appContextProvider.GetAppContext().SynchronizationContext;
|
||||
LgTvApiCore.SyncContext = _syncContext;
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
var primaryDisplayInfo = displays.FirstOrDefault(d => d.Display == primaryDisplay);
|
||||
var index = primaryDisplayInfo != null ? displays.IndexOf(primaryDisplayInfo) : 0;
|
||||
|
||||
cbxDitheringDisplay.Items.Clear();
|
||||
cbxDitheringDisplay.Items.AddRange(displays.ToArray());
|
||||
|
||||
if (cbxDitheringDisplay.SelectedIndex == -1)
|
||||
|
||||
@@ -192,6 +192,11 @@ namespace ColorControl.Services.NVIDIA
|
||||
|
||||
var powerLimits = GetPowerLimits();
|
||||
|
||||
if (!DefaultPowerInMilliWatts.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MinPowerInMilliWatts = (int)((decimal)DefaultPowerInMilliWatts / 100000 * powerLimits.Item1);
|
||||
MaxPowerInMilliWatts = (int)((decimal)DefaultPowerInMilliWatts / 100000 * powerLimits.Item2);
|
||||
}
|
||||
@@ -245,10 +250,13 @@ namespace ColorControl.Services.NVIDIA
|
||||
{
|
||||
if (DefaultPowerInMilliWatts.HasValue)
|
||||
{
|
||||
var powerInPCM = GPU.PowerTopologyInformation.PowerTopologyEntries.FirstOrDefault(e => e.Domain == PowerTopologyDomain.Board);
|
||||
var power = (uint)((decimal)powerInPCM.PowerUsageInPCM / 100000 * DefaultPowerInMilliWatts);
|
||||
return Logger.Swallow(() =>
|
||||
{
|
||||
var powerInPCM = GPU.PowerTopologyInformation.PowerTopologyEntries.FirstOrDefault(e => e.Domain == PowerTopologyDomain.Board);
|
||||
var power = (uint)((decimal)powerInPCM.PowerUsageInPCM / 100000 * DefaultPowerInMilliWatts);
|
||||
|
||||
return power;
|
||||
return power;
|
||||
});
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -946,14 +946,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
|
||||
var preset = GetSelectedNvPreset();
|
||||
|
||||
if (preset == null || string.IsNullOrEmpty(text))
|
||||
{
|
||||
edtShortcut.ForeColor = SystemColors.WindowText;
|
||||
}
|
||||
else
|
||||
{
|
||||
//edtShortcut.ForeColor = ShortCutExists(text, preset.id) ? Color.Red : SystemColors.WindowText;
|
||||
}
|
||||
FormUtils.UpdateShortcutTextBox(edtShortcut, preset);
|
||||
}
|
||||
|
||||
private void miNvResolutionIncluded_Click(object sender, EventArgs e)
|
||||
|
||||
@@ -309,6 +309,11 @@ namespace ColorControl.Services.NVIDIA
|
||||
SetHDRState(display, newHdrEnabled);
|
||||
}
|
||||
|
||||
if (hdrEnabled)
|
||||
{
|
||||
//CCD.SetSDRWhiteLevel(1000, display.Name);
|
||||
}
|
||||
|
||||
if (preset.applyRefreshRate || preset.applyResolution)
|
||||
{
|
||||
if (!SetMode(preset.applyResolution ? preset.resolutionWidth : 0, preset.applyResolution ? preset.resolutionHeight : 0, preset.applyRefreshRate ? preset.refreshRate : 0, true))
|
||||
@@ -619,7 +624,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
resolutionHeight = (uint)desktopRect.Height;
|
||||
}
|
||||
|
||||
var portrait = new[] { Rotate.Degree90, Rotate.Degree270 }.Contains(display.DisplayDevice.ScanOutInformation.SourceToTargetRotation);
|
||||
var portrait = IsDisplayInPortraitMode(display);
|
||||
|
||||
return SetRefreshRateInternal(display.Name, (int)refreshRate, portrait, (int)resolutionWidth, (int)resolutionHeight, updateRegistry);
|
||||
}
|
||||
@@ -637,12 +642,24 @@ namespace ColorControl.Services.NVIDIA
|
||||
return new List<uint>();
|
||||
}
|
||||
|
||||
var portrait = new[] { Rotate.Degree90, Rotate.Degree270 }.Contains(display.DisplayDevice.ScanOutInformation.SourceToTargetRotation);
|
||||
var portrait = IsDisplayInPortraitMode(display);
|
||||
var desktopRect = display.DisplayDevice.ScanOutInformation.SourceDesktopRectangle;
|
||||
|
||||
return GetAvailableRefreshRatesInternal(display.Name, portrait, desktopRect.Width, desktopRect.Height);
|
||||
}
|
||||
|
||||
private bool IsDisplayInPortraitMode(NvAPIWrapper.Display.Display display)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new[] { Rotate.Degree90, Rotate.Degree270 }.Contains(display.DisplayDevice.ScanOutInformation.SourceToTargetRotation);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public List<DEVMODEA> GetAvailableResolutions(NvPreset preset = null)
|
||||
{
|
||||
if (preset != null)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
internal class RawRequestMessage
|
||||
{
|
||||
public RawRequestMessage(RequestMessage rm, int commandCount)
|
||||
{
|
||||
Id = commandCount.ToString();
|
||||
Method = rm.Method;
|
||||
Params = rm.Params;
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("method")]
|
||||
public string Method { get; set; }
|
||||
[JsonProperty("params")]
|
||||
public object Params { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
public class RequestMessage
|
||||
{
|
||||
public RequestMessage(string method, object payload)
|
||||
{
|
||||
Method = method;
|
||||
Params = payload;
|
||||
}
|
||||
|
||||
public string Method { get; set; }
|
||||
public object Params { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
using ColorControl.Common;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Networking.Sockets;
|
||||
using Windows.Security.Cryptography.Certificates;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
public class SendMessageException : Exception
|
||||
{
|
||||
public SendMessageException(string message, Exception e) : base(message, e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void ConnectedDelegate(string token, bool disconnect);
|
||||
|
||||
public class SamTvConnection : IDisposable
|
||||
{
|
||||
public static SynchronizationContext SyncContext { get; set; }
|
||||
|
||||
public bool ConnectionClosed { get; private set; }
|
||||
public bool ClosedByDispose { get; private set; }
|
||||
|
||||
private MessageWebSocket _connection;
|
||||
private DataWriter _messageWriter;
|
||||
private int _commandCount;
|
||||
private int _readTimeout;
|
||||
|
||||
public event ConnectedDelegate Connected;
|
||||
private readonly ConcurrentDictionary<string, TaskCompletionSource<dynamic>> _tokens = new ConcurrentDictionary<string, TaskCompletionSource<dynamic>>();
|
||||
private readonly ConcurrentDictionary<string, Func<dynamic, bool>> _callbacks = new ConcurrentDictionary<string, Func<dynamic, bool>>();
|
||||
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public async Task<bool> Connect(Uri uri, int readTimeout = 5000)
|
||||
{
|
||||
_readTimeout = readTimeout;
|
||||
|
||||
try
|
||||
{
|
||||
_connection?.Dispose();
|
||||
|
||||
ConnectionClosed = false;
|
||||
_commandCount = 0;
|
||||
|
||||
// Not creating the web socket from main thread can cause a stackoverflow in combase32.dll
|
||||
if (Environment.CurrentManagedThreadId != 1)
|
||||
{
|
||||
SyncContext.Send((_) => CreateWebSocket(), null);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateWebSocket();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _connection.ConnectAsync(uri).AsTask().WaitAsync(TimeSpan.FromSeconds(5));
|
||||
|
||||
_messageWriter = new DataWriter(_connection.OutputStream);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (TimeoutException te)
|
||||
{
|
||||
Logger.Error($"Connect to {uri}: {te.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (SocketError.GetStatus(e.HResult))
|
||||
{
|
||||
case SocketErrorStatus.HostNotFound:
|
||||
// Handle HostNotFound Error
|
||||
break;
|
||||
default:
|
||||
// Handle Unknown Error
|
||||
break;
|
||||
}
|
||||
|
||||
Logger.Error($"Connect to {uri}: {e.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWebSocket()
|
||||
{
|
||||
_connection = new MessageWebSocket();
|
||||
_connection.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
|
||||
_connection.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
|
||||
_connection.Control.MessageType = SocketMessageType.Utf8;
|
||||
_connection.MessageReceived += Connection_MessageReceived;
|
||||
_connection.Closed += Connection_Closed;
|
||||
}
|
||||
|
||||
public async Task SendMessageAsync(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_messageWriter == null)
|
||||
{
|
||||
throw new Exception("SendMessageAsync: no writer");
|
||||
}
|
||||
|
||||
_messageWriter.WriteString(message);
|
||||
|
||||
await _messageWriter.StoreAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(5));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error("SendMessageAsync: " + e.Message);
|
||||
ConnectionClosed = true;
|
||||
_messageWriter?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<dynamic> SendCommandAsync(string id, string message, bool waitForAnswer = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (waitForAnswer)
|
||||
{
|
||||
var taskSource = new TaskCompletionSource<dynamic>();
|
||||
_tokens.TryAdd(id, taskSource);
|
||||
|
||||
await SendMessageAsync(message);
|
||||
if (ConnectionClosed)
|
||||
{
|
||||
throw new Exception("Connection closed");
|
||||
}
|
||||
|
||||
return await taskSource.Task;
|
||||
}
|
||||
else
|
||||
{
|
||||
await SendMessageAsync(message);
|
||||
if (ConnectionClosed)
|
||||
{
|
||||
throw new Exception("Connection closed");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new SendMessageException("Can't send message", e);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<dynamic> SendCommandAsync(RequestMessage message, bool waitForAnswer = true)
|
||||
{
|
||||
var rawMessage = new RawRequestMessage(message, ++_commandCount);
|
||||
var serialized = JsonConvert.SerializeObject(rawMessage, new JsonSerializerSettings()
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
//ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||
});
|
||||
return await SendCommandAsync(rawMessage.Id, serialized, waitForAnswer);
|
||||
}
|
||||
|
||||
public async Task<dynamic> SubscribeAsync(RequestMessage message, Func<dynamic, bool> callback)
|
||||
{
|
||||
var rawMessage = new RawRequestMessage(message, ++_commandCount);
|
||||
var serialized = JsonConvert.SerializeObject(rawMessage, new JsonSerializerSettings()
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||
});
|
||||
|
||||
_callbacks.TryAdd(rawMessage.Id, callback);
|
||||
|
||||
return await SendCommandAsync(rawMessage.Id, serialized);
|
||||
}
|
||||
|
||||
private void Connection_Closed(IWebSocket sender, WebSocketClosedEventArgs args)
|
||||
{
|
||||
var webSocket = Interlocked.Exchange(ref _connection, null);
|
||||
webSocket?.Dispose();
|
||||
ConnectionClosed = true;
|
||||
|
||||
Logger.Debug("Connection closed");
|
||||
|
||||
Connected?.Invoke(null, true);
|
||||
}
|
||||
|
||||
private const string MS_CHANNEL_CONNECT_EVENT = "ms.channel.connect";
|
||||
private const string MS_CHANNEL_CLIENT_CONNECT_EVENT = "ms.channel.clientConnect";
|
||||
private const string MS_CHANNEL_CLIENT_DISCONNECT_EVENT = "ms.channel.clientDisconnect";
|
||||
private const string MS_CHANNEL_READY_EVENT = "ms.channel.ready";
|
||||
private const string MS_CHANNEL_UNAUTHORIZED = "ms.channel.unauthorized";
|
||||
private const string MS_ERROR_EVENT = "ms.error";
|
||||
|
||||
private async void Connection_MessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var task = new Task<DataReader>(args.GetDataReader);
|
||||
task.Start();
|
||||
var dataReader = await task.WaitAsync(TimeSpan.FromMilliseconds(_readTimeout));
|
||||
|
||||
using (dataReader)
|
||||
{
|
||||
dataReader.UnicodeEncoding = UnicodeEncoding.Utf8;
|
||||
var message = dataReader.ReadString(dataReader.UnconsumedBufferLength);
|
||||
var obj = JsonConvert.DeserializeObject<dynamic>(message);
|
||||
var id = (string)obj.id;
|
||||
var type = (string)obj.@event;
|
||||
|
||||
Logger.Debug($"Received message: {message}");
|
||||
|
||||
// Response:
|
||||
// {"data":{"clients":[{"attributes":{"name":"c2Ftc3VuZ2N0bA=="},"connectTime":1685302606520,"deviceName":"c2Ftc3VuZ2N0bA==","id":"92e0cbc1-6f86-4013-9b9b-65a47afb2236","isHost":false}],"id":"92e0cbc1-6f86-4013-9b9b-65a47afb2236","token":"16224598"},"event":"ms.channel.connect"}
|
||||
// Second response:
|
||||
// {"data":{"clients":[{"attributes":{"name":"c2Ftc3VuZ2N0bA==","token":"16224598"},"connectTime":1685303321571,"deviceName":"c2Ftc3VuZ2N0bA==","id":"58589451-2ecf-44f0-9267-31983a5466","isHost":false}],"id":"58589451-2ecf-44f0-9267-31983a5466"},"event":"ms.channel.connect"}
|
||||
|
||||
//TaskCompletionSource<dynamic> taskCompletion;
|
||||
if (type == MS_CHANNEL_CONNECT_EVENT)
|
||||
{
|
||||
var token = (string)obj.data?.token;
|
||||
|
||||
if (token == null)
|
||||
{
|
||||
token = (string)obj.data?.clients[0]?.attributes?.token;
|
||||
}
|
||||
|
||||
if (token != null)
|
||||
{
|
||||
Connected?.Invoke(token, false);
|
||||
}
|
||||
|
||||
//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?.ToString()));
|
||||
// }
|
||||
// //else if (args.Cancelled)
|
||||
// //{
|
||||
// // taskSource.SetCanceled();
|
||||
// //}
|
||||
// taskCompletion.TrySetResult(obj.payload);
|
||||
|
||||
// if (_callbacks.TryGetValue(id, out Func<dynamic, bool> callback))
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// callback(obj.payload);
|
||||
// }
|
||||
// catch (Exception callbackException)
|
||||
// {
|
||||
// Logger.Error($"Connection_MessageReceived: the callback threw an exception: {callbackException.ToLogString()}");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
|
||||
Logger.Error($"Connection_MessageReceived: status: {status}, exception: {ex.ToLogString()}");
|
||||
|
||||
SetExceptionOnAllTokens(ex);
|
||||
|
||||
ConnectionClosed = true;
|
||||
|
||||
_messageWriter?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetExceptionOnAllTokens(Exception ex)
|
||||
{
|
||||
//Logger.Debug($"Tokens: {_tokens.Count}");
|
||||
|
||||
foreach (var taskCompletion in _tokens.Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (taskCompletion.Task.Status != TaskStatus.RanToCompletion)
|
||||
{
|
||||
Logger.Debug("taskCompletion.Task.Status: " + taskCompletion.Task.Status);
|
||||
taskCompletion.SetException(new Exception(ex.Message));
|
||||
}
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
Logger.Error("SetExceptionOnAllTokens: " + ex2.Message);
|
||||
}
|
||||
}
|
||||
|
||||
_tokens.Clear();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_connection?.Close(1000, "");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ClosedByDispose = true;
|
||||
Close();
|
||||
_connection?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
public class SamsungApp
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string AppId { get; set; }
|
||||
|
||||
public SamsungApp(string appId, string title)
|
||||
{
|
||||
AppId = appId;
|
||||
Title = title;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Title;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
public enum ButtonType
|
||||
{
|
||||
KEY_POWER,
|
||||
KEY_UP,
|
||||
KEY_DOWN,
|
||||
KEY_LEFT,
|
||||
KEY_RIGHT,
|
||||
KEY_CHUP,
|
||||
KEY_CHDOWN,
|
||||
KEY_ENTER,
|
||||
KEY_RETURN,
|
||||
KEY_CH_LIST,
|
||||
KEY_MENU,
|
||||
KEY_SOURCE,
|
||||
KEY_GUIDE,
|
||||
KEY_TOOLS,
|
||||
KEY_INFO,
|
||||
KEY_RED,
|
||||
KEY_GREEN,
|
||||
KEY_YELLOW,
|
||||
KEY_BLUE,
|
||||
KEY_PANNEL_CHDOWN,
|
||||
KEY_VOLUP,
|
||||
KEY_VOLDOWN,
|
||||
KEY_MUTE,
|
||||
KEY_0,
|
||||
KEY_1,
|
||||
KEY_2,
|
||||
KEY_3,
|
||||
KEY_4,
|
||||
KEY_5,
|
||||
KEY_6,
|
||||
KEY_7,
|
||||
KEY_8,
|
||||
KEY_9,
|
||||
KEY_DTV,
|
||||
KEY_HDMI,
|
||||
KEY_CONTENTS
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,568 @@
|
||||
using ColorControl.Common;
|
||||
using ColorControl.Services.Common;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
class SamsungDeviceOptions
|
||||
{
|
||||
public bool PowerOnAfterStartup { get; set; }
|
||||
public bool PowerOnAfterResume { get; set; }
|
||||
public bool PowerOffOnShutdown { get; set; }
|
||||
public bool PowerOffOnStandby { get; set; }
|
||||
public bool PowerOffOnScreenSaver { get; set; }
|
||||
public int ScreenSaverMinimalDuration { get; set; }
|
||||
public bool TurnScreenOffOnScreenSaver { get; set; }
|
||||
public bool HandleManualScreenSaver { get; set; }
|
||||
public bool PowerOnAfterScreenSaver { get; set; }
|
||||
public bool TurnScreenOnAfterScreenSaver { get; set; }
|
||||
public bool PowerOnAfterManualPowerOff { get; set; }
|
||||
public bool PowerOnByWindows { get; set; }
|
||||
public bool PowerOffByWindows { get; set; }
|
||||
public bool TriggersEnabled { get; set; }
|
||||
public int HDMIPortNumber { get; set; }
|
||||
|
||||
public bool UseSecureConnection { get; set; } = true;
|
||||
}
|
||||
|
||||
public enum PowerOffSource
|
||||
{
|
||||
Unknown,
|
||||
App,
|
||||
External
|
||||
}
|
||||
|
||||
class SamsungDevice
|
||||
{
|
||||
public class InvokableAction
|
||||
{
|
||||
public Func<Dictionary<string, object>, Task<bool>> AsyncFunction { get; set; }
|
||||
public string Name { get; set; }
|
||||
public Type EnumType { get; set; }
|
||||
public decimal MinValue { get; set; }
|
||||
public decimal MaxValue { get; set; }
|
||||
public string Category { get; set; }
|
||||
public string Title { get; set; }
|
||||
public int CurrentValue { get; set; }
|
||||
public int NumberOfValues { get; set; }
|
||||
public bool Advanced { get; set; }
|
||||
public List<string> ValueLabels { get; set; }
|
||||
}
|
||||
|
||||
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public string Name { get; private set; }
|
||||
public string IpAddress { get; private set; }
|
||||
public string MacAddress { get; private set; }
|
||||
public bool IsCustom { get; private set; }
|
||||
public string Token { get; set; }
|
||||
public SamsungDeviceOptions Options { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsDummy { get; private set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool PoweredOn { get; private set; }
|
||||
public DateTimeOffset PoweredOffAt { get; private set; }
|
||||
public PowerOffSource PoweredOffBy { get; internal set; }
|
||||
|
||||
[JsonIgnore]
|
||||
private SamTvConnection _samTvConnection;
|
||||
|
||||
[JsonIgnore]
|
||||
private ServiceManager _serviceManager;
|
||||
[JsonIgnore]
|
||||
private Timer _powerOffTimer;
|
||||
[JsonIgnore]
|
||||
private SemaphoreSlim _connectSemaphore = new SemaphoreSlim(1);
|
||||
[JsonIgnore]
|
||||
private TaskCompletionSource<string> _taskCompletionSource;
|
||||
|
||||
public SamsungDevice(string name, string ipAddress, string macAddress, bool isCustom = true, bool isDummy = false)
|
||||
{
|
||||
Options = new SamsungDeviceOptions();
|
||||
|
||||
Name = name;
|
||||
IpAddress = ipAddress;
|
||||
MacAddress = macAddress;
|
||||
IsCustom = isCustom;
|
||||
IsDummy = isDummy;
|
||||
|
||||
_serviceManager = Program.ServiceProvider.GetRequiredService<ServiceManager>();
|
||||
}
|
||||
|
||||
~SamsungDevice()
|
||||
{
|
||||
ClearPowerOffTask();
|
||||
}
|
||||
|
||||
public async Task<bool> ConnectAsync(bool force = false, bool retryToken = false)
|
||||
{
|
||||
await _connectSemaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (force)
|
||||
{
|
||||
_samTvConnection?.Dispose();
|
||||
_samTvConnection = null;
|
||||
}
|
||||
else if (IsConnected())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_samTvConnection = new SamTvConnection();
|
||||
_samTvConnection.Connected += Connection_Connected;
|
||||
var b64 = Utils.Base64Encode("samsungctl");
|
||||
|
||||
var firstTime = Token == null;
|
||||
var readTimeout = firstTime ? 60000 : 5000;
|
||||
|
||||
try
|
||||
{
|
||||
var protocol = Options.UseSecureConnection ? "wss" : "ws";
|
||||
var port = Options.UseSecureConnection ? 8002 : 8001;
|
||||
|
||||
var uriString = $"{protocol}://{IpAddress}:{port}/api/v2/channels/samsung.remote.control?name={b64}";
|
||||
|
||||
if (Token != null)
|
||||
{
|
||||
uriString += $"&token={Token}";
|
||||
}
|
||||
|
||||
var result = await _samTvConnection.Connect(new Uri(uriString), readTimeout);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var waitTime = Token != null ? 3000 : 60000;
|
||||
|
||||
_taskCompletionSource = new TaskCompletionSource<string>();
|
||||
|
||||
await _taskCompletionSource.Task.WaitAsync(TimeSpan.FromMilliseconds(waitTime));
|
||||
|
||||
_taskCompletionSource = null;
|
||||
|
||||
//if (Token != null)
|
||||
//{
|
||||
// await Task.Delay(1500);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// var seconds = 60;
|
||||
// while (seconds > 0 && Token == null)
|
||||
// {
|
||||
// await Task.Delay(1000);
|
||||
// seconds--;
|
||||
// }
|
||||
//}
|
||||
|
||||
if (firstTime && Token != null && !retryToken)
|
||||
{
|
||||
_samTvConnection.Dispose();
|
||||
_samTvConnection = null;
|
||||
|
||||
return await ConnectAsync(force, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Debug(ex);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
_connectSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
private void Connection_Connected(string token, bool disconnect)
|
||||
{
|
||||
if (disconnect)
|
||||
{
|
||||
Logger.Debug($"Disconnect event, powered off by: {PoweredOffBy}");
|
||||
|
||||
if (_samTvConnection?.ClosedByDispose != true && PoweredOffBy == PowerOffSource.Unknown)
|
||||
{
|
||||
PoweredOffBy = PowerOffSource.External;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Token = token;
|
||||
|
||||
_taskCompletionSource?.SetResult(token);
|
||||
PoweredOffBy = PowerOffSource.Unknown;
|
||||
}
|
||||
|
||||
internal async Task PowerOffAsync()
|
||||
{
|
||||
await SendKeyAsync("KEY_POWER");
|
||||
|
||||
PoweredOn = false;
|
||||
PoweredOffAt = DateTimeOffset.Now;
|
||||
PoweredOffBy = PowerOffSource.App;
|
||||
}
|
||||
|
||||
internal async Task<bool> WakeAndConnectWithRetries(int retries = 5)
|
||||
{
|
||||
var maxRetries = retries <= 1 ? 5 : retries;
|
||||
|
||||
var result = false;
|
||||
for (var retry = 0; retry < maxRetries && !result; retry++)
|
||||
{
|
||||
Logger.Debug($"WakeAndConnectWithRetries: attempt {retry + 1} of {maxRetries}...");
|
||||
|
||||
var ms = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
result = await WakeAndConnect();
|
||||
ms = DateTimeOffset.Now.ToUnixTimeMilliseconds() - ms;
|
||||
if (!result)
|
||||
{
|
||||
var delay = 2000 - ms;
|
||||
if (delay > 0)
|
||||
{
|
||||
await Task.Delay((int)delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal async Task<bool> WakeAndConnect(int connectDelay = 500)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = Utils.PingHost(IpAddress);
|
||||
|
||||
Logger.Debug($"Ping result: {result}");
|
||||
|
||||
var powerState = default(string);
|
||||
|
||||
if (result)
|
||||
{
|
||||
powerState = await GetPowerStateAsync();
|
||||
}
|
||||
|
||||
if (result && powerState == "on" && IsConnected())
|
||||
{
|
||||
Logger.Debug("Already powered on and connected");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!result || string.IsNullOrEmpty(powerState))
|
||||
{
|
||||
result = Wake();
|
||||
if (!result)
|
||||
{
|
||||
Logger.Debug("WOL failed");
|
||||
return false;
|
||||
}
|
||||
Logger.Debug("WOL succeeded");
|
||||
await Task.Delay(connectDelay);
|
||||
}
|
||||
|
||||
result = await ConnectAsync(true);
|
||||
|
||||
if (result && powerState == "standby")
|
||||
{
|
||||
await SendKeyAsync("KEY_POWER");
|
||||
//var powerState = await GetPowerStateAsync();
|
||||
|
||||
////if (!PoweredOn && (PoweredOffAt == DateTimeOffset.MinValue || PoweredOffAt >= DateTimeOffset.Now.AddMinutes(-2)))
|
||||
//if (powerState == "standby")
|
||||
//{
|
||||
// await SendKeyAsync("KEY_POWER");
|
||||
//}
|
||||
}
|
||||
|
||||
PoweredOn = true;
|
||||
|
||||
Logger.Debug("Connect succeeded: " + result);
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error("WakeAndConnectToSelectedDevice: " + e.ToLogString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool Wake()
|
||||
{
|
||||
var result = false;
|
||||
|
||||
if (MacAddress != null)
|
||||
{
|
||||
result = WOL.WakeFunctionCheckAdmin(MacAddress, IpAddress);
|
||||
//_justWokeUp = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Debug("Cannot wake device: the device has no MAC-address");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<string> GetPowerStateAsync()
|
||||
{
|
||||
var url = $"http://{IpAddress}:8001/api/v2/";
|
||||
|
||||
var json = await Utils.GetRestJsonAsync(url);
|
||||
|
||||
if (json == null)
|
||||
{
|
||||
Logger.Error("No power state received");
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var powerState = (string)json.device?.PowerState;
|
||||
|
||||
Logger.Error($"Current power state: {powerState}");
|
||||
|
||||
return powerState;
|
||||
}
|
||||
|
||||
internal async Task<bool> TestConnectionAsync()
|
||||
{
|
||||
var result = Utils.PingHost(IpAddress);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return await ConnectAsync();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsConnected()
|
||||
{
|
||||
return _samTvConnection?.ConnectionClosed == false;
|
||||
}
|
||||
|
||||
internal void ConvertToCustom()
|
||||
{
|
||||
IsCustom = true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{(IsDummy ? string.Empty : (IsCustom ? "Custom: " : "Auto detect: "))}{Name}{(!string.IsNullOrEmpty(IpAddress) ? ", " + IpAddress : string.Empty)}";
|
||||
}
|
||||
|
||||
internal async Task<bool> ExecutePresetAsync(SamsungPreset preset, AppContext appContext, SamsungServiceConfig config)
|
||||
{
|
||||
var hasApp = !string.IsNullOrEmpty(preset.AppId);
|
||||
|
||||
var hasWOL = preset.Steps.Any(s => s.Equals("WOL", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (hasWOL)
|
||||
{
|
||||
var connected = await WakeAndConnect();
|
||||
if (!connected)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (var tries = 0; tries <= 1; tries++)
|
||||
{
|
||||
if (!await ConnectAsync())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasApp)
|
||||
{
|
||||
try
|
||||
{
|
||||
//await _lgTvApi.LaunchApp(preset.appId, @params);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string logMessage = ex.ToLogString(Environment.StackTrace);
|
||||
Logger.Error("Error while launching app: " + logMessage);
|
||||
|
||||
if (tries == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
if (preset.Steps.Any())
|
||||
{
|
||||
if (hasApp)
|
||||
{
|
||||
await Task.Delay(1500);
|
||||
}
|
||||
try
|
||||
{
|
||||
await ExecuteStepsAsync(preset, config);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string logMessage = ex.ToLogString(Environment.StackTrace);
|
||||
Logger.Error("Error while executing steps: " + logMessage);
|
||||
|
||||
if (tries == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task ExecuteStepsAsync(SamsungPreset preset, SamsungServiceConfig config)
|
||||
{
|
||||
foreach (var step in preset.Steps)
|
||||
{
|
||||
var keySpec = step.Split(':');
|
||||
|
||||
var delay = config.DefaultButtonDelay;
|
||||
var key = step;
|
||||
if (keySpec.Length == 2)
|
||||
{
|
||||
delay = Utils.ParseInt(keySpec[1]);
|
||||
if (delay > 0)
|
||||
{
|
||||
key = keySpec[0];
|
||||
}
|
||||
}
|
||||
|
||||
var index = key.IndexOf("(");
|
||||
string[] parameters = null;
|
||||
if (index > -1)
|
||||
{
|
||||
var keyValue = key.Split('(');
|
||||
key = keyValue[0];
|
||||
parameters = keyValue[1].Substring(0, keyValue[1].Length - 1).Split(';');
|
||||
}
|
||||
|
||||
var executeKey = true;
|
||||
if (parameters != null && await _serviceManager.HandleExternalServiceAsync(key, parameters))
|
||||
{
|
||||
executeKey = false;
|
||||
}
|
||||
|
||||
if (executeKey)
|
||||
{
|
||||
await SendKeyAsync(key);
|
||||
delay = delay == 0 ? config.DefaultButtonDelay : delay;
|
||||
}
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
await Task.Delay(delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SendKeyAsync(string key)
|
||||
{
|
||||
var dynamic = new
|
||||
{
|
||||
Cmd = "Click",
|
||||
DataOfCmd = key,
|
||||
Option = "false",
|
||||
TypeOfRemote = "SendRemoteKey"
|
||||
};
|
||||
|
||||
var message = new RequestMessage("ms.remote.control", dynamic);
|
||||
|
||||
await _samTvConnection.SendCommandAsync(message, false);
|
||||
}
|
||||
|
||||
internal void ClearPowerOffTask()
|
||||
{
|
||||
_powerOffTimer?.Dispose();
|
||||
}
|
||||
|
||||
internal void PowerOffIn(int seconds)
|
||||
{
|
||||
ClearPowerOffTask();
|
||||
|
||||
_powerOffTimer = new Timer(PowerOffByTimer);
|
||||
_powerOffTimer.Change(TimeSpan.FromSeconds(seconds), TimeSpan.FromSeconds(seconds));
|
||||
}
|
||||
|
||||
private void PowerOffByTimer(object _)
|
||||
{
|
||||
ClearPowerOffTask();
|
||||
|
||||
var x = PerformActionOnScreenSaver();
|
||||
}
|
||||
|
||||
private bool IsPowerOffAllowed() => true;
|
||||
|
||||
public async Task<bool> PerformActionOnScreenSaver()
|
||||
{
|
||||
if (!IsPowerOffAllowed())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Options.TurnScreenOffOnScreenSaver)
|
||||
{
|
||||
Logger.Debug("Turning screen off on screen saver");
|
||||
//await _lgTvApi.TurnScreenOff();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Logger.Debug($"Device {Name} is now powering off due to delayed screensaver task");
|
||||
|
||||
await PowerOffAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> PerformActionAfterScreenSaver(int powerOnRetries)
|
||||
{
|
||||
if (Options.TurnScreenOffOnScreenSaver && IsConnected())
|
||||
{
|
||||
if (Options.TurnScreenOnAfterScreenSaver)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.Debug("Turning screen on after screen saver");
|
||||
//await _lgTvApi.TurnScreenOn();
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return await WakeAndConnectWithRetries(powerOnRetries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+840
@@ -0,0 +1,840 @@
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
partial class SamsungPanel
|
||||
{
|
||||
/// <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 Component 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()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
scSamsungController = new System.Windows.Forms.SplitContainer();
|
||||
btnSamsungDeviceOptionsSettings = new System.Windows.Forms.Button();
|
||||
btnSamsungSettings = new System.Windows.Forms.Button();
|
||||
chkSamsungQuickAccess = new System.Windows.Forms.CheckBox();
|
||||
cbxSamsungPcHdmiPort = new System.Windows.Forms.ComboBox();
|
||||
lblSamsungPcHdmiPort = new System.Windows.Forms.Label();
|
||||
edtSamsungPresetDescription = new System.Windows.Forms.TextBox();
|
||||
lblSamsungPresetDescription = new System.Windows.Forms.Label();
|
||||
btnSamsungDeviceOptionsHelp = new System.Windows.Forms.Button();
|
||||
btnSamsungPresetEditTriggerConditions = new System.Windows.Forms.Button();
|
||||
edtSamsungPresetTriggerConditions = new System.Windows.Forms.TextBox();
|
||||
lblSamsungPresetExcludedProcesses = new System.Windows.Forms.Label();
|
||||
edtSamsungPresetExcludedProcesses = new System.Windows.Forms.TextBox();
|
||||
lblSamsungPresetIncludedProcesses = new System.Windows.Forms.Label();
|
||||
edtSamsungPresetIncludedProcesses = new System.Windows.Forms.TextBox();
|
||||
lblSamsungPresetTriggerCondition = new System.Windows.Forms.Label();
|
||||
cbxSamsungPresetTrigger = new System.Windows.Forms.ComboBox();
|
||||
lblSamsungPresetTrigger = new System.Windows.Forms.Label();
|
||||
chkSamsungRemoteControlShow = new System.Windows.Forms.CheckBox();
|
||||
label3 = new System.Windows.Forms.Label();
|
||||
cbxSamsungDevices = new System.Windows.Forms.ComboBox();
|
||||
btnSamsungDeviceConvertToCustom = new System.Windows.Forms.Button();
|
||||
cbxSamsungApps = new System.Windows.Forms.ComboBox();
|
||||
lvSamsungPresets = new System.Windows.Forms.ListView();
|
||||
label5 = new System.Windows.Forms.Label();
|
||||
cbxSamsungPresetDevice = new System.Windows.Forms.ComboBox();
|
||||
btnDeleteLg = new System.Windows.Forms.Button();
|
||||
btnApplyLg = new System.Windows.Forms.Button();
|
||||
lblDeviceFilter = new System.Windows.Forms.Label();
|
||||
lblSamsungPresetDevice = new System.Windows.Forms.Label();
|
||||
btnAddLg = new System.Windows.Forms.Button();
|
||||
edtShortcutLg = new System.Windows.Forms.TextBox();
|
||||
edtSamsungDeviceFilter = new System.Windows.Forms.TextBox();
|
||||
btnSamsungRemoveDevice = new System.Windows.Forms.Button();
|
||||
btnSamsungRefreshApps = new System.Windows.Forms.Button();
|
||||
label2 = new System.Windows.Forms.Label();
|
||||
label1 = new System.Windows.Forms.Label();
|
||||
btnSamsungAddDevice = new System.Windows.Forms.Button();
|
||||
edtNameLg = new System.Windows.Forms.TextBox();
|
||||
btnSetShortcutLg = new System.Windows.Forms.Button();
|
||||
edtStepsLg = new System.Windows.Forms.TextBox();
|
||||
btnSamsungAddButton = new System.Windows.Forms.Button();
|
||||
mnuLgButtons = new System.Windows.Forms.ContextMenuStrip(components);
|
||||
mnuLgRcButtons = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuLgActions = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuLgNvPresets = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuLgAmdPresets = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuLgProgram = new System.Windows.Forms.ToolStripMenuItem();
|
||||
btnCloneLg = new System.Windows.Forms.Button();
|
||||
lblStepsLg = new System.Windows.Forms.Label();
|
||||
btnSamsungDeviceFilterRefresh = new System.Windows.Forms.Button();
|
||||
clbLgPower = new System.Windows.Forms.CheckedListBox();
|
||||
lblSamsungError = new System.Windows.Forms.Label();
|
||||
mnuLgSettings = new System.Windows.Forms.ContextMenuStrip(components);
|
||||
miTestPowerOffOn = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miNvSettings = new System.Windows.Forms.ToolStripMenuItem();
|
||||
((System.ComponentModel.ISupportInitialize)scSamsungController).BeginInit();
|
||||
scSamsungController.Panel1.SuspendLayout();
|
||||
scSamsungController.SuspendLayout();
|
||||
mnuLgButtons.SuspendLayout();
|
||||
mnuLgSettings.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// scSamsungController
|
||||
//
|
||||
scSamsungController.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
scSamsungController.Location = new System.Drawing.Point(0, 0);
|
||||
scSamsungController.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
scSamsungController.Name = "scSamsungController";
|
||||
//
|
||||
// scSamsungController.Panel1
|
||||
//
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungDeviceOptionsSettings);
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungSettings);
|
||||
scSamsungController.Panel1.Controls.Add(chkSamsungQuickAccess);
|
||||
scSamsungController.Panel1.Controls.Add(cbxSamsungPcHdmiPort);
|
||||
scSamsungController.Panel1.Controls.Add(lblSamsungPcHdmiPort);
|
||||
scSamsungController.Panel1.Controls.Add(edtSamsungPresetDescription);
|
||||
scSamsungController.Panel1.Controls.Add(lblSamsungPresetDescription);
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungDeviceOptionsHelp);
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungPresetEditTriggerConditions);
|
||||
scSamsungController.Panel1.Controls.Add(edtSamsungPresetTriggerConditions);
|
||||
scSamsungController.Panel1.Controls.Add(lblSamsungPresetExcludedProcesses);
|
||||
scSamsungController.Panel1.Controls.Add(edtSamsungPresetExcludedProcesses);
|
||||
scSamsungController.Panel1.Controls.Add(lblSamsungPresetIncludedProcesses);
|
||||
scSamsungController.Panel1.Controls.Add(edtSamsungPresetIncludedProcesses);
|
||||
scSamsungController.Panel1.Controls.Add(lblSamsungPresetTriggerCondition);
|
||||
scSamsungController.Panel1.Controls.Add(cbxSamsungPresetTrigger);
|
||||
scSamsungController.Panel1.Controls.Add(lblSamsungPresetTrigger);
|
||||
scSamsungController.Panel1.Controls.Add(chkSamsungRemoteControlShow);
|
||||
scSamsungController.Panel1.Controls.Add(label3);
|
||||
scSamsungController.Panel1.Controls.Add(cbxSamsungDevices);
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungDeviceConvertToCustom);
|
||||
scSamsungController.Panel1.Controls.Add(cbxSamsungApps);
|
||||
scSamsungController.Panel1.Controls.Add(lvSamsungPresets);
|
||||
scSamsungController.Panel1.Controls.Add(label5);
|
||||
scSamsungController.Panel1.Controls.Add(cbxSamsungPresetDevice);
|
||||
scSamsungController.Panel1.Controls.Add(btnDeleteLg);
|
||||
scSamsungController.Panel1.Controls.Add(btnApplyLg);
|
||||
scSamsungController.Panel1.Controls.Add(lblDeviceFilter);
|
||||
scSamsungController.Panel1.Controls.Add(lblSamsungPresetDevice);
|
||||
scSamsungController.Panel1.Controls.Add(btnAddLg);
|
||||
scSamsungController.Panel1.Controls.Add(edtShortcutLg);
|
||||
scSamsungController.Panel1.Controls.Add(edtSamsungDeviceFilter);
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungRemoveDevice);
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungRefreshApps);
|
||||
scSamsungController.Panel1.Controls.Add(label2);
|
||||
scSamsungController.Panel1.Controls.Add(label1);
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungAddDevice);
|
||||
scSamsungController.Panel1.Controls.Add(edtNameLg);
|
||||
scSamsungController.Panel1.Controls.Add(btnSetShortcutLg);
|
||||
scSamsungController.Panel1.Controls.Add(edtStepsLg);
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungAddButton);
|
||||
scSamsungController.Panel1.Controls.Add(btnCloneLg);
|
||||
scSamsungController.Panel1.Controls.Add(lblStepsLg);
|
||||
scSamsungController.Panel1.Controls.Add(btnSamsungDeviceFilterRefresh);
|
||||
scSamsungController.Panel1.Controls.Add(clbLgPower);
|
||||
scSamsungController.Panel1.Controls.Add(lblSamsungError);
|
||||
scSamsungController.Panel1MinSize = 750;
|
||||
scSamsungController.Panel2MinSize = 150;
|
||||
scSamsungController.Size = new System.Drawing.Size(1114, 539);
|
||||
scSamsungController.SplitterDistance = 899;
|
||||
scSamsungController.SplitterWidth = 5;
|
||||
scSamsungController.TabIndex = 43;
|
||||
//
|
||||
// btnSamsungDeviceOptionsSettings
|
||||
//
|
||||
btnSamsungDeviceOptionsSettings.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
btnSamsungDeviceOptionsSettings.Enabled = false;
|
||||
btnSamsungDeviceOptionsSettings.Location = new System.Drawing.Point(872, 103);
|
||||
btnSamsungDeviceOptionsSettings.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungDeviceOptionsSettings.Name = "btnSamsungDeviceOptionsSettings";
|
||||
btnSamsungDeviceOptionsSettings.Size = new System.Drawing.Size(22, 27);
|
||||
btnSamsungDeviceOptionsSettings.TabIndex = 65;
|
||||
btnSamsungDeviceOptionsSettings.Text = "S";
|
||||
btnSamsungDeviceOptionsSettings.UseVisualStyleBackColor = true;
|
||||
btnSamsungDeviceOptionsSettings.Click += btnSamsungDeviceOptionsSettings_Click;
|
||||
//
|
||||
// btnSamsungSettings
|
||||
//
|
||||
btnSamsungSettings.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
|
||||
btnSamsungSettings.Location = new System.Drawing.Point(807, 284);
|
||||
btnSamsungSettings.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungSettings.Name = "btnSamsungSettings";
|
||||
btnSamsungSettings.Size = new System.Drawing.Size(88, 27);
|
||||
btnSamsungSettings.TabIndex = 64;
|
||||
btnSamsungSettings.Text = "Settings...";
|
||||
btnSamsungSettings.UseVisualStyleBackColor = true;
|
||||
btnSamsungSettings.Click += btnSamsungSettings_Click;
|
||||
//
|
||||
// chkSamsungQuickAccess
|
||||
//
|
||||
chkSamsungQuickAccess.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
chkSamsungQuickAccess.AutoSize = true;
|
||||
chkSamsungQuickAccess.Enabled = false;
|
||||
chkSamsungQuickAccess.Location = new System.Drawing.Point(341, 320);
|
||||
chkSamsungQuickAccess.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkSamsungQuickAccess.Name = "chkSamsungQuickAccess";
|
||||
chkSamsungQuickAccess.Size = new System.Drawing.Size(96, 19);
|
||||
chkSamsungQuickAccess.TabIndex = 63;
|
||||
chkSamsungQuickAccess.Text = "Quick Access";
|
||||
chkSamsungQuickAccess.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// cbxSamsungPcHdmiPort
|
||||
//
|
||||
cbxSamsungPcHdmiPort.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
cbxSamsungPcHdmiPort.FormattingEnabled = true;
|
||||
cbxSamsungPcHdmiPort.Items.AddRange(new object[] { "None", "HDMI1", "HDMI2", "HDMI3", "HDMI4" });
|
||||
cbxSamsungPcHdmiPort.Location = new System.Drawing.Point(667, 42);
|
||||
cbxSamsungPcHdmiPort.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
cbxSamsungPcHdmiPort.Name = "cbxSamsungPcHdmiPort";
|
||||
cbxSamsungPcHdmiPort.Size = new System.Drawing.Size(86, 23);
|
||||
cbxSamsungPcHdmiPort.TabIndex = 62;
|
||||
cbxSamsungPcHdmiPort.SelectedIndexChanged += cbxSamsungPcHdmiPort_SelectedIndexChanged;
|
||||
//
|
||||
// lblSamsungPcHdmiPort
|
||||
//
|
||||
lblSamsungPcHdmiPort.AutoSize = true;
|
||||
lblSamsungPcHdmiPort.Location = new System.Drawing.Point(577, 45);
|
||||
lblSamsungPcHdmiPort.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblSamsungPcHdmiPort.Name = "lblSamsungPcHdmiPort";
|
||||
lblSamsungPcHdmiPort.Size = new System.Drawing.Size(84, 15);
|
||||
lblSamsungPcHdmiPort.TabIndex = 61;
|
||||
lblSamsungPcHdmiPort.Text = "PC HDMI port:";
|
||||
//
|
||||
// edtSamsungPresetDescription
|
||||
//
|
||||
edtSamsungPresetDescription.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
edtSamsungPresetDescription.Enabled = false;
|
||||
edtSamsungPresetDescription.Location = new System.Drawing.Point(100, 489);
|
||||
edtSamsungPresetDescription.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtSamsungPresetDescription.Multiline = true;
|
||||
edtSamsungPresetDescription.Name = "edtSamsungPresetDescription";
|
||||
edtSamsungPresetDescription.Size = new System.Drawing.Size(699, 43);
|
||||
edtSamsungPresetDescription.TabIndex = 60;
|
||||
//
|
||||
// lblSamsungPresetDescription
|
||||
//
|
||||
lblSamsungPresetDescription.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
lblSamsungPresetDescription.AutoSize = true;
|
||||
lblSamsungPresetDescription.Location = new System.Drawing.Point(6, 494);
|
||||
lblSamsungPresetDescription.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblSamsungPresetDescription.Name = "lblSamsungPresetDescription";
|
||||
lblSamsungPresetDescription.Size = new System.Drawing.Size(70, 15);
|
||||
lblSamsungPresetDescription.TabIndex = 59;
|
||||
lblSamsungPresetDescription.Text = "Description:";
|
||||
//
|
||||
// btnSamsungDeviceOptionsHelp
|
||||
//
|
||||
btnSamsungDeviceOptionsHelp.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
btnSamsungDeviceOptionsHelp.Location = new System.Drawing.Point(872, 70);
|
||||
btnSamsungDeviceOptionsHelp.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungDeviceOptionsHelp.Name = "btnSamsungDeviceOptionsHelp";
|
||||
btnSamsungDeviceOptionsHelp.Size = new System.Drawing.Size(22, 27);
|
||||
btnSamsungDeviceOptionsHelp.TabIndex = 58;
|
||||
btnSamsungDeviceOptionsHelp.Text = "?";
|
||||
btnSamsungDeviceOptionsHelp.UseVisualStyleBackColor = true;
|
||||
btnSamsungDeviceOptionsHelp.Click += btnSamsungDeviceOptionsHelp_Click;
|
||||
//
|
||||
// btnSamsungPresetEditTriggerConditions
|
||||
//
|
||||
btnSamsungPresetEditTriggerConditions.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnSamsungPresetEditTriggerConditions.Enabled = false;
|
||||
btnSamsungPresetEditTriggerConditions.Location = new System.Drawing.Point(804, 347);
|
||||
btnSamsungPresetEditTriggerConditions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungPresetEditTriggerConditions.Name = "btnSamsungPresetEditTriggerConditions";
|
||||
btnSamsungPresetEditTriggerConditions.Size = new System.Drawing.Size(88, 27);
|
||||
btnSamsungPresetEditTriggerConditions.TabIndex = 54;
|
||||
btnSamsungPresetEditTriggerConditions.Text = "Edit...";
|
||||
btnSamsungPresetEditTriggerConditions.UseVisualStyleBackColor = true;
|
||||
btnSamsungPresetEditTriggerConditions.Click += btnSamsungPresetEditTriggerConditions_Click;
|
||||
//
|
||||
// edtSamsungPresetTriggerConditions
|
||||
//
|
||||
edtSamsungPresetTriggerConditions.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
edtSamsungPresetTriggerConditions.Enabled = false;
|
||||
edtSamsungPresetTriggerConditions.Location = new System.Drawing.Point(601, 349);
|
||||
edtSamsungPresetTriggerConditions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtSamsungPresetTriggerConditions.Name = "edtSamsungPresetTriggerConditions";
|
||||
edtSamsungPresetTriggerConditions.ReadOnly = true;
|
||||
edtSamsungPresetTriggerConditions.Size = new System.Drawing.Size(194, 23);
|
||||
edtSamsungPresetTriggerConditions.TabIndex = 53;
|
||||
//
|
||||
// lblSamsungPresetExcludedProcesses
|
||||
//
|
||||
lblSamsungPresetExcludedProcesses.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
lblSamsungPresetExcludedProcesses.AutoSize = true;
|
||||
lblSamsungPresetExcludedProcesses.Location = new System.Drawing.Point(475, 414);
|
||||
lblSamsungPresetExcludedProcesses.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblSamsungPresetExcludedProcesses.Name = "lblSamsungPresetExcludedProcesses";
|
||||
lblSamsungPresetExcludedProcesses.Size = new System.Drawing.Size(112, 15);
|
||||
lblSamsungPresetExcludedProcesses.TabIndex = 52;
|
||||
lblSamsungPresetExcludedProcesses.Text = "Excluded processes:";
|
||||
//
|
||||
// edtSamsungPresetExcludedProcesses
|
||||
//
|
||||
edtSamsungPresetExcludedProcesses.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
edtSamsungPresetExcludedProcesses.Enabled = false;
|
||||
edtSamsungPresetExcludedProcesses.Location = new System.Drawing.Point(601, 411);
|
||||
edtSamsungPresetExcludedProcesses.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtSamsungPresetExcludedProcesses.Name = "edtSamsungPresetExcludedProcesses";
|
||||
edtSamsungPresetExcludedProcesses.Size = new System.Drawing.Size(289, 23);
|
||||
edtSamsungPresetExcludedProcesses.TabIndex = 51;
|
||||
//
|
||||
// lblSamsungPresetIncludedProcesses
|
||||
//
|
||||
lblSamsungPresetIncludedProcesses.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
lblSamsungPresetIncludedProcesses.AutoSize = true;
|
||||
lblSamsungPresetIncludedProcesses.Location = new System.Drawing.Point(475, 384);
|
||||
lblSamsungPresetIncludedProcesses.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblSamsungPresetIncludedProcesses.Name = "lblSamsungPresetIncludedProcesses";
|
||||
lblSamsungPresetIncludedProcesses.Size = new System.Drawing.Size(110, 15);
|
||||
lblSamsungPresetIncludedProcesses.TabIndex = 50;
|
||||
lblSamsungPresetIncludedProcesses.Text = "Included processes:";
|
||||
//
|
||||
// edtSamsungPresetIncludedProcesses
|
||||
//
|
||||
edtSamsungPresetIncludedProcesses.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
edtSamsungPresetIncludedProcesses.Enabled = false;
|
||||
edtSamsungPresetIncludedProcesses.Location = new System.Drawing.Point(601, 381);
|
||||
edtSamsungPresetIncludedProcesses.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtSamsungPresetIncludedProcesses.Name = "edtSamsungPresetIncludedProcesses";
|
||||
edtSamsungPresetIncludedProcesses.Size = new System.Drawing.Size(289, 23);
|
||||
edtSamsungPresetIncludedProcesses.TabIndex = 49;
|
||||
//
|
||||
// lblSamsungPresetTriggerCondition
|
||||
//
|
||||
lblSamsungPresetTriggerCondition.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
lblSamsungPresetTriggerCondition.AutoSize = true;
|
||||
lblSamsungPresetTriggerCondition.Location = new System.Drawing.Point(475, 353);
|
||||
lblSamsungPresetTriggerCondition.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblSamsungPresetTriggerCondition.Name = "lblSamsungPresetTriggerCondition";
|
||||
lblSamsungPresetTriggerCondition.Size = new System.Drawing.Size(63, 15);
|
||||
lblSamsungPresetTriggerCondition.TabIndex = 47;
|
||||
lblSamsungPresetTriggerCondition.Text = "Condition:";
|
||||
//
|
||||
// cbxSamsungPresetTrigger
|
||||
//
|
||||
cbxSamsungPresetTrigger.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
cbxSamsungPresetTrigger.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
cbxSamsungPresetTrigger.Enabled = false;
|
||||
cbxSamsungPresetTrigger.FormattingEnabled = true;
|
||||
cbxSamsungPresetTrigger.Location = new System.Drawing.Point(601, 318);
|
||||
cbxSamsungPresetTrigger.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
cbxSamsungPresetTrigger.Name = "cbxSamsungPresetTrigger";
|
||||
cbxSamsungPresetTrigger.Size = new System.Drawing.Size(289, 23);
|
||||
cbxSamsungPresetTrigger.TabIndex = 46;
|
||||
//
|
||||
// lblSamsungPresetTrigger
|
||||
//
|
||||
lblSamsungPresetTrigger.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
lblSamsungPresetTrigger.AutoSize = true;
|
||||
lblSamsungPresetTrigger.Location = new System.Drawing.Point(475, 321);
|
||||
lblSamsungPresetTrigger.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblSamsungPresetTrigger.Name = "lblSamsungPresetTrigger";
|
||||
lblSamsungPresetTrigger.Size = new System.Drawing.Size(46, 15);
|
||||
lblSamsungPresetTrigger.TabIndex = 45;
|
||||
lblSamsungPresetTrigger.Text = "Trigger:";
|
||||
//
|
||||
// chkSamsungRemoteControlShow
|
||||
//
|
||||
chkSamsungRemoteControlShow.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
chkSamsungRemoteControlShow.Appearance = System.Windows.Forms.Appearance.Button;
|
||||
chkSamsungRemoteControlShow.AutoSize = true;
|
||||
chkSamsungRemoteControlShow.Location = new System.Drawing.Point(793, 8);
|
||||
chkSamsungRemoteControlShow.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkSamsungRemoteControlShow.Name = "chkSamsungRemoteControlShow";
|
||||
chkSamsungRemoteControlShow.Size = new System.Drawing.Size(101, 25);
|
||||
chkSamsungRemoteControlShow.TabIndex = 43;
|
||||
chkSamsungRemoteControlShow.Text = "Remote Control";
|
||||
chkSamsungRemoteControlShow.UseVisualStyleBackColor = true;
|
||||
chkSamsungRemoteControlShow.CheckedChanged += chkSamsungRemoteControlShow_CheckedChanged;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
label3.AutoSize = true;
|
||||
label3.Location = new System.Drawing.Point(6, 14);
|
||||
label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label3.Name = "label3";
|
||||
label3.Size = new System.Drawing.Size(45, 15);
|
||||
label3.TabIndex = 31;
|
||||
label3.Text = "Device:";
|
||||
//
|
||||
// cbxSamsungDevices
|
||||
//
|
||||
cbxSamsungDevices.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
cbxSamsungDevices.DropDownWidth = 400;
|
||||
cbxSamsungDevices.FormattingEnabled = true;
|
||||
cbxSamsungDevices.Location = new System.Drawing.Point(100, 9);
|
||||
cbxSamsungDevices.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
cbxSamsungDevices.Name = "cbxSamsungDevices";
|
||||
cbxSamsungDevices.Size = new System.Drawing.Size(370, 23);
|
||||
cbxSamsungDevices.TabIndex = 30;
|
||||
cbxSamsungDevices.SelectedIndexChanged += cbxSamsungDevices_SelectedIndexChanged;
|
||||
//
|
||||
// btnSamsungDeviceConvertToCustom
|
||||
//
|
||||
btnSamsungDeviceConvertToCustom.Location = new System.Drawing.Point(667, 8);
|
||||
btnSamsungDeviceConvertToCustom.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungDeviceConvertToCustom.Name = "btnSamsungDeviceConvertToCustom";
|
||||
btnSamsungDeviceConvertToCustom.Size = new System.Drawing.Size(88, 27);
|
||||
btnSamsungDeviceConvertToCustom.TabIndex = 41;
|
||||
btnSamsungDeviceConvertToCustom.Text = "To custom...";
|
||||
btnSamsungDeviceConvertToCustom.UseVisualStyleBackColor = true;
|
||||
btnSamsungDeviceConvertToCustom.Click += btnSamsungDeviceConvertToCustom_Click;
|
||||
//
|
||||
// cbxSamsungApps
|
||||
//
|
||||
cbxSamsungApps.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
cbxSamsungApps.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
cbxSamsungApps.Enabled = false;
|
||||
cbxSamsungApps.FormattingEnabled = true;
|
||||
cbxSamsungApps.Location = new System.Drawing.Point(100, 380);
|
||||
cbxSamsungApps.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
cbxSamsungApps.Name = "cbxSamsungApps";
|
||||
cbxSamsungApps.Size = new System.Drawing.Size(233, 23);
|
||||
cbxSamsungApps.TabIndex = 26;
|
||||
cbxSamsungApps.KeyPress += cbxSamsungApps_KeyPress;
|
||||
//
|
||||
// lvSamsungPresets
|
||||
//
|
||||
lvSamsungPresets.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
lvSamsungPresets.CheckBoxes = true;
|
||||
lvSamsungPresets.FullRowSelect = true;
|
||||
lvSamsungPresets.Location = new System.Drawing.Point(6, 152);
|
||||
lvSamsungPresets.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
lvSamsungPresets.MultiSelect = false;
|
||||
lvSamsungPresets.Name = "lvSamsungPresets";
|
||||
lvSamsungPresets.ShowItemToolTips = true;
|
||||
lvSamsungPresets.Size = new System.Drawing.Size(888, 126);
|
||||
lvSamsungPresets.TabIndex = 8;
|
||||
lvSamsungPresets.UseCompatibleStateImageBehavior = false;
|
||||
lvSamsungPresets.View = System.Windows.Forms.View.Details;
|
||||
lvSamsungPresets.ColumnClick += lvSamsungPresets_ColumnClick;
|
||||
lvSamsungPresets.ItemChecked += lvSamsungPresets_ItemChecked;
|
||||
lvSamsungPresets.SelectedIndexChanged += lvSamsungPresets_SelectedIndexChanged;
|
||||
lvSamsungPresets.DoubleClick += lvSamsungPresets_DoubleClick;
|
||||
//
|
||||
// label5
|
||||
//
|
||||
label5.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
label5.AutoSize = true;
|
||||
label5.Location = new System.Drawing.Point(6, 384);
|
||||
label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label5.Name = "label5";
|
||||
label5.Size = new System.Drawing.Size(32, 15);
|
||||
label5.TabIndex = 25;
|
||||
label5.Text = "App:";
|
||||
//
|
||||
// cbxSamsungPresetDevice
|
||||
//
|
||||
cbxSamsungPresetDevice.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
cbxSamsungPresetDevice.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
cbxSamsungPresetDevice.Enabled = false;
|
||||
cbxSamsungPresetDevice.FormattingEnabled = true;
|
||||
cbxSamsungPresetDevice.Location = new System.Drawing.Point(100, 348);
|
||||
cbxSamsungPresetDevice.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
cbxSamsungPresetDevice.Name = "cbxSamsungPresetDevice";
|
||||
cbxSamsungPresetDevice.Size = new System.Drawing.Size(370, 23);
|
||||
cbxSamsungPresetDevice.TabIndex = 40;
|
||||
//
|
||||
// btnDeleteLg
|
||||
//
|
||||
btnDeleteLg.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnDeleteLg.Enabled = false;
|
||||
btnDeleteLg.Location = new System.Drawing.Point(289, 284);
|
||||
btnDeleteLg.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnDeleteLg.Name = "btnDeleteLg";
|
||||
btnDeleteLg.Size = new System.Drawing.Size(88, 27);
|
||||
btnDeleteLg.TabIndex = 27;
|
||||
btnDeleteLg.Text = "Delete";
|
||||
btnDeleteLg.UseVisualStyleBackColor = true;
|
||||
btnDeleteLg.Click += btnDeleteLg_Click;
|
||||
//
|
||||
// btnApplyLg
|
||||
//
|
||||
btnApplyLg.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnApplyLg.Enabled = false;
|
||||
btnApplyLg.Location = new System.Drawing.Point(6, 284);
|
||||
btnApplyLg.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnApplyLg.Name = "btnApplyLg";
|
||||
btnApplyLg.Size = new System.Drawing.Size(88, 27);
|
||||
btnApplyLg.TabIndex = 9;
|
||||
btnApplyLg.Text = "Apply";
|
||||
btnApplyLg.UseVisualStyleBackColor = true;
|
||||
btnApplyLg.Click += btnApplyLg_Click;
|
||||
//
|
||||
// lblDeviceFilter
|
||||
//
|
||||
lblDeviceFilter.AutoSize = true;
|
||||
lblDeviceFilter.Location = new System.Drawing.Point(6, 45);
|
||||
lblDeviceFilter.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblDeviceFilter.Name = "lblDeviceFilter";
|
||||
lblDeviceFilter.Size = new System.Drawing.Size(72, 15);
|
||||
lblDeviceFilter.TabIndex = 24;
|
||||
lblDeviceFilter.Text = "Device filter:";
|
||||
//
|
||||
// lblSamsungPresetDevice
|
||||
//
|
||||
lblSamsungPresetDevice.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
lblSamsungPresetDevice.AutoSize = true;
|
||||
lblSamsungPresetDevice.Location = new System.Drawing.Point(6, 351);
|
||||
lblSamsungPresetDevice.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblSamsungPresetDevice.Name = "lblSamsungPresetDevice";
|
||||
lblSamsungPresetDevice.Size = new System.Drawing.Size(45, 15);
|
||||
lblSamsungPresetDevice.TabIndex = 39;
|
||||
lblSamsungPresetDevice.Text = "Device:";
|
||||
//
|
||||
// btnAddLg
|
||||
//
|
||||
btnAddLg.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnAddLg.Location = new System.Drawing.Point(195, 284);
|
||||
btnAddLg.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnAddLg.Name = "btnAddLg";
|
||||
btnAddLg.Size = new System.Drawing.Size(88, 27);
|
||||
btnAddLg.TabIndex = 28;
|
||||
btnAddLg.Text = "Add";
|
||||
btnAddLg.UseVisualStyleBackColor = true;
|
||||
btnAddLg.Click += btnAddLg_Click;
|
||||
//
|
||||
// edtShortcutLg
|
||||
//
|
||||
edtShortcutLg.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
edtShortcutLg.Enabled = false;
|
||||
edtShortcutLg.Location = new System.Drawing.Point(100, 411);
|
||||
edtShortcutLg.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtShortcutLg.Name = "edtShortcutLg";
|
||||
edtShortcutLg.ReadOnly = true;
|
||||
edtShortcutLg.Size = new System.Drawing.Size(233, 23);
|
||||
edtShortcutLg.TabIndex = 11;
|
||||
edtShortcutLg.TextChanged += edtShortcutLg_TextChanged;
|
||||
edtShortcutLg.KeyDown += edtShortcut_KeyDown;
|
||||
edtShortcutLg.KeyUp += edtShortcut_KeyUp;
|
||||
//
|
||||
// edtSamsungDeviceFilter
|
||||
//
|
||||
edtSamsungDeviceFilter.Location = new System.Drawing.Point(100, 40);
|
||||
edtSamsungDeviceFilter.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtSamsungDeviceFilter.Name = "edtSamsungDeviceFilter";
|
||||
edtSamsungDeviceFilter.Size = new System.Drawing.Size(165, 23);
|
||||
edtSamsungDeviceFilter.TabIndex = 23;
|
||||
edtSamsungDeviceFilter.TextChanged += edtSamsungDeviceFilter_TextChanged;
|
||||
//
|
||||
// btnSamsungRemoveDevice
|
||||
//
|
||||
btnSamsungRemoveDevice.Location = new System.Drawing.Point(573, 8);
|
||||
btnSamsungRemoveDevice.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungRemoveDevice.Name = "btnSamsungRemoveDevice";
|
||||
btnSamsungRemoveDevice.Size = new System.Drawing.Size(88, 27);
|
||||
btnSamsungRemoveDevice.TabIndex = 38;
|
||||
btnSamsungRemoveDevice.Text = "Remove";
|
||||
btnSamsungRemoveDevice.UseVisualStyleBackColor = true;
|
||||
btnSamsungRemoveDevice.Click += btnSamsungRemoveDevice_Click;
|
||||
//
|
||||
// btnSamsungRefreshApps
|
||||
//
|
||||
btnSamsungRefreshApps.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnSamsungRefreshApps.Enabled = false;
|
||||
btnSamsungRefreshApps.Location = new System.Drawing.Point(341, 378);
|
||||
btnSamsungRefreshApps.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungRefreshApps.Name = "btnSamsungRefreshApps";
|
||||
btnSamsungRefreshApps.Size = new System.Drawing.Size(88, 27);
|
||||
btnSamsungRefreshApps.TabIndex = 29;
|
||||
btnSamsungRefreshApps.Text = "Refresh";
|
||||
btnSamsungRefreshApps.UseVisualStyleBackColor = true;
|
||||
btnSamsungRefreshApps.Click += btnSamsungRefreshApps_Click;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
label2.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
label2.AutoSize = true;
|
||||
label2.Location = new System.Drawing.Point(6, 415);
|
||||
label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label2.Name = "label2";
|
||||
label2.Size = new System.Drawing.Size(55, 15);
|
||||
label2.TabIndex = 12;
|
||||
label2.Text = "Shortcut:";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
label1.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
label1.AutoSize = true;
|
||||
label1.Location = new System.Drawing.Point(6, 321);
|
||||
label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label1.Name = "label1";
|
||||
label1.Size = new System.Drawing.Size(42, 15);
|
||||
label1.TabIndex = 20;
|
||||
label1.Text = "Name:";
|
||||
//
|
||||
// btnSamsungAddDevice
|
||||
//
|
||||
btnSamsungAddDevice.Location = new System.Drawing.Point(478, 8);
|
||||
btnSamsungAddDevice.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungAddDevice.Name = "btnSamsungAddDevice";
|
||||
btnSamsungAddDevice.Size = new System.Drawing.Size(88, 27);
|
||||
btnSamsungAddDevice.TabIndex = 37;
|
||||
btnSamsungAddDevice.Text = "Add";
|
||||
btnSamsungAddDevice.UseVisualStyleBackColor = true;
|
||||
btnSamsungAddDevice.Click += btnSamsungAddDevice_Click;
|
||||
//
|
||||
// edtNameLg
|
||||
//
|
||||
edtNameLg.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
edtNameLg.Enabled = false;
|
||||
edtNameLg.Location = new System.Drawing.Point(100, 318);
|
||||
edtNameLg.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtNameLg.Name = "edtNameLg";
|
||||
edtNameLg.Size = new System.Drawing.Size(233, 23);
|
||||
edtNameLg.TabIndex = 19;
|
||||
//
|
||||
// btnSetShortcutLg
|
||||
//
|
||||
btnSetShortcutLg.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnSetShortcutLg.Enabled = false;
|
||||
btnSetShortcutLg.Location = new System.Drawing.Point(384, 284);
|
||||
btnSetShortcutLg.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSetShortcutLg.Name = "btnSetShortcutLg";
|
||||
btnSetShortcutLg.Size = new System.Drawing.Size(88, 27);
|
||||
btnSetShortcutLg.TabIndex = 13;
|
||||
btnSetShortcutLg.Text = "Save";
|
||||
btnSetShortcutLg.UseVisualStyleBackColor = true;
|
||||
btnSetShortcutLg.Click += btnSetShortcutLg_Click;
|
||||
//
|
||||
// edtStepsLg
|
||||
//
|
||||
edtStepsLg.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
edtStepsLg.Enabled = false;
|
||||
edtStepsLg.Location = new System.Drawing.Point(100, 440);
|
||||
edtStepsLg.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtStepsLg.Multiline = true;
|
||||
edtStepsLg.Name = "edtStepsLg";
|
||||
edtStepsLg.Size = new System.Drawing.Size(699, 43);
|
||||
edtStepsLg.TabIndex = 17;
|
||||
//
|
||||
// btnSamsungAddButton
|
||||
//
|
||||
btnSamsungAddButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
|
||||
btnSamsungAddButton.ContextMenuStrip = mnuLgButtons;
|
||||
btnSamsungAddButton.Enabled = false;
|
||||
btnSamsungAddButton.Location = new System.Drawing.Point(807, 439);
|
||||
btnSamsungAddButton.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungAddButton.Name = "btnSamsungAddButton";
|
||||
btnSamsungAddButton.Size = new System.Drawing.Size(88, 27);
|
||||
btnSamsungAddButton.TabIndex = 32;
|
||||
btnSamsungAddButton.Text = "Add step";
|
||||
btnSamsungAddButton.UseVisualStyleBackColor = true;
|
||||
btnSamsungAddButton.Click += btnSamsungAddButton_Click;
|
||||
//
|
||||
// mnuLgButtons
|
||||
//
|
||||
mnuLgButtons.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
mnuLgButtons.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuLgRcButtons, mnuLgActions, mnuLgNvPresets, mnuLgAmdPresets, mnuLgProgram });
|
||||
mnuLgButtons.Name = "mnuLgButtons";
|
||||
mnuLgButtons.Size = new System.Drawing.Size(153, 114);
|
||||
mnuLgButtons.Opening += mnuLgButtons_Opening;
|
||||
//
|
||||
// mnuLgRcButtons
|
||||
//
|
||||
mnuLgRcButtons.Name = "mnuLgRcButtons";
|
||||
mnuLgRcButtons.Size = new System.Drawing.Size(152, 22);
|
||||
mnuLgRcButtons.Text = "Buttons";
|
||||
//
|
||||
// mnuLgActions
|
||||
//
|
||||
mnuLgActions.Name = "mnuLgActions";
|
||||
mnuLgActions.Size = new System.Drawing.Size(152, 22);
|
||||
mnuLgActions.Text = "Actions";
|
||||
//
|
||||
// mnuLgNvPresets
|
||||
//
|
||||
mnuLgNvPresets.Name = "mnuLgNvPresets";
|
||||
mnuLgNvPresets.Size = new System.Drawing.Size(152, 22);
|
||||
mnuLgNvPresets.Text = "NVIDIA presets";
|
||||
//
|
||||
// mnuLgAmdPresets
|
||||
//
|
||||
mnuLgAmdPresets.Name = "mnuLgAmdPresets";
|
||||
mnuLgAmdPresets.Size = new System.Drawing.Size(152, 22);
|
||||
mnuLgAmdPresets.Text = "AMD presets";
|
||||
//
|
||||
// mnuLgProgram
|
||||
//
|
||||
mnuLgProgram.Name = "mnuLgProgram";
|
||||
mnuLgProgram.Size = new System.Drawing.Size(152, 22);
|
||||
mnuLgProgram.Text = "Start Program";
|
||||
mnuLgProgram.Click += mnuLgProgram_Click;
|
||||
//
|
||||
// btnCloneLg
|
||||
//
|
||||
btnCloneLg.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnCloneLg.Enabled = false;
|
||||
btnCloneLg.Location = new System.Drawing.Point(100, 284);
|
||||
btnCloneLg.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnCloneLg.Name = "btnCloneLg";
|
||||
btnCloneLg.Size = new System.Drawing.Size(88, 27);
|
||||
btnCloneLg.TabIndex = 14;
|
||||
btnCloneLg.Text = "Clone";
|
||||
btnCloneLg.UseVisualStyleBackColor = true;
|
||||
btnCloneLg.Click += btnCloneLg_Click;
|
||||
//
|
||||
// lblStepsLg
|
||||
//
|
||||
lblStepsLg.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
lblStepsLg.AutoSize = true;
|
||||
lblStepsLg.Location = new System.Drawing.Point(6, 445);
|
||||
lblStepsLg.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblStepsLg.Name = "lblStepsLg";
|
||||
lblStepsLg.Size = new System.Drawing.Size(38, 15);
|
||||
lblStepsLg.TabIndex = 16;
|
||||
lblStepsLg.Text = "Steps:";
|
||||
//
|
||||
// btnSamsungDeviceFilterRefresh
|
||||
//
|
||||
btnSamsungDeviceFilterRefresh.Location = new System.Drawing.Point(273, 39);
|
||||
btnSamsungDeviceFilterRefresh.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSamsungDeviceFilterRefresh.Name = "btnSamsungDeviceFilterRefresh";
|
||||
btnSamsungDeviceFilterRefresh.Size = new System.Drawing.Size(88, 27);
|
||||
btnSamsungDeviceFilterRefresh.TabIndex = 35;
|
||||
btnSamsungDeviceFilterRefresh.Text = "Refresh";
|
||||
btnSamsungDeviceFilterRefresh.UseVisualStyleBackColor = true;
|
||||
btnSamsungDeviceFilterRefresh.Click += btnSamsungDeviceFilterRefresh_Click;
|
||||
//
|
||||
// clbLgPower
|
||||
//
|
||||
clbLgPower.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
clbLgPower.ColumnWidth = 240;
|
||||
clbLgPower.FormattingEnabled = true;
|
||||
clbLgPower.Items.AddRange(new object[] { "Power on after startup", "Power on after resume from standby", "Power off on shutdown", "Power off on standby", "Power off when screensaver activates", "Power on when screensaver deactivates", "Power on even after manual power off", "Allow triggers to be fired for this device", "Use Windows power settings to power on", "Use Windows power settings to power off", "Use secure connection" });
|
||||
clbLgPower.Location = new System.Drawing.Point(6, 70);
|
||||
clbLgPower.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
clbLgPower.MultiColumn = true;
|
||||
clbLgPower.Name = "clbLgPower";
|
||||
clbLgPower.Size = new System.Drawing.Size(861, 76);
|
||||
clbLgPower.TabIndex = 34;
|
||||
clbLgPower.ItemCheck += clbLgPower_ItemCheck;
|
||||
clbLgPower.SelectedIndexChanged += clbLgPower_SelectedIndexChanged;
|
||||
//
|
||||
// lblSamsungError
|
||||
//
|
||||
lblSamsungError.AutoSize = true;
|
||||
lblSamsungError.Location = new System.Drawing.Point(6, 9);
|
||||
lblSamsungError.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblSamsungError.Name = "lblSamsungError";
|
||||
lblSamsungError.Size = new System.Drawing.Size(53, 15);
|
||||
lblSamsungError.TabIndex = 15;
|
||||
lblSamsungError.Text = "ErrorText";
|
||||
lblSamsungError.Visible = false;
|
||||
//
|
||||
// mnuLgSettings
|
||||
//
|
||||
mnuLgSettings.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
mnuLgSettings.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miTestPowerOffOn, miNvSettings });
|
||||
mnuLgSettings.Name = "mnuLgButtons";
|
||||
mnuLgSettings.Size = new System.Drawing.Size(168, 48);
|
||||
//
|
||||
// miTestPowerOffOn
|
||||
//
|
||||
miTestPowerOffOn.Name = "miTestPowerOffOn";
|
||||
miTestPowerOffOn.Size = new System.Drawing.Size(167, 22);
|
||||
miTestPowerOffOn.Text = "Test power off/on";
|
||||
miTestPowerOffOn.Click += miTestPowerOffOn_Click;
|
||||
//
|
||||
// miNvSettings
|
||||
//
|
||||
miNvSettings.Name = "miNvSettings";
|
||||
miNvSettings.Size = new System.Drawing.Size(167, 22);
|
||||
miNvSettings.Text = "Settings";
|
||||
miNvSettings.Click += miNvSettings_Click;
|
||||
//
|
||||
// SamsungPanel
|
||||
//
|
||||
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
Controls.Add(scSamsungController);
|
||||
Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
Name = "SamsungPanel";
|
||||
Size = new System.Drawing.Size(1114, 539);
|
||||
scSamsungController.Panel1.ResumeLayout(false);
|
||||
scSamsungController.Panel1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)scSamsungController).EndInit();
|
||||
scSamsungController.ResumeLayout(false);
|
||||
mnuLgButtons.ResumeLayout(false);
|
||||
mnuLgSettings.ResumeLayout(false);
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuLgRcButtons;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuLgActions;
|
||||
private System.Windows.Forms.ContextMenuStrip mnuLgButtons;
|
||||
private System.Windows.Forms.SplitContainer scSamsungController;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.ComboBox cbxSamsungDevices;
|
||||
private System.Windows.Forms.Button btnSamsungDeviceConvertToCustom;
|
||||
private System.Windows.Forms.ComboBox cbxSamsungApps;
|
||||
private System.Windows.Forms.ListView lvSamsungPresets;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.ComboBox cbxSamsungPresetDevice;
|
||||
private System.Windows.Forms.Button btnDeleteLg;
|
||||
private System.Windows.Forms.Button btnApplyLg;
|
||||
private System.Windows.Forms.Label lblDeviceFilter;
|
||||
private System.Windows.Forms.Label lblSamsungPresetDevice;
|
||||
private System.Windows.Forms.Button btnAddLg;
|
||||
private System.Windows.Forms.TextBox edtShortcutLg;
|
||||
private System.Windows.Forms.TextBox edtSamsungDeviceFilter;
|
||||
private System.Windows.Forms.Button btnSamsungRemoveDevice;
|
||||
private System.Windows.Forms.Button btnSamsungRefreshApps;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Button btnSamsungAddDevice;
|
||||
private System.Windows.Forms.TextBox edtNameLg;
|
||||
private System.Windows.Forms.Button btnSetShortcutLg;
|
||||
private System.Windows.Forms.TextBox edtStepsLg;
|
||||
private System.Windows.Forms.Button btnSamsungAddButton;
|
||||
private System.Windows.Forms.Button btnCloneLg;
|
||||
private System.Windows.Forms.Label lblStepsLg;
|
||||
private System.Windows.Forms.Button btnSamsungDeviceFilterRefresh;
|
||||
private System.Windows.Forms.CheckedListBox clbLgPower;
|
||||
private System.Windows.Forms.Label lblSamsungError;
|
||||
private System.Windows.Forms.CheckBox chkSamsungRemoteControlShow;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuLgNvPresets;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuLgAmdPresets;
|
||||
private System.Windows.Forms.ComboBox cbxSamsungPresetTrigger;
|
||||
private System.Windows.Forms.Label lblSamsungPresetTrigger;
|
||||
private System.Windows.Forms.Label lblSamsungPresetTriggerCondition;
|
||||
private System.Windows.Forms.Label lblSamsungPresetExcludedProcesses;
|
||||
private System.Windows.Forms.TextBox edtSamsungPresetExcludedProcesses;
|
||||
private System.Windows.Forms.Label lblSamsungPresetIncludedProcesses;
|
||||
private System.Windows.Forms.TextBox edtSamsungPresetIncludedProcesses;
|
||||
private System.Windows.Forms.Button btnSamsungPresetEditTriggerConditions;
|
||||
private System.Windows.Forms.TextBox edtSamsungPresetTriggerConditions;
|
||||
private System.Windows.Forms.Button btnSamsungDeviceOptionsHelp;
|
||||
private System.Windows.Forms.TextBox edtSamsungPresetDescription;
|
||||
private System.Windows.Forms.Label lblSamsungPresetDescription;
|
||||
private System.Windows.Forms.ComboBox cbxSamsungPcHdmiPort;
|
||||
private System.Windows.Forms.Label lblSamsungPcHdmiPort;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuLgProgram;
|
||||
private System.Windows.Forms.CheckBox chkSamsungQuickAccess;
|
||||
private System.Windows.Forms.Button btnSamsungSettings;
|
||||
private System.Windows.Forms.ContextMenuStrip mnuLgSettings;
|
||||
private System.Windows.Forms.ToolStripMenuItem miTestPowerOffOn;
|
||||
private System.Windows.Forms.ToolStripMenuItem miNvSettings;
|
||||
private System.Windows.Forms.Button btnSamsungDeviceOptionsSettings;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuLgSetSvcMenuFlag;
|
||||
private System.Windows.Forms.ToolStripMenuItem miLgFullServiceMenuEnable;
|
||||
private System.Windows.Forms.ToolStripMenuItem miLgFullServiceMenuDisable;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,129 @@
|
||||
<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<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" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</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" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="mnuLgButtons.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>288, 16</value>
|
||||
</metadata>
|
||||
<metadata name="mnuLgExpert.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="mnuLgSettings.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>147, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -0,0 +1,98 @@
|
||||
using ColorControl.Services.Common;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
class SamsungPreset : PresetBase
|
||||
{
|
||||
public string AppId { get; set; }
|
||||
public List<string> Steps { get; set; }
|
||||
public string DeviceMacAddress { get; set; }
|
||||
public static List<SamsungDevice> SamsungDevices { get; internal set; }
|
||||
|
||||
public SamsungPreset() : base()
|
||||
{
|
||||
Steps = new List<string>();
|
||||
}
|
||||
|
||||
public SamsungPreset(SamsungPreset preset) : this()
|
||||
{
|
||||
id = GetNewId();
|
||||
|
||||
name = preset.name;
|
||||
AppId = preset.AppId;
|
||||
DeviceMacAddress = preset.DeviceMacAddress;
|
||||
Steps.AddRange(preset.Steps);
|
||||
}
|
||||
|
||||
public SamsungPreset Clone()
|
||||
{
|
||||
var preset = new SamsungPreset(this);
|
||||
|
||||
preset.name += " (copy)";
|
||||
|
||||
return preset;
|
||||
}
|
||||
|
||||
public static string[] GetColumnNames()
|
||||
{
|
||||
return new[] { "Name", "Device|120", "App|200", "Steps|400", "Shortcut", "Trigger" };
|
||||
}
|
||||
|
||||
public override List<string> GetDisplayValues(Config config = null)
|
||||
{
|
||||
var values = new List<string>();
|
||||
|
||||
values.Add(name);
|
||||
|
||||
var deviceString = "Global";
|
||||
if (!string.IsNullOrEmpty(DeviceMacAddress))
|
||||
{
|
||||
if (SamsungDevices != null)
|
||||
{
|
||||
var device = SamsungDevices.FirstOrDefault(d => !string.IsNullOrEmpty(d.MacAddress) && d.MacAddress.Equals(DeviceMacAddress));
|
||||
if (device != null)
|
||||
{
|
||||
deviceString = device.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceString = "Unknown: device not found";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceString = DeviceMacAddress;
|
||||
}
|
||||
}
|
||||
values.Add(deviceString);
|
||||
|
||||
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);
|
||||
|
||||
if (Triggers.Any())
|
||||
{
|
||||
values.Add(Triggers.First().ToString());
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
public string GetStepsDisplay()
|
||||
{
|
||||
return Steps.Aggregate("", (a, b) => (string.IsNullOrEmpty(a) ? "" : a + ", ") + b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,676 @@
|
||||
using ColorControl.Common;
|
||||
using ColorControl.Services.Common;
|
||||
using ColorControl.Services.EventDispatcher;
|
||||
using ColorControl.Services.LG;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using NWin32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
class SamsungService : ServiceBase<SamsungPreset>
|
||||
{
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public override string ServiceName => "Samsung";
|
||||
|
||||
protected override string PresetsBaseFilename => "SamsungPresets.json";
|
||||
|
||||
public SamsungServiceConfig Config { get; private set; }
|
||||
public SamsungDevice SelectedDevice { get; set; }
|
||||
|
||||
private bool _allowPowerOn;
|
||||
private ServiceManager _serviceManager;
|
||||
private readonly PowerEventDispatcher _powerEventDispatcher;
|
||||
private readonly SessionSwitchDispatcher _sessionSwitchDispatcher;
|
||||
private readonly RestartDetector _restartDetector;
|
||||
private readonly ProcessEventDispatcher _processEventDispatcher;
|
||||
private SamTvConnection _samTvConnection;
|
||||
private string _configFilename;
|
||||
private bool _poweredOffByScreenSaver;
|
||||
private int _poweredOffByScreenSaverProcessId;
|
||||
private object _lastTriggeredPreset;
|
||||
|
||||
public List<SamsungDevice> Devices { get; private set; }
|
||||
|
||||
public SamsungService(AppContextProvider appContextProvider, ServiceManager serviceManager, PowerEventDispatcher powerEventDispatcher, SessionSwitchDispatcher sessionSwitchDispatcher, RestartDetector restartDetector, ProcessEventDispatcher processEventDispatcher) : base(appContextProvider)
|
||||
{
|
||||
_allowPowerOn = appContextProvider.GetAppContext().StartUpParams.RunningFromScheduledTask;
|
||||
_serviceManager = serviceManager;
|
||||
_powerEventDispatcher = powerEventDispatcher;
|
||||
_sessionSwitchDispatcher = sessionSwitchDispatcher;
|
||||
_restartDetector = restartDetector;
|
||||
_processEventDispatcher = processEventDispatcher;
|
||||
SamTvConnection.SyncContext = _appContextProvider.GetAppContext().SynchronizationContext;
|
||||
|
||||
LoadConfig();
|
||||
LoadPresets();
|
||||
}
|
||||
|
||||
public static async Task<bool> ExecutePresetAsync(string presetName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var samsungService = Program.ServiceProvider.GetRequiredService<SamsungService>();
|
||||
|
||||
await samsungService.RefreshDevices(afterStartUp: true);
|
||||
|
||||
var result = await samsungService.ApplyPreset(presetName);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Console.WriteLine("Preset not found or error while executing.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error executing preset: " + ex.ToLogString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
var _ = RefreshDevices(afterStartUp: true);
|
||||
InstallEventHandlers();
|
||||
}
|
||||
|
||||
public void InstallEventHandlers()
|
||||
{
|
||||
_powerEventDispatcher.RegisterEventHandler(PowerEventDispatcher.Event_MonitorOn, PowerModeChanged);
|
||||
_powerEventDispatcher.RegisterEventHandler(PowerEventDispatcher.Event_MonitorOff, PowerModeChanged);
|
||||
_powerEventDispatcher.RegisterEventHandler(PowerEventDispatcher.Event_Suspend, PowerModeChanged);
|
||||
_powerEventDispatcher.RegisterEventHandler(PowerEventDispatcher.Event_Resume, PowerModeChanged);
|
||||
_powerEventDispatcher.RegisterEventHandler(PowerEventDispatcher.Event_Shutdown, PowerModeChanged);
|
||||
_processEventDispatcher.RegisterAsyncEventHandler(ProcessEventDispatcher.Event_ProcessChanged, ProcessChanged);
|
||||
}
|
||||
|
||||
private void LoadConfig()
|
||||
{
|
||||
_configFilename = Path.Combine(_dataPath, "SamsungConfig.json");
|
||||
try
|
||||
{
|
||||
if (File.Exists(_configFilename))
|
||||
{
|
||||
Config = JsonConvert.DeserializeObject<SamsungServiceConfig>(File.ReadAllText(_configFilename));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"LoadConfig: {ex.Message}");
|
||||
}
|
||||
Config ??= new SamsungServiceConfig();
|
||||
|
||||
//if (!Config.Devices.Any())
|
||||
//{
|
||||
// var device = new SamsungDevice("S95C", "192.168.178.40", "BC-45-5B-A4-70-A4", true);
|
||||
// device.Options.PowerOffOnShutdown = true;
|
||||
// device.Options.PowerOffOnStandby = true;
|
||||
// device.Options.PowerOnAfterResume = true;
|
||||
// device.Options.PowerOnAfterStartup = true;
|
||||
|
||||
// Config.Devices.Add(device);
|
||||
//}
|
||||
|
||||
SamsungPreset.SamsungDevices = Config.Devices;
|
||||
}
|
||||
|
||||
private void PowerModeChanged(object sender, PowerStateChangedEventArgs e)
|
||||
{
|
||||
Logger.Debug($"PowerModeChanged: {e.State}");
|
||||
|
||||
switch (e.State)
|
||||
{
|
||||
case PowerOnOffState.Resume:
|
||||
{
|
||||
WakeAfterStartupOrResume(PowerOnOffState.Resume);
|
||||
break;
|
||||
}
|
||||
case PowerOnOffState.StandBy:
|
||||
{
|
||||
var devices = Devices.Where(d => d.Options.PowerOffOnStandby);
|
||||
PowerOffDevices(devices, PowerOnOffState.StandBy);
|
||||
break;
|
||||
}
|
||||
case PowerOnOffState.ShutDown:
|
||||
{
|
||||
var devices = Devices.Where(d => d.Options.PowerOffOnShutdown);
|
||||
|
||||
PowerOffDevices(devices);
|
||||
break;
|
||||
}
|
||||
|
||||
case PowerOnOffState.MonitorOff:
|
||||
{
|
||||
var devices = Devices.Where(d => d.Options.PowerOffByWindows).ToList();
|
||||
PowerOffDevices(devices, PowerOnOffState.MonitorOff);
|
||||
break;
|
||||
}
|
||||
case PowerOnOffState.MonitorOn:
|
||||
{
|
||||
var devices = Devices.Where(d => d.Options.PowerOnByWindows).ToList();
|
||||
PowerOnDevicesTask(devices);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RefreshDevices(bool connect = true, bool afterStartUp = false)
|
||||
{
|
||||
Devices = Config.Devices;
|
||||
var customIpAddresses = Devices.Where(d => d.IsCustom).Select(d => d.IpAddress);
|
||||
|
||||
var pnpDevices = await Utils.GetPnpDevices(Config.DeviceSearchKey);
|
||||
|
||||
var autoDevices = pnpDevices.Where(p => !customIpAddresses.Contains(p.IpAddress)).Select(d => new SamsungDevice(d.Name, d.IpAddress, d.MacAddress, false)).ToList();
|
||||
var autoIpAddresses = pnpDevices.Select(d => d.IpAddress);
|
||||
|
||||
Devices.RemoveAll(d => !d.IsCustom && !autoIpAddresses.Contains(d.IpAddress));
|
||||
|
||||
var newAutoDevices = autoDevices.Where(ad => ad.IpAddress != null && !Devices.Any(d => d.IpAddress != null && d.IpAddress.Equals(ad.IpAddress)));
|
||||
Devices.AddRange(newAutoDevices);
|
||||
|
||||
if (Devices.Any())
|
||||
{
|
||||
var preferredDevice = Devices.FirstOrDefault(x => x.MacAddress != null && x.MacAddress.Equals(Config.PreferredMacAddress)) ?? Devices[0];
|
||||
|
||||
SelectedDevice = preferredDevice;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedDevice = null;
|
||||
}
|
||||
|
||||
if (afterStartUp && SelectedDevice == null && Config.PowerOnAfterStartup && !string.IsNullOrEmpty(Config.PreferredMacAddress))
|
||||
{
|
||||
Logger.Debug("No device has been found, trying to wake it first...");
|
||||
|
||||
var tempDevice = new LgDevice("Test", string.Empty, Config.PreferredMacAddress);
|
||||
tempDevice.Wake();
|
||||
|
||||
await Task.Delay(4000);
|
||||
await RefreshDevices();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (connect && SelectedDevice != null)
|
||||
{
|
||||
if (_allowPowerOn)
|
||||
{
|
||||
WakeAfterStartupOrResume();
|
||||
}
|
||||
else
|
||||
{
|
||||
var _ = SelectedDevice.ConnectAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override List<SamsungPreset> GetDefaultPresets()
|
||||
{
|
||||
return new List<SamsungPreset>();
|
||||
}
|
||||
|
||||
private void SavePresets()
|
||||
{
|
||||
Utils.WriteObject(_presetsFilename, _presets);
|
||||
}
|
||||
|
||||
private void SaveConfig()
|
||||
{
|
||||
Config.PowerOnAfterStartup = Devices?.Any(d => d.Options.PowerOnAfterStartup) ?? false;
|
||||
|
||||
Utils.WriteObject(_configFilename, Config);
|
||||
}
|
||||
|
||||
public void GlobalSave()
|
||||
{
|
||||
SavePresets();
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
public SamsungDevice GetPresetDevice(SamsungPreset preset)
|
||||
{
|
||||
var device = string.IsNullOrEmpty(preset.DeviceMacAddress)
|
||||
? SelectedDevice
|
||||
: Devices.FirstOrDefault(d => d.MacAddress?.Equals(preset.DeviceMacAddress, StringComparison.OrdinalIgnoreCase) ?? false);
|
||||
return device;
|
||||
}
|
||||
|
||||
public async Task<bool> ApplyPreset(string idOrName)
|
||||
{
|
||||
var preset = GetPresetByIdOrName(idOrName);
|
||||
if (preset != null)
|
||||
{
|
||||
return await ApplyPreset(preset, Program.AppContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ApplyPreset(SamsungPreset preset)
|
||||
{
|
||||
return await ApplyPreset(preset, Program.AppContext);
|
||||
}
|
||||
|
||||
public async Task<bool> ApplyPreset(SamsungPreset preset, AppContext appContext)
|
||||
{
|
||||
var result = true;
|
||||
|
||||
var device = GetPresetDevice(preset);
|
||||
|
||||
await device?.ExecutePresetAsync(preset, appContext, Config);
|
||||
|
||||
_lastAppliedPreset = preset;
|
||||
|
||||
PresetApplied();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void AddCustomDevice(SamsungDevice device)
|
||||
{
|
||||
Devices.Add(device);
|
||||
}
|
||||
|
||||
internal void RemoveCustomDevice(SamsungDevice device)
|
||||
{
|
||||
Devices.Remove(device);
|
||||
|
||||
if (!string.IsNullOrEmpty(device.MacAddress))
|
||||
{
|
||||
var presets = _presets.Where(p => !string.IsNullOrEmpty(p.DeviceMacAddress) && p.DeviceMacAddress.Equals(device.MacAddress, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
presets.ForEach(preset =>
|
||||
{
|
||||
preset.DeviceMacAddress = null;
|
||||
});
|
||||
}
|
||||
|
||||
if (SelectedDevice == device)
|
||||
{
|
||||
SelectedDevice = Devices.Any() ? Devices.First() : null;
|
||||
}
|
||||
}
|
||||
|
||||
internal void WakeAfterStartupOrResume(PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true)
|
||||
{
|
||||
//Devices.ForEach(d => d.ClearPowerOffTask());
|
||||
|
||||
var wakeDevices = Devices.Where(d => state == PowerOnOffState.StartUp && d.Options.PowerOnAfterStartup ||
|
||||
state == PowerOnOffState.Resume && d.Options.PowerOnAfterResume ||
|
||||
state == PowerOnOffState.ScreenSaver && d.Options.PowerOnAfterScreenSaver);
|
||||
|
||||
PowerOnDevicesTask(wakeDevices, state, checkUserSession);
|
||||
}
|
||||
|
||||
public void PowerOffDevices(IEnumerable<SamsungDevice> devices, PowerOnOffState state = PowerOnOffState.ShutDown)
|
||||
{
|
||||
if (!devices.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (NativeMethods.GetAsyncKeyState(NativeConstants.VK_CONTROL) < 0 || NativeMethods.GetAsyncKeyState(NativeConstants.VK_RCONTROL) < 0)
|
||||
{
|
||||
Logger.Debug("Not powering off because CONTROL-key is down");
|
||||
return;
|
||||
}
|
||||
|
||||
var error = NativeMethods.SetThreadExecutionState(NativeConstants.ES_CONTINUOUS | NativeConstants.ES_SYSTEM_REQUIRED | NativeConstants.ES_AWAYMODE_REQUIRED);
|
||||
try
|
||||
{
|
||||
Logger.Debug($"SetThreadExecutionState: {error}, Thread#: {Environment.CurrentManagedThreadId}");
|
||||
if (state == PowerOnOffState.ShutDown)
|
||||
{
|
||||
var sleep = Config.ShutdownDelay;
|
||||
|
||||
Logger.Debug($"PowerOffDevices: Waiting for a maximum of {sleep} milliseconds...");
|
||||
|
||||
while (sleep > 0 && _restartDetector?.PowerOffDetected == false)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
|
||||
if (_restartDetector != null && (_restartDetector.RestartDetected || _restartDetector.IsRebootInProgress()))
|
||||
{
|
||||
Logger.Debug("Not powering off because of a restart");
|
||||
return;
|
||||
}
|
||||
|
||||
sleep -= 100;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Debug("Powering off tv(s)...");
|
||||
var tasks = new List<Task>();
|
||||
foreach (var device in devices)
|
||||
{
|
||||
var task = device.PowerOffAsync();
|
||||
|
||||
tasks.Add(task);
|
||||
}
|
||||
|
||||
if (state == PowerOnOffState.StandBy)
|
||||
{
|
||||
var standByScript = Path.Combine(Program.DataDir, "StandByScript.bat");
|
||||
if (File.Exists(standByScript))
|
||||
{
|
||||
Utils.StartProcess(standByScript, hidden: true, wait: true);
|
||||
}
|
||||
}
|
||||
|
||||
// We can't use async here because we need to stay on the main thread...
|
||||
var _ = Task.WhenAll(tasks.ToArray()).ConfigureAwait(true);
|
||||
|
||||
Logger.Debug("Done powering off tv(s)");
|
||||
}
|
||||
finally
|
||||
{
|
||||
var error2 = NativeMethods.SetThreadExecutionState(NativeConstants.ES_CONTINUOUS);
|
||||
Logger.Debug($"SetThreadExecutionState (reset): {error2}, Thread#: {Environment.CurrentManagedThreadId}");
|
||||
}
|
||||
}
|
||||
|
||||
public void PowerOnDevicesTask(IEnumerable<SamsungDevice> devices, PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true)
|
||||
{
|
||||
Task.Run(async () => await PowerOnDevices(devices, state, checkUserSession));
|
||||
}
|
||||
|
||||
public async Task PowerOnDevices(IEnumerable<SamsungDevice> devices, PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true)
|
||||
{
|
||||
if (!devices.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkUserSession && !_sessionSwitchDispatcher.UserLocalSession)
|
||||
{
|
||||
Logger.Debug($"WakeAfterStartupOrResume: not waking because session info indicates no local session");
|
||||
return;
|
||||
}
|
||||
|
||||
var resumeScript = Path.Combine(Program.DataDir, "ResumeScript.bat");
|
||||
|
||||
var tasks = new List<Task>();
|
||||
|
||||
foreach (var device in devices)
|
||||
{
|
||||
if (!device.Options.PowerOnAfterManualPowerOff && device.PoweredOffBy == PowerOffSource.External)
|
||||
{
|
||||
Logger.Debug($"[{device.Name}]: device was manually powered off by user, not powering on");
|
||||
continue;
|
||||
}
|
||||
|
||||
//if (state == PowerOnOffState.ScreenSaver)
|
||||
//{
|
||||
// tasks.Add(device.PerformActionAfterScreenSaver(Config.PowerOnRetries));
|
||||
// continue;
|
||||
//}
|
||||
|
||||
var task = device.WakeAndConnectWithRetries(Config.PowerOnRetries);
|
||||
tasks.Add(task);
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks.ToArray());
|
||||
|
||||
if (File.Exists(resumeScript))
|
||||
{
|
||||
Utils.StartProcess(resumeScript, hidden: true);
|
||||
}
|
||||
}
|
||||
|
||||
internal List<SamsungApp> GetApps()
|
||||
{
|
||||
return new List<SamsungApp>();
|
||||
}
|
||||
|
||||
|
||||
public async Task ProcessChanged(object sender, ProcessChangedEventArgs args, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
var wasConnected = Devices.Any(d => d.IsConnected());
|
||||
|
||||
var applicableDevices = Devices.Where(d => d.Options.PowerOffOnScreenSaver || d.Options.PowerOnAfterScreenSaver || d.Options.TriggersEnabled && _presets.Any(p => p.Triggers.Any(t => t.Trigger != PresetTriggerType.None) &&
|
||||
((string.IsNullOrEmpty(p.DeviceMacAddress) && d == SelectedDevice) || p.DeviceMacAddress.Equals(d.MacAddress, StringComparison.OrdinalIgnoreCase))));
|
||||
|
||||
if (!applicableDevices.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_poweredOffByScreenSaver && !_sessionSwitchDispatcher.UserLocalSession)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var processes = args.RunningProcesses;
|
||||
|
||||
if (_poweredOffByScreenSaver)
|
||||
{
|
||||
if (processes.Any(p => p.Id == _poweredOffByScreenSaverProcessId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var process = processes.FirstOrDefault(p => p.ProcessName.ToLowerInvariant().EndsWith(".scr"));
|
||||
|
||||
if (process != null)
|
||||
{
|
||||
Logger.Debug($"Detected screen saver process switch from {_poweredOffByScreenSaverProcessId} to {process.Id}");
|
||||
|
||||
_poweredOffByScreenSaverProcessId = process.Id;
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Debug("Screensaver stopped, waking");
|
||||
_poweredOffByScreenSaver = false;
|
||||
_poweredOffByScreenSaverProcessId = 0;
|
||||
|
||||
WakeAfterStartupOrResume(PowerOnOffState.ScreenSaver);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var connectedDevices = applicableDevices.Where(d => d.IsConnected()).ToList();
|
||||
|
||||
if (!connectedDevices.Any())
|
||||
{
|
||||
if (wasConnected)
|
||||
{
|
||||
Logger.Debug("Process monitor: TV(s) where connected, but not any longer");
|
||||
wasConnected = false;
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var devices = applicableDevices.ToList();
|
||||
foreach (var device in devices)
|
||||
{
|
||||
//Logger.Debug($"Process monitor: test connection with {device.Name}...");
|
||||
|
||||
var test = await device.TestConnectionAsync();
|
||||
//Logger.Debug("Process monitor: test connection result: " + test);
|
||||
}
|
||||
|
||||
connectedDevices = applicableDevices.Where(d => d.IsConnected()).ToList();
|
||||
|
||||
if (!connectedDevices.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!wasConnected)
|
||||
{
|
||||
Logger.Debug("Process monitor: TV(s) where not connected, but connection has now been established");
|
||||
wasConnected = true;
|
||||
}
|
||||
|
||||
if (connectedDevices.Any(d => d.Options.PowerOffOnScreenSaver || d.Options.PowerOnAfterScreenSaver))
|
||||
{
|
||||
await HandleScreenSaverProcessAsync(processes, connectedDevices);
|
||||
}
|
||||
|
||||
await ExecuteProcessPresets(args, connectedDevices);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("ProcessChanged: " + ex.ToLogString());
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteProcessPresets(ProcessChangedEventArgs context, IList<SamsungDevice> connectedDevices)
|
||||
{
|
||||
var triggerDevices = connectedDevices.Where(d => d.Options.TriggersEnabled).ToList();
|
||||
|
||||
if (context.IsScreenSaverActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedDevice = SelectedDevice;
|
||||
|
||||
var presets = _presets.Where(p => p.Triggers.Any(t => t.Trigger == PresetTriggerType.ProcessSwitch) &&
|
||||
((string.IsNullOrEmpty(p.DeviceMacAddress) && selectedDevice?.Options.TriggersEnabled == true)
|
||||
|| Devices.Any(d => d.Options.TriggersEnabled && p.DeviceMacAddress.Equals(d.MacAddress, StringComparison.OrdinalIgnoreCase))));
|
||||
if (!presets.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var changedProcesses = new List<Process>();
|
||||
if (context.ForegroundProcess != null)
|
||||
{
|
||||
changedProcesses.Add(context.ForegroundProcess);
|
||||
}
|
||||
|
||||
if (context.ForegroundProcess != null && context.ForegroundProcessIsFullScreen)
|
||||
{
|
||||
presets = presets.Where(p => p.Triggers.Any(t => t.Conditions.HasFlag(PresetConditionType.FullScreen)));
|
||||
}
|
||||
else if (context.StoppedFullScreen)
|
||||
{
|
||||
presets = presets.Where(p => p.Triggers.Any(t => !t.Conditions.HasFlag(PresetConditionType.FullScreen)));
|
||||
}
|
||||
|
||||
var isHDRActive = CCD.IsHDREnabled();
|
||||
|
||||
var isGsyncActive = await _serviceManager.HandleExternalServiceAsync("GsyncEnabled", new[] { "" });
|
||||
|
||||
var triggerContext = new PresetTriggerContext
|
||||
{
|
||||
IsHDRActive = isHDRActive,
|
||||
IsGsyncActive = isGsyncActive,
|
||||
ForegroundProcess = context.ForegroundProcess,
|
||||
ForegroundProcessIsFullScreen = context.ForegroundProcessIsFullScreen,
|
||||
ChangedProcesses = changedProcesses,
|
||||
IsNotificationDisabled = context.IsNotificationDisabled
|
||||
};
|
||||
|
||||
var toApplyPresets = presets.Where(p => p.Triggers.Any(t => t.TriggerActive(triggerContext))).ToList();
|
||||
|
||||
if (toApplyPresets.Any())
|
||||
{
|
||||
var toApplyPreset = toApplyPresets.FirstOrDefault(p => toApplyPresets.Count == 1 || p.Triggers.Any(t => !t.IncludedProcesses.Contains("*"))) ?? toApplyPresets.First();
|
||||
|
||||
if (_lastTriggeredPreset != toApplyPreset)
|
||||
{
|
||||
Logger.Debug($"Applying triggered preset: {toApplyPreset.name} because trigger conditions are met");
|
||||
|
||||
await ApplyPreset(toApplyPreset);
|
||||
|
||||
_lastTriggeredPreset = toApplyPreset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleScreenSaverProcessAsync(IList<Process> processes, List<SamsungDevice> connectedDevices)
|
||||
{
|
||||
var process = processes.FirstOrDefault(p => p.ProcessName.ToLowerInvariant().EndsWith(".scr"));
|
||||
|
||||
var powerOffDevices = connectedDevices.Where(d => d.Options.PowerOffOnScreenSaver).ToList();
|
||||
|
||||
if (process == null)
|
||||
{
|
||||
powerOffDevices.ForEach(d => d.ClearPowerOffTask());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = process.Parent(processes);
|
||||
|
||||
// Ignore manually started screen savers if no devices prefer this
|
||||
if (parent?.ProcessName.Contains("winlogon") != true && !connectedDevices.Any(d => d.Options.HandleManualScreenSaver))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Debug($"Screensaver started: {process.ProcessName}, parent: {parent.ProcessName}");
|
||||
try
|
||||
{
|
||||
foreach (var device in powerOffDevices)
|
||||
{
|
||||
Logger.Debug($"Screensaver check: test connection with {device.Name}...");
|
||||
|
||||
var test = await device.TestConnectionAsync();
|
||||
Logger.Debug("Screensaver check: test connection result: " + test);
|
||||
if (!test)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (device.Options.ScreenSaverMinimalDuration > 0)
|
||||
{
|
||||
Logger.Debug($"Screensaver check: powering off tv {device.Name} in {device.Options.ScreenSaverMinimalDuration} seconds because of screensaver");
|
||||
|
||||
_poweredOffByScreenSaver = true;
|
||||
|
||||
device.PowerOffIn(device.Options.ScreenSaverMinimalDuration);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger.Debug($"Screensaver check: powering off tv {device.Name} because of screensaver");
|
||||
try
|
||||
{
|
||||
_poweredOffByScreenSaver = await device.PerformActionOnScreenSaver().WaitAsync(TimeSpan.FromSeconds(5));
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
// Assume powering off was successful
|
||||
_poweredOffByScreenSaver = true;
|
||||
Logger.Error($"Screensaver check: timeout exception while powering off (probably connection closed)");
|
||||
}
|
||||
catch (Exception pex)
|
||||
{
|
||||
// Assume powering off was successful
|
||||
_poweredOffByScreenSaver = true;
|
||||
Logger.Error($"Screensaver check: exception while powering off (probably connection closed): " + pex.Message);
|
||||
}
|
||||
Logger.Debug($"Screensaver check: powered off tv {device.Name}");
|
||||
}
|
||||
|
||||
_poweredOffByScreenSaverProcessId = process.Id;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Screensaver check: can't power off: " + e.ToLogString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ColorControl.Services.Samsung
|
||||
{
|
||||
class SamsungServiceConfig
|
||||
{
|
||||
public bool PowerOnAfterStartup { get; set; }
|
||||
public int PowerOnRetries { get; set; }
|
||||
public string PreferredMacAddress { get; set; }
|
||||
public string DeviceSearchKey { get; set; }
|
||||
public List<SamsungDevice> Devices { get; set; }
|
||||
public int ShutdownDelay { get; set; }
|
||||
public bool SetSelectedDeviceByPowerOn { get; set; }
|
||||
public string QuickAccessShortcut { get; set; }
|
||||
public int DefaultButtonDelay { get; set; }
|
||||
|
||||
public SamsungServiceConfig()
|
||||
{
|
||||
ShutdownDelay = 1000;
|
||||
DeviceSearchKey = "Samsung";
|
||||
PowerOnRetries = 10;
|
||||
DefaultButtonDelay = 500;
|
||||
Devices = new List<SamsungDevice>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace ColorControl
|
||||
public const string ExecuteNvidiaPresetParam = "--nvpreset";
|
||||
public const string ExecuteAmdPresetParam = "--amdpreset";
|
||||
public const string ExecuteLgPresetParam = "--lgpreset";
|
||||
public const string ExecuteSamsungPresetParam = "--sampreset";
|
||||
public const string NoGuiParam = "--nogui";
|
||||
public const string EnableAutoStartParam = "--enable-auto-start";
|
||||
public const string DisableAutoStartParam = "--disable-auto-start";
|
||||
@@ -36,6 +37,8 @@ namespace ColorControl
|
||||
public string AmdPresetIdOrName { get; private set; }
|
||||
public bool ExecuteLgPreset { get; private set; }
|
||||
public string LgPresetName { get; private set; }
|
||||
public bool ExecuteSamsungPreset { get; private set; }
|
||||
public string SamsungPresetName { get; private set; }
|
||||
public bool NoGui { get; set; }
|
||||
public bool EnableAutoStart { get; private set; }
|
||||
public TaskRunLevel AutoStartRunLevel { get; private set; } = TaskRunLevel.LUA;
|
||||
@@ -85,6 +88,11 @@ namespace ColorControl
|
||||
settings.LgPresetName = arg;
|
||||
break;
|
||||
}
|
||||
case ExecuteSamsungPresetParam:
|
||||
{
|
||||
settings.SamsungPresetName = arg;
|
||||
break;
|
||||
}
|
||||
case SetProcessAffinityParam:
|
||||
{
|
||||
if (settings.ProcessId == 0)
|
||||
@@ -172,6 +180,12 @@ namespace ColorControl
|
||||
parseNameParam = ExecuteLgPresetParam;
|
||||
break;
|
||||
}
|
||||
case ExecuteSamsungPresetParam:
|
||||
{
|
||||
settings.ExecuteSamsungPreset = true;
|
||||
parseNameParam = ExecuteSamsungPresetParam;
|
||||
break;
|
||||
}
|
||||
case NoGuiParam:
|
||||
{
|
||||
settings.NoGui = true;
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
namespace LgTv
|
||||
{
|
||||
public delegate void IsConnectedDelegate(bool status);
|
||||
}
|
||||
@@ -20,6 +20,8 @@ namespace LgTv
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void IsConnectedDelegate(bool status);
|
||||
|
||||
public class LgTvApiCore : IDisposable
|
||||
{
|
||||
public static SynchronizationContext SyncContext { get; set; }
|
||||
@@ -111,17 +113,6 @@ namespace LgTv
|
||||
_messageWriter.WriteString(message);
|
||||
|
||||
await _messageWriter.StoreAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(5));
|
||||
|
||||
//using (var cancellationTokenSource = new CancellationTokenSource(5000))
|
||||
//{
|
||||
// await _messageWriter.StoreAsync().AsTask(cancellationTokenSource.Token).ContinueWith((antecedent) =>
|
||||
// {
|
||||
// if (antecedent.Status != TaskStatus.RanToCompletion)
|
||||
// {
|
||||
// throw new Exception("SendMessageAsync cancelled due to timeout");
|
||||
// }
|
||||
// });
|
||||
//}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -197,11 +188,6 @@ namespace LgTv
|
||||
task.Start();
|
||||
var dataReader = await task.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
|
||||
//if (!result)
|
||||
//{
|
||||
// throw new Exception("Timeout while reading response, possible disconnect");
|
||||
//}
|
||||
|
||||
using (dataReader)
|
||||
{
|
||||
dataReader.UnicodeEncoding = UnicodeEncoding.Utf8;
|
||||
|
||||
Reference in new issue
Block a user