diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj
index af8ce9f..df4d882 100644
--- a/ColorControl/ColorControl.csproj
+++ b/ColorControl/ColorControl.csproj
@@ -27,7 +27,7 @@
ColorControl
Maassoft
0
- 1.1.0.%2a
+ 1.2.0.0
false
true
true
diff --git a/ColorControl/Config.cs b/ColorControl/Config.cs
index a33af3d..828037b 100644
--- a/ColorControl/Config.cs
+++ b/ColorControl/Config.cs
@@ -4,6 +4,8 @@
{
public bool StartMinimized { get; set; }
+ public bool MinimizeOnClose { get; set; }
+
public int DisplaySettingsDelay { get; set; }
public string ScreenSaverShortcut { get; set; }
diff --git a/ColorControl/LgService.cs b/ColorControl/LgService.cs
index 71bea36..f5e2afc 100644
--- a/ColorControl/LgService.cs
+++ b/ColorControl/LgService.cs
@@ -132,7 +132,7 @@ namespace ColorControl
return false;
}
- if (reconnect || _lgTvApi == null || !string.Equals(_lgTvApi.GetIpAddress(), SelectedDevice.IpAddress))
+ if (reconnect || _lgTvApi == null || _lgTvApi.ConnectionClosed || !string.Equals(_lgTvApi.GetIpAddress(), SelectedDevice.IpAddress))
{
if (!await ConnectToSelectedDevice())
{
@@ -146,40 +146,64 @@ namespace ColorControl
public async Task ApplyPreset(LgPreset preset, bool reconnect = false)
{
- if (!await Connected(reconnect))
- {
- return false;
- }
-
var hasApp = !string.IsNullOrEmpty(preset.appId);
- if (hasApp)
+ for (var tries = 0; tries <= 1; tries++)
{
- await _lgTvApi.LaunchApp(preset.appId);
-
- if (_justWokeUp)
+ if (!await Connected(reconnect || tries == 1))
{
- _justWokeUp = false;
- await Task.Delay(500);
- }
- }
-
- if (preset.steps.Any())
- {
- if (hasApp)
- {
- await Task.Delay(1500);
- }
- try
- {
- await ExecuteSteps(_lgTvApi, preset);
- }
- catch (Exception ex)
- {
- string logMessage = ex.ToLogString(Environment.StackTrace);
- Logger.Error("Error while executing steps: " + logMessage);
return false;
}
+
+ if (hasApp)
+ {
+ try
+ {
+ await _lgTvApi.LaunchApp(preset.appId);
+ }
+ catch (Exception ex)
+ {
+ string logMessage = ex.ToLogString(Environment.StackTrace);
+ Logger.Error("Error while launching app: " + logMessage);
+
+ if (tries == 0)
+ {
+ continue;
+ }
+ return false;
+ }
+
+ if (_justWokeUp)
+ {
+ _justWokeUp = false;
+ await Task.Delay(1000);
+ }
+ }
+
+ if (preset.steps.Any())
+ {
+ if (hasApp)
+ {
+ await Task.Delay(1500);
+ }
+ try
+ {
+ await ExecuteSteps(_lgTvApi, preset);
+ }
+ catch (Exception ex)
+ {
+ string logMessage = ex.ToLogString(Environment.StackTrace);
+ Logger.Error("Error while executing steps: " + logMessage);
+
+ if (tries == 0)
+ {
+ continue;
+ }
+ return false;
+ }
+ }
+
+ return true;
}
return true;
@@ -227,8 +251,13 @@ namespace ColorControl
return null;
}
- var api = await LgTvApi.CreateLgTvApi(SelectedDevice.IpAddress);
- var list = await api.GetApps(force);
+ if (!await Connected(force))
+ {
+ Logger.Debug("Cannot refresh apps: no connection could be made");
+ return null;
+ }
+
+ var list = await _lgTvApi.GetApps(force);
return list.ToList();
}
diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs
index 54d2c33..c0c7df1 100644
--- a/ColorControl/MainForm.Designer.cs
+++ b/ColorControl/MainForm.Designer.cs
@@ -98,6 +98,7 @@
this.edtDelayDisplaySettings = new System.Windows.Forms.NumericUpDown();
this.label6 = new System.Windows.Forms.Label();
this.grpGeneralOptions = new System.Windows.Forms.GroupBox();
+ this.chkMinimizeOnClose = new System.Windows.Forms.CheckBox();
this.chkStartMinimized = new System.Windows.Forms.CheckBox();
this.chkStartAfterLogin = new System.Windows.Forms.CheckBox();
this.tabLog = new System.Windows.Forms.TabPage();
@@ -722,7 +723,7 @@
this.grpMiscellaneousOptions.Controls.Add(this.edtBlankScreenSaverShortcut);
this.grpMiscellaneousOptions.Controls.Add(this.label10);
this.grpMiscellaneousOptions.Controls.Add(this.chkFixChromeFonts);
- this.grpMiscellaneousOptions.Location = new System.Drawing.Point(6, 275);
+ this.grpMiscellaneousOptions.Location = new System.Drawing.Point(6, 309);
this.grpMiscellaneousOptions.Name = "grpMiscellaneousOptions";
this.grpMiscellaneousOptions.Size = new System.Drawing.Size(400, 130);
this.grpMiscellaneousOptions.TabIndex = 5;
@@ -784,7 +785,7 @@
this.grpLGOptions.Controls.Add(this.label9);
this.grpLGOptions.Controls.Add(this.edtLgPowerOnAfterResumeDelay);
this.grpLGOptions.Controls.Add(this.label8);
- this.grpLGOptions.Location = new System.Drawing.Point(6, 162);
+ this.grpLGOptions.Location = new System.Drawing.Point(6, 196);
this.grpLGOptions.Name = "grpLGOptions";
this.grpLGOptions.Size = new System.Drawing.Size(403, 107);
this.grpLGOptions.TabIndex = 4;
@@ -843,7 +844,7 @@
//
this.grpHDROptions.Controls.Add(this.edtDelayDisplaySettings);
this.grpHDROptions.Controls.Add(this.label6);
- this.grpHDROptions.Location = new System.Drawing.Point(6, 84);
+ this.grpHDROptions.Location = new System.Drawing.Point(6, 118);
this.grpHDROptions.Name = "grpHDROptions";
this.grpHDROptions.Size = new System.Drawing.Size(400, 72);
this.grpHDROptions.TabIndex = 3;
@@ -881,15 +882,27 @@
//
// grpGeneralOptions
//
+ this.grpGeneralOptions.Controls.Add(this.chkMinimizeOnClose);
this.grpGeneralOptions.Controls.Add(this.chkStartMinimized);
this.grpGeneralOptions.Controls.Add(this.chkStartAfterLogin);
this.grpGeneralOptions.Location = new System.Drawing.Point(6, 6);
this.grpGeneralOptions.Name = "grpGeneralOptions";
- this.grpGeneralOptions.Size = new System.Drawing.Size(400, 72);
+ this.grpGeneralOptions.Size = new System.Drawing.Size(400, 106);
this.grpGeneralOptions.TabIndex = 2;
this.grpGeneralOptions.TabStop = false;
this.grpGeneralOptions.Text = "General";
//
+ // chkMinimizeOnClose
+ //
+ this.chkMinimizeOnClose.AutoSize = true;
+ this.chkMinimizeOnClose.Location = new System.Drawing.Point(6, 65);
+ this.chkMinimizeOnClose.Name = "chkMinimizeOnClose";
+ this.chkMinimizeOnClose.Size = new System.Drawing.Size(109, 17);
+ this.chkMinimizeOnClose.TabIndex = 4;
+ this.chkMinimizeOnClose.Text = "Minimize on close";
+ this.chkMinimizeOnClose.UseVisualStyleBackColor = true;
+ this.chkMinimizeOnClose.CheckedChanged += new System.EventHandler(this.chkMinimizeOnClose_CheckedChanged);
+ //
// chkStartMinimized
//
this.chkStartMinimized.AutoSize = true;
@@ -1032,6 +1045,7 @@
this.MinimumSize = new System.Drawing.Size(800, 398);
this.Name = "MainForm";
this.Text = "ColorControl";
+ this.Activated += new System.EventHandler(this.MainForm_Activated);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed);
this.Load += new System.EventHandler(this.MainForm_Load);
@@ -1146,6 +1160,7 @@
private System.Windows.Forms.Button btnSetShortcutScreenSaver;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.TextBox edtBlankScreenSaverShortcut;
+ private System.Windows.Forms.CheckBox chkMinimizeOnClose;
}
}
diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs
index 19cd48f..c922e3e 100644
--- a/ColorControl/MainForm.cs
+++ b/ColorControl/MainForm.cs
@@ -45,6 +45,8 @@ namespace ColorControl
private static int WM_HOTKEY = 0x0312;
private static string TS_TASKNAME = "ColorControl";
private static bool SystemShutdown = false;
+ private static bool EndSession = false;
+ private static bool UserExit = false;
private static int SHORTCUTID_SCREENSAVER = -100;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
@@ -119,6 +121,14 @@ namespace ColorControl
var converter = new ColorDataConverter();
_JsonDeserializer.RegisterConverters(new[] { converter });
+ try
+ {
+ _nvService = new NvService();
+ }
+ catch (Exception)
+ {
+ }
+
_nvPresetsFilename = Path.Combine(_dataDir, "NvPresets.json");
FillNvPresets();
@@ -140,13 +150,6 @@ namespace ColorControl
_configFilename = Path.Combine(_dataDir, "Settings.json");
LoadConfig();
- try
- {
- _nvService = new NvService();
- }
- catch (Exception)
- {
- }
try
{
_lgService = new LgService(_dataDir, StartUpParams.RunningFromScheduledTask);
@@ -268,6 +271,7 @@ namespace ColorControl
void Exit(object sender, EventArgs e)
{
+ UserExit = true;
Close();
}
@@ -329,6 +333,8 @@ namespace ColorControl
}
+ UpdateDisplayInfoItems();
+
foreach (var preset in _presets)
{
AddOrUpdateItem(preset);
@@ -338,6 +344,79 @@ namespace ColorControl
//UpdateTrayMenuNv();
}
+ private void UpdateDisplayInfoItems()
+ {
+ if (_nvService == null)
+ {
+ return;
+ }
+
+ var displays = _nvService.GetDisplays();
+ foreach (var display in displays)
+ {
+ var id = Math.Abs((int)display.Handle.MemoryAddress.ToInt64());
+
+ ListViewItem item = null;
+ for (var i = 0; i < lvNvPresets.Items.Count; i++)
+ {
+ item = lvNvPresets.Items[i];
+
+ if (item.Tag == null && item.ImageIndex == id)
+ {
+ break;
+ }
+ item = null;
+ }
+
+ if (item == null)
+ {
+ item = lvNvPresets.Items.Add(display.Name);
+ item.ImageIndex = id;
+ item.Font = new Font(item.Font, item.Font.Style | FontStyle.Bold);
+ item.BackColor = Color.LightGray;
+ }
+
+ var values = new List();
+
+ var name = display.Name;
+
+ var screen = Screen.AllScreens.FirstOrDefault(x => x.DeviceName.Equals(name));
+ if (screen != null)
+ {
+ name += " (" + screen.DeviceFriendlyName() + ")";
+ }
+
+ values.Add(name);
+
+ var colorData = display.DisplayDevice.CurrentColorData;
+ var colorSettings = string.Format("{0}, {1}, {2}, {3}", colorData.ColorDepth, colorData.ColorFormat, colorData.DynamicRange, colorData.Colorimetry);
+
+ values.Add(colorSettings);
+
+ var refreshRate = display.DisplayDevice.CurrentTiming.Extra.RefreshRate;
+
+ values.Add($"{refreshRate}Hz");
+
+ //values.Add(_nvService.GetDithering() ? "Yes" : "No");
+ values.Add(string.Empty);
+
+ values.Add(_nvService.IsHDREnabled() ? "Yes" : "No");
+
+ item.Text = values[0];
+ for (var i = 1; i < values.Count; i++)
+ {
+ if (item.SubItems.Count - 1 >= i)
+ {
+ item.SubItems[i].Text = values[i];
+ }
+ else
+ {
+ item.SubItems.Add(values[i]);
+ }
+ }
+ }
+ }
+
private void RegisterShortcut(int id, string shortcut, bool clear = false)
{
if (clear)
@@ -392,6 +471,14 @@ namespace ColorControl
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
+ if (!(SystemShutdown || EndSession || UserExit) && _config.MinimizeOnClose)
+ {
+ e.Cancel = true;
+ WindowState = FormWindowState.Minimized;
+ UserExit = false;
+ return;
+ }
+
SaveNvPresets();
SaveLgPresets();
@@ -430,14 +517,11 @@ namespace ColorControl
File.WriteAllText(_lgPresetsFilename, json);
}
- private void button1_Click_1(object sender, EventArgs e)
- {
-
- }
-
private void lvNvPresets_SelectedIndexChanged(object sender, EventArgs e)
{
- var enabled = lvNvPresets.SelectedItems.Count > 0;
+ var preset = GetSelectedNvPreset();
+ var enabled = preset != null;
+
btnApply.Enabled = enabled;
btnChange.Enabled = enabled;
edtShortcut.Enabled = enabled;
@@ -445,7 +529,6 @@ namespace ColorControl
btnClone.Enabled = enabled;
btnNvPresetDelete.Enabled = enabled;
- var preset = GetSelectedNvPreset();
if (preset != null)
{
edtShortcut.Text = preset.shortcut;
@@ -496,6 +579,10 @@ namespace ColorControl
{
SystemShutdown = true;
}
+ else if (m.Msg == NativeConstants.WM_ENDSESSION)
+ {
+ EndSession = true;
+ }
base.WndProc(ref m);
}
@@ -652,6 +739,7 @@ namespace ColorControl
}
chkStartMinimized.Checked = _config.StartMinimized;
+ chkMinimizeOnClose.Checked = _config.MinimizeOnClose;
edtDelayDisplaySettings.Value = _config.DisplaySettingsDelay;
edtBlankScreenSaverShortcut.Text = _config.ScreenSaverShortcut;
@@ -820,6 +908,7 @@ namespace ColorControl
miNvApply.Enabled = preset != null;
mnuNvDisplay.Enabled = preset != null;
miNvPresetColorSettings.Enabled = preset != null;
+ mnuNvPresetsColorSettings.Enabled = preset != null;
mnuRefreshRate.Enabled = preset != null;
miNvPresetDithering.Enabled = preset != null;
miNvHDR.Enabled = preset != null;
@@ -1511,6 +1600,8 @@ namespace ColorControl
{
throw new Exception("Error while applying NVIDIA preset");
}
+
+ UpdateDisplayInfoItems();
}
catch (Exception e)
{
@@ -1674,7 +1765,7 @@ See Options to test this functionality."
);
}
- this.BeginInvoke(new Action(() =>
+ BeginInvoke(new Action(() =>
{
_lgService.Config.PowerOnAfterStartup = clbLgPower.GetItemChecked(0);
_lgService.Config.PowerOnAfterResume = clbLgPower.GetItemChecked(1);
@@ -1742,5 +1833,15 @@ Do you want to continue?";
RegisterShortcut(SHORTCUTID_SCREENSAVER, shortcut, clear);
}
+
+ private void chkMinimizeOnClose_CheckedChanged(object sender, EventArgs e)
+ {
+ _config.MinimizeOnClose = chkMinimizeOnClose.Checked;
+ }
+
+ private void MainForm_Activated(object sender, EventArgs e)
+ {
+ UpdateDisplayInfoItems();
+ }
}
}
\ No newline at end of file
diff --git a/ColorControl/NvPreset.cs b/ColorControl/NvPreset.cs
index aa64bbe..9fc09ce 100644
--- a/ColorControl/NvPreset.cs
+++ b/ColorControl/NvPreset.cs
@@ -69,7 +69,7 @@ namespace ColorControl
public static string[] GetColumnNames()
{
//return new[] { "BPC", "Format", "Dynamic range", "Toggle HDR", "Shortcut" };
- return new[] { "Display|80", "Color settings (BPC, format, dyn. range, color space)|260", "Refresh rate|100", "Dithering", "HDR", "Shortcut" };
+ return new[] { "Display|140", "Color settings (BPC, format, dyn. range, color space)|260", "Refresh rate|100", "Dithering", "HDR", "Shortcut" };
}
public List GetDisplayValues()
diff --git a/ColorControl/NvService.cs b/ColorControl/NvService.cs
index e9b682d..ad9551e 100644
--- a/ColorControl/NvService.cs
+++ b/ColorControl/NvService.cs
@@ -1,9 +1,6 @@
using NvAPIWrapper;
using NvAPIWrapper.Display;
-using NvAPIWrapper.Native;
using NvAPIWrapper.Native.Display;
-using NvAPIWrapper.Native.Display.Structures;
-using NvAPIWrapper.Native.Exceptions;
using NvAPIWrapper.Native.GPU.Structures;
using NWin32;
using NWin32.NativeTypes;
@@ -39,6 +36,20 @@ namespace ColorControl
[In] uint mode
);
+ public delegate long NvAPI_Disp_GetDitherControl(
+ [In] PhysicalGPUHandle physicalGpu,
+ [Out] uint OutputId,
+ [In] [Out] IntPtr ditherControl);
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct NV_GPU_DITHER_CONTROL_V1
+ {
+ public int version;
+ public uint state;
+ public uint bits;
+ public uint mode;
+ };
+
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
private Display _currentDisplay;
@@ -149,6 +160,37 @@ namespace ColorControl
}
}
+ public bool GetDithering()
+ {
+ var ptr = NvAPI64_QueryInterface(0x932AC8FB);
+ if (ptr != IntPtr.Zero)
+ {
+ var delegateValue = Marshal.GetDelegateForFunctionPointer(ptr, typeof(NvAPI_Disp_GetDitherControl)) as NvAPI_Disp_GetDitherControl;
+
+ var displayDevice = GetCurrentDisplay().DisplayDevice;
+
+ var gpuHandle = displayDevice.PhysicalGPU.Handle;
+ var displayId = displayDevice.DisplayId;
+
+ NV_GPU_DITHER_CONTROL_V1 info = new NV_GPU_DITHER_CONTROL_V1();
+ info.version = 1;
+ IntPtr bla = Marshal.AllocHGlobal(Marshal.SizeOf(info));
+ Marshal.StructureToPtr(info, bla, false);
+
+ // Does not work yet...What is the exact interface of NvAPI_Disp_GetDitherControl?
+
+ //var result = delegateValue(gpuHandle, displayId, bla);
+ //if (result != 0)
+ //{
+ // Logger.Error($"Could not get dithering because NvAPI_Disp_GetDitherControl returned a non-zero return code: {result}");
+ //}
+
+ return info.state == 1;
+ }
+
+ return false;
+ }
+
public bool SetRefreshRate(uint refreshRate)
{
var display = GetCurrentDisplay();
diff --git a/ColorControl/Properties/AssemblyInfo.cs b/ColorControl/Properties/AssemblyInfo.cs
index 316cf9e..7f2619d 100644
--- a/ColorControl/Properties/AssemblyInfo.cs
+++ b/ColorControl/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.1.0.0")]
-[assembly: AssemblyFileVersion("1.1.0.0")]
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/ColorControl/WOL.cs b/ColorControl/WOL.cs
index e981f7e..97ae727 100644
--- a/ColorControl/WOL.cs
+++ b/ColorControl/WOL.cs
@@ -32,13 +32,13 @@ namespace ColorControl
foreach (var device in devices)
{
- if (device is NpcapDevice npcapDevice)
- {
- if (!npcapDevice.Interface.GatewayAddresses.Any())
- {
- continue;
- }
- }
+ //if (device is NpcapDevice npcapDevice)
+ //{
+ // if (!npcapDevice.Interface.GatewayAddresses.Any())
+ // {
+ // continue;
+ // }
+ //}
Logger.Debug("Opening network device: " + device.Name);
diff --git a/ColorControl/lgtv/LgTvApi.cs b/ColorControl/lgtv/LgTvApi.cs
index cf17c4e..8b3aefc 100644
--- a/ColorControl/lgtv/LgTvApi.cs
+++ b/ColorControl/lgtv/LgTvApi.cs
@@ -21,6 +21,8 @@ namespace LgTv
}
public class LgTvApi:IDisposable
{
+ public bool ConnectionClosed { get => _connection == null || _connection.ConnectionClosed; }
+
private readonly LgTvApiCore _connection;
private LgWebOsMouseService _mouseConnection;
@@ -61,7 +63,7 @@ namespace LgTv
return null;
}
- public LgTvApi(string ip, LgTvApiCore connection, ClientKeyStore keyStore)
+ private LgTvApi(string ip, LgTvApiCore connection, ClientKeyStore keyStore)
{
webSocketUri = "ws://" + ip + ":3000";
_ip = ip;
@@ -92,7 +94,6 @@ namespace LgTv
public async Task Connect()
{
-
var ctx = _connection.Connect(new Uri(webSocketUri));
return await ctx;
}
diff --git a/ColorControl/lgtv/LgTvConnection.cs b/ColorControl/lgtv/LgTvConnection.cs
index c4485e3..ecfa61b 100644
--- a/ColorControl/lgtv/LgTvConnection.cs
+++ b/ColorControl/lgtv/LgTvConnection.cs
@@ -23,6 +23,8 @@ namespace LgTv
public class LgTvApiCore : IDisposable
{
+ public bool ConnectionClosed { get; private set; }
+
private MessageWebSocket _connection;
private DataWriter _messageWriter;
private int _commandCount;
@@ -37,6 +39,7 @@ namespace LgTv
{
try
{
+ ConnectionClosed = false;
_commandCount = 0;
_connection = new MessageWebSocket();
_connection.Control.MessageType = SocketMessageType.Utf8;
@@ -66,11 +69,21 @@ namespace LgTv
}
}
+
public async void SendMessageAsync(string message)
{
- _messageWriter.WriteString(message);
- await _messageWriter.StoreAsync();
+ try
+ {
+ _messageWriter.WriteString(message);
+ await _messageWriter.StoreAsync();
+ }
+ catch (Exception e)
+ {
+ ConnectionClosed = true;
+ _messageWriter?.Dispose();
+ }
}
+
public Task SendCommandAsync(string message)
{
var obj = JsonConvert.DeserializeObject(message);
@@ -84,16 +97,18 @@ namespace LgTv
var taskSource = new TaskCompletionSource();
_tokens.TryAdd(id, taskSource);
SendMessageAsync(message);
+ if (ConnectionClosed)
+ {
+ throw new Exception("Connection closed");
+ }
return taskSource.Task;
}
catch (Exception e)
{
throw new SendMessageException("Can't send message", e);
}
-
}
-
public Task SendCommandAsync(RequestMessage message)
{
var rawMessage = new RawRequestMessage(message, ++_commandCount);
@@ -109,6 +124,7 @@ namespace LgTv
{
MessageWebSocket webSocket = Interlocked.Exchange(ref _connection, null);
webSocket?.Dispose();
+ ConnectionClosed = true;
}
private void Connection_MessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args)