diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj
index 332c52e..4c2ad31 100644
--- a/ColorControl/ColorControl.csproj
+++ b/ColorControl/ColorControl.csproj
@@ -19,8 +19,8 @@
Maassoft
Maassoft
0
- 8.0.0.0
- 8.0.0.0
+ 8.1.0.0
+ 8.1.0.0
false
true
false
diff --git a/ColorControl/Common/Utils.cs b/ColorControl/Common/Utils.cs
index 481a9e7..61de190 100644
--- a/ColorControl/Common/Utils.cs
+++ b/ColorControl/Common/Utils.cs
@@ -426,6 +426,12 @@ The best and suggested method to provide this is via a Windows Service. Only whe
public static T WaitForTask(Task task)
{
+ if (ConsoleOpened)
+ {
+ task.Wait();
+ return task.Result;
+ }
+
while (task != null && (task.Status < TaskStatus.WaitingForChildrenToComplete))
{
Thread.Sleep(10);
@@ -436,6 +442,12 @@ The best and suggested method to provide this is via a Windows Service. Only whe
public static void WaitForTask(System.Threading.Tasks.Task task)
{
+ if (ConsoleOpened)
+ {
+ task.Wait();
+ return;
+ }
+
while (task != null && (task.Status < TaskStatus.WaitingForChildrenToComplete))
{
Thread.Sleep(10);
@@ -733,7 +745,7 @@ The best and suggested method to provide this is via a Windows Service. Only whe
return null;
}
- public static void StartProcess(string fileName, string arguments = null, bool hidden = false, bool wait = false, bool setWorkingDir = false, bool elevate = false, uint affinityMask = 0, uint priorityClass = 0)
+ public static Process StartProcess(string fileName, string arguments = null, bool hidden = false, bool wait = false, bool setWorkingDir = false, bool elevate = false, uint affinityMask = 0, uint priorityClass = 0)
{
var process = Process.Start(new ProcessStartInfo(fileName, arguments)
{
@@ -757,6 +769,8 @@ The best and suggested method to provide this is via a Windows Service. Only whe
{
process.WaitForExit();
}
+
+ return process;
}
internal static void SetProcessAffinity(int processId, uint affinityMask)
diff --git a/ColorControl/Forms/ListViewColumnSorter.cs b/ColorControl/Forms/ListViewColumnSorter.cs
index 854c4f2..93887b8 100644
--- a/ColorControl/Forms/ListViewColumnSorter.cs
+++ b/ColorControl/Forms/ListViewColumnSorter.cs
@@ -64,7 +64,9 @@ namespace ColorControl
else
{
// Compare the two items
- compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
+ var subItemTextX = listviewX.SubItems.Count > ColumnToSort ? listviewX.SubItems[ColumnToSort].Text : string.Empty;
+ var subItemTextY = listviewY.SubItems.Count > ColumnToSort ? listviewY.SubItems[ColumnToSort].Text : string.Empty;
+ compareResult = ObjectCompare.Compare(subItemTextX, subItemTextY);
}
// Calculate correct return value based on object comparison
diff --git a/ColorControl/Forms/MessageForms.cs b/ColorControl/Forms/MessageForms.cs
index f4dc00a..cfbdca5 100644
--- a/ColorControl/Forms/MessageForms.cs
+++ b/ColorControl/Forms/MessageForms.cs
@@ -198,7 +198,7 @@ namespace ColorControl.Forms
if (field.Values != null && field.Values.Any())
{
- var compoundValue = field.Value is int ? (int)field.Value : (int)((uint)field.Value);
+ var compoundValue = field.Value is uint ? (int)(uint)field.Value : (int)field.Value;
var enumValue = 1;
foreach (var value in field.Values)
{
diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs
index 3969130..95fe407 100644
--- a/ColorControl/MainForm.Designer.cs
+++ b/ColorControl/MainForm.Designer.cs
@@ -171,6 +171,7 @@
this.clbLgPower = new System.Windows.Forms.CheckedListBox();
this.lblLgError = new System.Windows.Forms.Label();
this.tabGameLauncher = new System.Windows.Forms.TabPage();
+ this.cbxGameStepType = new System.Windows.Forms.ComboBox();
this.btnGameOptions = new System.Windows.Forms.Button();
this.mnuGameOptions = new System.Windows.Forms.ContextMenuStrip(this.components);
this.miGameProcessorAffinity = new System.Windows.Forms.ToolStripMenuItem();
@@ -193,7 +194,6 @@
this.mnuGameAmdPresets = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGameLgPresets = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGameStartProgram = new System.Windows.Forms.ToolStripMenuItem();
- this.lblGamePreLaunch = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.edtGameName = new System.Windows.Forms.TextBox();
this.btnGameDelete = new System.Windows.Forms.Button();
@@ -1821,17 +1821,19 @@
this.clbLgPower.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.clbLgPower.CheckOnClick = true;
- this.clbLgPower.ColumnWidth = 380;
+ this.clbLgPower.ColumnWidth = 240;
this.clbLgPower.FormattingEnabled = true;
this.clbLgPower.Items.AddRange(new object[] {
- "Automatically power on after startup",
- "Automatically power on after resume from standby",
- "Automatically power off on shutdown",
- "Automatically power off on standby",
- "Automatically power off/on when screensaver activates/deactivates",
+ "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"});
+ "Use Windows power settings to power on",
+ "Use Windows power settings to power off"});
this.clbLgPower.Location = new System.Drawing.Point(6, 70);
this.clbLgPower.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.clbLgPower.MultiColumn = true;
@@ -1853,6 +1855,7 @@
//
// tabGameLauncher
//
+ this.tabGameLauncher.Controls.Add(this.cbxGameStepType);
this.tabGameLauncher.Controls.Add(this.btnGameOptions);
this.tabGameLauncher.Controls.Add(this.chkGameQuickAccess);
this.tabGameLauncher.Controls.Add(this.btnGameSettings);
@@ -1864,7 +1867,6 @@
this.tabGameLauncher.Controls.Add(this.edtGamePath);
this.tabGameLauncher.Controls.Add(this.edtGamePrelaunchSteps);
this.tabGameLauncher.Controls.Add(this.btnGameAddStep);
- this.tabGameLauncher.Controls.Add(this.lblGamePreLaunch);
this.tabGameLauncher.Controls.Add(this.label4);
this.tabGameLauncher.Controls.Add(this.edtGameName);
this.tabGameLauncher.Controls.Add(this.btnGameDelete);
@@ -1881,6 +1883,19 @@
this.tabGameLauncher.Text = "Game Launcher";
this.tabGameLauncher.UseVisualStyleBackColor = true;
//
+ // cbxGameStepType
+ //
+ this.cbxGameStepType.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.cbxGameStepType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cbxGameStepType.Enabled = false;
+ this.cbxGameStepType.FormattingEnabled = true;
+ this.cbxGameStepType.Location = new System.Drawing.Point(10, 474);
+ this.cbxGameStepType.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.cbxGameStepType.Name = "cbxGameStepType";
+ this.cbxGameStepType.Size = new System.Drawing.Size(136, 23);
+ this.cbxGameStepType.TabIndex = 46;
+ this.cbxGameStepType.SelectedIndexChanged += new System.EventHandler(this.cbxGameStepType_SelectedIndexChanged);
+ //
// btnGameOptions
//
this.btnGameOptions.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
@@ -1994,10 +2009,10 @@
//
this.edtGameParameters.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.edtGameParameters.Enabled = false;
- this.edtGameParameters.Location = new System.Drawing.Point(112, 442);
+ this.edtGameParameters.Location = new System.Drawing.Point(154, 442);
this.edtGameParameters.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.edtGameParameters.Name = "edtGameParameters";
- this.edtGameParameters.Size = new System.Drawing.Size(665, 23);
+ this.edtGameParameters.Size = new System.Drawing.Size(623, 23);
this.edtGameParameters.TabIndex = 40;
//
// btnGameBrowse
@@ -2029,22 +2044,23 @@
//
this.edtGamePath.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.edtGamePath.Enabled = false;
- this.edtGamePath.Location = new System.Drawing.Point(112, 413);
+ this.edtGamePath.Location = new System.Drawing.Point(154, 413);
this.edtGamePath.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.edtGamePath.Name = "edtGamePath";
- this.edtGamePath.Size = new System.Drawing.Size(665, 23);
+ this.edtGamePath.Size = new System.Drawing.Size(623, 23);
this.edtGamePath.TabIndex = 37;
//
// edtGamePrelaunchSteps
//
this.edtGamePrelaunchSteps.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.edtGamePrelaunchSteps.Enabled = false;
- this.edtGamePrelaunchSteps.Location = new System.Drawing.Point(112, 471);
+ this.edtGamePrelaunchSteps.Location = new System.Drawing.Point(154, 471);
this.edtGamePrelaunchSteps.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.edtGamePrelaunchSteps.Multiline = true;
this.edtGamePrelaunchSteps.Name = "edtGamePrelaunchSteps";
- this.edtGamePrelaunchSteps.Size = new System.Drawing.Size(665, 48);
+ this.edtGamePrelaunchSteps.Size = new System.Drawing.Size(623, 48);
this.edtGamePrelaunchSteps.TabIndex = 35;
+ this.edtGamePrelaunchSteps.Leave += new System.EventHandler(this.edtGamePrelaunchSteps_Leave);
//
// btnGameAddStep
//
@@ -2097,17 +2113,6 @@
this.mnuGameStartProgram.Text = "Start Program";
this.mnuGameStartProgram.Click += new System.EventHandler(this.mnuGameStartProgram_Click);
//
- // lblGamePreLaunch
- //
- this.lblGamePreLaunch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
- this.lblGamePreLaunch.AutoSize = true;
- this.lblGamePreLaunch.Location = new System.Drawing.Point(8, 477);
- this.lblGamePreLaunch.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.lblGamePreLaunch.Name = "lblGamePreLaunch";
- this.lblGamePreLaunch.Size = new System.Drawing.Size(98, 15);
- this.lblGamePreLaunch.TabIndex = 34;
- this.lblGamePreLaunch.Text = "Pre-launch steps:";
- //
// label4
//
this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
@@ -2123,10 +2128,10 @@
//
this.edtGameName.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.edtGameName.Enabled = false;
- this.edtGameName.Location = new System.Drawing.Point(112, 384);
+ this.edtGameName.Location = new System.Drawing.Point(154, 384);
this.edtGameName.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.edtGameName.Name = "edtGameName";
- this.edtGameName.Size = new System.Drawing.Size(233, 23);
+ this.edtGameName.Size = new System.Drawing.Size(191, 23);
this.edtGameName.TabIndex = 32;
//
// btnGameDelete
@@ -3205,7 +3210,6 @@
private System.Windows.Forms.TextBox edtGamePath;
private System.Windows.Forms.TextBox edtGamePrelaunchSteps;
private System.Windows.Forms.Button btnGameAddStep;
- private System.Windows.Forms.Label lblGamePreLaunch;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox edtGameName;
private System.Windows.Forms.Button btnGameDelete;
@@ -3247,6 +3251,7 @@
private System.Windows.Forms.Button btnStartStopService;
private System.Windows.Forms.Label lblShowLog;
private System.Windows.Forms.ComboBox cbxLogType;
+ private System.Windows.Forms.ComboBox cbxGameStepType;
}
}
diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs
index aa8eb5f..79f434e 100644
--- a/ColorControl/MainForm.cs
+++ b/ColorControl/MainForm.cs
@@ -1719,6 +1719,19 @@ NOTE: installing the service may cause a User Account Control popup.");
{
UpdateDisplayInfoItems();
}
+ else if (tcMain.SelectedTab == tabGameLauncher)
+ {
+ UpdateGameLauncherTab();
+ }
+ }
+
+ private void UpdateGameLauncherTab()
+ {
+ if (cbxGameStepType.Items.Count == 0)
+ {
+ cbxGameStepType.Items.AddRange(Utils.GetDescriptions().ToArray());
+ cbxGameStepType.SelectedIndex = 0;
+ }
}
private void InitLgTab()
@@ -1769,7 +1782,8 @@ NOTE: installing the service may cause a User Account Control popup.");
ElevationMethod.None => rbElevationNone.Checked = true,
ElevationMethod.RunAsAdmin => rbElevationAdmin.Checked = true,
ElevationMethod.UseService => rbElevationService.Checked = true,
- ElevationMethod.UseElevatedProcess => rbElevationProcess.Checked = true
+ ElevationMethod.UseElevatedProcess => rbElevationProcess.Checked = true,
+ _ => false
};
}
finally
@@ -1865,10 +1879,12 @@ NOTE: installing the service may cause a User Account Control popup.");
clbLgPower.SetItemChecked(1, device?.PowerOnAfterResume ?? false);
clbLgPower.SetItemChecked(2, device?.PowerOffOnShutdown ?? false);
clbLgPower.SetItemChecked(3, device?.PowerOffOnStandby ?? false);
- clbLgPower.SetItemChecked(4, device?.PowerSwitchOnScreenSaver ?? false);
- clbLgPower.SetItemChecked(5, device?.PowerOnAfterManualPowerOff ?? false);
- clbLgPower.SetItemChecked(6, device?.TriggersEnabled ?? true);
- clbLgPower.SetItemChecked(7, device?.PowerByWindows ?? false);
+ clbLgPower.SetItemChecked(4, device?.PowerOffOnScreenSaver ?? false);
+ clbLgPower.SetItemChecked(5, device?.PowerOnAfterScreenSaver ?? false);
+ clbLgPower.SetItemChecked(6, device?.PowerOnAfterManualPowerOff ?? false);
+ clbLgPower.SetItemChecked(7, device?.TriggersEnabled ?? true);
+ clbLgPower.SetItemChecked(8, device?.PowerOffByWindows ?? false);
+ clbLgPower.SetItemChecked(8, device?.PowerOnByWindows ?? false);
}
finally
{
@@ -2388,7 +2404,7 @@ NOTE: installing the service may cause a User Account Control popup.");
return;
}
- if (e.Index is 0 or 1 or 4 or 7 && !(device.PowerOnAfterResume || device.PowerOnAfterStartup || device.PowerSwitchOnScreenSaver || device.PowerByWindows))
+ if (e.Index is 0 or 1 or 4 or 7 && !(device.PowerOnAfterResume || device.PowerOnAfterStartup || device.PowerOnAfterScreenSaver || device.PowerOnByWindows))
{
MessageForms.InfoOk(
@"Be sure to activate the following setting on the TV, or the app will not be able to wake the TV:
@@ -2406,10 +2422,12 @@ You can also activate this option by using the Expert-button and selecting Wake-
device.PowerOnAfterResume = clbLgPower.GetItemChecked(1);
device.PowerOffOnShutdown = clbLgPower.GetItemChecked(2);
device.PowerOffOnStandby = clbLgPower.GetItemChecked(3);
- device.PowerSwitchOnScreenSaver = clbLgPower.GetItemChecked(4);
- device.PowerOnAfterManualPowerOff = clbLgPower.GetItemChecked(5);
- device.TriggersEnabled = clbLgPower.GetItemChecked(6);
- device.PowerByWindows = clbLgPower.GetItemChecked(7);
+ device.PowerOffOnScreenSaver = clbLgPower.GetItemChecked(4);
+ device.PowerOnAfterScreenSaver = clbLgPower.GetItemChecked(5);
+ device.PowerOnAfterManualPowerOff = clbLgPower.GetItemChecked(6);
+ device.TriggersEnabled = clbLgPower.GetItemChecked(7);
+ device.PowerOffByWindows = clbLgPower.GetItemChecked(8);
+ device.PowerOnByWindows = clbLgPower.GetItemChecked(9);
_lgService.InstallEventHandlers();
});
@@ -3166,16 +3184,7 @@ Do you want to continue?";
var device = _lgService.GetPresetDevice(preset);
- var actions = device?.GetInvokableActions();
- foreach (var action in actions.Where(a => a.Function != null))
- {
- var text = action.Title ?? action.Name;
-
- var item = mnuLgActions.DropDownItems.Add(text);
- item.Tag = action;
- item.Click += miLgAddAction_Click;
- }
-
+ BuildLgActionMenu(device, mnuLgActions.DropDownItems, mnuLgActions.Name, miLgAddAction_Click);
BuildServicePresetsMenu(mnuLgNvPresets, _nvService, "NVIDIA", miLgAddNvPreset_Click);
BuildServicePresetsMenu(mnuLgAmdPresets, _amdService, "AMD", miLgAddAmdPreset_Click);
}
@@ -3232,40 +3241,51 @@ Do you want to continue?"
var device = _lgService.SelectedDevice;
var eligibleModels = new[] { "B9", "C9", "E9", "W9", "C2", "G2" };
+ var eligibleModelsEnable = new[] { "B9", "C9", "E9", "W9" };
- var visible = device?.ModelName != null ? eligibleModels.Any(m => device.ModelName.Contains(m)) : false;
+ var visible = eligibleModels.Any(m => device?.ModelName?.Contains(m) == true);
+ var enableVisible = eligibleModelsEnable.Any(m => device?.ModelName?.Contains(m) == true);
mnuLgOLEDMotionPro.Visible = visible;
+ miLgEnableMotionPro.Visible = enableVisible;
miLgExpertSeparator1.Visible = visible;
- // Does not work yet, getting a "401 no permissions" error
- //var task = device?.GetPictureSettings();
- //var settings = Utils.WaitForTask(task);
+ BuildLgActionMenu(device, mnuLgExpert.Items, mnuLgExpert.Name, btnLgExpertColorGamut_Click, _lgService.Config.ShowAdvancedActions, true);
+ }
+ private void BuildLgActionMenu(LgDevice device, ToolStripItemCollection parent, string parentName, EventHandler clickEvent, bool showAdvanced = false, bool showGameBar = false)
+ {
if (device == null)
{
return;
}
- var actions = device.GetInvokableActions(_lgService.Config.ShowAdvancedActions);
+ var actions = device.GetInvokableActions(showAdvanced);
var gameBarActions = device.GetInvokableActionsForGameBar();
var activatedGameBarActions = device.GetActionsForGameBar();
const string gameBarName = "miGameBar";
- var expertActions = actions.Where(a => !a.Name.Contains("uhd", StringComparison.OrdinalIgnoreCase) &&
- !a.Name.Contains("gameOpt", StringComparison.OrdinalIgnoreCase) &&
- !a.Name.Contains("hdmiPc", StringComparison.OrdinalIgnoreCase) &&
- (a.EnumType != null || a.MaxValue > a.MinValue)).ToList();
+ var expertActions = actions.Where(a => a.EnumType != null || a.MaxValue > a.MinValue).ToList();
var categories = expertActions.Select(a => a.Category ?? "misc").Where(c => !string.IsNullOrEmpty(c)).Distinct();
foreach (var category in categories)
{
- var catMenuItem = FormUtils.BuildDropDownMenuEx(mnuLgExpert.Items, mnuLgExpert.Name, Utils.FirstCharUpperCase(category), null, null, category);
+ var catMenuItem = FormUtils.BuildDropDownMenuEx(parent, parentName, Utils.FirstCharUpperCase(category), null, null, category);
foreach (var action in expertActions.Where(a => (a.Category ?? "misc") == category))
{
- var menu = FormUtils.BuildDropDownMenuEx(catMenuItem.DropDownItems, catMenuItem.Name, action.Title, action.EnumType, btnLgExpertColorGamut_Click, action, (int)action.MinValue, (int)action.MaxValue, action.NumberOfValues > 1);
+ if (!showGameBar)
+ {
+ var text = action.Title ?? action.Name;
+
+ var item = catMenuItem.DropDownItems.Add(text);
+ item.Tag = action;
+ item.Click += clickEvent;
+ continue;
+ }
+
+ var menu = FormUtils.BuildDropDownMenuEx(catMenuItem.DropDownItems, catMenuItem.Name, action.Title, action.EnumType, clickEvent, action, (int)action.MinValue, (int)action.MaxValue, action.NumberOfValues > 1);
if (!gameBarActions.Contains(action))
{
@@ -3289,16 +3309,16 @@ Do you want to continue?"
}
}
- if (!_lgService.Config.ShowAdvancedActions)
+ if (!showAdvanced)
{
return;
}
var presetActions = actions.Where(a => a.Preset != null);
- if (presetActions.Any() && mnuLgExpert.Items.Find("miLgExpertActionsSeparator", false).Length == 0)
+ if (presetActions.Any() && parent.Find("miLgExpertActionsSeparator", false).Length == 0)
{
- mnuLgExpert.Items.Add(new ToolStripSeparator
+ parent.Add(new ToolStripSeparator
{
Name = "miLgExpertActionsSeparator"
});
@@ -3306,7 +3326,7 @@ Do you want to continue?"
foreach (var presetAction in presetActions)
{
- var menu = FormUtils.BuildDropDownMenuEx(mnuLgExpert.Items, mnuLgExpert.Name, presetAction.Name, null, btnLgExpertPresetAction_Click, presetAction.Preset);
+ var menu = FormUtils.BuildDropDownMenuEx(parent, parentName, presetAction.Name, null, btnLgExpertPresetAction_Click, presetAction.Preset);
}
}
@@ -3709,7 +3729,7 @@ The InStart and Software Update items are now visible under the Expert-button."
edtGameParameters.Text = preset.Parameters;
chkGameRunAsAdmin.Checked = preset.RunAsAdministrator;
chkGameQuickAccess.Checked = preset.ShowInQuickAccess;
- edtGamePrelaunchSteps.Text = string.Join(", ", preset.PreLaunchSteps);
+ ShowGameSteps();
}
else
{
@@ -3768,6 +3788,11 @@ The InStart and Software Update items are now visible under the Expert-button."
}
private void btnGameSave_Click(object sender, EventArgs e)
+ {
+ SaveGamePreset();
+ }
+
+ private void SaveGamePreset()
{
var shortcut = string.Empty;
if (!Utils.ValidateShortcut(shortcut))
@@ -3801,7 +3826,15 @@ The InStart and Software Update items are now visible under the Expert-button."
var text = edtGamePrelaunchSteps.Text;
- Utils.ParseWords(preset.PreLaunchSteps, text);
+ var stepsList = (GameStepType)cbxGameStepType.SelectedIndex switch
+ {
+ GameStepType.PreLaunch => preset.PreLaunchSteps,
+ GameStepType.PostLaunch => preset.PostLaunchSteps,
+ GameStepType.Finalize => preset.FinalizeSteps,
+ _ => throw new InvalidOperationException("Invalid game step type")
+ };
+
+ Utils.ParseWords(stepsList, text);
AddOrUpdateItemGame();
@@ -4320,5 +4353,38 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
{
LoadLog();
}
+
+ private void cbxGameStepType_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ ShowGameSteps();
+ }
+
+ private void ShowGameSteps()
+ {
+ var preset = GetSelectedGamePreset();
+
+ if (preset == null)
+ {
+ return;
+ }
+
+ switch ((GameStepType)cbxGameStepType.SelectedIndex)
+ {
+ case GameStepType.PreLaunch:
+ edtGamePrelaunchSteps.Text = string.Join(", ", preset.PreLaunchSteps);
+ break;
+ case GameStepType.PostLaunch:
+ edtGamePrelaunchSteps.Text = string.Join(", ", preset.PostLaunchSteps);
+ break;
+ case GameStepType.Finalize:
+ edtGamePrelaunchSteps.Text = string.Join(", ", preset.FinalizeSteps);
+ break;
+ }
+ }
+
+ private void edtGamePrelaunchSteps_Leave(object sender, EventArgs e)
+ {
+ SaveGamePreset();
+ }
}
}
\ No newline at end of file
diff --git a/ColorControl/Services/GameLauncher/GamePreset.cs b/ColorControl/Services/GameLauncher/GamePreset.cs
index bf9e66f..6a95b2b 100644
--- a/ColorControl/Services/GameLauncher/GamePreset.cs
+++ b/ColorControl/Services/GameLauncher/GamePreset.cs
@@ -1,9 +1,20 @@
using ColorControl.Services.Common;
using NWin32;
using System.Collections.Generic;
+using System.ComponentModel;
namespace ColorControl.Services.GameLauncher
{
+ public enum GameStepType
+ {
+ [Description("Pre-launch steps")]
+ PreLaunch = 0,
+ [Description("Post-launch steps")]
+ PostLaunch = 1,
+ [Description("Finalize steps")]
+ Finalize = 2,
+ }
+
public enum GamePriorityClass
{
Idle = NativeConstants.IDLE_PRIORITY_CLASS,
@@ -21,6 +32,7 @@ namespace ColorControl.Services.GameLauncher
public bool RunAsAdministrator { get; set; }
public List PreLaunchSteps { get; set; }
public List PostLaunchSteps { get; set; }
+ public List FinalizeSteps { get; set; }
public uint ProcessAffinityMask { get; set; }
public uint ProcessPriorityClass { get; set; }
@@ -28,6 +40,7 @@ namespace ColorControl.Services.GameLauncher
{
PreLaunchSteps = new List();
PostLaunchSteps = new List();
+ FinalizeSteps = new List();
}
public GamePreset(GamePreset preset) : this()
@@ -40,6 +53,7 @@ namespace ColorControl.Services.GameLauncher
RunAsAdministrator = preset.RunAsAdministrator;
PreLaunchSteps.AddRange(preset.PreLaunchSteps);
PostLaunchSteps.AddRange(preset.PostLaunchSteps);
+ FinalizeSteps.AddRange(preset.FinalizeSteps);
}
public GamePreset Clone()
@@ -53,7 +67,7 @@ namespace ColorControl.Services.GameLauncher
public static string[] GetColumnNames()
{
- return new[] { "Name|160", "File/URI|400", "Parameters|200", "Pre-launch steps|300" };
+ return new[] { "Name|160", "File/URI|400", "Parameters|200", "Pre-launch steps|300", "Post-launch steps|300", "Finalize steps|300" };
}
public override List GetDisplayValues(Config config = null)
@@ -66,6 +80,7 @@ namespace ColorControl.Services.GameLauncher
values.Add(string.Join(", ", PreLaunchSteps));
values.Add(string.Join(", ", PostLaunchSteps));
+ values.Add(string.Join(", ", FinalizeSteps));
return values;
}
diff --git a/ColorControl/Services/GameLauncher/GameService.cs b/ColorControl/Services/GameLauncher/GameService.cs
index 3551b8a..57ed3e2 100644
--- a/ColorControl/Services/GameLauncher/GameService.cs
+++ b/ColorControl/Services/GameLauncher/GameService.cs
@@ -2,6 +2,8 @@
using ColorControl.Services.Common;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
using System.Threading.Tasks;
namespace ColorControl.Services.GameLauncher
@@ -79,7 +81,44 @@ namespace ColorControl.Services.GameLauncher
{
var result = true;
- foreach (var step in preset.PreLaunchSteps)
+ ExecuteSteps(preset.PreLaunchSteps);
+
+ Process process = null;
+
+ if (!string.IsNullOrEmpty(preset.Path))
+ {
+ process = Utils.StartProcess(preset.Path, preset.Parameters, setWorkingDir: true, elevate: preset.RunAsAdministrator, affinityMask: preset.ProcessAffinityMask, priorityClass: preset.ProcessPriorityClass);
+ }
+
+ ExecuteSteps(preset.PostLaunchSteps);
+
+ if (process != null && preset.FinalizeSteps?.Any() == true)
+ {
+ var _ = ExecuteFinalizationStepsAsync(process, preset.FinalizeSteps);
+ }
+
+ _lastAppliedPreset = preset;
+
+ PresetApplied();
+
+ return result;
+ }
+
+ private async Task ExecuteFinalizationStepsAsync(Process process, List finalizeSteps)
+ {
+ await process.WaitForExitAsync();
+
+ ExecuteSteps(finalizeSteps);
+ }
+
+ private void ExecuteSteps(List steps)
+ {
+ if (steps?.Any() != true)
+ {
+ return;
+ }
+
+ foreach (var step in steps)
{
var keySpec = step.Split(':');
@@ -120,17 +159,6 @@ namespace ColorControl.Services.GameLauncher
}
}
-
- if (!string.IsNullOrEmpty(preset.Path))
- {
- Utils.StartProcess(preset.Path, preset.Parameters, setWorkingDir: true, elevate: preset.RunAsAdministrator, affinityMask: preset.ProcessAffinityMask, priorityClass: preset.ProcessPriorityClass);
- }
-
- _lastAppliedPreset = preset;
-
- PresetApplied();
-
- return result;
}
}
}
diff --git a/ColorControl/Services/LG/LgDevice.cs b/ColorControl/Services/LG/LgDevice.cs
index 79e0130..65b5566 100644
--- a/ColorControl/Services/LG/LgDevice.cs
+++ b/ColorControl/Services/LG/LgDevice.cs
@@ -24,6 +24,8 @@ namespace ColorControl.Services.LG
public int NumberOfValues { get; set; }
public LgPreset Preset { get; set; }
public bool Advanced { get; set; }
+ public ModelYear FromModelYear { get; set; } = ModelYear.None;
+ public ModelYear ToModelYear { get; set; } = ModelYear.None;
}
public class LgDevicePictureSettings
@@ -51,6 +53,17 @@ namespace ColorControl.Services.LG
Manually
}
+ public enum ModelYear
+ {
+ None = 0,
+ SeriesPre2018,
+ Series2018,
+ Series2019,
+ Series2020,
+ Series2021,
+ Series2022
+ }
+
protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
public static Func ExternalServiceHandler;
public static List DefaultActionsOnGameBar = new() { "backlight", "contrast", "brightness", "color" };
@@ -66,9 +79,11 @@ namespace ColorControl.Services.LG
public bool PowerOnAfterResume { get; set; }
public bool PowerOffOnShutdown { get; set; }
public bool PowerOffOnStandby { get; set; }
- public bool PowerSwitchOnScreenSaver { get; set; }
+ public bool PowerOffOnScreenSaver { get; set; }
+ public bool PowerOnAfterScreenSaver { get; set; }
public bool PowerOnAfterManualPowerOff { get; set; }
- public bool PowerByWindows { get; set; }
+ public bool PowerOnByWindows { get; set; }
+ public bool PowerOffByWindows { get; set; }
public bool TriggersEnabled { get; set; }
public int HDMIPortNumber { get; set; }
@@ -114,6 +129,8 @@ namespace ColorControl.Services.LG
[JsonIgnore]
public string ModelName { get; private set; }
+ [JsonIgnore]
+ public ModelYear Year { get; private set; }
[JsonIgnore]
public LgDevicePictureSettings PictureSettings { get; private set; }
@@ -153,8 +170,8 @@ namespace ColorControl.Services.LG
AddGenericPictureAction("eyeComfortMode", typeof(OffToOn), title: "Eye Comfort Mode");
//AddGenericPictureAction("dynamicColor", typeof(OffToAuto));
//AddGenericPictureAction("superResolution", typeof(OffToAuto));
- AddGenericPictureAction("peakBrightness", typeof(OffToHigh), title: "Peak Brightness");
- AddGenericPictureAction("smoothGradation", typeof(OffToAuto), title: "Smooth Gradation");
+ AddGenericPictureAction("peakBrightness", typeof(OffToHigh), title: "Peak Brightness", fromModelYear: ModelYear.Series2019);
+ AddGenericPictureAction("smoothGradation", typeof(OffToAuto), title: "Smooth Gradation", fromModelYear: ModelYear.Series2019);
AddGenericPictureAction("energySaving", typeof(EnergySaving), title: "Energy Saving");
AddGenericPictureAction("hdrDynamicToneMapping", typeof(DynamicTonemapping), title: "HDR Dynamic Tone Mapping");
AddGenericPictureAction("blackLevel", typeof(BlackLevel), title: "HDMI Black Level");
@@ -170,7 +187,7 @@ namespace ColorControl.Services.LG
AddGenericPictureAction("truMotionMode", typeof(TruMotionMode), title: "TruMotion");
AddGenericPictureAction("truMotionJudder", minValue: 0, maxValue: 10, title: "TruMotion Judder");
AddGenericPictureAction("truMotionBlur", minValue: 0, maxValue: 10, title: "TruMotion Blur");
- AddGenericPictureAction("motionProOLED", typeof(OffToHigh), title: "OLED Motion Pro");
+ AddGenericPictureAction("motionProOLED", typeof(OffToHigh), title: "OLED Motion Pro", fromModelYear: ModelYear.Series2019);
AddGenericPictureAction("motionPro", typeof(OffToOn), title: "Motion Pro");
AddGenericPictureAction("uhdDeepColorHDMI1", typeof(OffToOn), category: "other");
AddGenericPictureAction("uhdDeepColorHDMI2", typeof(OffToOn), category: "other");
@@ -180,7 +197,10 @@ namespace ColorControl.Services.LG
AddGenericPictureAction("gameOptimizationHDMI2", typeof(OffToOn), category: "other");
AddGenericPictureAction("gameOptimizationHDMI3", typeof(OffToOn), category: "other");
AddGenericPictureAction("gameOptimizationHDMI4", typeof(OffToOn), category: "other");
- //AddGenericPictureAction("freesyncOLEDHDMI4", typeof(OffToOn), category: "other");
+ AddGenericPictureAction("freesyncOLEDHDMI1", typeof(OffToOn), category: "other", fromModelYear: ModelYear.Series2020);
+ AddGenericPictureAction("freesyncOLEDHDMI2", typeof(OffToOn), category: "other", fromModelYear: ModelYear.Series2020);
+ AddGenericPictureAction("freesyncOLEDHDMI3", typeof(OffToOn), category: "other", fromModelYear: ModelYear.Series2020);
+ AddGenericPictureAction("freesyncOLEDHDMI4", typeof(OffToOn), category: "other", fromModelYear: ModelYear.Series2020);
//AddGenericPictureAction("freesyncSupport", typeof(OffToOn), category: "other");
AddGenericPictureAction("hdmiPcMode_hdmi1", typeof(FalseToTrue), category: "other");
AddGenericPictureAction("hdmiPcMode_hdmi2", typeof(FalseToTrue), category: "other");
@@ -236,7 +256,7 @@ namespace ColorControl.Services.LG
_invokableActions.Add(action);
}
- private void AddGenericPictureAction(string name, Type type = null, decimal minValue = 0, decimal maxValue = 0, string category = "picture", string title = null, int numberOfValues = 1)
+ private void AddGenericPictureAction(string name, Type type = null, decimal minValue = 0, decimal maxValue = 0, string category = "picture", string title = null, int numberOfValues = 1, ModelYear fromModelYear = ModelYear.None)
{
var action = new InvokableAction
{
@@ -247,7 +267,8 @@ namespace ColorControl.Services.LG
MaxValue = maxValue,
NumberOfValues = numberOfValues,
Category = category,
- Title = title == null ? Utils.FirstCharUpperCase(name) : title
+ Title = title == null ? Utils.FirstCharUpperCase(name) : title,
+ FromModelYear = fromModelYear
};
_invokableActions.Add(action);
@@ -318,12 +339,13 @@ namespace ColorControl.Services.LG
//Test();
//_lgTvApi.Test3();
- if (_lgTvApi != null)
+ if (_lgTvApi != null && !Utils.ConsoleOpened)
{
var info = await _lgTvApi.GetSystemInfo("modelName");
if (info != null)
{
ModelName = info.modelName;
+ SetModelYear();
}
//await _lgTvApi.SubscribeVolume(VolumeChanged);
@@ -360,6 +382,38 @@ namespace ColorControl.Services.LG
}
}
+ private void SetModelYear()
+ {
+ if (ModelName == null || ModelName.Contains("OLED") != true)
+ {
+ Year = ModelYear.None;
+ return;
+ }
+
+ var normalized = ModelName.Replace("OLED", "").Replace(" ", "");
+
+ if (normalized.Length > 3)
+ {
+ normalized = normalized.Substring(3);
+ }
+
+ var suffix = normalized.First();
+
+ Year = suffix switch
+ {
+ '6' => ModelYear.SeriesPre2018,
+ '7' => ModelYear.SeriesPre2018,
+ '8' => ModelYear.Series2018,
+ '9' => ModelYear.Series2019,
+ 'X' => ModelYear.Series2020,
+ '1' => ModelYear.Series2021,
+ '2' => ModelYear.Series2022,
+ _ => ModelYear.None
+ };
+
+ _invokableActions = _invokableActions.Where(a => Year == ModelYear.None || a.FromModelYear == ModelYear.None || Year >= a.FromModelYear).ToList();
+ }
+
public bool VolumeChanged(dynamic payload)
{
return true;
@@ -798,7 +852,7 @@ namespace ColorControl.Services.LG
public List GetInvokableActions(bool includedAdvanced = false)
{
- return includedAdvanced ? _invokableActions : _invokableActions.Where(a => !a.Advanced).ToList();
+ return _invokableActions.Where(a => includedAdvanced || !a.Advanced).ToList();
}
public List GetInvokableActionsForGameBar()
diff --git a/ColorControl/Services/LG/LgService.cs b/ColorControl/Services/LG/LgService.cs
index f977831..1da42a6 100644
--- a/ColorControl/Services/LG/LgService.cs
+++ b/ColorControl/Services/LG/LgService.cs
@@ -420,7 +420,7 @@ namespace ColorControl.Services.LG
{
var wakeDevices = Devices.Where(d => state == PowerOnOffState.StartUp && d.PowerOnAfterStartup ||
state == PowerOnOffState.Resume && d.PowerOnAfterResume ||
- state == PowerOnOffState.ScreenSaver && d.PowerSwitchOnScreenSaver);
+ state == PowerOnOffState.ScreenSaver && d.PowerOnAfterScreenSaver);
PowerOnDevices(wakeDevices, state, checkUserSession);
}
@@ -514,12 +514,12 @@ namespace ColorControl.Services.LG
public bool ShouldMonitorProcesses()
{
- return Devices.Any(d => d.PowerSwitchOnScreenSaver) || _presets.Any(p => p.Triggers.Any(t => t.Trigger != PresetTriggerType.None));
+ return Devices.Any(d => d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver) || _presets.Any(p => p.Triggers.Any(t => t.Trigger != PresetTriggerType.None));
}
public async Task CheckProcesses()
{
- var wasConnected = Devices.Any(d => d.PowerSwitchOnScreenSaver && d.IsConnected());
+ var wasConnected = Devices.Any(d => (d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver) && d.IsConnected());
_monitorTaskCounter++;
var validCounter = _monitorTaskCounter;
var lastProcessId = 0;
@@ -535,7 +535,7 @@ namespace ColorControl.Services.LG
try
{
- var applicableDevices = Devices.Where(d => d.PowerSwitchOnScreenSaver || d.TriggersEnabled && _presets.Any(p => p.Triggers.Any(t => t.Trigger != PresetTriggerType.None) &&
+ var applicableDevices = Devices.Where(d => d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver || d.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())
@@ -601,7 +601,7 @@ namespace ColorControl.Services.LG
wasConnected = true;
}
- if (connectedDevices.Any(d => d.PowerSwitchOnScreenSaver))
+ if (connectedDevices.Any(d => d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver))
{
lastProcessId = await HandleScreenSaverProcessAsync(lastProcessId, processes, connectedDevices);
}
@@ -634,7 +634,7 @@ namespace ColorControl.Services.LG
Logger.Debug($"Screensaver started: {process.ProcessName}, parent: {parent.ProcessName}");
try
{
- foreach (var device in connectedDevices)
+ foreach (var device in connectedDevices.Where(d => d.PowerOffOnScreenSaver))
{
Logger.Debug($"Screensaver check: test connection with {device.Name}...");
var test = await device.TestConnection();
@@ -815,14 +815,15 @@ namespace ColorControl.Services.LG
public void PowerSettingChanged(WindowsPowerSetting setting)
{
- var devices = Devices.Where(d => d.PowerByWindows).ToList();
if (setting == WindowsPowerSetting.Off)
{
+ var devices = Devices.Where(d => d.PowerOffByWindows).ToList();
PowerOffDevices(devices, PowerOnOffState.StandBy);
}
else if (setting == WindowsPowerSetting.On)
{
+ var devices = Devices.Where(d => d.PowerOnByWindows).ToList();
PowerOnDevices(devices);
}
}
diff --git a/ColorControl/Svc/ColorControlBackgroundService.cs b/ColorControl/Svc/ColorControlBackgroundService.cs
index d3607d4..a8ac8d0 100644
--- a/ColorControl/Svc/ColorControlBackgroundService.cs
+++ b/ColorControl/Svc/ColorControlBackgroundService.cs
@@ -63,7 +63,7 @@ namespace ColorControl.Svc
}
catch (Exception ex)
{
- Logger.Error($"While handling message: {message}");
+ Logger.Error(ex, $"Error while handling message: {message}");
var result = SvcResultMessage.FromResult(false, ex.Message);
var resultJson = JsonConvert.SerializeObject(result);
@@ -104,7 +104,8 @@ namespace ColorControl.Svc
SvcMessageType.SetLgConfig => HandleSetLgConfigMessage(message),
SvcMessageType.GetLog => HandleGetLogMessage(message),
SvcMessageType.ClearLog => HandleClearLogMessage(message),
- SvcMessageType.ExecuteRpc => HandleExecuteRpcCommand(message)
+ SvcMessageType.ExecuteRpc => HandleExecuteRpcCommand(message),
+ _ => SvcResultMessage.FromResult(false, "Unexpected message type")
};
return result;
diff --git a/ColorControl/lgtv/LgTvConnection.cs b/ColorControl/lgtv/LgTvConnection.cs
index 052637e..5c83b19 100644
--- a/ColorControl/lgtv/LgTvConnection.cs
+++ b/ColorControl/lgtv/LgTvConnection.cs
@@ -1,14 +1,13 @@
-using System;
+using ColorControl.Common;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Serialization;
+using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
-using Newtonsoft.Json;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
-using Newtonsoft.Json.Serialization;
-using Newtonsoft.Json.Linq;
-using ColorControl;
-using ColorControl.Common;
namespace LgTv
{
@@ -19,7 +18,7 @@ namespace LgTv
}
}
-
+
public class LgTvApiCore : IDisposable
{
public bool ConnectionClosed { get; private set; }
@@ -58,30 +57,6 @@ namespace LgTv
{
return false;
}
-
- //using (var cancellationTokenSource = new CancellationTokenSource(5000))
- //{
- // var connectTask = _connection.ConnectAsync(uri).AsTask(cancellationTokenSource.Token);
- // var result = await connectTask.ContinueWith((antecedent) =>
- // {
- // if (antecedent.Status == TaskStatus.RanToCompletion)
- // {
- // // connectTask ran to completion, so we know that the MessageWebSocket is connected.
- // // Add additional code here to use the MessageWebSocket.
- // IsConnected?.Invoke(true);
-
- // _messageWriter = new DataWriter(_connection.OutputStream);
- // return true;
- // }
- // else
- // {
- // // connectTask timed out, or faulted.
- // return false;
- // }
- // });
-
- // return result;
- //}
}
catch (Exception e)
{
@@ -145,9 +120,8 @@ namespace LgTv
{
throw new Exception("Connection closed");
}
- var result = await taskSource.Task.ConfigureAwait(false);
- return result;
+ return await taskSource.Task;
}
catch (Exception e)
{