using System; using System.IO; using System.Linq; using System.Reflection; using System.Windows.Forms; using IPCamLib; using IPCamLib.Concrete; using Microsoft.Win32; using Newtonsoft.Json; namespace IPCamAppBar { public partial class MainForm : Form { private readonly Config config; private readonly AppBar appBar; private bool paused = false; public MainForm() { InitializeComponent(); // ReSharper disable once PossibleNullReferenceException // ReSharper disable once AssignNullToNotNullAttribute using (var file = File.OpenText(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "config.json"))) { var serializer = new JsonSerializer(); config = (Config)serializer.Deserialize(file, typeof(Config)); } var monitor = GetMonitor(config.AppBar.Monitor); var position = GetAppBarPosition(config.AppBar.Side); appBar = new AppBar(Handle); appBar.SetPosition(monitor, position, config.AppBar.Size); CameraViewContainer.FlowDirection = config.AppBar.Side == ConfigSide.Left || config.AppBar.Side == ConfigSide.Right ? FlowDirection.TopDown : FlowDirection.LeftToRight; config.Cameras?.ForEach(AddCamera); SystemEvents.SessionSwitch += SystemEventsOnSessionSwitch; } protected override void WndProc(ref Message m) { appBar?.HandleMessage(m); base.WndProc(ref m); } private static Screen GetMonitor(int number) { // Since I could not find any way to get the numbers as assigned in the // display control panel, we'll just order them left-to-right. var orderedScreens = Screen.AllScreens.OrderBy(s => s.Bounds.Left).ToList(); // 0 means primary. Yeah. Totally not losing geek-creds for using a 1-based // index here. No sir. 'tis a feature! return number > 0 && number <= orderedScreens.Count ? orderedScreens[number - 1] : Screen.PrimaryScreen; } private static AppBarPosition GetAppBarPosition(ConfigSide side) { return side switch { ConfigSide.Top => AppBarPosition.Top, ConfigSide.Bottom => AppBarPosition.Bottom, ConfigSide.Left => AppBarPosition.Left, ConfigSide.Right => AppBarPosition.Right, _ => throw new ArgumentOutOfRangeException(nameof(side), side, @"Invalid side value") }; } private void AddCamera(ConfigCamera configCamera) { ICamera camera = configCamera.Type switch { ConfigCameraType.HTTPMJPEG => new HTTPMJPEGStreamCamera(new Uri(configCamera.URL)), ConfigCameraType.RTSP => new RTSPStreamCamera(new Uri(configCamera.URL), configCamera.Width, configCamera.Height), _ => throw new ArgumentOutOfRangeException($"Camera type in configuration is not valid: {configCamera.Type}") }; var margin = new Padding(0); if (CameraViewContainer.FlowDirection == FlowDirection.LeftToRight) margin.Right = config.AppBar.Spacing; else margin.Bottom = config.AppBar.Spacing; var view = new CameraView(camera, configCamera.OverlayDateTime) { Width = configCamera.Width, Height = configCamera.Height, Margin = margin }; CameraViewContainer.Controls.Add(view); } private void MainForm_FormClosed(object sender, FormClosedEventArgs e) { appBar.Dispose(); } private void CloseToolStripMenuItem_Click(object sender, EventArgs e) { Close(); } private void SystemEventsOnSessionSwitch(object sender, SessionSwitchEventArgs e) { if (InvokeRequired) { Invoke(new Action(() => SystemEventsOnSessionSwitch(sender, e))); return; } var pause = e.Reason == SessionSwitchReason.ConsoleDisconnect || e.Reason == SessionSwitchReason.RemoteDisconnect || e.Reason == SessionSwitchReason.SessionLock || e.Reason == SessionSwitchReason.SessionLogoff; if (pause == paused) return; foreach (var control in CameraViewContainer.Controls) { if (control is CameraView cameraView) cameraView.SetPaused(pause); } paused = pause; } } }