Pause video feed while the computer is locked
This commit is contained in:
parent
6284bd0609
commit
3995ab92a2
17
IPCamAppBar/CameraView.Designer.cs
generated
17
IPCamAppBar/CameraView.Designer.cs
generated
@ -28,10 +28,13 @@
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,4 +117,18 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="PausedOverlay.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
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==
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
IPCamAppBar/Resources/Paused.png
Normal file
BIN
IPCamAppBar/Resources/Paused.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1018 B |
Loading…
Reference in New Issue
Block a user