diff --git a/Mamesaver/BlankScreen.cs b/Mamesaver/BlankScreen.cs
index 69dea49..52cddf6 100644
--- a/Mamesaver/BlankScreen.cs
+++ b/Mamesaver/BlankScreen.cs
@@ -10,7 +10,7 @@
namespace Mamesaver
{
- internal class BlankScreen
+ internal class BlankScreen : IDisposable
{
private readonly PowerManager _powerManager;
public BackgroundForm BackgroundForm { get; }
@@ -96,5 +96,21 @@ private void ReleaseDeviceContext()
Log.Error(ex, "Error releasing device context for {screen}", Screen.DeviceName);
}
}
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing) return;
+
+ _powerManager?.Dispose();
+ BackgroundForm?.Dispose();
+ }
+
+ ~BlankScreen() => Dispose(false);
}
}
\ No newline at end of file
diff --git a/Mamesaver/CaptureScreen.cs b/Mamesaver/CaptureScreen.cs
index 5dbe190..b20d39f 100644
--- a/Mamesaver/CaptureScreen.cs
+++ b/Mamesaver/CaptureScreen.cs
@@ -33,7 +33,7 @@ public void Dispose()
GC.SuppressFinalize(this);
}
- public virtual void Dispose(bool disposing) => ReleaseUnmanagedResources();
+ protected virtual void Dispose(bool disposing) => ReleaseUnmanagedResources();
~CaptureScreen() => Dispose(false);
private void ReleaseUnmanagedResources()
diff --git a/Mamesaver/GamePlayManager.cs b/Mamesaver/GamePlayManager.cs
index 79a7c4f..d8c3e81 100644
--- a/Mamesaver/GamePlayManager.cs
+++ b/Mamesaver/GamePlayManager.cs
@@ -26,9 +26,9 @@ internal class GamePlayManager : IDisposable
private readonly PowerManager _powerManager;
private readonly MameInvoker _invoker;
- public delegate void PlayGameEventHandler(object sender, EventArgs args);
- public delegate void StartGameEventHandler(object sender, EventArgs args);
- public delegate void GameStartedEventHandler(object sender, EventArgs args);
+ public delegate void PlayGameEventHandler(object sender, EventArgs e);
+ public delegate void StartGameEventHandler(object sender, EventArgs e);
+ public delegate void GameStartedEventHandler(object sender, EventArgs e);
///
/// Game has been started by MAME.
@@ -139,7 +139,7 @@ private void PreviousGame()
}
///
- /// Deselects a game, saving configuration and playing the next game
+ /// Deselects a game, saving configuration and playing the next game.
///
private void DeselectGame(Game game)
{
diff --git a/Mamesaver/MameScreen.cs b/Mamesaver/MameScreen.cs
index 10d1541..140e03d 100644
--- a/Mamesaver/MameScreen.cs
+++ b/Mamesaver/MameScreen.cs
@@ -12,7 +12,7 @@ namespace Mamesaver
/// A screen that will launch MAME with a random game from the list. If configured, this screen also handles hotkey events which
/// affect the MAME process.
///
- internal class MameScreen : BlankScreen, IDisposable
+ internal class MameScreen : BlankScreen
{
private readonly Settings _settings;
private readonly GamePlayManager _gamePlayManager;
@@ -163,8 +163,10 @@ private void GameTimerTick(object sender, EventArgs e)
/// Stop the timer, set cancelled flag, close any current process and close the background form.
/// Once this has all been done, the application should end.
///
- public virtual void Dispose(bool disposing)
+ protected override void Dispose(bool disposing)
{
+ base.Dispose(disposing);
+
if (!disposing || !_initialised) return;
Log.Information("Closing primary MAME screen {screen}", Screen.DeviceName);
@@ -187,12 +189,6 @@ private void DisposeTimers()
_gameTimer = _splashTimer = null;
}
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
~MameScreen() => Dispose(false);
}
}
\ No newline at end of file
diff --git a/Mamesaver/Power/PowerEventWatcher.cs b/Mamesaver/Power/PowerEventWatcher.cs
index 1d06f38..3adfd34 100644
--- a/Mamesaver/Power/PowerEventWatcher.cs
+++ b/Mamesaver/Power/PowerEventWatcher.cs
@@ -8,7 +8,7 @@ namespace Mamesaver.Power
/// Listens for power source change events, firing a event
/// if received.
///
- public class PowerEventWatcher
+ public class PowerEventWatcher : IDisposable
{
///
/// Value of event corresponding to a power state change.
@@ -21,7 +21,7 @@ public class PowerEventWatcher
private ManagementEventWatcher _managementEventWatcher;
public event PowerEventHandler PowerStateChanged;
- public delegate void PowerEventHandler(object sender, EventArgs args);
+ public delegate void PowerEventHandler(object sender, EventArgs e);
///
/// Initialises the power event watcher to fire
@@ -51,7 +51,7 @@ private void PowerEventArrived(object sender, EventArrivedEventArgs args)
}
}
- public virtual void Dispose(bool disposing)
+ protected virtual void Dispose(bool disposing)
{
if (!disposing) return;
diff --git a/Mamesaver/Power/PowerManager.cs b/Mamesaver/Power/PowerManager.cs
index bc62715..3c25e05 100644
--- a/Mamesaver/Power/PowerManager.cs
+++ b/Mamesaver/Power/PowerManager.cs
@@ -21,7 +21,7 @@ public class PowerManager : IDisposable
private readonly PowerEventWatcher _eventWatcher;
private Timer _sleepTimer;
- public delegate void SleepTriggerManager(object sender, EventArgs args);
+ public delegate void SleepTriggerManager(object sender, EventArgs e);
///
/// Fired when the screensaver should turn the display to sleep.
@@ -32,7 +32,7 @@ public class PowerManager : IDisposable
/// Time before a event is published, based on the user's power management
/// configuration.
///
- private TimeSpan _sleepTimeout;
+ private TimeSpan? _sleepTimeout;
///
/// Current power source type.
@@ -72,24 +72,43 @@ public void Initialise()
// Identify policy for selected power type
_sleepTimeout = GetSleepTimeout(powerType.Value);
- Log.Information("Connected to {powerType} power; sleeping after {min} minutes",
- powerType.Value.ToString(), _sleepTimeout.TotalMinutes);
-
- // Create a timer which fires once when the display or computer should go to sleep
- _sleepTimer = new Timer { Interval = Math.Min(_sleepTimeout.TotalMilliseconds, int.MaxValue), AutoReset = false };
-
- _sleepTimer.Elapsed += SleepTimerTick;
- _sleepTimer.Start();
+ if (_sleepTimeout == null)
+ {
+ Log.Information("Connected to {powerType} power; no sleep configured", powerType.Value.ToString());
+ }
+ else
+ {
+ // Create a timer which fires once when the display or computer should go to sleep
+ Log.Information("Connected to {powerType} power; sleeping after {min} minutes", powerType.Value.ToString(), _sleepTimeout.Value.TotalMinutes);
+ InitSleepTimer();
+ }
// Receive notifications for power state changes so the timer can be updated
_eventWatcher.Initialise();
_eventWatcher.PowerStateChanged += PowerStateChanged;
}
+ ///
+ /// Either creates or updates the sleep timer.
+ ///
+ private void InitSleepTimer()
+ {
+ if (_sleepTimeout == null) throw new InvalidOperationException("Can't create a timer with no timeout specified");
+
+ if (_sleepTimer == null)
+ {
+ _sleepTimer = new Timer { AutoReset = false };
+ _sleepTimer.Elapsed += SleepTimerTick;
+ }
+
+ _sleepTimer.Interval = (int)_sleepTimeout.Value.TotalMilliseconds;
+ _sleepTimer.Start();
+ }
+
///
/// Returns the lowest of screen and PC sleep settings for a given power type.
///
- private static TimeSpan GetSleepTimeout(PowerType powerType)
+ private static TimeSpan? GetSleepTimeout(PowerType powerType)
{
var powerPolicy = PowerInterop.GetPowerPolicy(powerType);
return new[] { powerPolicy.VideoTimeout, powerPolicy.IdleTimeout }.Min();
@@ -119,16 +138,20 @@ private void PowerStateChanged(object sender, EventArgs args)
if (_currentPowerType == powerType) return;
_currentPowerType = powerType.Value;
+ _sleepTimer?.Stop();
+
// Identify policy for selected power type
_sleepTimeout = GetSleepTimeout(powerType.Value);
- Log.Information("Power changed to {powerType} power; sleeping after {min} minutes",
- powerType.Value.ToString(), _sleepTimeout.TotalMinutes);
-
- // Update sleep timer on power state change due to different sleep configurations
- _sleepTimer.Interval = Math.Min(_sleepTimeout.TotalMilliseconds, int.MaxValue);
-
- _sleepTimer.Stop();
- _sleepTimer.Start();
+ if (_sleepTimeout == null)
+ {
+ Log.Information("Power changed to {powerType} power; no sleep configured", powerType.Value.ToString());
+ }
+ else
+ {
+ // Update sleep timer on power state change due to different sleep configurations
+ Log.Information("Power changed to {powerType} power; sleeping after {min} minutes", powerType.Value.ToString(), _sleepTimeout.Value.TotalMinutes);
+ InitSleepTimer();
+ }
}
///
@@ -142,7 +165,7 @@ public void Dispose()
GC.SuppressFinalize(this);
}
- public virtual void Dispose(bool disposing)
+ protected virtual void Dispose(bool disposing)
{
if (!disposing) return;
_sleepTimer?.Dispose();
diff --git a/Mamesaver/Windows/PlatformInvokeGDI32.cs b/Mamesaver/Windows/PlatformInvokeGDI32.cs
index 10aba38..bb0b2e1 100644
--- a/Mamesaver/Windows/PlatformInvokeGDI32.cs
+++ b/Mamesaver/Windows/PlatformInvokeGDI32.cs
@@ -4,38 +4,38 @@
namespace Mamesaver.Windows
{
- public class PlatformInvokeGdi32
+ internal class PlatformInvokeGdi32
{
- public const int SRCOPY = 13369376;
+ internal const int SRCOPY = 13369376;
[DllImport("gdi32.dll", EntryPoint = "DeleteDC")]
- public static extern IntPtr DeleteDC(IntPtr hDc);
+ internal static extern IntPtr DeleteDC(IntPtr hDc);
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
- public static extern IntPtr DeleteObject(IntPtr hDc);
+ internal static extern IntPtr DeleteObject(IntPtr hDc);
[DllImport("gdi32.dll", EntryPoint = "BitBlt")]
- public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int rasterOp);
+ internal static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int rasterOp);
[DllImport("gdi32.dll", EntryPoint = "StretchBlt")]
- public static extern bool StretchBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int wSrc, int hSrc, int RasterOp);
+ internal static extern bool StretchBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, int wSrc, int hSrc, int RasterOp);
[DllImport("gdi32.dll")]
- public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
+ internal static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll")]
- public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
+ internal static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
[DllImport("gdi32.dll", EntryPoint = "SelectObject")]
- public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
+ internal static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
- public static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
+ internal static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
///
/// DeviceCap - Device capabilities
///
- public enum DeviceCap
+ internal enum DeviceCap
{
///
/// Logical pixels inch in X
diff --git a/Mamesaver/Windows/PlatformInvokeUSER32.cs b/Mamesaver/Windows/PlatformInvokeUSER32.cs
index 4d94ac3..d539329 100644
--- a/Mamesaver/Windows/PlatformInvokeUSER32.cs
+++ b/Mamesaver/Windows/PlatformInvokeUSER32.cs
@@ -4,51 +4,51 @@
namespace Mamesaver.Windows
{
- public class PlatformInvokeUser32
+ internal class PlatformInvokeUser32
{
- public const int SM_CXSCREEN = 0;
- public const int SM_CYSCREEN = 1;
- public const int SW_MINIMIZE = 6;
+ internal const int SM_CXSCREEN = 0;
+ internal const int SM_CYSCREEN = 1;
+ internal const int SW_MINIMIZE = 6;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
+ internal static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
[DllImport("user32.dll")]
- public static extern void SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
+ internal static extern void SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
- public static extern IntPtr GetDesktopWindow();
+ internal static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", EntryPoint = "GetDC")]
- public static extern IntPtr GetDC(IntPtr ptr);
+ internal static extern IntPtr GetDC(IntPtr ptr);
[DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
- public static extern int GetSystemMetrics(int abc);
+ internal static extern int GetSystemMetrics(int abc);
[DllImport("user32.dll", EntryPoint = "GetWindowDC")]
- public static extern IntPtr GetWindowDC(Int32 ptr);
+ internal static extern IntPtr GetWindowDC(Int32 ptr);
[DllImport("user32.dll", EntryPoint = "ReleaseDC")]
- public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
+ internal static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
+ internal static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+ internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[StructLayout(LayoutKind.Sequential)]
- public struct RECT
+ internal struct RECT
{
- public int Left; // x position of upper-left corner
- public int Top; // y position of upper-left corner
- public int Right; // x position of lower-right corner
- public int Bottom; // y position of lower-right corner
+ internal int Left; // x position of upper-left corner
+ internal int Top; // y position of upper-left corner
+ internal int Right; // x position of lower-right corner
+ internal int Bottom; // y position of lower-right corner
}
[DllImport("user32.dll")]
- public static extern bool SetProcessDPIAware();
+ internal static extern bool SetProcessDPIAware();
}
}
diff --git a/Mamesaver/Windows/PowerInterop.cs b/Mamesaver/Windows/PowerInterop.cs
index af23e4f..7eb333f 100644
--- a/Mamesaver/Windows/PowerInterop.cs
+++ b/Mamesaver/Windows/PowerInterop.cs
@@ -37,10 +37,10 @@ public static PowerPolicy GetPowerPolicy(PowerType powerType)
{
IdleTimeout =
userPolicy.IdleTimeoutAc == 0 || userPolicy.IdleAc.Action == POWER_ACTION.PowerActionNone
- ? TimeSpan.MaxValue
+ ? (TimeSpan?)null
: TimeSpan.FromSeconds(userPolicy.IdleTimeoutAc),
VideoTimeout = userPolicy.VideoTimeoutAc == 0
- ? TimeSpan.MaxValue
+ ? (TimeSpan?)null
: TimeSpan.FromSeconds(userPolicy.VideoTimeoutAc)
};
case PowerType.DC:
@@ -48,10 +48,10 @@ public static PowerPolicy GetPowerPolicy(PowerType powerType)
{
IdleTimeout =
userPolicy.IdleTimeoutDc == 0 || userPolicy.IdleDc.Action == POWER_ACTION.PowerActionNone
- ? TimeSpan.MaxValue
+ ? (TimeSpan?)null
: TimeSpan.FromSeconds(userPolicy.IdleTimeoutDc),
VideoTimeout = userPolicy.VideoTimeoutDc == 0
- ? TimeSpan.MaxValue
+ ? (TimeSpan?)null
: TimeSpan.FromSeconds(userPolicy.VideoTimeoutDc)
};
default:
@@ -68,7 +68,14 @@ public enum PowerType
public class PowerPolicy
{
- public TimeSpan VideoTimeout { get; set; }
- public TimeSpan IdleTimeout { get; set; }
+ ///
+ /// Timeout for screen to go to sleep, or null if no sleep is specified.
+ ///
+ public TimeSpan? VideoTimeout { get; set; }
+
+ ///
+ /// Timeout for PC to go to sleep, or null if no sleep is specified.
+ ///
+ public TimeSpan? IdleTimeout { get; set; }
}
}
\ No newline at end of file
diff --git a/Mamesaver/Windows/UserActivityHook.cs b/Mamesaver/Windows/UserActivityHook.cs
index 233b6b7..b828907 100644
--- a/Mamesaver/Windows/UserActivityHook.cs
+++ b/Mamesaver/Windows/UserActivityHook.cs
@@ -479,19 +479,20 @@ public UserActivityHook(bool InstallMouseHook, bool InstallKeyboardHook)
Start(InstallMouseHook, InstallKeyboardHook);
}
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- Stop(true, true, false);
- }
- }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposing) return;
+
+ Stop(true, true, false);
+ }
+
+
~UserActivityHook() => Dispose(false);
///