|
@@ -3,6 +3,7 @@ using System.ComponentModel;
|
|
|
using System.Runtime.InteropServices;
|
|
|
using System.Threading;
|
|
|
using MediaBrowser.Controller.Power;
|
|
|
+using MediaBrowser.Model.Logging;
|
|
|
using Microsoft.Win32.SafeHandles;
|
|
|
|
|
|
namespace MediaBrowser.ServerApplication.Native
|
|
@@ -10,31 +11,83 @@ namespace MediaBrowser.ServerApplication.Native
|
|
|
public class WindowsPowerManagement : IPowerManagement
|
|
|
{
|
|
|
[DllImport("kernel32.dll")]
|
|
|
- public static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName);
|
|
|
+ public static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes,
|
|
|
+ bool bManualReset,
|
|
|
+ string lpTimerName);
|
|
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
|
- public static extern bool SetWaitableTimer(SafeWaitHandle hTimer, [In] ref long pDueTime, int lPeriod, IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, bool fResume);
|
|
|
+ public static extern bool SetWaitableTimer(SafeWaitHandle hTimer,
|
|
|
+ [In] ref long pDueTime,
|
|
|
+ int lPeriod,
|
|
|
+ IntPtr pfnCompletionRoutine,
|
|
|
+ IntPtr lpArgToCompletionRoutine,
|
|
|
+ bool fResume);
|
|
|
+
|
|
|
+ private BackgroundWorker _bgWorker;
|
|
|
+ private readonly ILogger _logger;
|
|
|
+ private readonly object _initLock = new object();
|
|
|
+
|
|
|
+ public WindowsPowerManagement(ILogger logger)
|
|
|
+ {
|
|
|
+ _logger = logger;
|
|
|
+ }
|
|
|
|
|
|
public void ScheduleWake(DateTime utcTime)
|
|
|
{
|
|
|
- long duetime = utcTime.ToFileTime();
|
|
|
+ Initialize();
|
|
|
+ _bgWorker.RunWorkerAsync(utcTime.ToFileTime());
|
|
|
+ }
|
|
|
|
|
|
- using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, "MyWaitabletimer"))
|
|
|
+ private void Initialize()
|
|
|
+ {
|
|
|
+ lock (_initLock)
|
|
|
{
|
|
|
- if (SetWaitableTimer(handle, ref duetime, 0, IntPtr.Zero, IntPtr.Zero, true))
|
|
|
+ if (_bgWorker == null)
|
|
|
{
|
|
|
- using (EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset))
|
|
|
- {
|
|
|
- wh.SafeWaitHandle = handle;
|
|
|
- wh.WaitOne();
|
|
|
- }
|
|
|
+ _bgWorker = new BackgroundWorker();
|
|
|
+
|
|
|
+ _bgWorker.DoWork += bgWorker_DoWork;
|
|
|
+ _bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;
|
|
|
}
|
|
|
- else
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
|
+ {
|
|
|
+ //if (Woken != null)
|
|
|
+ //{
|
|
|
+ // Woken(this, new EventArgs());
|
|
|
+ //}
|
|
|
+ }
|
|
|
+
|
|
|
+ private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ long waketime = (long)e.Argument;
|
|
|
+
|
|
|
+ using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, GetType().Assembly.GetName().Name + "Timer"))
|
|
|
{
|
|
|
- throw new Win32Exception(Marshal.GetLastWin32Error());
|
|
|
+ if (SetWaitableTimer(handle, ref waketime, 0, IntPtr.Zero, IntPtr.Zero, true))
|
|
|
+ {
|
|
|
+ using (EventWaitHandle wh = new EventWaitHandle(false,
|
|
|
+ EventResetMode.AutoReset))
|
|
|
+ {
|
|
|
+ wh.SafeWaitHandle = handle;
|
|
|
+ wh.WaitOne();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new Win32Exception(Marshal.GetLastWin32Error());
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ _logger.ErrorException("Error scheduling wake timer", ex);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|