2025-08-28 20:47:56 +02:00

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;
}
}
}