diff --git a/IPCamAppBar/CameraView.Designer.cs b/IPCamAppBar/CameraView.Designer.cs
index de2c2e3..3461427 100644
--- a/IPCamAppBar/CameraView.Designer.cs
+++ b/IPCamAppBar/CameraView.Designer.cs
@@ -28,10 +28,13 @@
///
private void InitializeComponent()
{
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CameraView));
this.ConnectingLabel = new System.Windows.Forms.Label();
this.StreamView = new System.Windows.Forms.PictureBox();
this.IssueLabel = new System.Windows.Forms.Label();
+ this.PausedOverlay = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.StreamView)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.PausedOverlay)).BeginInit();
this.SuspendLayout();
//
// ConnectingLabel
@@ -71,17 +74,30 @@
this.IssueLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.IssueLabel.Visible = false;
//
+ // PausedOverlay
+ //
+ this.PausedOverlay.BackColor = System.Drawing.Color.Transparent;
+ this.PausedOverlay.Image = ((System.Drawing.Image)(resources.GetObject("PausedOverlay.Image")));
+ this.PausedOverlay.Location = new System.Drawing.Point(19, 40);
+ this.PausedOverlay.Name = "PausedOverlay";
+ this.PausedOverlay.Size = new System.Drawing.Size(64, 64);
+ this.PausedOverlay.TabIndex = 3;
+ this.PausedOverlay.TabStop = false;
+ this.PausedOverlay.Visible = false;
+ //
// CameraView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Gray;
+ this.Controls.Add(this.PausedOverlay);
this.Controls.Add(this.IssueLabel);
this.Controls.Add(this.StreamView);
this.Controls.Add(this.ConnectingLabel);
this.Margin = new System.Windows.Forms.Padding(0);
this.Name = "CameraView";
((System.ComponentModel.ISupportInitialize)(this.StreamView)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.PausedOverlay)).EndInit();
this.ResumeLayout(false);
}
@@ -91,5 +107,6 @@
private System.Windows.Forms.Label ConnectingLabel;
private System.Windows.Forms.PictureBox StreamView;
private System.Windows.Forms.Label IssueLabel;
+ private System.Windows.Forms.PictureBox PausedOverlay;
}
}
diff --git a/IPCamAppBar/CameraView.cs b/IPCamAppBar/CameraView.cs
index 4446ee0..05b643b 100644
--- a/IPCamAppBar/CameraView.cs
+++ b/IPCamAppBar/CameraView.cs
@@ -1,6 +1,7 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
+using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -11,32 +12,50 @@ namespace IPCamAppBar
{
public partial class CameraView : UserControl, IRetryableCameraObserver
{
+ private readonly ICamera camera;
private readonly bool overlayDateTime;
private Bitmap viewBitmap;
-
+ private CancellationTokenSource streamCancellationTokenSource;
+
public CameraView(ICamera camera, bool overlayDateTime)
{
+ this.camera = camera;
this.overlayDateTime = overlayDateTime;
InitializeComponent();
- var streamCancellationTokenSource = new CancellationTokenSource();
+ StartCamera();
+
+ Disposed += (_, _) =>
+ {
+ StopCamera();
+ };
+ }
+
+ private void StartCamera()
+ {
+ streamCancellationTokenSource = new CancellationTokenSource();
+
Task.Run(async () =>
{
var retryableCamera = new RetryableCamera(camera);
await retryableCamera.Fetch(this, streamCancellationTokenSource.Token);
});
-
- Disposed += (_, _) =>
- {
- streamCancellationTokenSource.Cancel();
- };
+ }
+
+
+ private void StopCamera()
+ {
+ streamCancellationTokenSource.Cancel();
}
private Bitmap resizedBitmap;
-
+
public Task OnFrame(Image image)
{
+ if (streamCancellationTokenSource.IsCancellationRequested)
+ return Task.CompletedTask;
+
if (overlayDateTime || image is not Bitmap bitmap || image.Width != Width || image.Height != Height)
{
resizedBitmap ??= new Bitmap(Width, Height);
@@ -100,6 +119,7 @@ namespace IPCamAppBar
ConnectingLabel.Visible = false;
StreamView.Visible = true;
IssueLabel.Visible = false;
+ PausedOverlay.Visible = false;
if (viewBitmap == null)
@@ -130,12 +150,28 @@ namespace IPCamAppBar
private void InvokeDisconnected(Exception exception, TimeSpan retryDelay)
{
- if (IsDisposed)
+ if (IsDisposed || streamCancellationTokenSource.IsCancellationRequested)
return;
IssueLabel.Text = (exception?.Message ?? "Camera disconnected") + $", retrying in {retryDelay.TotalSeconds} seconds";
IssueLabel.Visible = true;
IssueLabel.BringToFront();
}
+
+
+ public void SetPaused(bool pause)
+ {
+ if (pause)
+ {
+ StopCamera();
+
+ PausedOverlay.Left = (Width - PausedOverlay.Width) / 2;
+ PausedOverlay.Top = (Height - PausedOverlay.Height) / 2;
+ PausedOverlay.Visible = true;
+ PausedOverlay.BringToFront();
+ }
+ else
+ StartCamera();
+ }
}
}
diff --git a/IPCamAppBar/CameraView.resx b/IPCamAppBar/CameraView.resx
index 1af7de1..efbee42 100644
--- a/IPCamAppBar/CameraView.resx
+++ b/IPCamAppBar/CameraView.resx
@@ -117,4 +117,18 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m
+ dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAF8SURBVHhetc8xCsAAEALB/P/TF9PaSZiBrcXnvG/j
+ TxQfiD60RvGB6ENrFB+IPrRG8YHoQ2sUH4g+tEbxgehDaxQfiD60RvGB6ENrFB+IPrRG8YHoQ2sUH4g+
+ tEbxgehDaxQfiD60RvGB6ENrFB+IPrRG8YHoQ2sUH4g+tEbxgehDaxQfiD60RvGB6ENrFB+IPrRG8YHo
+ Q2sUH4g+tEbxgehDaxQfiD60RvGB6ENrFB+IPrRG8YHoQ2sUH4g+tEbxgehDaxQfiD60RvGB6ENrFB+I
+ PrRG8YHoQ2sUH4g+tEbxgehDaxQfiD60RvGB6ENrFB+IPrRG8YHoQ2sUH4g+tEbxgehDaxQfiD60RvGB
+ 6ENrFB+IPrRG8YHoQ2sUH4g+tEbxgehDaxQfiD60RvGB6ENrFB+IPrRG8YHoQ2sUH4g+tEbxgehDaxQf
+ iD60RvGB6ENrFB+IPrRG8YHoQ2sUH4g+tEbxgehDaxQfiD60RvGB6ENrFB+IPrQG3b1Awcd2Z2RJDQAA
+ AABJRU5ErkJggg==
+
+
\ No newline at end of file
diff --git a/IPCamAppBar/MainForm.cs b/IPCamAppBar/MainForm.cs
index 66be7a0..f8d1977 100644
--- a/IPCamAppBar/MainForm.cs
+++ b/IPCamAppBar/MainForm.cs
@@ -5,6 +5,7 @@ using System.Reflection;
using System.Windows.Forms;
using IPCamLib;
using IPCamLib.Concrete;
+using Microsoft.Win32;
using Newtonsoft.Json;
namespace IPCamAppBar
@@ -13,6 +14,7 @@ namespace IPCamAppBar
{
private readonly Config config;
private readonly AppBar appBar;
+ private bool paused = false;
public MainForm()
@@ -39,6 +41,9 @@ namespace IPCamAppBar
: FlowDirection.LeftToRight;
config.Cameras?.ForEach(AddCamera);
+
+
+ SystemEvents.SessionSwitch += SystemEventsOnSessionSwitch;
}
@@ -65,15 +70,14 @@ namespace IPCamAppBar
private static AppBarPosition GetAppBarPosition(ConfigSide side)
{
- switch (side)
+ return side switch
{
- case ConfigSide.Top: return AppBarPosition.Top;
- case ConfigSide.Bottom: return AppBarPosition.Bottom;
- case ConfigSide.Left: return AppBarPosition.Left;
- case ConfigSide.Right: return AppBarPosition.Right;
- default:
- throw new ArgumentOutOfRangeException(nameof(side), side, @"Invalid side value");
- }
+ 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")
+ };
}
@@ -113,5 +117,31 @@ namespace IPCamAppBar
{
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;
+ }
}
}
diff --git a/IPCamAppBar/Resources/Paused.png b/IPCamAppBar/Resources/Paused.png
new file mode 100644
index 0000000..9f19584
Binary files /dev/null and b/IPCamAppBar/Resources/Paused.png differ