Skip to content

Commit

Permalink
Merge pull request #30 from nullpainter/feature/bug-fixes
Browse files Browse the repository at this point in the history
Prevented sleep timer creation if no power saving enabled - Better Fix for #29 
Some cleanup of code
  • Loading branch information
mika76 authored Sep 7, 2018
2 parents a795e38 + f47a806 commit 4185518
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 80 deletions.
18 changes: 17 additions & 1 deletion Mamesaver/BlankScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Mamesaver
{
internal class BlankScreen
internal class BlankScreen : IDisposable
{
private readonly PowerManager _powerManager;
public BackgroundForm BackgroundForm { get; }
Expand Down Expand Up @@ -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);
}
}
2 changes: 1 addition & 1 deletion Mamesaver/CaptureScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
8 changes: 4 additions & 4 deletions Mamesaver/GamePlayManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/// <summary>
/// Game has been started by MAME.
Expand Down Expand Up @@ -139,7 +139,7 @@ private void PreviousGame()
}

/// <summary>
/// Deselects a game, saving configuration and playing the next game
/// Deselects a game, saving configuration and playing the next game.
/// </summary>
private void DeselectGame(Game game)
{
Expand Down
12 changes: 4 additions & 8 deletions Mamesaver/MameScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// </summary>
internal class MameScreen : BlankScreen, IDisposable
internal class MameScreen : BlankScreen
{
private readonly Settings _settings;
private readonly GamePlayManager _gamePlayManager;
Expand Down Expand Up @@ -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.
/// </summary>
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);
Expand All @@ -187,12 +189,6 @@ private void DisposeTimers()
_gameTimer = _splashTimer = null;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

~MameScreen() => Dispose(false);
}
}
6 changes: 3 additions & 3 deletions Mamesaver/Power/PowerEventWatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Mamesaver.Power
/// Listens for power source change events, firing a <see cref="PowerStateChanged"/> event
/// if received.
/// </summary>
public class PowerEventWatcher
public class PowerEventWatcher : IDisposable
{
/// <summary>
/// Value of event corresponding to a power state change.
Expand All @@ -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);

/// <summary>
/// Initialises the power event watcher to fire <see cref="PowerStateChanged"/>
Expand Down Expand Up @@ -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;

Expand Down
63 changes: 43 additions & 20 deletions Mamesaver/Power/PowerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/// <summary>
/// Fired when the screensaver should turn the display to sleep.
Expand All @@ -32,7 +32,7 @@ public class PowerManager : IDisposable
/// Time before a <see cref="SleepTriggered"/> event is published, based on the user's power management
/// configuration.
/// </summary>
private TimeSpan _sleepTimeout;
private TimeSpan? _sleepTimeout;

/// <summary>
/// Current power source type.
Expand Down Expand Up @@ -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;
}

/// <summary>
/// Either creates or updates the sleep timer.
/// </summary>
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();
}

/// <summary>
/// Returns the lowest of screen and PC sleep settings for a given power type.
/// </summary>
private static TimeSpan GetSleepTimeout(PowerType powerType)
private static TimeSpan? GetSleepTimeout(PowerType powerType)
{
var powerPolicy = PowerInterop.GetPowerPolicy(powerType);
return new[] { powerPolicy.VideoTimeout, powerPolicy.IdleTimeout }.Min();
Expand Down Expand Up @@ -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();
}
}

/// <summary>
Expand All @@ -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();
Expand Down
22 changes: 11 additions & 11 deletions Mamesaver/Windows/PlatformInvokeGDI32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/// <summary>
/// DeviceCap - Device capabilities
/// </summary>
public enum DeviceCap
internal enum DeviceCap
{
/// <summary>
/// Logical pixels inch in X
Expand Down
38 changes: 19 additions & 19 deletions Mamesaver/Windows/PlatformInvokeUSER32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
19 changes: 13 additions & 6 deletions Mamesaver/Windows/PowerInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,21 @@ 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:
return new PowerPolicy
{
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:
Expand All @@ -68,7 +68,14 @@ public enum PowerType

public class PowerPolicy
{
public TimeSpan VideoTimeout { get; set; }
public TimeSpan IdleTimeout { get; set; }
/// <summary>
/// Timeout for screen to go to sleep, or <c>null</c> if no sleep is specified.
/// </summary>
public TimeSpan? VideoTimeout { get; set; }

/// <summary>
/// Timeout for PC to go to sleep, or <c>null</c> if no sleep is specified.
/// </summary>
public TimeSpan? IdleTimeout { get; set; }
}
}
Loading

0 comments on commit 4185518

Please sign in to comment.