Fixed errors not showing up

Set timeout for the stream to 10 seconds instead of the default 5 minutes
Added Close menu
This commit is contained in:
Mark van Renswoude 2019-08-24 17:35:41 +02:00
parent 8f61224777
commit c334b7fdac
7 changed files with 89 additions and 33 deletions

View File

@ -12,12 +12,20 @@ namespace IPCamAppBar
public Image Image { get; set; } public Image Image { get; set; }
} }
public class StreamExceptionEventArgs : EventArgs
{
public Exception Exception { get; set; }
}
public delegate void FrameEvent(object sender, FrameEventArgs args); public delegate void FrameEvent(object sender, FrameEventArgs args);
public delegate void StreamExceptionEvent(object sender, StreamExceptionEventArgs args);
internal abstract class CameraStream : IDisposable internal abstract class CameraStream : IDisposable
{ {
public event FrameEvent Frame; public event FrameEvent Frame;
public event StreamExceptionEvent StreamException;
private readonly CancellationTokenSource cancelTaskTokenSource = new CancellationTokenSource(); private readonly CancellationTokenSource cancelTaskTokenSource = new CancellationTokenSource();
private Task streamTask; private Task streamTask;
@ -57,6 +65,8 @@ namespace IPCamAppBar
request.Credentials = new NetworkCredential(parts[0], parts.Length > 1 ? parts[1] : ""); request.Credentials = new NetworkCredential(parts[0], parts.Length > 1 ? parts[1] : "");
} }
request.ReadWriteTimeout = 10;
try try
{ {
HttpWebResponse response; HttpWebResponse response;
@ -83,7 +93,11 @@ namespace IPCamAppBar
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
break; break;
// TODO onException OnStreamException(new StreamExceptionEventArgs
{
Exception = e
});
await Task.Delay(5000, cancellationToken); await Task.Delay(5000, cancellationToken);
} }
} }
@ -97,6 +111,12 @@ namespace IPCamAppBar
{ {
Frame?.Invoke(this, args); Frame?.Invoke(this, args);
} }
protected virtual void OnStreamException(StreamExceptionEventArgs args)
{
StreamException?.Invoke(this, args);
}
} }

36
CameraView.Designer.cs generated
View File

@ -28,9 +28,11 @@
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
this.components = new System.ComponentModel.Container();
this.ConnectingLabel = new System.Windows.Forms.Label(); this.ConnectingLabel = new System.Windows.Forms.Label();
this.StreamView = new System.Windows.Forms.PictureBox(); this.StreamView = new System.Windows.Forms.PictureBox();
this.NoDataLabel = new System.Windows.Forms.Label(); this.IssueLabel = new System.Windows.Forms.Label();
this.NoDataTimer = new System.Windows.Forms.Timer(this.components);
((System.ComponentModel.ISupportInitialize)(this.StreamView)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.StreamView)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
@ -57,26 +59,31 @@
this.StreamView.TabStop = false; this.StreamView.TabStop = false;
this.StreamView.Visible = false; this.StreamView.Visible = false;
// //
// NoDataLabel // IssueLabel
// //
this.NoDataLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) this.IssueLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right))); | System.Windows.Forms.AnchorStyles.Right)));
this.NoDataLabel.BackColor = System.Drawing.Color.Black; this.IssueLabel.BackColor = System.Drawing.Color.Black;
this.NoDataLabel.ForeColor = System.Drawing.Color.DarkRed; this.IssueLabel.ForeColor = System.Drawing.Color.DarkRed;
this.NoDataLabel.Location = new System.Drawing.Point(0, 129); this.IssueLabel.Location = new System.Drawing.Point(0, 0);
this.NoDataLabel.Name = "NoDataLabel"; this.IssueLabel.Name = "IssueLabel";
this.NoDataLabel.Size = new System.Drawing.Size(150, 21); this.IssueLabel.Size = new System.Drawing.Size(150, 21);
this.NoDataLabel.TabIndex = 2; this.IssueLabel.TabIndex = 2;
this.NoDataLabel.Text = "No data for x seconds"; this.IssueLabel.Text = "Someone set up us the bomb";
this.NoDataLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; this.IssueLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.NoDataLabel.Visible = false; this.IssueLabel.Visible = false;
//
// NoDataTimer
//
this.NoDataTimer.Interval = 1000;
this.NoDataTimer.Tick += new System.EventHandler(this.NoDataTimer_Tick);
// //
// CameraView // CameraView
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Gray; this.BackColor = System.Drawing.Color.Gray;
this.Controls.Add(this.NoDataLabel); this.Controls.Add(this.IssueLabel);
this.Controls.Add(this.StreamView); this.Controls.Add(this.StreamView);
this.Controls.Add(this.ConnectingLabel); this.Controls.Add(this.ConnectingLabel);
this.Margin = new System.Windows.Forms.Padding(0); this.Margin = new System.Windows.Forms.Padding(0);
@ -90,6 +97,7 @@
private System.Windows.Forms.Label ConnectingLabel; private System.Windows.Forms.Label ConnectingLabel;
private System.Windows.Forms.PictureBox StreamView; private System.Windows.Forms.PictureBox StreamView;
private System.Windows.Forms.Label NoDataLabel; private System.Windows.Forms.Label IssueLabel;
private System.Windows.Forms.Timer NoDataTimer;
} }
} }

View File

@ -9,7 +9,6 @@ namespace IPCamAppBar
public partial class CameraView : UserControl public partial class CameraView : UserControl
{ {
private DateTime lastFrameTime; private DateTime lastFrameTime;
private Timer noDataTimer;
public CameraView(string url) public CameraView(string url)
@ -18,22 +17,15 @@ namespace IPCamAppBar
var cameraStream = new CameraMJPEGStream(); var cameraStream = new CameraMJPEGStream();
cameraStream.Frame += CameraStreamOnFrame; cameraStream.Frame += CameraStreamOnFrame;
cameraStream.StreamException += CameraStreamOnStreamException;
cameraStream.Start(url); cameraStream.Start(url);
noDataTimer = new Timer
{
Interval = 1000
};
noDataTimer.Tick += CheckNoData;
Disposed += (sender, args) => Disposed += (sender, args) =>
{ {
noDataTimer?.Dispose();
cameraStream?.Dispose(); cameraStream?.Dispose();
}; };
} }
private void CameraStreamOnFrame(object sender, FrameEventArgs args) private void CameraStreamOnFrame(object sender, FrameEventArgs args)
{ {
// The event comes from a background thread, so if needed invoke it on the main thread // The event comes from a background thread, so if needed invoke it on the main thread
@ -45,10 +37,10 @@ namespace IPCamAppBar
ConnectingLabel.Visible = false; ConnectingLabel.Visible = false;
StreamView.Visible = true; StreamView.Visible = true;
NoDataLabel.Visible = false; IssueLabel.Visible = false;
lastFrameTime = DateTime.Now; lastFrameTime = DateTime.Now;
noDataTimer.Start(); NoDataTimer.Start();
var viewImage = new Bitmap(Width, Height); var viewImage = new Bitmap(Width, Height);
using (var graphics = Graphics.FromImage(viewImage)) using (var graphics = Graphics.FromImage(viewImage))
@ -86,14 +78,23 @@ namespace IPCamAppBar
} }
private void CheckNoData(object sender, EventArgs e) private void CameraStreamOnStreamException(object sender, StreamExceptionEventArgs args)
{
IssueLabel.Text = args.Exception.Message;
IssueLabel.Visible = true;
IssueLabel.BringToFront();
}
private void NoDataTimer_Tick(object sender, EventArgs e)
{ {
var timeSinceLastFrame = DateTime.Now - lastFrameTime; var timeSinceLastFrame = DateTime.Now - lastFrameTime;
if (timeSinceLastFrame.TotalSeconds < 10) if (timeSinceLastFrame.TotalSeconds < 10)
return; return;
NoDataLabel.Text = $@"No data for {timeSinceLastFrame.TotalSeconds} seconds"; IssueLabel.Text = $@"No data for {(int)timeSinceLastFrame.TotalSeconds} seconds";
NoDataLabel.Visible = true; IssueLabel.Visible = true;
IssueLabel.BringToFront();
} }
} }
} }

View File

@ -117,4 +117,7 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<metadata name="NoDataTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root> </root>

23
MainForm.Designer.cs generated
View File

@ -28,18 +28,36 @@
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
this.components = new System.ComponentModel.Container();
this.CameraViewContainer = new System.Windows.Forms.FlowLayoutPanel(); this.CameraViewContainer = new System.Windows.Forms.FlowLayoutPanel();
this.DefaultContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
this.closeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.DefaultContextMenu.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
// //
// CameraViewContainer // CameraViewContainer
// //
this.CameraViewContainer.ContextMenuStrip = this.DefaultContextMenu;
this.CameraViewContainer.Dock = System.Windows.Forms.DockStyle.Fill; this.CameraViewContainer.Dock = System.Windows.Forms.DockStyle.Fill;
this.CameraViewContainer.Location = new System.Drawing.Point(0, 0); this.CameraViewContainer.Location = new System.Drawing.Point(0, 0);
this.CameraViewContainer.Margin = new System.Windows.Forms.Padding(0); this.CameraViewContainer.Margin = new System.Windows.Forms.Padding(0);
this.CameraViewContainer.Name = "CameraViewContainer"; this.CameraViewContainer.Name = "CameraViewContainer";
this.CameraViewContainer.Size = new System.Drawing.Size(269, 211); this.CameraViewContainer.Size = new System.Drawing.Size(269, 211);
this.CameraViewContainer.TabIndex = 0; this.CameraViewContainer.TabIndex = 0;
this.CameraViewContainer.Click += new System.EventHandler(this.CameraViewContainer_Click); //
// DefaultContextMenu
//
this.DefaultContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.closeToolStripMenuItem});
this.DefaultContextMenu.Name = "ContextMenu";
this.DefaultContextMenu.Size = new System.Drawing.Size(181, 48);
//
// closeToolStripMenuItem
//
this.closeToolStripMenuItem.Name = "closeToolStripMenuItem";
this.closeToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
this.closeToolStripMenuItem.Text = "&Close";
this.closeToolStripMenuItem.Click += new System.EventHandler(this.CloseToolStripMenuItem_Click);
// //
// MainForm // MainForm
// //
@ -53,6 +71,7 @@
this.ShowInTaskbar = false; this.ShowInTaskbar = false;
this.Text = "IPCam AppBar"; this.Text = "IPCam AppBar";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed); this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed);
this.DefaultContextMenu.ResumeLayout(false);
this.ResumeLayout(false); this.ResumeLayout(false);
} }
@ -60,6 +79,8 @@
#endregion #endregion
private System.Windows.Forms.FlowLayoutPanel CameraViewContainer; private System.Windows.Forms.FlowLayoutPanel CameraViewContainer;
private System.Windows.Forms.ContextMenuStrip DefaultContextMenu;
private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem;
} }
} }

View File

@ -85,9 +85,9 @@ namespace IPCamAppBar
} }
private void CameraViewContainer_Click(object sender, EventArgs e) private void CloseToolStripMenuItem_Click(object sender, EventArgs e)
{ {
//Close(); Close();
} }
} }
} }

View File

@ -117,4 +117,7 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<metadata name="DefaultContextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root> </root>