using KlvPlayer;
using KlvPlayerDemoWpf.Properties;
using Newtonsoft.Json.Linq;
using StCoreWr;
using StMonitorAgent;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Threading;
namespace KlvPlayerDemoWpf
{
public partial class MainWindow : Window
{
private CKlvPlayer m_KlvPlayer = null;
private bool m_fPlaying = false;
private bool m_fPaused = false;
private int m_KlvPid = -1;
private long m_KlvPacketsCounter = 0;
private CStMonitorAgent m_MonitorAgent = null;
private DateTime m_LastMonitorKlvUpdate = DateTime.Now;
private int MaxMonitorKlvUpdateRate = 200;
DispatcherTimer m_InfoUpdateTimer;
private bool m_dragStarted = false;
public MainWindow()
{
InitializeComponent();
Trace.WriteLine("Creating player");
try
{
m_KlvPlayer = new CKlvPlayer();
bool fLicExists = !string.IsNullOrEmpty(Settings.Default.LicensePath) && File.Exists(Settings.Default.LicensePath);
if (fLicExists && string.IsNullOrEmpty(Settings.Default.LicenseKey))
{
string license;
string licenseError;
if (m_KlvPlayer.Activate(Settings.Default.LicensePath, out license, out licenseError) == false)
{
ShowStatusMessage($"License not valid. {licenseError}. Demo mode.");
}
}
else
if (fLicExists && !string.IsNullOrEmpty(Settings.Default.LicenseKey))
{
if (m_KlvPlayer.Activate("KlvPlayer", Settings.Default.LicensePath, Settings.Default.LicenseKey) == false)
{
ShowStatusMessage("License not valid");
}
}
else
{
ShowStatusMessage("No License info. Demo mode.");
}
m_KlvPlayer.Hwnd = (int)this.VideoPanel.Handle;
m_KlvPlayer.FrameAccuracyMode = Settings.Default.FrameAccuracyMode;
m_KlvPlayer.FrameAccuracyRequiresSequenceHeaders = Settings.Default.FrameAccuracyRequiresSequenceHeaders;
m_KlvPlayer.AudioMayBeMissing = true;
m_KlvPlayer.PidDetectionEvent += new NotifyPidDetection(OnPidDetectionEvent);
m_KlvPlayer.PlayerEvent += new NotifyPlayerEvent(OnPlayerEvent);
m_KlvPlayer.SyncFrameEvent += new NotifySyncFrame(OnSyncFrameEvent);
m_KlvPlayer.ErrorEvent += new NotifyError(OnErrorEvent);
}
catch (System.Exception ex)
{
Trace.WriteLine(ex.Message);
}
}
private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
try
{
FillSettings();
m_InfoUpdateTimer = new DispatcherTimer();
m_InfoUpdateTimer.Tick += new EventHandler(OnInfoUpdateTimer);
m_InfoUpdateTimer.Interval = TimeSpan.FromMilliseconds(100);
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
SetGuiForStream();
}));
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (m_MonitorAgent != null)
m_MonitorAgent.CloseAllSubscribers();
Settings.Default.Nic = NicComboBox.Text;
Settings.Default.FilePlayback = RadioBttnFile.IsChecked.Value;
Settings.Default.Save();
}
void OnPidDetectionEvent(List<PidInfoWr> pidList)
{
pidList.ForEach(pid =>
{
if (pid.streamType == StreamType.KLV && m_KlvPid == -1)
m_KlvPid = pid.streamId;
});
}
void OnPlayerEvent(Player_State ev, string info, long param)
{
ShowStatusMessage(string.Format("{0} {1}", ev, info));
switch (ev)
{
case Player_State.Running:
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
if (m_fPaused)
{
m_fPaused = false;
SetGuiOnPause(false);
}
if (RadioBttnFile.IsChecked.Value)
PlayerSlider.Maximum = m_KlvPlayer.GetDuration();
}));
break;
case Player_State.Paused:
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
m_fPaused = true;
SetGuiOnPause(true);
}));
break;
case Player_State.Completed:
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
m_KlvPlayer.Stop();
SetGuiOnStop();
}));
break;
case Player_State.Demo_Expired:
ShowStatusMessage("Demo Expired");
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
System.Windows.Forms.MessageBox.Show("Player Demo Expired", "Demo Expired");
}));
break;
default:
break;
}
}
void OnSyncFrameEvent(List<StreamFrameInfoWr> streamList)
{
streamList.ForEach(delegate (StreamFrameInfoWr streamFrame)
{
switch (streamFrame.streamType)
{
case StreamType.VIDEO:
{
VideoFrameInfoWr vf = streamFrame as VideoFrameInfoWr;
}
break;
case StreamType.KLV:
{
KlvFrameInfoWr kf = streamFrame as KlvFrameInfoWr;
if (kf.duplicateCounter == 0 && kf.decodedData != null)
{
if (m_MonitorAgent != null && DateTime.Now.Subtract(m_LastMonitorKlvUpdate).TotalMilliseconds > MaxMonitorKlvUpdateRate)
{
PubToMonitor(kf);
m_LastMonitorKlvUpdate = DateTime.Now;
}
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
KlvPackets.Content = ++m_KlvPacketsCounter;
updateOverlay(kf);
}));
}
}
break;
case StreamType.PRIVATE_DATA:
{
DataFrameInfoWr df = streamFrame as DataFrameInfoWr;
}
break;
}
});
}
private void updateOverlay(KlvFrameInfoWr kf)
{
var jsonPckt = (JObject)kf.decodedData;
KlvTime.Text = ConvertToDateTime((long)jsonPckt["2"]).ToString("MM/dd/yyyy HH:mm:ss.fff");
if (jsonPckt["13"] != null)
KlvLat.Text = jsonPckt["13"].ToString();
if (jsonPckt["14"] != null)
KlvLon.Text = jsonPckt["14"].ToString();
if (jsonPckt["15"] != null)
KlvAlt.Text = jsonPckt["15"].ToString();
}
void OnErrorEvent(Error_Type e, string err)
{
string errMessage = string.Format("{0} {1}", e, err);
ShowStatusMessage(errMessage);
}
private void BttnPlayStartStop_Click(object sender, System.Windows.RoutedEventArgs e)
{
if (m_fPlaying == false)
{
if (RadioBttnFile.IsChecked == true)
StartFilePlayback();
else
StartStreamPlayback();
m_KlvPacketsCounter = 0;
m_fPlaying = true;
m_fPaused = false;
GridSettings.IsEnabled = false;
BttnPlayStartStop.Content = "Stop";
BttnPlayPause.IsEnabled = true;
}
else
{
m_KlvPlayer.Stop();
SetGuiOnStop();
}
}
private void BttnPlayPause_Click(object sender, RoutedEventArgs e)
{
if (!m_fPaused)
m_KlvPlayer.Pause();
else
m_KlvPlayer.Start();
}
private void BttnStepBackward_Click(object sender, RoutedEventArgs e)
{
m_KlvPlayer.StepBackward();
}
private void BttnStepForward_Click(object sender, RoutedEventArgs e)
{
m_KlvPlayer.StepForward();
}
private void BttnShowKlv_Click(object sender, RoutedEventArgs e)
{
if (m_MonitorAgent == null)
{
BttnShowKlv.Content = "Klv Off";
Task.Factory.StartNew(() =>
{
m_MonitorAgent = new CStMonitorAgent();
if (!m_MonitorAgent.OpenMonitorWindow())
{
System.Windows.Forms.MessageBox.Show("Cannot open StMonitor");
m_MonitorAgent = null;
}
});
}
else
{
m_MonitorAgent.CloseAllSubscribers();
m_MonitorAgent = null;
BttnShowKlv.Content = "Klv On";
}
}
private void RadioBttnFile_Click(object sender, RoutedEventArgs e)
{
SetGuiForStream();
}
private void RadioBttnStream_Click(object sender, RoutedEventArgs e)
{
SetGuiForStream();
}
private void SetGuiOnStop()
{
m_fPlaying = false;
GridSettings.IsEnabled = true;
BttnPlayPause.IsEnabled = false;
BttnStepBackward.IsEnabled = false;
BttnStepForward.IsEnabled = false;
BttnPlayStartStop.Content = "Start";
BttnPlayPause.Content = "Pause";
PlayerSlider.Value = 0;
m_InfoUpdateTimer.Stop();
}
private void SetGuiOnPause(bool fPaused)
{
if (fPaused)
{
BttnStepBackward.IsEnabled = true;
BttnStepForward.IsEnabled = true;
BttnPlayPause.Content = "Resume";
}
else
{
BttnStepBackward.IsEnabled = false;
BttnStepForward.IsEnabled = false;
BttnPlayPause.Content = "Pause";
}
}
private void SetGuiForStream()
{
if (RadioBttnStream.IsChecked.Value)
{
BttnStepBackward.Opacity = 0.2;
BttnStepForward.Opacity = 0.2;
BttnPlayPause.Opacity = 0.2;
PlayerSlider.Opacity = 0.2;
}
else
{
BttnStepBackward.Opacity = 1.0;
BttnStepForward.Opacity = 1.0;
BttnPlayPause.Opacity = 1.0;
PlayerSlider.Opacity = 1.0;
}
}
private void StartFilePlayback()
{
if (File.Exists(Settings.Default.FilePath))
{
m_KlvPlayer.Init(Settings.Default.FilePath);
m_KlvPlayer.Start();
m_InfoUpdateTimer.Start();
}
else
System.Windows.Forms.MessageBox.Show(string.Format("File {0} does not exist", Settings.Default.FilePath));
}
private void StartStreamPlayback()
{
if (String.IsNullOrEmpty(NicComboBox.Text))
{
System.Windows.Forms.MessageBox.Show("Please select Network Interface");
return;
}
if (String.IsNullOrEmpty(IPTextBox.Text))
{
System.Windows.Forms.MessageBox.Show("Please select IP address");
return;
}
if (String.IsNullOrEmpty(PortTextBox.Text))
{
System.Windows.Forms.MessageBox.Show("Please select a Port");
return;
}
string url = String.Format(@"udp://{0}:{1}/nic={2}/timeout={3}", IPTextBox.Text, PortTextBox.Text, NicComboBox.Text, 1000);
m_KlvPlayer.Caching = Properties.Settings.Default.Caching;
m_KlvPlayer.Init(url);
m_KlvPlayer.Start();
m_InfoUpdateTimer.Start();
}
private void BttnBrowse_Click(object sender, System.Windows.RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Video (*.MPG;*.MPEG;*.TS;*.M3U8)|*.MPG;*.MPEG;*.TS;*.M3U8|" + "All files (*.*)|*.*";
ofd.Multiselect = true;
ofd.Title = "Please Select Video File";
DialogResult res = ofd.ShowDialog();
if (res == System.Windows.Forms.DialogResult.OK)
{
Settings.Default.FilePath = ofd.FileName;
UrlTextBox.Text = ofd.FileName;
}
else
return;
}
private void FillSettings()
{
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
IPAddress[] ipv4Addresses = Array.FindAll(Dns.GetHostEntry(string.Empty).AddressList, a => a.AddressFamily == AddressFamily.InterNetwork);
NicComboBox.ItemsSource = ipv4Addresses;
if (ipv4Addresses.Count() > 0)
NicComboBox.SelectedIndex = 0;
RadioBttnFile.IsChecked = Settings.Default.FilePlayback;
RadioBttnStream.IsChecked = !Settings.Default.FilePlayback;
}));
}
private void ShowStatusMessage(string message)
{
Trace.WriteLine(message);
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
Status.Content = message;
}));
}
private void PubToMonitor(KlvFrameInfoWr kf)
{
var jsonPckt = new JObject();
jsonPckt.Add("pcktNumber", m_KlvPlayer.GetReceivedStatisticPcktInfo(m_KlvPid).TotalPackets);
jsonPckt["klvs"] = (JObject)kf.decodedData;
m_MonitorAgent.PubNewPacket(jsonPckt.ToString());
}
private void OnInfoUpdateTimer(object sender, EventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
{
var pos = m_KlvPlayer.GetCurrentPosition();
var t = TimeSpan.FromSeconds(pos);
PlayerCurPosition.Text = string.Format("{0:00}:{1:00}:{2:00}", t.Hours, t.Minutes, t.Seconds);
PlayerCurPositionMs.Text = string.Format(".{0:000}", t.Milliseconds);
if (RadioBttnFile.IsChecked.Value && !m_dragStarted)
PlayerSlider.Value = pos;
}));
}
private void PlayerSlider_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
m_dragStarted = true;
}
private void PlayerSlider_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
m_KlvPlayer.SetPosition(PlayerSlider.Value);
ResetDragStarted(120);
}
private async void ResetDragStarted(int delay)
{
await Task.Delay(delay);
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
m_dragStarted = false;
}));
}
private void OverlayBorder_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
Point p = e.GetPosition(null);
MouseX.Text = ((int)p.X).ToString();
MouseY.Text = ((int)p.Y).ToString();
}
private void OverlayBorder_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
}
public static DateTime ConvertToDateTime(long unixTime)
{
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
return dt.AddTicks(unixTime * 10);
}
}
}