2212 lines
78 KiB
C#
2212 lines
78 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Linq.Expressions;
|
|
using System.Numerics;
|
|
using System.Reflection.Metadata.Ecma335;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using ImGuiNET;
|
|
using SDL2Demo.Net;
|
|
using skyscraper5.Docsis;
|
|
using skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs;
|
|
using skyscraper5.Dvb.Descriptors;
|
|
using skyscraper5.Dvb.Psi.Model;
|
|
using skyscraper5.Mhp;
|
|
using skyscraper5.Mhp.Descriptors;
|
|
using skyscraper5.Mhp.Si;
|
|
using skyscraper5.Mhp.Si.Model;
|
|
using skyscraper5.Mpeg2;
|
|
using skyscraper5.Mpeg2.Descriptors;
|
|
using skyscraper5.Mpeg2.Psi.Model;
|
|
using skyscraper5.Scte35;
|
|
using skyscraper5.Skyscraper.Equipment;
|
|
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
|
using skyscraper5.Skyscraper.Net;
|
|
using skyscraper5.Skyscraper.Scraper;
|
|
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
|
|
using skyscraper5.Teletext.Wss;
|
|
using skyscraper8.Skyscraper.Drawing;
|
|
using skyscraper8.Skyscraper.FrequencyListGenerator;
|
|
using testdrid.SdlWrapper;
|
|
|
|
namespace SDL2Demo.Forms
|
|
{
|
|
internal class JobDisplay : IRenderable, ISkyscraperUiJunction
|
|
{
|
|
|
|
public void Render()
|
|
{
|
|
if (!memorySaverMode)
|
|
{
|
|
RenderTableIndex();
|
|
RenderEit();
|
|
RenderSdt();
|
|
RenderPat();
|
|
RenderPmt();
|
|
RenderNit();
|
|
RenderMpe();
|
|
RenderAit();
|
|
RenderDataCarousels();
|
|
RenderWss();
|
|
RenderBat();
|
|
RenderObjectCarousels();
|
|
RenderTot();
|
|
RenderTdt();
|
|
RenderCat();
|
|
RenderScte35();
|
|
RenderDocsis();
|
|
RenderFramegrabs();
|
|
}
|
|
}
|
|
|
|
#region Table-Index
|
|
|
|
private int TsType;
|
|
private bool HasPat;
|
|
private bool HasPmt;
|
|
private bool HasSdt;
|
|
private bool HasNit;
|
|
private bool HasEit;
|
|
private bool HasMpe;
|
|
private bool HasAit;
|
|
private bool HasDsmCc;
|
|
private bool HasWss;
|
|
private bool HasBat;
|
|
private bool HasTot;
|
|
private bool HasTdt;
|
|
private bool HasCat;
|
|
private bool HasScte35;
|
|
private bool ipTrafficContainsDab;
|
|
private Process myProcess;
|
|
|
|
private void RenderTableIndex()
|
|
{
|
|
if (ImGui.Begin("Table Overview"))
|
|
{
|
|
if (myProcess == null)
|
|
myProcess = Process.GetCurrentProcess();
|
|
|
|
myProcess.Refresh();
|
|
SafeText(String.Format("Used memory: {0} MB",myProcess.PrivateMemorySize64 / 1000 / 1000));
|
|
|
|
ImGui.BeginDisabled(true);
|
|
ImGui.RadioButton("TS", ref TsType, 1);
|
|
ImGui.SameLine();
|
|
ImGui.RadioButton("GS", ref TsType, 2);
|
|
ImGui.SameLine();
|
|
ImGui.RadioButton("DOCSIS", ref TsType, 3);
|
|
ImGui.SameLine();
|
|
ImGui.RadioButton("Blockstream", ref TsType, 4);
|
|
|
|
ImGuiStylePtr style = ImGui.GetStyle();
|
|
float window_visible_x2 = ImGui.GetWindowPos().X + ImGui.GetWindowContentRegionMax().X;
|
|
float el_width = 100;
|
|
if (TsType == 1)
|
|
{
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("PAT ", ref HasPat);
|
|
float lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
float nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("PMT ", ref HasPmt);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("SDT ", ref HasSdt);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("NIT ", ref HasNit);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("EIT ", ref HasEit);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("MPE ", ref HasMpe);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("AIT ", ref HasAit);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("DSM-CC ", ref HasDsmCc);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("WSS ", ref HasWss);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("BAT ", ref HasBat);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("TOT ", ref HasTot);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("TDT ", ref HasTdt);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("CAT ", ref HasCat);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
|
|
ImGui.SetNextItemWidth(el_width);
|
|
ImGui.Checkbox("SCTE-35", ref HasScte35);
|
|
lastButtonX2 = ImGui.GetItemRectMax().X;
|
|
nextButtonX2 = lastButtonX2 + style.ItemSpacing.X + el_width;
|
|
if (nextButtonX2 < window_visible_x2)
|
|
ImGui.SameLine();
|
|
}
|
|
|
|
if (TsType == 2)
|
|
{
|
|
ImGui.Checkbox("IP", ref HasMpe);
|
|
ImGui.Checkbox("SDAB", ref ipTrafficContainsDab);
|
|
}
|
|
|
|
if (TsType == 3)
|
|
{
|
|
ImGui.Checkbox("Packets", ref _docsisEnvironment.DocsisEnvironmentStatistics.PacketPduPresent);
|
|
ImGui.Checkbox("Special Use", ref _docsisEnvironment.DocsisEnvironmentStatistics.SpecialUseMacPresent);
|
|
ImGui.Checkbox("Isolation Packets", ref _docsisEnvironment.DocsisEnvironmentStatistics.IsolationPacketPduPresent);
|
|
ImGui.Checkbox("MAC Specific", ref _docsisEnvironment.DocsisEnvironmentStatistics.MacSpecificHeadersPresent);
|
|
}
|
|
ImGui.EndDisabled();
|
|
ImGui.End();
|
|
}
|
|
}
|
|
|
|
private void SafeText(string s)
|
|
{
|
|
if (string.IsNullOrEmpty(s))
|
|
{
|
|
ImGui.Text("<null>");
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(s))
|
|
{
|
|
ImGui.Text("[null]");
|
|
return;
|
|
}
|
|
|
|
if (s.Contains("% "))
|
|
s = s.Replace("% ", "%% ");
|
|
|
|
ImGui.Text(s);
|
|
}
|
|
#endregion Table-Index
|
|
|
|
#region EIT
|
|
private struct EitEventCoordinate
|
|
{
|
|
public DateTime StartTime;
|
|
public ushort NetworkId;
|
|
public ushort ServiceId;
|
|
}
|
|
|
|
private struct EitDay
|
|
{
|
|
public DateTime Date;
|
|
public bool Visible;
|
|
public Guid tableGuid;
|
|
}
|
|
|
|
private class EitDayComparer : IComparer<EitDay>
|
|
{
|
|
public int Compare(EitDay x, EitDay y)
|
|
{
|
|
return x.Date.CompareTo(y.Date);
|
|
}
|
|
}
|
|
|
|
private class EitEventCoordinateComparer : IComparer<EitEventCoordinate>
|
|
{
|
|
public int Compare(EitEventCoordinate x, EitEventCoordinate y)
|
|
{
|
|
return x.StartTime.Ticks.CompareTo(y.StartTime.Ticks);
|
|
}
|
|
}
|
|
|
|
private SortedList<EitDay, SortedList<EitEventCoordinate, string>> eitDisplay;
|
|
private void RenderEit()
|
|
{
|
|
if (eitDisplay == null)
|
|
return;
|
|
|
|
if (ImGui.Begin("Event Information Table"))
|
|
{
|
|
lock (eitDisplay)
|
|
{
|
|
foreach (KeyValuePair<EitDay, SortedList<EitEventCoordinate, string>> keyValuePair in eitDisplay)
|
|
{
|
|
EitDay day = keyValuePair.Key;
|
|
if (ImGui.CollapsingHeader(keyValuePair.Key.Date.ToLongDateString(), ref day.Visible))
|
|
{
|
|
if (day.tableGuid == Guid.Empty)
|
|
day.tableGuid = Guid.NewGuid();
|
|
ImGui.BeginTable(day.ToString(), 3,
|
|
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.NoSavedSettings);
|
|
foreach (KeyValuePair<EitEventCoordinate, string> valuePair in keyValuePair.Value)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(valuePair.Key.StartTime.ToShortTimeString());
|
|
ImGui.TableSetColumnIndex(1);
|
|
string sName = ResolveServiceDisplayName(valuePair.Key.ServiceId);
|
|
SafeText(sName);
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(valuePair.Value);
|
|
}
|
|
|
|
ImGui.EndTable();
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui.End();
|
|
}
|
|
}
|
|
|
|
public void NotifyEvent(EitEvent eitEvent)
|
|
{
|
|
if (eitDisplay == null)
|
|
eitDisplay = new SortedList<EitDay, SortedList<EitEventCoordinate, string>>(new EitDayComparer());
|
|
|
|
TsType = 1;
|
|
HasEit = true;
|
|
|
|
EitDay date = new EitDay();
|
|
date.Date = eitEvent.StartTime.Date;
|
|
date.Visible = true;
|
|
lock (eitDisplay)
|
|
{
|
|
if (!eitDisplay.ContainsKey(date))
|
|
{
|
|
eitDisplay[date] = new SortedList<EitEventCoordinate, string>(new EitEventCoordinateComparer());
|
|
}
|
|
|
|
SortedList<EitEventCoordinate, string> sortedList = eitDisplay[date];
|
|
|
|
EitEventCoordinate coordinate = new EitEventCoordinate();
|
|
coordinate.StartTime = eitEvent.StartTime;
|
|
coordinate.NetworkId = eitEvent.OriginalNetworkId;
|
|
coordinate.ServiceId = eitEvent.ServiceId;
|
|
if (!sortedList.ContainsKey(coordinate))
|
|
{
|
|
sortedList.Add(coordinate, eitEvent.EventName);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion EIT
|
|
|
|
#region SDT
|
|
|
|
private string ResolveServiceDisplayName(ushort serviceId)
|
|
{
|
|
if (sdtDisplay == null)
|
|
return String.Format("0x{0:X4}", serviceId);
|
|
|
|
lock (sdtDisplay)
|
|
{
|
|
if (sdtDisplay.ContainsKey(serviceId))
|
|
{
|
|
string v = sdtDisplay[serviceId].ServiceName;
|
|
if (string.IsNullOrEmpty(v))
|
|
return "???";
|
|
else
|
|
return v;
|
|
}
|
|
}
|
|
|
|
return String.Format("0x{0:X4}", serviceId);
|
|
}
|
|
|
|
private SdtCoordinate ResolveService(ushort serviceId)
|
|
{
|
|
if (sdtDisplay == null)
|
|
return new SdtCoordinate();
|
|
|
|
lock (sdtDisplay)
|
|
{
|
|
if (sdtDisplay.ContainsKey(serviceId))
|
|
{
|
|
return sdtDisplay[serviceId];
|
|
}
|
|
}
|
|
|
|
return new SdtCoordinate();
|
|
}
|
|
|
|
private struct SdtCoordinate
|
|
{
|
|
public string ProviderName;
|
|
public string ServiceName;
|
|
public bool FreeCaMode;
|
|
public ushort[] CaIdentifiers;
|
|
public ServiceDescriptor.ServiceTypeCoding? ServiceType;
|
|
}
|
|
|
|
private SortedList<ushort, SdtCoordinate> sdtDisplay;
|
|
private string sdtTableUuid;
|
|
private void RenderSdt()
|
|
{
|
|
if (sdtDisplay == null)
|
|
return;
|
|
|
|
if (string.IsNullOrEmpty(sdtTableUuid))
|
|
sdtTableUuid = Guid.NewGuid().ToString();
|
|
|
|
|
|
ImGui.Begin("Service Description Table");
|
|
if (ImGui.BeginTable(sdtTableUuid, 4, ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.SizingFixedFit))
|
|
{
|
|
ImGui.TableSetupColumn("Service ID");
|
|
ImGui.TableSetupColumn("Name");
|
|
ImGui.TableSetupColumn("Provider");
|
|
ImGui.TableSetupColumn("CA");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (sdtDisplay)
|
|
{
|
|
foreach (KeyValuePair<ushort, SdtCoordinate> keyValuePair in sdtDisplay)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(String.Format("{0:X4}", keyValuePair.Key));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(keyValuePair.Value.ServiceName);
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(keyValuePair.Value.ProviderName);
|
|
|
|
ImGui.TableSetColumnIndex(3);
|
|
bool ca = keyValuePair.Value.FreeCaMode;
|
|
ImGui.BeginDisabled(true);
|
|
ImGui.Checkbox("", ref ca);
|
|
ImGui.EndDisabled();
|
|
}
|
|
}
|
|
|
|
ImGui.EndTable();
|
|
ImGui.End();
|
|
}
|
|
}
|
|
|
|
public void NotifySdtService(SdtService sdtService)
|
|
{
|
|
TsType = 1;
|
|
HasSdt = true;
|
|
if (sdtDisplay == null)
|
|
sdtDisplay = new SortedList<ushort, SdtCoordinate>();
|
|
|
|
if (sdtDisplay.ContainsKey(sdtService.ServiceId))
|
|
return;
|
|
|
|
SdtCoordinate child = new SdtCoordinate();
|
|
child.ProviderName = sdtService.ServiceProviderName;
|
|
child.ServiceName = sdtService.ServiceName;
|
|
child.FreeCaMode = sdtService.FreeCaMode;
|
|
child.CaIdentifiers = sdtService.CaIdentifiers;
|
|
child.ServiceType = sdtService.ServiceType;
|
|
|
|
lock (sdtDisplay)
|
|
{
|
|
sdtDisplay.Add(sdtService.ServiceId, child);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region PAT
|
|
private class PatEntry
|
|
{
|
|
public ushort programId;
|
|
public ProgramMapping pmt;
|
|
public string PmtViewUuid;
|
|
}
|
|
|
|
private SortedList<int, PatEntry> patDisplay;
|
|
public void NotifyPatProgram(int pmtPid, ushort programId)
|
|
{
|
|
HasPat = true;
|
|
TsType = 1;
|
|
|
|
if (patDisplay == null)
|
|
patDisplay = new SortedList<int, PatEntry>();
|
|
|
|
if (patDisplay.ContainsKey(pmtPid))
|
|
return;
|
|
|
|
PatEntry patEntry = new PatEntry();
|
|
patEntry.programId = programId;
|
|
lock (patDisplay)
|
|
{
|
|
patDisplay.Add(pmtPid, patEntry);
|
|
}
|
|
}
|
|
|
|
private string patTableUuid;
|
|
public void RenderPat()
|
|
{
|
|
if (patDisplay == null)
|
|
return;
|
|
|
|
if (string.IsNullOrEmpty(patTableUuid))
|
|
patTableUuid = Guid.NewGuid().ToString();
|
|
if (ImGui.Begin("Program Allocation Table"))
|
|
{
|
|
if (ImGui.BeginTable(patTableUuid, 2, ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.SizingFixedFit))
|
|
{
|
|
ImGui.TableSetupColumn("PMT PID");
|
|
ImGui.TableSetupColumn("Service");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (patDisplay)
|
|
{
|
|
foreach (KeyValuePair<int, PatEntry> keyValuePair in patDisplay)
|
|
{
|
|
string k = String.Format("0x{0:X4}", keyValuePair.Key);
|
|
string v = ResolveServiceDisplayName(keyValuePair.Value.programId);
|
|
if (v == null)
|
|
v = "???";
|
|
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(k);
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(v);
|
|
}
|
|
}
|
|
ImGui.EndTable();
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region PMT
|
|
|
|
public void NotifyPmtProgram(ProgramMapping result, int pmtPid)
|
|
{
|
|
HasPmt = true;
|
|
TsType = 1;
|
|
|
|
if (!patDisplay.ContainsKey(pmtPid))
|
|
return;
|
|
|
|
PatEntry patEntry = patDisplay[pmtPid];
|
|
if (patEntry.pmt != null)
|
|
return;
|
|
|
|
patEntry.pmt = result;
|
|
}
|
|
|
|
private string pmtTabBarUuid;
|
|
public void RenderPmt()
|
|
{
|
|
if (!HasPmt)
|
|
return;
|
|
|
|
if (string.IsNullOrEmpty(pmtTabBarUuid))
|
|
pmtTabBarUuid = Guid.NewGuid().ToString();
|
|
|
|
if (ImGui.Begin("Program Map Table"))
|
|
{
|
|
if (ImGui.BeginTabBar(pmtTabBarUuid, ImGuiTabBarFlags.FittingPolicyScroll | ImGuiTabBarFlags.TabListPopupButton))
|
|
{
|
|
lock (patDisplay)
|
|
{
|
|
foreach (KeyValuePair<int, PatEntry> keyValuePair in patDisplay)
|
|
{
|
|
if (ImGui.BeginTabItem(ResolveServiceDisplayName(keyValuePair.Value.programId)))
|
|
{
|
|
if (string.IsNullOrEmpty(keyValuePair.Value.PmtViewUuid))
|
|
keyValuePair.Value.PmtViewUuid = Guid.NewGuid().ToString();
|
|
|
|
if (keyValuePair.Value.pmt == null)
|
|
continue;
|
|
|
|
ProgramMapping pmt = keyValuePair.Value.pmt;
|
|
|
|
SafeText(String.Format("Service ID: 0x{0:X4}", pmt.ProgramNumber));
|
|
|
|
ImGui.BeginTable(keyValuePair.Value.PmtViewUuid, 2, ImGuiTableFlags.NoSavedSettings);
|
|
ImGui.TableSetupColumn("PID");
|
|
ImGui.TableSetupColumn("Type");
|
|
ImGui.TableHeadersRow();
|
|
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(String.Format("0x{0:X4}", keyValuePair.Key));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText("PMT");
|
|
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(String.Format("0x{0:X4}", keyValuePair.Value.pmt.PcrPid));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText("PCR");
|
|
|
|
foreach (ProgramMappingStream programMappingStream in pmt.Streams)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(String.Format("0x{0:X4}", programMappingStream.ElementaryPid));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(StreamTypeAsString(programMappingStream,pmt.RegistrationFormatIdentifier));
|
|
}
|
|
|
|
ImGui.EndTable();
|
|
ImGui.EndTabItem();
|
|
}
|
|
}
|
|
}
|
|
ImGui.EndTabBar();
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
|
|
private string StreamTypeAsString(ProgramMappingStream stream, uint? parentRegistrationFormatIdentifier)
|
|
{
|
|
if (streamTypes != null)
|
|
{
|
|
if (streamTypes.ContainsKey(stream.ElementaryPid))
|
|
{
|
|
return streamTypes[stream.ElementaryPid];
|
|
}
|
|
}
|
|
if (stream.StreamType == PmtStreamType.H262)
|
|
return "MPEG-2 Video";
|
|
if (stream.AvcStillPresent.HasValue)
|
|
return "MPEG-4 Video (still frame)";
|
|
if (stream.AudioType.HasValue)
|
|
{
|
|
switch (stream.AudioType)
|
|
{
|
|
case AudioType.CleanEffects: return "Audio (no effects)";
|
|
case AudioType.HearingImpaired: return "Audio (for hearing impaired)";
|
|
case AudioType.VisualImpairedCommentary: return "Audio (for visually impaired)";
|
|
}
|
|
}
|
|
|
|
if (stream.StreamType == PmtStreamType.AvcVideoStream)
|
|
{
|
|
return "MPEG-4 Video";
|
|
}
|
|
|
|
if (stream.StreamType == PmtStreamType.Iso11172Audio)
|
|
{
|
|
return "Audio";
|
|
}
|
|
|
|
if (stream.StreamType == PmtStreamType.Iso13818_3Audio)
|
|
return "MPEG-2 Audio";
|
|
if (stream.StreamType == PmtStreamType.Iso13818_7AudioADTS)
|
|
return "AAC Audio";
|
|
if (stream.StreamType == PmtStreamType.HevcVideoStream)
|
|
return "H.265 Video";
|
|
if (stream.StreamType == PmtStreamType.Iso13818_1PesPackets && stream.Ac4ChannelMode.HasValue)
|
|
return "Dolby AC-4 Audio";
|
|
if (stream.StreamType == PmtStreamType.Iso13818_1PesPackets && stream.BSID.HasValue)
|
|
return "Dolby AC-3 Audio";
|
|
if (stream.StreamType == PmtStreamType.Iso14496_3Audio && stream.AacProfileAndLevel.HasValue)
|
|
return "AAC Audio";
|
|
if ((int)stream.StreamType == 0x81 && stream.ComponentType.HasValue)
|
|
return "Dolby AC-3 Audio";
|
|
if (stream.Teletexts != null)
|
|
return "Teletext";
|
|
|
|
if (stream.Applications != null)
|
|
return "Red-button Application";
|
|
|
|
if (stream.DataBroadcastId == 0x0123)
|
|
return "Red-button Application";
|
|
|
|
if (stream.DataBroadcastId == 0x000a)
|
|
return "System Software Update";
|
|
|
|
if (stream.StreamType == PmtStreamType.Iso13818_1PesPackets && stream.Subtitlings != null && stream.Subtitlings.Length > 0)
|
|
return "Subtitle";
|
|
|
|
if (stream.DataBroadcastId == 0xf0)
|
|
return "MHP Application";
|
|
|
|
|
|
if (stream.FormatIdentifier.HasValue && stream.FormatIdentifier == 0x43554549 && (int)stream.StreamType == 0x86)
|
|
return "Advertising Metadata";
|
|
|
|
if ((int)stream.StreamType == 0x86 && parentRegistrationFormatIdentifier.HasValue && parentRegistrationFormatIdentifier.Value == 0x43554549)
|
|
return "Advertising Metadata";
|
|
|
|
if (stream.DataBroadcastId == 0x0007)
|
|
return "Object Carousel";
|
|
|
|
if (stream.StreamType == PmtStreamType.Iso13818_1PesPackets && stream.VbiData != null)
|
|
return "Teletext";
|
|
|
|
if ((byte)stream.StreamType == 0x89 && stream.AncillaryDataDescriptor != null && stream.AncillaryDataDescriptor.RdsOnly)
|
|
return "Radio Data Service";
|
|
|
|
if (stream.DataBroadcastId.HasValue && stream.DataBroadcastId.Value == 0x0005 /*&& stream.StreamType == PmtStreamType.Iso13818_6TypeD*/)
|
|
return "Multiprotocol Encapsulation";
|
|
|
|
if (stream.DataBroadcastId == 0x0106)
|
|
return "MHEG-5";
|
|
|
|
if (stream.DataBroadcastId == 0x000b)
|
|
return "IP/MAC Notification";
|
|
|
|
if (stream.RelatedContentDescriptorPresent.HasValue)
|
|
if (stream.RelatedContentDescriptorPresent.Value && stream.StreamType == PmtStreamType.Iso13818_1PrivateSections)
|
|
return "Related Content Table Information";
|
|
|
|
if (stream.NumT2MiStreams.HasValue && stream.StreamType == PmtStreamType.Iso13818_1PesPackets)
|
|
return "T2-MI";
|
|
|
|
return String.Format("??? (Type 0x{0:X2})", (int)stream.StreamType);
|
|
}
|
|
#endregion
|
|
|
|
#region NIT
|
|
|
|
private class NitNetworkMeta
|
|
{
|
|
public ushort ONID;
|
|
public string DisplayUUID;
|
|
|
|
public override string ToString()
|
|
{
|
|
return String.Format("Network 0x{0:X4}", ONID);
|
|
}
|
|
|
|
public bool Equals(NitNetworkMeta other)
|
|
{
|
|
return ONID == other.ONID;
|
|
}
|
|
|
|
public override bool Equals(object? obj)
|
|
{
|
|
return obj is NitNetworkMeta other && Equals(other);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return ONID.GetHashCode();
|
|
}
|
|
}
|
|
|
|
private class NitCoordinateComparer : IComparer<NitNetworkMeta>
|
|
{
|
|
public int Compare(NitNetworkMeta x, NitNetworkMeta y)
|
|
{
|
|
return x.ONID.CompareTo(y.ONID);
|
|
}
|
|
}
|
|
|
|
private SortedList<NitNetworkMeta,SortedList<ushort, NitTransportStream>> nitDisplay;
|
|
private string nitTableUuid;
|
|
|
|
public void NotifyNit(NitTransportStream transportStream)
|
|
{
|
|
TsType = 1;
|
|
HasNit = true;
|
|
|
|
if (nitDisplay == null)
|
|
nitDisplay = new SortedList<NitNetworkMeta, SortedList<ushort, NitTransportStream>>(new NitCoordinateComparer());
|
|
|
|
NitNetworkMeta nnm = new NitNetworkMeta();
|
|
nnm.ONID = transportStream.OriginalNetworkId;
|
|
if (!nitDisplay.ContainsKey(nnm))
|
|
{
|
|
lock (nitDisplay)
|
|
{
|
|
nitDisplay.Add(nnm, new SortedList<ushort, NitTransportStream>());
|
|
}
|
|
}
|
|
|
|
SortedList<ushort, NitTransportStream> nitTransportStreams = nitDisplay[nnm];
|
|
if (nitTransportStreams.ContainsKey(transportStream.TransportStreamId))
|
|
return;
|
|
|
|
lock (nitTransportStreams)
|
|
{
|
|
nitTransportStreams.Add(transportStream.TransportStreamId, transportStream);
|
|
}
|
|
}
|
|
|
|
private string GetFrequencyString(NitTransportStream nts)
|
|
{
|
|
if (nts.Frequency.HasValue && nts.Polarization.HasValue)
|
|
return String.Format("{0} Mhz, {1}", nts.Frequency.Value / 100, nts.Polarization.ToString().Substring(0, 1));
|
|
|
|
return "???";
|
|
}
|
|
|
|
private void RenderNit()
|
|
{
|
|
if (nitDisplay == null)
|
|
return;
|
|
|
|
if (string.IsNullOrWhiteSpace(nitTableUuid))
|
|
nitTableUuid = Guid.NewGuid().ToString();
|
|
|
|
if (ImGui.Begin("Network Information Table"))
|
|
{
|
|
lock (nitDisplay)
|
|
{
|
|
foreach (KeyValuePair<NitNetworkMeta, SortedList<ushort, NitTransportStream>> keyValuePair in nitDisplay)
|
|
{
|
|
if (ImGui.CollapsingHeader(keyValuePair.Key.ToString()))
|
|
{
|
|
if (string.IsNullOrEmpty(keyValuePair.Key.DisplayUUID))
|
|
keyValuePair.Key.DisplayUUID = Guid.NewGuid().ToString();
|
|
if (ImGui.BeginTable(keyValuePair.Key.DisplayUUID, 4, ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.SizingFixedFit))
|
|
{
|
|
lock (keyValuePair.Value)
|
|
{
|
|
foreach (KeyValuePair<ushort, NitTransportStream> nitTransportStream in keyValuePair
|
|
.Value)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(nitTransportStream.Value.DeliveryMethod.ToString().Replace('_', '_'));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
if (nitTransportStream.Value.OrbitalPosition.HasValue &&
|
|
nitTransportStream.Value.East.HasValue)
|
|
{
|
|
SafeText(String.Format("{0:F1} °{1}",
|
|
nitTransportStream.Value.OrbitalPosition.Value,
|
|
nitTransportStream.Value.East.Value ? "E" : "W"));
|
|
}
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(GetFrequencyString(nitTransportStream.Value));
|
|
|
|
ImGui.TableSetColumnIndex(3);
|
|
if (nitTransportStream.Value.SymbolRate.HasValue)
|
|
SafeText(String.Format("{0} ksym/s",
|
|
nitTransportStream.Value.SymbolRate / 10));
|
|
}
|
|
}
|
|
}
|
|
ImGui.EndTable();
|
|
}
|
|
}
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MPE
|
|
|
|
private IpTrafficInfoComparer trafficInfoComparer;
|
|
private string mpeTableUuid;
|
|
private List<KeyValuePair<IpTrafficInfo, IpPerformanceInfo>> mpeDisplays;
|
|
public void NotifyMpeTraffic(IpTrafficInfo iti, int ipv4PacketLength)
|
|
{
|
|
if (trafficInfoComparer == null)
|
|
trafficInfoComparer = new IpTrafficInfoComparer();
|
|
HasMpe = true;
|
|
if (mpeDisplays == null)
|
|
mpeDisplays = new List<KeyValuePair<IpTrafficInfo, IpPerformanceInfo>>();
|
|
|
|
lock (mpeDisplays)
|
|
{
|
|
foreach (KeyValuePair<IpTrafficInfo, IpPerformanceInfo> line in mpeDisplays)
|
|
{
|
|
if (line.Key.Equals(iti))
|
|
{
|
|
line.Value.CountPacket(ipv4PacketLength);
|
|
return;
|
|
}
|
|
}
|
|
|
|
KeyValuePair<IpTrafficInfo, IpPerformanceInfo> newChild = new KeyValuePair<IpTrafficInfo, IpPerformanceInfo>(iti, new IpPerformanceInfo());
|
|
newChild.Value.CountPacket(ipv4PacketLength);
|
|
mpeDisplays.Add(newChild);
|
|
}
|
|
}
|
|
|
|
private DateTime prev, next;
|
|
private void RenderMpe()
|
|
{
|
|
if (mpeDisplays == null)
|
|
return;
|
|
|
|
prev = next;
|
|
next = DateTime.Now;
|
|
if (prev.Second != next.Second)
|
|
{
|
|
lock (mpeDisplays)
|
|
{
|
|
foreach (KeyValuePair<IpTrafficInfo, IpPerformanceInfo> line in mpeDisplays)
|
|
{
|
|
line.Value.UpdatePerSeconds();
|
|
}
|
|
}
|
|
}
|
|
|
|
string windowName = String.Format("{0} Encapsulation", TsType == 1 ? "Multiprotocol" : "Generic Stream");
|
|
if (ImGui.Begin(windowName))
|
|
{
|
|
if (mpeDisplays != null)
|
|
{
|
|
if (mpeDisplays.Count > 0)
|
|
{
|
|
SafeText(String.Format("Communication parties: {0}", mpeDisplays.Count));
|
|
}
|
|
}
|
|
if (string.IsNullOrEmpty(mpeTableUuid))
|
|
mpeTableUuid = Guid.NewGuid().ToString();
|
|
if (ImGui.BeginTable(mpeTableUuid, 5, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.NoSavedSettings))
|
|
{
|
|
ImGui.TableSetupColumn("Protocol");
|
|
ImGui.TableSetupColumn("Source IP");
|
|
ImGui.TableSetupColumn("Destination IP");
|
|
ImGui.TableSetupColumn("Packets");
|
|
ImGui.TableSetupColumn("Traffic");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (mpeDisplays)
|
|
{
|
|
mpeDisplays.Sort(trafficInfoComparer);
|
|
foreach (KeyValuePair<IpTrafficInfo, IpPerformanceInfo> ipPerformanceInfo in mpeDisplays)
|
|
{
|
|
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(IpTrafficInfo.GetProtocolName(ipPerformanceInfo.Key.Protocol));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(RenderIp(ipPerformanceInfo, false));
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(RenderIp(ipPerformanceInfo, true));
|
|
|
|
ImGui.TableSetColumnIndex(3);
|
|
SafeText(ipPerformanceInfo.Value.TotalPackets.ToString());
|
|
|
|
ImGui.TableSetColumnIndex(4);
|
|
SafeText(String.Format("{0:F1} kb/s",
|
|
(double)ipPerformanceInfo.Value.BytesPerSecond / 1000.0));
|
|
}
|
|
}
|
|
|
|
ImGui.EndTable();
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
|
|
private string RenderIp(KeyValuePair<IpTrafficInfo, IpPerformanceInfo> ipPerformanceInfo, bool destination)
|
|
{
|
|
if (!destination)
|
|
{
|
|
if (string.IsNullOrEmpty(ipPerformanceInfo.Key.SourceName))
|
|
return ipPerformanceInfo.Key.Source.ToString();
|
|
else
|
|
return ipPerformanceInfo.Key.SourceName;
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrEmpty(ipPerformanceInfo.Key.TargetName))
|
|
return ipPerformanceInfo.Key.Target.ToString();
|
|
else
|
|
return ipPerformanceInfo.Key.TargetName;
|
|
}
|
|
/*if (destination)
|
|
{
|
|
if (!string.IsNullOrEmpty(ipPerformanceInfo.Value.DestinationResolution))
|
|
{
|
|
return ipPerformanceInfo.Value.DestinationResolution;
|
|
}
|
|
else
|
|
{
|
|
return ipPerformanceInfo.Key.Target.ToString();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!string.IsNullOrEmpty(ipPerformanceInfo.Value.SourceResolution))
|
|
{
|
|
return ipPerformanceInfo.Value.SourceResolution;
|
|
}
|
|
else
|
|
{
|
|
return ipPerformanceInfo.Key.Source.ToString();
|
|
}
|
|
}*/
|
|
}
|
|
|
|
public int GseCommunicationParties
|
|
{
|
|
get
|
|
{
|
|
if (TsType != 2)
|
|
return 0;
|
|
|
|
if (mpeDisplays == null)
|
|
return 0;
|
|
|
|
return mpeDisplays.Count;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region AIT
|
|
|
|
private SortedList<ApplicationIdentifier, AitApplication> aitDisplay;
|
|
private string aitTableUuid;
|
|
public void NotifyAit(AitApplication aitApplication)
|
|
{
|
|
TsType = 1;
|
|
HasAit = true;
|
|
|
|
if (aitDisplay == null)
|
|
aitDisplay = new SortedList<ApplicationIdentifier, AitApplication>(new ApplicationIdentifierComparer());
|
|
|
|
lock (aitDisplay)
|
|
{
|
|
if (!aitDisplay.ContainsKey(aitApplication.ApplicationIdentifier))
|
|
{
|
|
aitDisplay.Add(aitApplication.ApplicationIdentifier, aitApplication);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RenderAit()
|
|
{
|
|
if (aitDisplay == null)
|
|
return;
|
|
|
|
if (ImGui.Begin("Application Identification Table"))
|
|
{
|
|
if (string.IsNullOrEmpty(aitTableUuid))
|
|
aitTableUuid = Guid.NewGuid().ToString();
|
|
|
|
if (ImGui.BeginTable(aitTableUuid, 2,ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.SizingFixedFit))
|
|
{
|
|
ImGui.TableSetupColumn("Application Name");
|
|
ImGui.TableSetupColumn("Transport");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (aitDisplay)
|
|
{
|
|
foreach (KeyValuePair<ApplicationIdentifier, AitApplication> keyValuePair in aitDisplay)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(keyValuePair.Value.TryGetName());
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
foreach (TransportProtocolDescriptor transportProtocolDescriptor in keyValuePair.Value.TransportProtocols)
|
|
{
|
|
SafeText(transportProtocolDescriptor.Selector.ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui.EndTable();
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Data Carousel
|
|
|
|
private struct DsmCcModuleIdentifier
|
|
{
|
|
public int pid;
|
|
public ushort moduleId;
|
|
public byte moduleVersion;
|
|
|
|
}
|
|
|
|
private sealed class DsmCcModuleIdentifierComparer : IComparer<DsmCcModuleIdentifier>
|
|
{
|
|
public int Compare(DsmCcModuleIdentifier x, DsmCcModuleIdentifier y)
|
|
{
|
|
var pidComparison = x.pid.CompareTo(y.pid);
|
|
if (pidComparison != 0) return pidComparison;
|
|
var moduleIdComparison = x.moduleId.CompareTo(y.moduleId);
|
|
if (moduleIdComparison != 0) return moduleIdComparison;
|
|
return x.moduleVersion.CompareTo(y.moduleVersion);
|
|
}
|
|
}
|
|
|
|
|
|
private SortedList<DsmCcModuleIdentifier, double> dsmCcDisplay;
|
|
private string objectCarouselTableUuid;
|
|
|
|
public void DsmCcModuleAdd(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion)
|
|
{
|
|
TsType = 1;
|
|
HasDsmCc = true;
|
|
|
|
if (dsmCcDisplay == null)
|
|
dsmCcDisplay = new SortedList<DsmCcModuleIdentifier, double>(new DsmCcModuleIdentifierComparer());
|
|
|
|
DsmCcModuleIdentifier id = new DsmCcModuleIdentifier();
|
|
id.pid = elementaryPid;
|
|
id.moduleId = moduleInfoModuleId;
|
|
id.moduleVersion = moduleInfoModuleVersion;
|
|
lock (dsmCcDisplay)
|
|
{
|
|
dsmCcDisplay.Add(id, 0);
|
|
}
|
|
}
|
|
|
|
public void DsmCcModuleProgress(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion, double progress)
|
|
{
|
|
TsType = 1;
|
|
HasDsmCc = true;
|
|
|
|
if (dsmCcDisplay == null)
|
|
return;
|
|
|
|
DsmCcModuleIdentifier id = new DsmCcModuleIdentifier();
|
|
id.pid = elementaryPid;
|
|
id.moduleId = moduleInfoModuleId;
|
|
id.moduleVersion = moduleInfoModuleVersion;
|
|
if (!dsmCcDisplay.ContainsKey(id))
|
|
return;
|
|
lock (dsmCcDisplay)
|
|
{
|
|
dsmCcDisplay[id] = progress;
|
|
}
|
|
}
|
|
|
|
public void DsmCcModuleComplete(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion)
|
|
{
|
|
TsType = 1;
|
|
HasDsmCc = true;
|
|
|
|
if (dsmCcDisplay == null)
|
|
return;
|
|
|
|
DsmCcModuleIdentifier id = new DsmCcModuleIdentifier();
|
|
id.pid = elementaryPid;
|
|
id.moduleId = moduleModuleId;
|
|
id.moduleVersion = moduleModuleVersion;
|
|
lock (dsmCcDisplay)
|
|
{
|
|
dsmCcDisplay.Remove(id);
|
|
}
|
|
}
|
|
|
|
private void RenderDataCarousels()
|
|
{
|
|
if (dsmCcDisplay == null)
|
|
return;
|
|
if (dsmCcDisplay.Count == 0)
|
|
return;
|
|
|
|
if (ImGui.Begin("Digital Storage Media Command & Control, Data Carousels"))
|
|
{
|
|
if (string.IsNullOrEmpty(objectCarouselTableUuid))
|
|
{
|
|
objectCarouselTableUuid = Guid.NewGuid().ToString();
|
|
}
|
|
|
|
if (ImGui.BeginTable(objectCarouselTableUuid, 4, ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.SizingFixedFit))
|
|
{
|
|
ImGui.TableSetupColumn("PID");
|
|
ImGui.TableSetupColumn("Module ID");
|
|
ImGui.TableSetupColumn("Version");
|
|
ImGui.TableSetupColumn("Progress");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (dsmCcDisplay)
|
|
{
|
|
foreach (KeyValuePair<DsmCcModuleIdentifier, double> keyValuePair in dsmCcDisplay)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(String.Format("{0}", keyValuePair.Key.pid));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(String.Format("{0}", keyValuePair.Key.moduleId));
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(String.Format("{0}", keyValuePair.Key.moduleVersion));
|
|
|
|
ImGui.TableSetColumnIndex(3);
|
|
ImGui.SetNextItemWidth(100);
|
|
ImGui.ProgressBar(Convert.ToSingle(keyValuePair.Value) / 100.0f, Vector2.Zero, String.Format("{0}%", keyValuePair.Value));
|
|
}
|
|
}
|
|
ImGui.EndTable();
|
|
}
|
|
ImGui.End();
|
|
}
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region WSS
|
|
|
|
private string wssTableUuid;
|
|
private SortedList<ushort, WssDataBlock> wssDisplay;
|
|
public void NotifyWss(ushort programNumber, WssDataBlock wssDataBlock)
|
|
{
|
|
HasWss = true;
|
|
TsType = 1;
|
|
|
|
if (wssDisplay == null)
|
|
wssDisplay = new SortedList<ushort, WssDataBlock>();
|
|
|
|
if (!wssDisplay.ContainsKey(programNumber))
|
|
{
|
|
lock (wssDisplay)
|
|
{
|
|
wssDisplay.Add(programNumber, wssDataBlock);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RenderWss()
|
|
{
|
|
if (wssDisplay == null)
|
|
return;
|
|
|
|
if (ImGui.Begin("Wide Screen Signalling"))
|
|
{
|
|
if (String.IsNullOrEmpty(wssTableUuid))
|
|
wssTableUuid = Guid.NewGuid().ToString();
|
|
|
|
if (ImGui.BeginTable(wssTableUuid, 7, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.NoSavedSettings))
|
|
{
|
|
ImGui.TableSetupColumn("Service");
|
|
ImGui.TableSetupColumn("Aspect Ratio");
|
|
ImGui.TableSetupColumn("Film Mode");
|
|
ImGui.TableSetupColumn("Motion Adaptive Color");
|
|
ImGui.TableSetupColumn("Subtitle");
|
|
ImGui.TableSetupColumn("Surround Sound");
|
|
ImGui.TableSetupColumn("Copy restricted");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (wssDisplay)
|
|
{
|
|
foreach (KeyValuePair<ushort, WssDataBlock> wssDataBlock in wssDisplay)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(ResolveServiceDisplayName(wssDataBlock.Key));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(wssDataBlock.Value.AspectRatioToString());
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
ImGui.BeginDisabled(true);
|
|
bool b = wssDataBlock.Value.FilmMode;
|
|
ImGui.Checkbox("", ref b);
|
|
|
|
ImGui.TableSetColumnIndex(3);
|
|
b = wssDataBlock.Value.MotionAdaptiveColorPlus;
|
|
ImGui.Checkbox("", ref b);
|
|
|
|
ImGui.TableSetColumnIndex(4);
|
|
b = wssDataBlock.Value.SubtitlesWithinTeletext;
|
|
ImGui.Checkbox("", ref b);
|
|
|
|
ImGui.TableSetColumnIndex(5);
|
|
b = wssDataBlock.Value.SurroundSound;
|
|
ImGui.Checkbox("", ref b);
|
|
|
|
ImGui.TableSetColumnIndex(6);
|
|
b = wssDataBlock.Value.CopyingRestricted;
|
|
ImGui.Checkbox("", ref b);
|
|
ImGui.EndDisabled();
|
|
}
|
|
}
|
|
|
|
ImGui.EndTable();
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Stream Type Autodetection
|
|
|
|
private Dictionary<int, string> streamTypes;
|
|
|
|
public void NotifyStreamTypeDetection(string contestantTag, int pid)
|
|
{
|
|
if (streamTypes == null)
|
|
streamTypes = new Dictionary<int, string>();
|
|
streamTypes[pid] = contestantTag;
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
#region BAT
|
|
|
|
private struct DisplayableBat
|
|
{
|
|
public string Name;
|
|
public List<LinkageDescriptor> Linkages;
|
|
public string TableUuid;
|
|
public HashSet<BatTransportStream> TransportStreams;
|
|
}
|
|
|
|
private SortedList<ushort, DisplayableBat> batDisplay;
|
|
|
|
public void NotifyBat(BatBouquet batBouquet)
|
|
{
|
|
TsType = 1;
|
|
HasBat = true;
|
|
|
|
if (batDisplay == null)
|
|
batDisplay = new SortedList<ushort, DisplayableBat>();
|
|
|
|
if (batDisplay.ContainsKey(batBouquet.BouquetId))
|
|
return;
|
|
|
|
DisplayableBat child = new DisplayableBat();
|
|
child.Name = batBouquet.TryGetName();
|
|
child.Linkages = batBouquet.Linkages;
|
|
child.TableUuid = Guid.NewGuid().ToString();
|
|
child.TransportStreams = new HashSet<BatTransportStream>();
|
|
|
|
lock (batDisplay)
|
|
{
|
|
batDisplay[batBouquet.BouquetId] = child;
|
|
}
|
|
}
|
|
|
|
public void NotifyBatTs(ushort batBouquetBouquetId, BatTransportStream child)
|
|
{
|
|
TsType = 1;
|
|
HasBat = true;
|
|
|
|
if (batDisplay == null)
|
|
return;
|
|
if (!batDisplay.ContainsKey(batBouquetBouquetId))
|
|
return;
|
|
|
|
batDisplay[batBouquetBouquetId].TransportStreams.Add(child);
|
|
}
|
|
|
|
private void RenderBat()
|
|
{
|
|
if (batDisplay == null)
|
|
return;
|
|
|
|
if (batDisplay.Count == 0)
|
|
return;
|
|
|
|
if (ImGui.Begin("Bouquet Association Table"))
|
|
{
|
|
lock (batDisplay)
|
|
{
|
|
foreach (KeyValuePair<ushort, DisplayableBat> keyValuePair in batDisplay)
|
|
{
|
|
if (ImGui.CollapsingHeader(String.Format("Bouquet #{0} - {1}", keyValuePair.Key, keyValuePair.Value.Name)))
|
|
{
|
|
if (ImGui.BeginTable(keyValuePair.Value.TableUuid, 5, ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.SizingFixedFit))
|
|
{
|
|
ImGui.TableSetupColumn("L/TS");
|
|
ImGui.TableSetupColumn("ONID");
|
|
ImGui.TableSetupColumn("TSID");
|
|
ImGui.TableSetupColumn("Service");
|
|
ImGui.TableSetupColumn("");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (keyValuePair.Value.Linkages)
|
|
{
|
|
foreach (LinkageDescriptor linkageDescriptor in keyValuePair.Value.Linkages)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText("Link");
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(String.Format("{0:X4}",linkageDescriptor.OriginalNetworkId));
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(String.Format("{0:X4}", linkageDescriptor.TransportStreamId));
|
|
|
|
ImGui.TableSetColumnIndex(3);
|
|
SafeText(ResolveServiceDisplayName(linkageDescriptor.ServiceId));
|
|
|
|
ImGui.TableSetColumnIndex(4);
|
|
SafeText(linkageDescriptor.LinkageType.ToString());
|
|
}
|
|
}
|
|
|
|
lock (keyValuePair.Value.TransportStreams)
|
|
{
|
|
foreach (BatTransportStream valueTransportStream in keyValuePair.Value.TransportStreams)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText("TS");
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(String.Format("{0:X4}", valueTransportStream.OriginalNetworkId));
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(String.Format("{0:X4}", valueTransportStream.TransportStreamId));
|
|
|
|
if (valueTransportStream.ServiceList != null)
|
|
{
|
|
foreach (ServiceListDescriptor.Service service in valueTransportStream.ServiceList)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText("Service");
|
|
|
|
ImGui.TableSetColumnIndex(3);
|
|
SafeText(ResolveServiceDisplayName(service.ServiceId));
|
|
|
|
ImGui.TableSetColumnIndex(4);
|
|
SafeText(service.ServiceType.ToString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ImGui.EndTable();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Object Carousel
|
|
|
|
private SortedList<int, VfsDirectory> displayObjectCarouselRoots;
|
|
|
|
private string GetServiceNameFromPid(int pid)
|
|
{
|
|
lock (patDisplay)
|
|
{
|
|
foreach (KeyValuePair<int, PatEntry> keyValuePair in patDisplay)
|
|
{
|
|
PatEntry patEntry = keyValuePair.Value;
|
|
if (patEntry.pmt == null)
|
|
continue;
|
|
|
|
foreach (ProgramMappingStream programMappingStream in patEntry.pmt.Streams)
|
|
{
|
|
if (programMappingStream.ElementaryPid == pid)
|
|
{
|
|
return ResolveServiceDisplayName(patEntry.programId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return "???";
|
|
}
|
|
|
|
public void DsmCcVfs(VfsFile vfsFile)
|
|
{
|
|
TsType = 1;
|
|
HasDsmCc = true;
|
|
if (displayObjectCarouselRoots == null)
|
|
displayObjectCarouselRoots = new SortedList<int, VfsDirectory>();
|
|
if (displayObjectCarouselRoots.ContainsKey(vfsFile.SourcePid))
|
|
return;
|
|
|
|
VfsDirectory masterDirectory = vfsFile.ParentDirectory;
|
|
while (masterDirectory.ParentDirectory != null)
|
|
masterDirectory = masterDirectory.ParentDirectory;
|
|
|
|
lock (displayObjectCarouselRoots)
|
|
{
|
|
displayObjectCarouselRoots.Add(vfsFile.SourcePid, masterDirectory);
|
|
}
|
|
}
|
|
|
|
private void RenderObjectCarousels()
|
|
{
|
|
if (displayObjectCarouselRoots == null)
|
|
return;
|
|
|
|
if (ImGui.Begin("Digital Storage Media - Command & Control, Object Carousels"))
|
|
{
|
|
lock (displayObjectCarouselRoots)
|
|
{
|
|
foreach (KeyValuePair<int, VfsDirectory> displayObjectCarouselRoot in displayObjectCarouselRoots)
|
|
{
|
|
string name = String.Format("Object Carousel in PID 0x{1:X4} (Service: {0})", GetServiceNameFromPid(displayObjectCarouselRoot.Key), displayObjectCarouselRoot.Key);
|
|
if (ImGui.CollapsingHeader(name))
|
|
{
|
|
RenderDirectoryNode(displayObjectCarouselRoot.Value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RenderDirectoryNode(VfsDirectory directory)
|
|
{
|
|
if (!directory.SkyscrpaerUiData.ContainsKey("UUID"))
|
|
directory.SkyscrpaerUiData.Add("UUID", Guid.NewGuid().ToString());
|
|
|
|
string dname = directory.Name;
|
|
if (string.IsNullOrEmpty(dname) && directory.ParentDirectory == null)
|
|
dname = "<root directory>";
|
|
|
|
if (ImGui.TreeNode(directory.SkyscrpaerUiData["UUID"].ToString(), dname))
|
|
{
|
|
foreach (VfsDirectory subdirectory in directory.subdirectories)
|
|
{
|
|
RenderDirectoryNode(subdirectory);
|
|
}
|
|
|
|
foreach (VfsFile directoryFile in directory.files)
|
|
{
|
|
SafeText(directoryFile.Name);
|
|
}
|
|
|
|
foreach (VfsEvent directoryEvent in directory.events)
|
|
{
|
|
SafeText(directoryEvent.Name);
|
|
}
|
|
ImGui.TreePop();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region TOT
|
|
|
|
private DateTime? totTime;
|
|
private LocalTimeOffsetDescriptor totDescriptor;
|
|
private string totDisplayUuid;
|
|
|
|
public void NotifyTot(DateTime utcTime, LocalTimeOffsetDescriptor ltod)
|
|
{
|
|
TsType = 1;
|
|
HasTot = true;
|
|
|
|
totTime = utcTime;
|
|
totDescriptor = ltod;
|
|
}
|
|
|
|
private void RenderTot()
|
|
{
|
|
if (!totTime.HasValue)
|
|
return;
|
|
|
|
if (ImGui.Begin("Time Offset Table"))
|
|
{
|
|
SafeText(totTime.ToString());
|
|
|
|
if (totDescriptor != null)
|
|
{
|
|
if (totDescriptor.Valid)
|
|
{
|
|
if (string.IsNullOrEmpty(totDisplayUuid))
|
|
totDisplayUuid = Guid.NewGuid().ToString();
|
|
|
|
if (ImGui.BeginTable(totDisplayUuid, 3, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.NoSavedSettings))
|
|
{
|
|
ImGui.TableSetupColumn("Region");
|
|
ImGui.TableSetupColumn("Polarity");
|
|
ImGui.TableSetupColumn("Offset");
|
|
ImGui.TableHeadersRow();
|
|
|
|
foreach (LocalTimeOffsetDescriptor.LocalTime totDescriptorLocalTimeOffset in totDescriptor.LocalTimeOffsets)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(totDescriptorLocalTimeOffset.CountryCode);
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
bool b = totDescriptorLocalTimeOffset.LocalTimeOffsetPolarity;
|
|
ImGui.BeginDisabled(true);
|
|
ImGui.Checkbox("", ref b);
|
|
ImGui.EndDisabled();
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(totDescriptorLocalTimeOffset.LocalTimeOffset.ToString());
|
|
}
|
|
ImGui.EndTable();
|
|
}
|
|
}
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region TDT
|
|
|
|
private DateTime? tdtDisplay;
|
|
public void NotifyTdt(DateTime utcTime)
|
|
{
|
|
TsType = 1;
|
|
HasTdt = true;
|
|
tdtDisplay = utcTime;
|
|
}
|
|
|
|
|
|
|
|
private void RenderTdt()
|
|
{
|
|
if (tdtDisplay.HasValue)
|
|
{
|
|
if (ImGui.Begin("Time and Date Table"))
|
|
{
|
|
SafeText(tdtDisplay.Value.ToString());
|
|
ImGui.End();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CAT
|
|
private string caTableUuid;
|
|
private HashSet<CaDescriptor> caDisplay;
|
|
public void NotifyCat(CaDescriptor caDescriptor)
|
|
{
|
|
TsType = 1;
|
|
HasCat = true;
|
|
|
|
if (caDisplay == null)
|
|
caDisplay = new HashSet<CaDescriptor>();
|
|
|
|
lock (caDisplay)
|
|
{
|
|
caDisplay.Add(caDescriptor);
|
|
}
|
|
}
|
|
private void RenderCat()
|
|
{
|
|
if (caDisplay == null)
|
|
return;
|
|
|
|
if (ImGui.Begin("Conditional Access Table"))
|
|
{
|
|
if (string.IsNullOrEmpty(caTableUuid))
|
|
caTableUuid = Guid.NewGuid().ToString();
|
|
|
|
if (ImGui.BeginTable(caTableUuid, 3, ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.SizingFixedFit))
|
|
{
|
|
ImGui.TableSetupColumn("CA System");
|
|
ImGui.TableSetupColumn("ECM/EMM PID");
|
|
ImGui.TableSetupColumn("Private Data");
|
|
ImGui.TableHeadersRow();
|
|
lock (caDisplay)
|
|
{
|
|
foreach (CaDescriptor caDescriptor in caDisplay)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(CaSystemNames.GetHumanReadableName(caDescriptor.CaSystemId));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(String.Format("{0:X4}", caDescriptor.CaPid));
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
if (caDescriptor.PrivateData != null)
|
|
{
|
|
if (caDescriptor.PrivateData.Length != 0)
|
|
SafeText(BitConverter.ToString(caDescriptor.PrivateData));
|
|
}
|
|
}
|
|
}
|
|
ImGui.EndTable();
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
#endregion CAT
|
|
|
|
#region SCTE-35
|
|
class Scte35DisplayData
|
|
{
|
|
private const string NONE = "<none>";
|
|
|
|
public SpliceInsert LastSplice { get; set; }
|
|
public TimeSignal TimeSignal { get; set; }
|
|
|
|
public string LastSpliceToString()
|
|
{
|
|
if (LastSplice == null)
|
|
return NONE;
|
|
|
|
if (!LastSplice.SpliceTime.HasValue)
|
|
return NONE;
|
|
|
|
return String.Format("0x{0:X12}", LastSplice.SpliceTime.Value);
|
|
}
|
|
|
|
public string TimeSignalToString()
|
|
{
|
|
if (TimeSignal == null)
|
|
return NONE;
|
|
|
|
if (!TimeSignal.Value.HasValue)
|
|
return NONE;
|
|
|
|
return String.Format("0x{0:X12}", TimeSignal.Value.Value);
|
|
}
|
|
}
|
|
|
|
private SortedList<ushort, Scte35DisplayData> _scte35DisplayDatas;
|
|
private string scte35DisplayTableId;
|
|
|
|
private Scte35DisplayData GetScte35DisplayData(ushort program)
|
|
{
|
|
if (_scte35DisplayDatas == null)
|
|
_scte35DisplayDatas = new SortedList<ushort, Scte35DisplayData>();
|
|
|
|
scte35DisplayTableId = Guid.NewGuid().ToString();
|
|
|
|
if (_scte35DisplayDatas.ContainsKey(program))
|
|
{
|
|
return _scte35DisplayDatas[program];
|
|
}
|
|
else
|
|
{
|
|
Scte35DisplayData result = new Scte35DisplayData();
|
|
lock (_scte35DisplayDatas)
|
|
{
|
|
_scte35DisplayDatas.Add(program, result);
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public void NotifyScte35(ushort programNumber, SpliceInsert spliceInsert)
|
|
{
|
|
TsType = 1;
|
|
HasScte35 = true;
|
|
Scte35DisplayData mod = GetScte35DisplayData(programNumber);
|
|
mod.LastSplice = spliceInsert;
|
|
}
|
|
|
|
public void NotifyScte35(ushort programNumber, TimeSignal spliceInsert)
|
|
{
|
|
TsType = 1;
|
|
HasScte35 = true;
|
|
Scte35DisplayData mod = GetScte35DisplayData(programNumber);
|
|
mod.TimeSignal = spliceInsert;
|
|
}
|
|
|
|
private bool memorySaverMode;
|
|
private readonly JobContext jobContext;
|
|
|
|
public JobDisplay(JobContext jobContext)
|
|
{
|
|
this.jobContext = jobContext;
|
|
}
|
|
|
|
public void SetMemorySaverMode(bool saveMemory)
|
|
{
|
|
this.memorySaverMode = saveMemory;
|
|
this.jobContext.MemorySaverMode = saveMemory;
|
|
}
|
|
|
|
|
|
public void RenderScte35()
|
|
{
|
|
if (_scte35DisplayDatas == null)
|
|
return;
|
|
|
|
if (ImGui.Begin("SCTE-35 Cue Messages"))
|
|
{
|
|
if (ImGui.BeginTable(scte35DisplayTableId, 3,
|
|
ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.SizingFixedFit))
|
|
{
|
|
ImGui.TableSetupColumn("Service");
|
|
ImGui.TableSetupColumn("Time Signal");
|
|
ImGui.TableSetupColumn("Last Splice");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (_scte35DisplayDatas)
|
|
{
|
|
foreach (KeyValuePair<ushort, Scte35DisplayData> scte35DisplayData in _scte35DisplayDatas)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(ResolveServiceDisplayName(scte35DisplayData.Key));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(scte35DisplayData.Value.TimeSignalToString());
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(scte35DisplayData.Value.LastSpliceToString());
|
|
}
|
|
}
|
|
ImGui.EndTable();
|
|
}
|
|
ImGui.End();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region DOCSIS
|
|
private DocsisEnvironment _docsisEnvironment;
|
|
public void NotifyDocsisCarrier(DocsisEnvironment docsisEnvironment)
|
|
{
|
|
_docsisEnvironment = docsisEnvironment;
|
|
TsType = 3;
|
|
}
|
|
|
|
private void RenderDocsis()
|
|
{
|
|
if (_docsisEnvironment == null)
|
|
return;
|
|
|
|
RenderDocsisParticipants();
|
|
RenderDocsisFrequencies();
|
|
}
|
|
|
|
private DateTime prevStamp, currStamp;
|
|
private void RenderDocsisParticipants()
|
|
{
|
|
prevStamp = currStamp;
|
|
currStamp = DateTime.Now;
|
|
if (currStamp.Second != prevStamp.Second)
|
|
{
|
|
_docsisEnvironment.DocsisEnvironmentStatistics.ParticipantStatistics.Sort((x, y) => y.Throughput.CompareTo(x.Throughput));
|
|
_docsisEnvironment.DocsisEnvironmentStatistics.CaptureSecond();
|
|
}
|
|
|
|
ImGui.Begin("DOCSIS Participant infos");
|
|
SafeText(String.Format("Total scrambled packets: {0} ({1} p/s)", _docsisEnvironment.DocsisEnvironmentStatistics.ScrambledPacketsTotal,_docsisEnvironment.DocsisEnvironmentStatistics.ScrambledPacketsPerSecond));
|
|
SafeText(String.Format("Total clear packets: {0} ({1} p/s)", _docsisEnvironment.DocsisEnvironmentStatistics.UnscrambledPacketsTotal,_docsisEnvironment.DocsisEnvironmentStatistics.UnscrambledPacketsPerSecond));
|
|
SafeText(String.Format("Current bandwidth: {0:F1} mb/s", (float)_docsisEnvironment.DocsisEnvironmentStatistics.ThroughputPerSecond / 1000000.0f));
|
|
|
|
ImGui.BeginTable("DOCSIS Participant Index", 6, ImGuiTableFlags.Resizable);
|
|
|
|
ImGui.TableSetupColumn("MAC");
|
|
ImGui.TableSetupColumn("IP");
|
|
ImGui.TableSetupColumn("Manufacturer");
|
|
ImGui.TableSetupColumn("Packet/s");
|
|
ImGui.TableSetupColumn("Bandwidth used");
|
|
ImGui.TableSetupColumn("Cumulative usage");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (_docsisEnvironment.DocsisEnvironmentStatistics.ParticipantStatistics)
|
|
{
|
|
foreach (DocsisEnvironment.Statistics.ParticipantStatistic participantStatistic in _docsisEnvironment.DocsisEnvironmentStatistics.ParticipantStatistics)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(participantStatistic.Address.ToString());
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(participantStatistic.Ip?.ToString());
|
|
|
|
ImGui.TableSetColumnIndex(2);
|
|
SafeText(GetParticipantManufacturer(participantStatistic));
|
|
|
|
ImGui.TableSetColumnIndex(3);
|
|
SafeText(participantStatistic.PacketsPerSecond.ToString());
|
|
|
|
ImGui.TableSetColumnIndex(4);
|
|
SafeText(String.Format("{0:F1} kb/s", (double)participantStatistic.ThroughputPerSecond / 1000.0));
|
|
|
|
ImGui.TableSetColumnIndex(5);
|
|
double percent = ((double)participantStatistic.ThroughputTotal * 100.0) /
|
|
(double)_docsisEnvironment.DocsisEnvironmentStatistics.ThroughputTotal;
|
|
SafeText(String.Format("{0:F1} %%", percent));
|
|
}
|
|
}
|
|
ImGui.EndTable();
|
|
ImGui.End();
|
|
}
|
|
|
|
private bool dontBotherWithOuis;
|
|
private Dictionary<string, string> ouiLookupTable;
|
|
private string GetParticipantManufacturer(DocsisEnvironment.Statistics.ParticipantStatistic stat)
|
|
{
|
|
if (dontBotherWithOuis)
|
|
return "???";
|
|
|
|
if (ouiLookupTable == null)
|
|
{
|
|
ouiLookupTable = new Dictionary<string, string>();
|
|
FileInfo dbFile = new FileInfo("standards-oui.ieee.org.txt");
|
|
if (!dbFile.Exists)
|
|
{
|
|
dontBotherWithOuis = true;
|
|
return "???";
|
|
}
|
|
|
|
StreamReader streamReader = dbFile.OpenText();
|
|
while (!streamReader.EndOfStream)
|
|
{
|
|
string? readLine = streamReader.ReadLine();
|
|
if (readLine.Contains(" (base 16)"))
|
|
{
|
|
string[] strings = readLine.Split("\t");
|
|
string k = strings[0].Split(" ")[0];
|
|
if (ouiLookupTable.ContainsKey(k))
|
|
continue;
|
|
string v = strings[strings.Length - 1];
|
|
ouiLookupTable.Add(k, v);
|
|
}
|
|
}
|
|
streamReader.Dispose();
|
|
}
|
|
|
|
string victim = stat.Address.ToString().Substring(0, 6);
|
|
if (ouiLookupTable.ContainsKey(victim))
|
|
return ouiLookupTable[victim];
|
|
return "???";
|
|
}
|
|
|
|
private SortedList<uint, Tuple<bool, object>> docsisFreqs;
|
|
public void NotifyDocsisFrequency(uint? frequency, bool isUpstream, object mmm)
|
|
{
|
|
if (!frequency.HasValue)
|
|
return;
|
|
|
|
if (docsisFreqs == null)
|
|
docsisFreqs = new SortedList<uint, Tuple<bool, object>>();
|
|
|
|
if (docsisFreqs.ContainsKey(frequency.Value))
|
|
return;
|
|
|
|
lock (docsisFreqs)
|
|
{
|
|
docsisFreqs.Add(frequency.Value, new Tuple<bool, object>(isUpstream, mmm));
|
|
}
|
|
}
|
|
|
|
public void SetGseMode()
|
|
{
|
|
TsType = 2;
|
|
}
|
|
|
|
|
|
private void RenderDocsisFrequencies()
|
|
{
|
|
if (docsisFreqs == null)
|
|
return;
|
|
|
|
ImGui.Begin("DOCSIS Frequency Mapping");
|
|
|
|
ImGui.BeginTable("DOCSIS Participant Index", 3);
|
|
|
|
ImGui.TableSetupColumn("Frequency");
|
|
ImGui.TableSetupColumn("Usage");
|
|
ImGui.TableHeadersRow();
|
|
|
|
lock (docsisFreqs)
|
|
{
|
|
foreach (KeyValuePair<uint, Tuple<bool, object>> docsisFreq in docsisFreqs)
|
|
{
|
|
ImGui.TableNextRow();
|
|
ImGui.TableSetColumnIndex(0);
|
|
SafeText(String.Format("{0:F1} Mhz", (float)docsisFreq.Key / 1000000.0f));
|
|
|
|
ImGui.TableSetColumnIndex(1);
|
|
SafeText(docsisFreq.Value.Item1 ? "Upstream" : "Downstream");
|
|
}
|
|
}
|
|
|
|
ImGui.EndTable();
|
|
|
|
ImGui.End();
|
|
}
|
|
#endregion
|
|
|
|
#region Framegrabs
|
|
private List<PictureWindow> _framegrabWindows;
|
|
private Queue<Tuple<Renderer, string, byte[]>> _framegrabQueue;
|
|
public void ShowFramegrab(int currentNetworkId, int transportStreamId, ushort mappingProgramNumber, int mappingStreamElementaryPid, byte[] imageData)
|
|
{
|
|
string resolveServiceDisplayName = ResolveServiceDisplayName(mappingProgramNumber);
|
|
if (string.IsNullOrEmpty(resolveServiceDisplayName))
|
|
resolveServiceDisplayName = String.Format("Framegrab of Service #{0:X4}");
|
|
else
|
|
resolveServiceDisplayName = String.Format("Framegrab of \"{0}\"", resolveServiceDisplayName);
|
|
|
|
if (PictureWindow.Renderer == null)
|
|
return;
|
|
|
|
if (_framegrabQueue == null)
|
|
_framegrabQueue = new Queue<Tuple<Renderer, string, byte[]>>();
|
|
|
|
lock (_framegrabQueue)
|
|
{
|
|
_framegrabQueue.Enqueue(new Tuple<Renderer, string, byte[]>(PictureWindow.Renderer, resolveServiceDisplayName, imageData));
|
|
}
|
|
}
|
|
|
|
private void RenderFramegrabs()
|
|
{
|
|
if (_framegrabQueue != null)
|
|
{
|
|
if (_framegrabQueue.Count > 0)
|
|
{
|
|
Tuple<Renderer, string, byte[]> candidate = null;
|
|
lock (_framegrabQueue)
|
|
{
|
|
candidate = _framegrabQueue.Dequeue();
|
|
}
|
|
|
|
PictureWindow child = new PictureWindow(candidate.Item1, candidate.Item2, candidate.Item3);
|
|
if (_framegrabWindows == null)
|
|
_framegrabWindows = new List<PictureWindow>();
|
|
lock (_framegrabWindows)
|
|
{
|
|
int pos = _framegrabWindows.Count + 1;
|
|
pos *= 20;
|
|
pos += 100;
|
|
child.SetPosition(pos, pos);
|
|
_framegrabWindows.Add(child);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (_framegrabWindows != null)
|
|
{
|
|
lock (_framegrabWindows)
|
|
{
|
|
_framegrabWindows.ForEach(x => x.Render());
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Blockstream
|
|
|
|
public void NotifyBlockstreamCarrier()
|
|
{
|
|
TsType = 4;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region DB-Schnittstelle
|
|
|
|
public IEnumerable<HumanReadableService> GetServices()
|
|
{
|
|
if (HasPmt)
|
|
{
|
|
foreach (var (pmtPid, patValue) in patDisplay)
|
|
{
|
|
ushort serviceId = patValue.programId;
|
|
SdtCoordinate sdt = ResolveService(serviceId);
|
|
string providerName = sdt.ProviderName;
|
|
string serviceName = sdt.ServiceName;
|
|
ushort? caId = ResolveCaId(patValue.pmt, sdt);
|
|
ServiceDescriptor.ServiceTypeCoding? serviceType = sdt.ServiceType;
|
|
yield return new HumanReadableService(serviceId, providerName, serviceName, caId, serviceType.GetValueOrDefault());
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void OnBlindscanOpenFoundFrquenciesWindow(List<BlindscanSearchResult> foundFrequencies, STD_TYPE tunerMetadataType)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanJobDone(bool success)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanErrorMessage(string blindscanningLowHorizontalAreaFailed)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanBandComplete()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanBeforeBLScan(int minimum, int currentProgress, int maximum)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanAfterBLScan()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanSearchResult1Callback(BlindscanSearchResult searchResult, int polarityIndex,
|
|
int lnbTypeMinimumFrequency, int lnbTypeMaximumFrequency)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanBeforeSetChannel(BlindscanSearchResult blindscanResult,LnbType lnbType)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnScrapeBandComplete()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanScrapeTransponderComplete(BlindscanSearchResult blindscanResult)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanBeginRfSpectrum()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanRfSpectrumEnqueueSample(SatelliteDeliverySystemDescriptor.PolarizationEnum polarization, int frequency, double rf)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanEndRfSpectrum()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanBeginIqSpectrum(IqChartData result)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanEndIq()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanLockFail(SearchResult satelliteSr, BlindscanResultState resultState)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanFilterSetUp()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanScrapeStopCondition()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanAfterPacketDrain()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanPacketError(int errorCount, int length)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public void OnBlindscanPacketOk(int numPackets, int packetsQueueCount)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public bool IsZapNowRequested()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public bool MayAutoZap()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public TaskQueue Tasks { get; set; }
|
|
|
|
private ushort? ResolveCaId(ProgramMapping patValuePmt, SdtCoordinate sdt)
|
|
{
|
|
if (patValuePmt != null)
|
|
{
|
|
if (patValuePmt.CaSystemId.HasValue)
|
|
return patValuePmt.CaSystemId.Value;
|
|
|
|
foreach (ProgramMappingStream stream in patValuePmt.Streams)
|
|
{
|
|
if (stream.CaSystemId.HasValue)
|
|
return stream.CaSystemId;
|
|
}
|
|
}
|
|
|
|
if (sdt.CaIdentifiers != null)
|
|
{
|
|
if (sdt.CaIdentifiers.Length > 0)
|
|
return sdt.CaIdentifiers[0];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
}
|
|
}
|