Zzz – Rev 1

Subversion Repositories:
Rev:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using InTheHand.Net.Bluetooth;
using Newtonsoft.Json.Linq;
using Serilog;
using Zzz.Properties;

namespace Zzz.Idle
{
    public class Idler : EventArgs, IDisposable
    {
        #region Public Properties & Fields

        public TimeSpan IdleTimeout { 
            get { 
                return _timeout; 
            } 
            set { 
                _timeout = value;

                Log.Information("[{Identifier}] Set timeout to {Timeout}.", _identifier, _timeout);
            } 
        }

        public bool IsRunning => _running;

        #endregion

        #region Static Fields and Constants

        private Timer _idleTimer;

        private MouseInput _mouseInput;

        private KeyboardInput _keyboardInput;

        private BluetoothScan _bluetoothScan;

        private bool _announced;

        #endregion

        #region Public Events & Delegates

        public event EventHandler<IdleEventArgs> Idle;

        public event EventHandler<IdleImminentEventArgs> IdleImminent;

        #endregion

        #region Private Delegates, Events, Enums, Properties, Indexers and Fields

        private bool _running;

        private WindowPresence _windowPresence;

        private TimeSpan _timeout;

        private Configuration.Configuration _configuration;

        private string _identifier;

        #endregion

        #region Constructors, Destructors and Finalizers

        public Idler(Configuration.Configuration configuration, string identifier)
        {
            _configuration = configuration;

            _identifier = identifier;
        }

        public void Dispose()
        {
            if (_windowPresence != null)
            {
                _windowPresence.WindowDetected -= WindowPresence_WindowDetected;
                _windowPresence.Dispose();
                _windowPresence = null;
            }

            if (BluetoothRadio.IsSupported)
            {
                if (_bluetoothScan != null)
                {
                    _bluetoothScan.BluetoothDeviceDetected -= BluetoothScan_BluetoothDeviceDetected;
                    _bluetoothScan.Dispose();
                    _bluetoothScan = null;
                }
            }

            if (_mouseInput != null)
            {
                _mouseInput.MouseMoved -= MouseInput_MouseMoved;
                _mouseInput.MouseClicked -= MouseInput_MouseClicked;
                _mouseInput.MouseWheelScrolled -= MouseInput_MouseWheelScrolled;
                _mouseInput.Dispose();
                _mouseInput = null;
            }

            if (_keyboardInput != null)
            {
                _keyboardInput.KeyboardKeyPressed -= KeyboardInput_KeyboardKeyPressed;
                _keyboardInput.Dispose();
                _keyboardInput = null;
            }
        }

        #endregion

        #region Event Handlers

        private void BluetoothScan_BluetoothDeviceDetected(object sender, EventArgs e)
        {
            Log.Information("[{Identifier}] Idler reset by bluetooth device.", _identifier);

            _idleTimer?.Change(_timeout, Timeout.InfiniteTimeSpan);
        }

        private void MouseInput_MouseMoved(object sender, MouseMovedEventArgs e)
        {
            if (e.Distance < (int)_configuration.MouseMoveTolerance)
            {
                Log.Information("[{Identifier}] Mouse movement too small to reset idler.", _identifier);

                return;
            }

            Log.Information("[{Identifier}] Idler reset by mouse movement.", _identifier);

            _idleTimer?.Change(_timeout, Timeout.InfiniteTimeSpan);
        }

        private void MouseInput_MouseClicked(object sender, EventArgs e)
        {
            Log.Information("[{Identifier}] Idler reset by mouse click.", _identifier);

            _idleTimer?.Change(_timeout, Timeout.InfiniteTimeSpan);
        }

        private void MouseInput_MouseWheelScrolled(object sender, EventArgs e)
        {
            Log.Information("[{Identifier}] Idler reset by mouse scroll.", _identifier);

            _idleTimer?.Change(_timeout, Timeout.InfiniteTimeSpan);
        }

        private void KeyboardInput_KeyboardKeyPressed(object sender, EventArgs e)
        {
            Log.Information("[{Identifier}] Idler reset by key press.", _identifier);

            _idleTimer?.Change(_timeout, Timeout.InfiniteTimeSpan);
        }

        private void WindowPresence_WindowDetected(object sender, EventArgs e)
        {
            Log.Information("[{Identifier}] Idler reset by detected window.", _identifier);

            _idleTimer?.Change(_timeout, Timeout.InfiniteTimeSpan);
        }

        #endregion

        #region Public Methods

        public void Start(TimeSpan timeout)
        {
            if (_running)
            {
                return;
            }

            _timeout = timeout;

            // Bind input events.
            if (_configuration.MonitorMouse)
            {
                if (_mouseInput == null)
                {
                    _mouseInput = new MouseInput();
                    _mouseInput.MouseClicked += MouseInput_MouseClicked;
                    _mouseInput.MouseMoved += MouseInput_MouseMoved;
                    _mouseInput.MouseWheelScrolled += MouseInput_MouseWheelScrolled;
                }
            }

            if (_configuration.MonitorKeyboard)
            {
                if (_keyboardInput == null)
                {
                    _keyboardInput = new KeyboardInput();
                    _keyboardInput.KeyboardKeyPressed += KeyboardInput_KeyboardKeyPressed;
                }
            }

            // Bind bluetooth events.
            if (BluetoothRadio.IsSupported)
            {
                if (_configuration.MonitorBluetooth)
                {
                    if (_bluetoothScan == null)
                    {
                        _bluetoothScan = new BluetoothScan(_configuration);
                        _bluetoothScan.BluetoothDeviceDetected += BluetoothScan_BluetoothDeviceDetected;
                    }
                }
            }

            if (_configuration.MonitorWindows)
            {
                if (_windowPresence == null)
                {
                    _windowPresence = new WindowPresence(_configuration);
                    _windowPresence.WindowDetected += WindowPresence_WindowDetected;
                }
            }

            // Reset the announcement flag.
            _announced = false;

            // Reset the idle timer.
            _idleTimer = new Timer(IdleTimeCallback, null,
                _timeout.Subtract(TimeSpan.FromMinutes(1)),
                Timeout.InfiniteTimeSpan);

            _running = true;

            Log.Information("[{Identifier}] Idler enabled.", _identifier);
        }

        public void Stop()
        {
            if (!_running)
            {
                return;
            }

            if (_windowPresence != null)
            {
                _windowPresence.WindowDetected -= WindowPresence_WindowDetected;
                _windowPresence.Dispose();
                _windowPresence = null;
            }

            if (BluetoothRadio.IsSupported)
            {
                if (_bluetoothScan != null)
                {
                    _bluetoothScan.BluetoothDeviceDetected -= BluetoothScan_BluetoothDeviceDetected;
                    _bluetoothScan.Dispose();
                    _bluetoothScan = null;
                }
            }

            if (_mouseInput != null)
            {
                _mouseInput.MouseMoved -= MouseInput_MouseMoved;
                _mouseInput.MouseClicked -= MouseInput_MouseClicked;
                _mouseInput.MouseWheelScrolled -= MouseInput_MouseWheelScrolled;
                _mouseInput.Dispose();
                _mouseInput = null;
            }

            if (_keyboardInput != null)
            {
                _keyboardInput.KeyboardKeyPressed -= KeyboardInput_KeyboardKeyPressed;
                _keyboardInput.Dispose();
                _keyboardInput = null;
            }

            if (_idleTimer != null)
            {
                _idleTimer.Change(Timeout.Infinite, Timeout.Infinite);
                _idleTimer.Dispose();
                _idleTimer = null;
            }

            _running = false;

            Log.Information("[{Identifier}] Idler disabled.", _identifier);
        }

        #endregion

        #region Private Methods

        private void IdleTimeCallback(object state)
        {
            if (!_announced)
            {
                Log.Information("[{Identifier}] Announcing that idle timeout has been reached.", _identifier);

                // Invoke the idle imminent event on the parent task scheduler.
                IdleImminent?.Invoke(this, new IdleImminentEventArgs());

                // Reschedule one minute.
                _idleTimer.Change(TimeSpan.FromMinutes(1), Timeout.InfiniteTimeSpan);

                _announced = true;

                return;
            }

            Log.Information("[{Identifier}] Idling state reached.", _identifier);

            // Invoke the idle event on the parent task scheduler.
            Idle?.Invoke(this, new IdleEventArgs());
        }

        #endregion
    }
}

Generated by GNU Enscript 1.6.5.90.