|
|
|
@ -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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|