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.Net; using skyscraper5.Skyscraper.Scraper; using skyscraper5.src.Skyscraper.FrequencyListGenerator; using skyscraper5.Teletext.Wss; 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(""); 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 { public int Compare(EitDay x, EitDay y) { return x.Date.CompareTo(y.Date); } } private class EitEventCoordinateComparer : IComparer { public int Compare(EitEventCoordinate x, EitEventCoordinate y) { return x.StartTime.Ticks.CompareTo(y.StartTime.Ticks); } } private SortedList> eitDisplay; private void RenderEit() { if (eitDisplay == null) return; if (ImGui.Begin("Event Information Table")) { lock (eitDisplay) { foreach (KeyValuePair> 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 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>(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(new EitEventCoordinateComparer()); } SortedList 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 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 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(); 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 patDisplay; public void NotifyPatProgram(int pmtPid, ushort programId) { HasPat = true; TsType = 1; if (patDisplay == null) patDisplay = new SortedList(); 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 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 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 { public int Compare(NitNetworkMeta x, NitNetworkMeta y) { return x.ONID.CompareTo(y.ONID); } } private SortedList> nitDisplay; private string nitTableUuid; public void NotifyNit(NitTransportStream transportStream) { TsType = 1; HasNit = true; if (nitDisplay == null) nitDisplay = new SortedList>(new NitCoordinateComparer()); NitNetworkMeta nnm = new NitNetworkMeta(); nnm.ONID = transportStream.OriginalNetworkId; if (!nitDisplay.ContainsKey(nnm)) { lock (nitDisplay) { nitDisplay.Add(nnm, new SortedList()); } } SortedList 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> 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 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> mpeDisplays; public void NotifyMpeTraffic(IpTrafficInfo iti, int ipv4PacketLength) { if (trafficInfoComparer == null) trafficInfoComparer = new IpTrafficInfoComparer(); HasMpe = true; if (mpeDisplays == null) mpeDisplays = new List>(); lock (mpeDisplays) { foreach (KeyValuePair line in mpeDisplays) { if (line.Key.Equals(iti)) { line.Value.CountPacket(ipv4PacketLength); return; } } KeyValuePair newChild = new KeyValuePair(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 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 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 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 aitDisplay; private string aitTableUuid; public void NotifyAit(AitApplication aitApplication) { TsType = 1; HasAit = true; if (aitDisplay == null) aitDisplay = new SortedList(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 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 { 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 dsmCcDisplay; private string objectCarouselTableUuid; public void DsmCcModuleAdd(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion) { TsType = 1; HasDsmCc = true; if (dsmCcDisplay == null) dsmCcDisplay = new SortedList(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 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 wssDisplay; public void NotifyWss(ushort programNumber, WssDataBlock wssDataBlock) { HasWss = true; TsType = 1; if (wssDisplay == null) wssDisplay = new SortedList(); 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 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 streamTypes; public void NotifyStreamTypeDetection(string contestantTag, int pid) { if (streamTypes == null) streamTypes = new Dictionary(); streamTypes[pid] = contestantTag; } #endregion #region BAT private struct DisplayableBat { public string Name; public List Linkages; public string TableUuid; public HashSet TransportStreams; } private SortedList batDisplay; public void NotifyBat(BatBouquet batBouquet) { TsType = 1; HasBat = true; if (batDisplay == null) batDisplay = new SortedList(); 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(); 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 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 displayObjectCarouselRoots; private string GetServiceNameFromPid(int pid) { lock (patDisplay) { foreach (KeyValuePair 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(); 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 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 = ""; 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 caDisplay; public void NotifyCat(CaDescriptor caDescriptor) { TsType = 1; HasCat = true; if (caDisplay == null) caDisplay = new HashSet(); 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 = ""; 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 _scte35DisplayDatas; private string scte35DisplayTableId; private Scte35DisplayData GetScte35DisplayData(ushort program) { if (_scte35DisplayDatas == null) _scte35DisplayDatas = new SortedList(); 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 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 ouiLookupTable; private string GetParticipantManufacturer(DocsisEnvironment.Statistics.ParticipantStatistic stat) { if (dontBotherWithOuis) return "???"; if (ouiLookupTable == null) { ouiLookupTable = new Dictionary(); 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> docsisFreqs; public void NotifyDocsisFrequency(uint? frequency, bool isUpstream, object mmm) { if (!frequency.HasValue) return; if (docsisFreqs == null) docsisFreqs = new SortedList>(); if (docsisFreqs.ContainsKey(frequency.Value)) return; lock (docsisFreqs) { docsisFreqs.Add(frequency.Value, new Tuple(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> 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 _framegrabWindows; private Queue> _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>(); lock (_framegrabQueue) { _framegrabQueue.Enqueue(new Tuple(PictureWindow.Renderer, resolveServiceDisplayName, imageData)); } } private void RenderFramegrabs() { if (_framegrabQueue != null) { if (_framegrabQueue.Count > 0) { Tuple candidate = null; lock (_framegrabQueue) { candidate = _framegrabQueue.Dequeue(); } PictureWindow child = new PictureWindow(candidate.Item1, candidate.Item2, candidate.Item3); if (_framegrabWindows == null) _framegrabWindows = new List(); 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 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()); } } } 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; } #endregion } }