using Newtonsoft.Json; using skyscraper5.Docsis; using skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs; using skyscraper5.Dvb.Descriptors; using skyscraper5.Dvb.Psi.Model; using skyscraper5.Mhp.Si.Model; 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 System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; namespace skyscraper5.UI.Overrides { internal class Form1UiJunction : ISkyscraperUiJunction { private INodeEngine form1; public Dictionary SdtNames { get; private set; } public Dictionary PidToPrograms { get; private set; } private JsonSerializerSettings jsonSerializerSettings; public Dictionary UsageLabels { get; private set; } public Form1UiJunction(INodeEngine form1) { this.form1 = form1; this.jsonSerializerSettings = new JsonSerializerSettings(); this.jsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore; this.jsonSerializerSettings.Formatting = Formatting.Indented; SetPidUsage(0x0000, "PAT"); SetPidUsage(0x0001, "CAT"); SetPidUsage(0x0002, "TSDT"); SetPidUsage(0x0010, "NIT"); SetPidUsage(0x0011, "SDT/BAT"); SetPidUsage(0x0012, "EIT/CIT"); SetPidUsage(0x0013, "RST"); SetPidUsage(0x0014, "TDT/TOT"); SetPidUsage(0x0015, "network synchronization"); SetPidUsage(0x0016, "RNT"); SetPidUsage(0x001c, "link-local inband signalling"); SetPidUsage(0x001d, "measurement"); SetPidUsage(0x001e, "DIT"); SetPidUsage(0x001f, "SIT"); } private void SetPidUsage(int pid, string name) { if (UsageLabels == null) UsageLabels = new Dictionary(); UsageLabels[pid] = name; } public void DsmCcModuleAdd(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion) { throw new NotImplementedException(); } public void DsmCcModuleComplete(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion) { throw new NotImplementedException(); } public void DsmCcModuleProgress(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion, double moduleInfoDownloadProgress) { throw new NotImplementedException(); } public void DsmCcVfs(VfsFile vfsFile) { SkyscraperUiNode dsmCcNode = form1.EnsureNodeExists("DSM-CC"); form1.SetIcon(dsmCcNode, 1); string outName = String.Format("DSM-CC\\Object Carousels\\PID 0x{0:X4}\\{1}", vfsFile.SourcePid, vfsFile.Name); string[] args = outName.Split("\\"); form1.EnsureNodeExists(args); } public IEnumerable GetServices() { throw new NotImplementedException(); } public void NotifyAit(AitApplication aitApplication) { SkyscraperUiNode applicationNode = form1.EnsureNodeExists("AIT", aitApplication.TryGetName()); form1.SetIcon((SkyscraperUiNode)applicationNode.Parent, 1); } private Dictionary bats; public void NotifyBat(BatBouquet batBouquet) { if (bats == null) bats = new Dictionary(); string name = String.Format("{0} ({1})", batBouquet.BouquetId, batBouquet.BouquetName); if (!bats.ContainsKey(batBouquet.BouquetId)) bats.Add(batBouquet.BouquetId, name); SkyscraperUiNode bouquetNode = form1.EnsureNodeExists("BAT", name); form1.SetIcon((SkyscraperUiNode)bouquetNode.Parent, 1); form1.SetIcon(bouquetNode, 7); } public void NotifyBatTs(ushort batBouquetBouquetId, BatTransportStream child) { string name = bats[batBouquetBouquetId]; string name2 = String.Format("TS #{0}", child.TransportStreamId); SkyscraperUiNode batTsNode = form1.EnsureNodeExists("BAT", name, name2); form1.SetIcon(batTsNode, 4); } public void NotifyBlockstreamCarrier() { throw new NotImplementedException(); } public void NotifyCat(CaDescriptor caDescriptor) { string systemName = CaSystemNames.GetHumanReadableName(caDescriptor.CaSystemId); string caName = String.Format("0x{0:X4} ({1})",caDescriptor.CaSystemId,systemName); SkyscraperUiNode catNode = form1.EnsureNodeExists("CAT", caName); if (!catNode.FillOutComplete) { form1.SetIcon((SkyscraperUiNode)catNode.Parent, 1); form1.SetIcon(catNode, 6); catNode.DetailedText = JsonConvert.SerializeObject(caDescriptor, jsonSerializerSettings); SetPidUsage(caDescriptor.CaPid, String.Format("{0} ECM/EMM", systemName)); catNode.FillOutComplete = true; } } public void NotifyDocsisCarrier(DocsisEnvironment docsisEnvironment) { throw new NotImplementedException(); } public void NotifyDocsisFrequency(uint? frequency, bool isUpstream, object mmm) { throw new NotImplementedException(); } public void NotifyEvent(EitEvent eitEvent) { SkyscraperUiNode serviceNode = form1.EnsureNodeExists("EIT", eitEvent.StartTime.ToShortDateString(), eitEvent.ServiceId.ToString()); form1.SetIcon((SkyscraperUiNode)serviceNode.Parent.Parent, 1); form1.SetIcon((SkyscraperUiNode)serviceNode.Parent, 5); form1.SetIcon(serviceNode, 8); } public void NotifyMpeTraffic(IpTrafficInfo iti, int ipv4PacketLength) { throw new NotImplementedException(); } public void NotifyNit(NitTransportStream transportStream) { SkyscraperUiNode nitNode = form1.EnsureNodeExists("NIT", transportStream.RenderForUi()); if (!nitNode.FillOutComplete) { nitNode.DetailedText = JsonConvert.SerializeObject(nitNode, jsonSerializerSettings); nitNode.FillOutComplete = true; form1.SetIcon((SkyscraperUiNode)nitNode.Parent, 1); form1.SetIcon(nitNode, 4); } } public void NotifyPatProgram(int pmtPid, ushort programId) { string name = String.Format("PMT PID 0x{0:X4} - Program {0}", programId, pmtPid); SkyscraperUiNode patNode = form1.EnsureNodeExists("PAT", name); form1.SetIcon((SkyscraperUiNode)patNode.Parent, 1); } public void NotifyPmtProgram(ProgramMapping result, int pmtPid) { string name = String.Format("PMT PID 0x{0:X4} - Program {0}", result.ProgramNumber,pmtPid); SkyscraperUiNode programNode = form1.EnsureNodeExists("PAT",name); if (!programNode.FillOutComplete) { form1.RunOnUiThread(() => form1.EnsureNodeExists("PAT").Expand()); if (!programNode.FillOutComplete) { programNode.DetailedText = JsonConvert.SerializeObject(result, jsonSerializerSettings); programNode.FillOutComplete = true; } string sdtName = null; form1.RunOnUiThread(() => sdtName = TrySdtFromPmt(result.ProgramNumber)); if (sdtName != null) { form1.EnsureNodeExists("PAT", name, String.Format("SDT: {0}", sdtName)); form1.RunOnUiThread(() => programNode.Expand()); } foreach (ProgramMappingStream pmtEntry in result.Streams) { string name2 = String.Format("PID 0x{0:X4}", pmtEntry.ElementaryPid); SkyscraperUiNode pidNode = form1.EnsureNodeExists("PAT", name, name2); form1.SetIcon((SkyscraperUiNode)pidNode.Parent, 8); pidNode.DetailedText = JsonConvert.SerializeObject(pmtEntry, jsonSerializerSettings); if (PidToPrograms == null) PidToPrograms = new Dictionary(); PidToPrograms.Add(pmtEntry.ElementaryPid, result.ProgramNumber); SetPidUsage(pmtEntry.ElementaryPid, StreamTypeAsString(pmtEntry,result.PrivateDataSpecifier)); } PidToPrograms.Add(pmtPid, result.ProgramNumber); SetPidUsage(pmtPid, "PMT"); programNode.FillOutComplete = true; } } private string TrySdtFromPmt(ushort programNumber) { if (!form1.TestForNode("SDT")) return null; SkyscraperUiNode sdtNode = form1.EnsureNodeExists("SDT"); foreach(TreeNode node in sdtNode.Nodes) { string prefix = String.Format("{0} ", programNumber); if (node.Text.StartsWith(prefix)) { string result = node.Text.Substring(node.Text.Length); return result; } } return null; } public void NotifyScte35(ushort programNumber, SpliceInsert spliceInsert) { throw new NotImplementedException(); } public void NotifyScte35(ushort programNumber, TimeSignal spliceInsert) { throw new NotImplementedException(); } public void NotifySdtService(SdtService sdtService) { string name = String.Format("{0} {1}", sdtService.ServiceId, sdtService.ServiceName); SkyscraperUiNode node = form1.EnsureNodeExists("SDT", name); if (!node.FillOutComplete) { if (SdtNames == null) SdtNames = new Dictionary(); SdtNames.Add(sdtService.ServiceId, sdtService.ServiceName); node.DetailedText = JsonConvert.SerializeObject(sdtService, jsonSerializerSettings); form1.RunOnUiThread(new Action(() => { TrySdtToPmt(sdtService.ServiceId, sdtService.ServiceName); })); form1.SetIcon((SkyscraperUiNode)node.Parent, 1); node.FillOutComplete = true; } } private void TrySdtToPmt(uint programNo, string serviceName) { if (!form1.TestForNode("PAT")) return; string query = String.Format(" {0}", programNo); SkyscraperUiNode patNode = form1.EnsureNodeExists("PAT"); foreach(TreeNode node in patNode.Nodes) { if (node.Text.EndsWith(query)) { SkyscraperUiNode childNode = new SkyscraperUiNode(); childNode.Text = String.Format("SDT: {0}", serviceName); node.Nodes.Add(childNode); break; } } } public void NotifyStreamTypeDetection(string contestantTag, int pid) { throw new NotImplementedException(); } public void NotifyTdt(DateTime utcTime) { SkyscraperUiNode skyscraperUiNode = form1.EnsureNodeExists("TDT"); form1.SetIcon(skyscraperUiNode, 1); if (skyscraperUiNode.Nodes.Count == 0) { SkyscraperUiNode child = new SkyscraperUiNode(); child.Text = utcTime.ToString(); form1.RunOnUiThread(() => { skyscraperUiNode.Nodes.Add(child); skyscraperUiNode.Expand(); } ); form1.SetIcon(child, 3); } else { SkyscraperUiNode oldChild = (SkyscraperUiNode)skyscraperUiNode.Nodes[0]; form1.RunOnUiThread(() => oldChild.Text = utcTime.ToString()); } } public void NotifyTot(DateTime utcTime, LocalTimeOffsetDescriptor ltod) { SkyscraperUiNode skyscraperUiNode = form1.EnsureNodeExists("TOT"); form1.SetIcon(skyscraperUiNode, 1); if (skyscraperUiNode.Nodes.Count == 0) { SkyscraperUiNode child = new SkyscraperUiNode(); child.Text = utcTime.ToString(); form1.RunOnUiThread(() => { skyscraperUiNode.Nodes.Add(child); skyscraperUiNode.Expand(); } ); if (!child.FillOutComplete) { form1.SetIcon(child, 3); child.DetailedText = JsonConvert.SerializeObject(ltod, jsonSerializerSettings); } } else { SkyscraperUiNode oldChild = (SkyscraperUiNode)skyscraperUiNode.Nodes[0]; form1.RunOnUiThread(() => oldChild.Text = utcTime.ToString()); } } public void NotifyWss(ushort programNumber, WssDataBlock wssDataBlock) { throw new NotImplementedException(); } public void SetGseMode() { throw new NotImplementedException(); } public void SetMemorySaverMode(bool saveMemory) { throw new NotImplementedException(); } public void ShowFramegrab(int currentNetworkId, int transportStreamId, ushort mappingProgramNumber, int mappingStreamElementaryPid, byte[] imageData) { throw new NotImplementedException(); } private string StreamTypeAsString(ProgramMappingStream stream, uint? parentRegistrationFormatIdentifier) { if (stream.StreamType == PmtStreamType.H262) return "MPEG-2 Video"; if (stream.AvcStillPresent.HasValue) return "MPEG-4 Video"; if (stream.AudioType.HasValue) { switch (stream.AudioType) { case AudioType.CleanEffects: return "Audio"; 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); } } }