예제 #1
0
 public static void OffIfIdle(int idleTimeMs, bool mute)
 {
     if (LastInput.GetLastInputAgeMs() >= idleTimeMs)
     {
         Off(mute);
     }
 }
예제 #2
0
        private static void PartialWakeLogic(bool mute, int totalInputs = 1, PartialWakeNotifier pwn = null, int iterations = 0)
        {
            double    inputsRequired    = BPMath.Clamp(Program.settings.inputsRequiredToWake, 1, 50);
            const int maxIterations     = 100;
            const int iterationInterval = 100;

            if (totalInputs >= inputsRequired)
            {
                // Input requirements met.  Full Wake.
                if (pwn != null)
                {
                    pwn.Terminate();
                }
            }
            else if (iterations < maxIterations)
            {
                // Waiting for more inputs.
                if (pwn == null)
                {
                    pwn          = new PartialWakeNotifier();
                    pwn.Progress = (int)((totalInputs / inputsRequired) * 100);
                    SetTimeout.OnBackground(() => { Application.Run(pwn); }, 0);
                }
                pwn.SetSecondsRemaining((int)(((maxIterations - iterations) * iterationInterval) / 1000.0));
                SetTimeout.OnBackground(() =>
                {
                    if (LastInput.GetLastInputAgeMs() < maxIterations)
                    {
                        totalInputs++;
                        pwn.Progress = (int)((totalInputs / inputsRequired) * 100);
                    }
                    PartialWakeLogic(mute, totalInputs, pwn, iterations + 1);
                }, iterationInterval);
            }
            else
            {
                // Input requires not met.  Go back to sleep.
                if (pwn != null)
                {
                    pwn.Terminate();
                }
                Off(mute);
            }
        }
예제 #3
0
        private static void WaitForWakeProcedure(object arg)
        {
            try
            {
                dynamic   args          = arg;
                uint      lastInputAge  = args.lastInputAge;
                Stopwatch sleepTimer    = Stopwatch.StartNew();
                int       timesToSetOff = 12;
                // In theory the last input counter will roll over after 49.7102696 days. Or maybe it'll just stop incrementing?  Either way, lets hope the PC doesn't stay idle that long.
                while (true)
                {
                    uint inputAge = LastInput.GetLastInputAgeMs();
                    if (inputAge < lastInputAge || currentMonitorStatus != "off")
                    {
                        break;
                    }
                    lastInputAge = inputAge;
                    Thread.Sleep(1000);
                    if (timesToSetOff > 0 && sleepTimer.ElapsedMilliseconds >= 5000)
                    {
                        sleepTimer.Restart();
                        timesToSetOff--;
                        SetMonitorInState(2);
                    }
                }
                bool doPartialWakeLogic = Program.settings.inputsRequiredToWake > 1 && currentMonitorStatus == "off";
                bool lastOffDidMute     = didMute;

                currentMonitorStatus = "on";
                UnmuteIfNeeded();

                if (doPartialWakeLogic)
                {
                    PartialWakeLogic(lastOffDidMute);
                }
            }
            catch (ThreadAbortException)
            {
            }
            catch (Exception ex)
            {
                Logger.Debug(ex);
            }
        }
예제 #4
0
        public static void Off(bool mute)
        {
            UnmuteIfNeeded();

            currentMonitorStatus = "off";
            SetMonitorInState(2);

            uint lastInputAge = LastInput.GetLastInputAgeMs();

            lock (myLock)
            {
                didMute = false;
                if (mute && !AudioManager.GetMasterVolumeMute())
                {
                    AudioManager.SetMasterVolumeMute(true);
                    didMute = true;
                }
                StopMonitorOffThread();
                StopWaitForWakeThread();
                StartWaitForWakeThread(new { lastInputAge });
            }
        }
예제 #5
0
        public override void handleGETRequest(HttpProcessor p)
        {
            if (!Program.settings.IpIsWhitelisted(p.RemoteIPAddressStr))
            {
                p.writeFailure("403 Forbidden");
                return;
            }
            string successMessage = "<div>" + p.requestedPage + " command successful</div>";
            List <KeyValuePair <string, string> > additionalHeaders = new List <KeyValuePair <string, string> >();

            additionalHeaders.Add(new KeyValuePair <string, string>("Access-Control-Allow-Origin", "*"));
            if (p.requestedPage == "on")
            {
                On(p);
            }
            else if (p.requestedPage == "off")
            {
                int    idleTimeMs = p.GetIntParam("ifidle", 0);
                int    delayMs    = p.GetIntParam("delay", 0);
                Action setOff     = () =>
                {
                    if (idleTimeMs <= 0 || LastInput.GetLastInputAgeMs() >= idleTimeMs)
                    {
                        Off(p.GetBoolParam("mute"));
                    }
                };
                if (delayMs > 0)
                {
                    SetTimeout.OnBackground(setOff, delayMs);
                }
                else
                {
                    setOff();
                }
            }
            else if (p.requestedPage == "off_if_idle")
            {
                OffIfIdle(Program.settings.idleTimeMs, p.GetBoolParam("mute"));
            }
            else if (p.requestedPage == "standby")
            {
                currentMonitorStatus = "off";
                SetMonitorInState(1);
            }
            else if (p.requestedPage == "status")
            {
                p.writeSuccess("text/plain", additionalHeaders: additionalHeaders);
                p.outputStream.Write(currentMonitorStatus);
                return;
            }
            else if (p.requestedPage == "idle")
            {
                p.writeSuccess("text/plain", additionalHeaders: additionalHeaders);
                p.outputStream.Write(LastInput.GetLastInputAgeMs());
                return;
            }
            else if (p.requestedPage == "smarttoggle")
            {
                if (currentMonitorStatus == "on")
                {
                    OffIfIdle(Program.settings.idleTimeMs, p.GetBoolParam("mute"));
                }
                else
                {
                    On(p);
                }
            }
            else if (p.requestedPage == "cancel")
            {
                StopMonitorOffThread();
            }
            else if (p.requestedPage == "getvolume")
            {
                int level = 0;
                try
                {
                    level = (int)Math.Round(AudioManager.GetMasterVolume());
                    //level = Audio.GetVolume();
                }
                catch (Exception ex)
                {
                    p.writeSuccess("text/plain; charset=utf-8", responseCode: "500 Internal Server Error");
                    p.outputStream.Write(ex.ToString());
                    return;
                }
                p.writeSuccess("text/plain");
                p.outputStream.Write(level);
            }
            else if (p.requestedPage == "setvolume")
            {
                int level = p.GetIntParam("level");
                level = level.Clamp(0, 100);
                try
                {
                    AudioManager.SetMasterVolume(level);
                    //Audio.SetVolume(level);
                }
                catch (Exception ex)
                {
                    p.writeSuccess("text/plain; charset=utf-8", responseCode: "500 Internal Server Error");
                    p.outputStream.Write(ex.ToString());
                    return;
                }
                p.writeSuccess("text/plain");
                p.outputStream.Write(level);
            }
            else if (p.requestedPage == "mute")
            {
                try
                {
                    AudioManager.SetMasterVolumeMute(true);
                    //Audio.SetMute(true);
                }
                catch (Exception ex)
                {
                    p.writeSuccess("text/plain; charset=utf-8", responseCode: "500 Internal Server Error");
                    p.outputStream.Write(ex.ToString());
                    return;
                }
                p.writeSuccess("text/plain");
                p.outputStream.Write("muted");
            }
            else if (p.requestedPage == "unmute")
            {
                try
                {
                    AudioManager.SetMasterVolumeMute(false);
                    //Audio.SetMute(false);
                }
                catch (Exception ex)
                {
                    p.writeSuccess("text/plain; charset=utf-8", responseCode: "500 Internal Server Error");
                    p.outputStream.Write(ex.ToString());
                    return;
                }
                p.writeSuccess("text/plain");
                p.outputStream.Write("unmuted");
            }
            else if (p.requestedPage == "getmute")
            {
                bool muted = false;
                try
                {
                    muted = AudioManager.GetMasterVolumeMute();
                    //muted = Audio.GetMute();
                }
                catch (Exception ex)
                {
                    p.writeSuccess("text/plain; charset=utf-8", responseCode: "500 Internal Server Error");
                    p.outputStream.Write(ex.ToString());
                    return;
                }
                p.writeSuccess("text/plain");
                p.outputStream.Write(muted ? "muted" : "unmuted");
            }
            else if (p.requestedPage == "mousemove")
            {
                int dx    = p.GetIntParam("dx");                           // x change
                int dy    = p.GetIntParam("dy");                           // y change
                int delay = p.GetIntParam("delay").Clamp(1, 200);          // Approximate milliseconds between movements.
                int times = p.GetIntParam("times").Clamp(1, 5000 / delay); // Number of times to perform the change.  Limited to about 5 seconds of movement.
                try
                {
                    DragMouse(dx, dy, delay, times);
                }
                catch (Exception ex)
                {
                    p.writeSuccess("text/plain; charset=utf-8", responseCode: "500 Internal Server Error");
                    p.outputStream.Write(ex.ToString());
                    return;
                }
                p.writeSuccess("text/plain; charset=utf-8");
                p.outputStream.Write("move complete. moved " + dx + "," + dy + " " + times + " times with " + delay + " ms delay");
            }
            else if (p.requestedPage == "AllowLocalOverride")
            {
                Program.settings.syncAllowLocalOverride = true;
                Program.settings.Save();
                p.writeSuccess("text/plain; charset=utf-8");
                p.outputStream.Write("✅ Allow local input to override synced state");
            }
            else if (p.requestedPage == "DisallowLocalOverride")
            {
                Program.settings.syncAllowLocalOverride = false;
                Program.settings.Save();
                p.writeSuccess("text/plain; charset=utf-8");
                p.outputStream.Write("❌ Allow local input to override synced state");
            }
            else
            {
                successMessage = "";
            }

            if (p.responseWritten)
            {
                return;
            }

            p.writeSuccess(additionalHeaders: additionalHeaders);
            p.outputStream.Write("<html><head><title>Monitor Control Service</title></head>"
                                 + "<style type=\"text/css\">"
                                 + " table { border-collapse: collapse; }"
                                 + " th, td { border: 1px solid black; padding: 3px 5px; }"
                                 + "</style>"
                                 + "<body>"
                                 + "<p class=\"result\">" + successMessage + "</p>"
                                 + "<p class=\"syncStatus\">(Remote server \"" + Program.settings.syncAddress + "\") " + HttpUtility.HtmlEncode(MonitorControlService.syncedServerStatus) + "</p>"
                                 + "<table>"
                                 //+ "<thead>"
                                 //+ "<tr><th></th><th></th></tr>"
                                 //+ "</thead>"
                                 + "<tbody>"
                                 + BuildRow("on", "turn displays on")
                                 + BuildRow("on?offAfterSecs=15", "turn displays on, then after 15 seconds, off")
                                 + BuildRow("cancel", "cancel a scheduled monitor off command (see above)")
                                 + BuildRow("off", "turn displays off")
                                 + BuildRow("off?ifidle=3000", "turn displays off if idle for 3000ms")
                                 + BuildRow("off?delay=3000&ifidle=2900", "wait 3000ms, then turn displays off if idle for 2900ms")
                                 + BuildRow("off?delay=3000&ifidle=2900&mute=1", "wait 3000ms, then turn displays off if idle for 2900ms, and also mute until the computer is no longer idle")
                                 + BuildRow("off_if_idle", "turn displays off if idle for the configured idle time (" + Program.settings.idleTimeMs + " ms)")
                                 + BuildRow("off_if_idle?mute=1", "turn displays off if idle for the configured idle time (" + Program.settings.idleTimeMs + " ms). Also mute until the computer is no longer idle.")
                                 + BuildRow("standby", "change displays to standby state -- probably does nothing")
                                 + BuildRow("status", "return the current status (\"on\" or \"off\")")
                                 + BuildRow("idle", "return the time in milliseconds since the last user input")
                                 + BuildRow("smarttoggle", "if status is \"on\" then <b>off_if_idle</b>, else <b>on</b>. Also supports the <b>mute</b> boolean argument.")
                                 + BuildRow("getvolume", "returns default audio device volume from 0 to 100")
                                 + BuildRow("setvolume?level=10", "sets default audio device volume from 0 to 100")
                                 + BuildRow("mute", "mutes default audio device")
                                 + BuildRow("unmute", "unmutes default audio device")
                                 + BuildRow("getmute", "returns \"muted\" or \"unmuted\"")
                                 + BuildRow("mousemove?dx=2&dy=-2&delay=4&times=5", "moves the mouse cursor up 2px and to the right 2px, 5 times, waiting 4ms between each movement. Max delay 200ms. Max 5 seconds movement per command.")
                                 + BuildRow("AllowLocalOverride", "Enables the setting \"Allow local input to override synced state\"")
                                 + BuildRow("DisallowLocalOverride", "Disables the setting \"Allow local input to override synced state\"")
                                 + "</tbody>"
                                 + "</table>"
                                 + "</body>"
                                 + "</html>");
        }