add minimize on close option, fix reconnection issues, send WOL packet to all network interfaces, add current display settings line

This commit is contained in:
Vincent Maas committed 2020-09-05 14:46:31 +02:00
1 parent 840e8a1a71
commit f666a6117b
11 files changed
+276 -70

No files matched your search

+1 -1
View File
@@ -27,7 +27,7 @@
<ProductName>ColorControl</ProductName>
<PublisherName>Maassoft</PublisherName>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.1.0.%2a</ApplicationVersion>
<ApplicationVersion>1.2.0.0</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
+2
View File
@@ -4,6 +4,8 @@
{
public bool StartMinimized { get; set; }
public bool MinimizeOnClose { get; set; }
public int DisplaySettingsDelay { get; set; }
public string ScreenSaverShortcut { get; set; }
+60 -31
View File
@@ -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<bool> 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();
}
+19 -4
View File
@@ -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;
}
}
+116 -15
View File
@@ -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<string>();
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();
}
}
}
+1 -1
View File
@@ -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<string> GetDisplayValues()
+45 -3
View File
@@ -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();
+2 -2
View File
@@ -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")]
+7 -7
View File
@@ -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);
+3 -2
View File
@@ -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<bool> Connect()
{
var ctx = _connection.Connect(new Uri(webSocketUri));
return await ctx;
}
+20 -4
View File
@@ -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<dynamic> SendCommandAsync(string message)
{
var obj = JsonConvert.DeserializeObject<dynamic>(message);
@@ -84,16 +97,18 @@ namespace LgTv
var taskSource = new TaskCompletionSource<dynamic>();
_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<dynamic> 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)