From 7d218ade9c9a0411d39f5962fef9e6899503aa10 Mon Sep 17 00:00:00 2001
From: feyris-tan <4116042+feyris-tan@users.noreply.github.com>
Date: Thu, 17 Jul 2025 17:08:19 +0200
Subject: [PATCH] Added a failed attempt at OpenTV Parsing.
---
.../SingleTreeDictionaryEntry.cs | 275 +++++++++++++++++
.../DVBServices/Mpeg2ExtendedHeader.cs | 149 +++++++++
.../OpenTV/OpenTVExtendedDescriptionRecord.cs | 111 +++++++
.../DVBServices/OpenTV/OpenTVRecordBase.cs | 195 ++++++++++++
.../OpenTV/OpenTVSeriesLinkRecord.cs | 111 +++++++
.../OpenTV/OpenTVShortDescriptionRecord.cs | 116 +++++++
.../DVBServices/OpenTV/OpenTVSummaryData.cs | 244 +++++++++++++++
.../DVBServices/OpenTV/OpenTVSummaryHeader.cs | 161 ++++++++++
.../OpenTV/OpenTVSummarySection.cs | 151 +++++++++
.../DVBServices/OpenTV/OpenTVTitleData.cs | 289 ++++++++++++++++++
.../OpenTV/OpenTVTitleDataRecord.cs | 164 ++++++++++
.../DVBServices/OpenTV/OpenTVTitleHeader.cs | 165 ++++++++++
.../DVBServices/OpenTV/OpenTVTitleSection.cs | 126 ++++++++
.../EPGCollectorSide/DVBServices/Utils.cs | 37 +++
.../DomainObjects/TraceEntry.cs | 266 ++++++++++++++++
.../OpenTV/OpenTvDataStorage.cs | 68 +++++
.../OpenTV/OpenTvExpectedDataType.cs | 14 +
.../SkyscraperSide/OpenTV/OpenTvHandler.cs | 16 +
.../SkyscraperSide/OpenTV/OpenTvScraper.cs | 59 ++++
.../OpenTV/OpenTvSummaryContestant.cs | 68 +++++
.../OpenTV/OpenTvSummaryParser.cs | 42 +++
.../OpenTV/OpenTvTitleContestant.cs | 62 ++++
.../OpenTV/OpenTvTitleParser.cs | 42 +++
skyscraper8/Program.cs | 1 +
skyscraper8/Properties/launchSettings.json | 2 +-
.../Skyscraper/Scraper/SkyscraperContext.cs | 19 +-
26 files changed, 2934 insertions(+), 19 deletions(-)
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Decompressors/SingleTreeDictionaryEntry.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Mpeg2ExtendedHeader.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVExtendedDescriptionRecord.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVRecordBase.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSeriesLinkRecord.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVShortDescriptionRecord.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummaryData.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummaryHeader.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummarySection.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleData.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleDataRecord.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleHeader.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleSection.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DomainObjects/TraceEntry.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvDataStorage.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvExpectedDataType.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvHandler.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvScraper.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvSummaryContestant.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvSummaryParser.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvTitleContestant.cs
create mode 100644 PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvTitleParser.cs
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Decompressors/SingleTreeDictionaryEntry.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Decompressors/SingleTreeDictionaryEntry.cs
new file mode 100644
index 0000000..ec03c65
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Decompressors/SingleTreeDictionaryEntry.cs
@@ -0,0 +1,275 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes a dictionary entry for a single tree Huffman scenario.
+ ///
+ public class SingleTreeDictionaryEntry
+ {
+ ///
+ /// Get or set the flag for not starting at the first bit in the compressed string.
+ ///
+ public static bool OffsetStart
+ {
+ get { return (offsetStart); }
+ set { offsetStart = value; }
+ }
+
+ ///
+ /// Get the decode string.
+ ///
+ public string Decode { get { return (decode); } }
+
+ private string decode;
+ private string pattern;
+
+ private static HuffmanEntry[] roots = new HuffmanEntry[2];
+ private static bool offsetStart = true;
+
+ ///
+ /// Initialize a new instance of the SingleTreeDictionaryEntry class.
+ ///
+ /// The Huffman bit pattern.
+ /// The decode for the bit pattern.
+ public SingleTreeDictionaryEntry(string pattern, string decode)
+ {
+ this.pattern = pattern;
+ this.decode = decode;
+ }
+
+ ///
+ /// Load the dictionary entries ino the first root.
+ ///
+ /// True if the file has been loaded; false otherwise.
+ public static bool Load(string fileName)
+ {
+ return (Load(fileName, 1));
+ }
+
+ ///
+ /// Load the dictionary entries.
+ ///
+ /// True if the file has been loaded; false otherwise.
+ public static bool Load(string fileName, int rootNumber)
+ {
+ FileStream fileStream = null;
+
+ Logger.Instance.Write("Loading Huffman Dictionary from " + fileName);
+
+ try { fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); }
+ catch (IOException e)
+ {
+ Logger.Instance.Write("Huffman Dictionary file " + fileName + " not available");
+ Logger.Instance.Write(e.Message);
+ return (false);
+ }
+
+ StreamReader streamReader = new StreamReader(fileStream);
+ roots[rootNumber - 1] = null;
+
+ while (!streamReader.EndOfStream)
+ {
+ string line = streamReader.ReadLine();
+
+ if (line != string.Empty && !line.StartsWith("####"))
+ {
+ string[] parts = line.Split(new char[] { '=' });
+ if (parts.Length == 2)
+ addEntry(rootNumber, parts[1], getDecode(parts[0]));
+ else
+ {
+ if (parts.Length == 3 && parts[0] == string.Empty && parts[1] == string.Empty)
+ addEntry(rootNumber, parts[2], "=");
+ else
+ Logger.Instance.Write("Dictionary line '" + line + "' format wrong - line ignored ");
+ }
+ }
+ }
+
+ streamReader.Close();
+ fileStream.Close();
+
+ Logger.Instance.Write("Dictionary loaded");
+
+ return (true);
+ }
+
+ private static void addEntry(int rootNumber, string pattern, string decode)
+ {
+ if (roots[rootNumber - 1] == null)
+ roots[rootNumber - 1] = new HuffmanEntry();
+
+ HuffmanEntry currentEntry = roots[rootNumber - 1];
+
+ for (int index = 0; index < pattern.Length; index++)
+ {
+ char patternChar = pattern[index];
+
+ switch (patternChar)
+ {
+ case '0':
+ if (currentEntry.P0 == null)
+ {
+ currentEntry.P0 = new HuffmanEntry();
+ currentEntry = currentEntry.P0;
+ if (index == pattern.Length - 1)
+ currentEntry.Value = decode;
+ }
+ else
+ {
+ currentEntry = currentEntry.P0;
+ if (currentEntry.Value != null && index == pattern.Length - 1)
+ Logger.Instance.Write("Dictionary entry already set");
+ }
+ break;
+ case '1':
+ if (currentEntry.P1 == null)
+ {
+ currentEntry.P1 = new HuffmanEntry();
+ currentEntry = currentEntry.P1;
+ if (index == pattern.Length - 1)
+ currentEntry.Value = decode;
+ }
+ else
+ {
+ currentEntry = currentEntry.P1;
+ if (currentEntry.Value != null && index == pattern.Length - 1)
+ Logger.Instance.Write("Dictionary entry already set");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private static string getDecode(string originalParameter)
+ {
+ if (originalParameter.Length != 4)
+ return (originalParameter);
+
+ if (originalParameter[0] != '<' || originalParameter[3] != '>')
+ return (originalParameter);
+
+ return (((char)(Int32.Parse(originalParameter.Substring(1, 2), NumberStyles.HexNumber))).ToString());
+ }
+
+ ///
+ /// Decompress a compressed Huffman string using the first root table.
+ ///
+ /// The compressed byte data.
+ /// The decompressed string.
+ public static string DecodeData(byte[] byteData)
+ {
+ return (DecodeData(1, byteData));
+ }
+
+ ///
+ /// Decompress a compressed Huffman string.
+ ///
+ /// The root table to use.
+ /// The compressed byte data.
+ /// The decompressed string.
+ public static string DecodeData(int rootNumber, byte[] byteData)
+ {
+ StringBuilder outputString = new StringBuilder();
+
+ HuffmanEntry currentEntry = roots[rootNumber - 1];
+
+ byte mask;
+ if (offsetStart)
+ mask = 0x20;
+ else
+ mask = 0x80;
+
+ StringBuilder bitString = new StringBuilder();
+
+ for (int index = 0; index < byteData.Length; index++)
+ {
+ byte dataByte = byteData[index];
+
+ while (mask > 0)
+ {
+ if (currentEntry.Value != null)
+ {
+ if (currentEntry.Value != "??")
+ outputString.Append(currentEntry.Value);
+ currentEntry = roots[rootNumber - 1];
+ bitString = new StringBuilder();
+ }
+
+ if ((dataByte & mask) == 0)
+ {
+ bitString.Append("0");
+
+ if (currentEntry.P0 != null)
+ currentEntry = currentEntry.P0;
+ else
+ {
+ Logger.Instance.Write(" ** DECOMPRESSION FAILED **");
+ Logger.Instance.Write("Original data: " + Utils.ConvertToHex(byteData));
+ Logger.Instance.Write("Decoded data: " + outputString.ToString());
+ Logger.Instance.Write("Bit string: " + bitString.ToString());
+ return (outputString.ToString() + " ** DECOMPRESSION FAILED **");
+ }
+ }
+ else
+ {
+ bitString.Append("1");
+
+ if (currentEntry.P1 != null)
+ currentEntry = currentEntry.P1;
+ else
+ {
+ Logger.Instance.Write(" ** DECOMPRESSION FAILED **");
+ Logger.Instance.Write("Original data: " + Utils.ConvertToHex(byteData));
+ Logger.Instance.Write("Decoded data: " + outputString.ToString());
+ Logger.Instance.Write("Bit string: " + bitString.ToString());
+ return (outputString.ToString() + " ** DECOMPRESSION FAILED **");
+ }
+ }
+
+ mask = (byte)(mask >> 1);
+ }
+
+ mask = 0x80;
+ }
+
+ /*if (currentEntry.Value != null && currentEntry.Value != "??")
+ outputString.Append(currentEntry.Value);*/
+
+ if (currentEntry.Value != null)
+ outputString.Append(currentEntry.Value);
+
+ return(outputString.ToString());
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Mpeg2ExtendedHeader.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Mpeg2ExtendedHeader.cs
new file mode 100644
index 0000000..3813463
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Mpeg2ExtendedHeader.cs
@@ -0,0 +1,149 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes an MPEG2 extended header.
+ ///
+ public class Mpeg2ExtendedHeader : Mpeg2BasicHeader
+ {
+ ///
+ /// Get the table identification extension.
+ ///
+ public int TableIDExtension { get { return (tableIDExtension); } }
+ ///
+ /// Return true if the MPEG2 section is current; false otherwise.
+ ///
+ public bool CurrentNextIndicator { get { return (currentNextIndicator); } }
+ ///
+ /// Get the version number.
+ ///
+ public int VersionNumber { get { return (versionNumber); } }
+ ///
+ /// Get the section number.
+ ///
+ public int SectionNumber { get { return (sectionNumber); } }
+ ///
+ /// Get the last section number.
+ ///
+ public int LastSectionNumber { get { return (lastSectionNumber); } }
+
+ ///
+ /// Return true if the MPEG2 section is current; false otherwise.
+ ///
+ public bool Current { get { return (currentNextIndicator); } }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following the header.
+ ///
+ ///
+ /// The header has not been processed.
+ ///
+ public override int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("Mpeg2ExtendedHeader: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private int tableIDExtension;
+ private bool currentNextIndicator;
+ private int versionNumber;
+ private int sectionNumber;
+ private int lastSectionNumber;
+
+ private int lastIndex = -1;
+
+ // MPEG extended header layout is as follows
+ //
+ // table ID extension word uimsbf
+ //
+ // reserved 2 bits bslbf
+ // version no 5 bits uimsbf
+ // current/next ind 1 bit bslbf
+ //
+ // section no byte uimsbf
+ // last section no byte uimsbf
+
+ ///
+ /// Initialize a new instance of the Mpeg2ExtendedHeader class.
+ ///
+ public Mpeg2ExtendedHeader() { }
+
+ ///
+ /// Parse the header.
+ ///
+ /// The MPEG2 section containing the header.
+ public override void Process(byte[] byteData)
+ {
+ base.Process(byteData);
+ lastIndex = base.Index;
+
+ try
+ {
+ tableIDExtension = (byteData[lastIndex] * 256) + (int)byteData[lastIndex + 1];
+ lastIndex += 2;
+
+ versionNumber = ((int)((byteData[lastIndex] >> 1) & 0x1f));
+ currentNextIndicator = (byteData[lastIndex] & 0x01) != 0;
+ lastIndex++;
+
+ sectionNumber = (int)byteData[lastIndex];
+ lastIndex++;
+
+ lastSectionNumber = (int)byteData[lastIndex];
+ lastIndex++;
+
+ Validate();
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw (new ArgumentOutOfRangeException("MPEG2 extended header short"));
+ }
+ }
+
+ ///
+ /// Validate the header fields.
+ ///
+ ///
+ /// A header field is not valid.
+ ///
+ public override void Validate()
+ {
+ base.Validate();
+ }
+
+ ///
+ /// Log the header fields.
+ ///
+ public override void LogMessage()
+ {
+ base.LogMessage();
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVExtendedDescriptionRecord.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVExtendedDescriptionRecord.cs
new file mode 100644
index 0000000..8e5ed36
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVExtendedDescriptionRecord.cs
@@ -0,0 +1,111 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes an OpenTV extended description record.
+ ///
+ internal class OpenTVExtendedDescriptionRecord : OpenTVRecordBase
+ {
+ ///
+ /// Get the tag value for this record.
+ ///
+ public const int TagValue = 0xbb;
+
+ ///
+ /// Get the extended description.
+ ///
+ public string Description { get { return (SingleTreeDictionaryEntry.DecodeData(description)); } }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following the record.
+ ///
+ ///
+ /// The record has not been processed.
+ ///
+ public override int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("OpenTVExtendedDescriptionRecord: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private byte[] description;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVExtendedDescriptionRecord class.
+ ///
+ internal OpenTVExtendedDescriptionRecord() { }
+
+ ///
+ /// Parse the record.
+ ///
+ /// The MPEG2 section containing the record.
+ /// Index of the first byte of the record data in the MPEG2 section.
+ internal override void Process(byte[] byteData, int index)
+ {
+ lastIndex = index;
+
+ try
+ {
+ description = Utils.GetBytes(byteData, lastIndex, Length);
+ lastIndex += Length;
+
+ Validate();
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw (new ArgumentOutOfRangeException("lastIndex = " + lastIndex));
+ }
+ }
+
+ ///
+ /// Validate the record data fields.
+ ///
+ ///
+ /// A record data field is not valid.
+ ///
+ internal override void Validate() { }
+
+ ///
+ /// Log the record data fields.
+ ///
+ internal override void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "");
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "OPENTV EXTENDED DESCRIPTION RECORD: Description: " + Utils.ConvertToHex(description));
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVRecordBase.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVRecordBase.cs
new file mode 100644
index 0000000..a034ef7
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVRecordBase.cs
@@ -0,0 +1,195 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.ObjectModel;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The base OpenTV record class.
+ ///
+ internal class OpenTVRecordBase
+ {
+ ///
+ /// Get the tag of the record.
+ ///
+ internal int Tag { get { return (tag); } }
+ ///
+ /// Get the length of the record data.
+ ///
+ internal int Length { get { return (length); } }
+ ///
+ /// Get the record data.
+ ///
+ internal byte[] Data { get { return (data); } }
+
+ ///
+ /// Get the total length of the record.
+ ///
+ internal int TotalLength { get { return (Length + 2); } }
+ ///
+ /// Return true if the record is undefined; false otherwise.
+ ///
+ internal bool IsUndefined { get { return (isUndefined); } }
+
+ ///
+ /// Return the collection of unknown records.
+ ///
+ internal static Collection UnknownRecords { get { return (unknownRecords); } }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following this record.
+ ///
+ ///
+ /// The descriptor has not been processed.
+ ///
+ public virtual int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("OpenTVRecordBase: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private int lastIndex = -1;
+
+ private int tag;
+ private int length;
+ private byte[] data;
+
+ private bool isUndefined;
+
+ private static Collection unknownRecords;
+
+ ///
+ /// Create an instance of the record class.
+ ///
+ /// The MPEG2 section containing the record.
+ /// The index of the tag byte of the record.
+ /// A descriptor instance.
+ internal static OpenTVRecordBase Instance(byte[] byteData, int index)
+ {
+ OpenTVRecordBase record;
+
+ switch ((int)byteData[index])
+ {
+ case OpenTVTitleDataRecord.TagValue:
+ record = new OpenTVTitleDataRecord();
+ break;
+ case OpenTVShortDescriptionRecord.TagValue:
+ record = new OpenTVShortDescriptionRecord();
+ break;
+ case OpenTVExtendedDescriptionRecord.TagValue:
+ record = new OpenTVExtendedDescriptionRecord();
+ break;
+ case OpenTVSeriesLinkRecord.TagValue:
+ record = new OpenTVSeriesLinkRecord();
+ break;
+ default:
+ record = new OpenTVRecordBase();
+
+ if (DebugEntry.IsDefined(DebugName.LogUnknownRecords))
+ {
+ if (unknownRecords == null)
+ unknownRecords = new Collection();
+ unknownRecords.Add(record);
+ }
+
+ break;
+ }
+
+ record.tag = (int)byteData[index];
+ index++;
+
+ record.length = (int)byteData[index];
+ index++;
+
+ record.Process(byteData, index);
+
+ return (record);
+ }
+
+ ///
+ /// Initialize a new instance of the OpenTVRecordBase class.
+ ///
+ internal OpenTVRecordBase() { }
+
+ ///
+ /// Parse the descriptor.
+ ///
+ /// The MPEG2 section containing the record.
+ /// Index of the byte in the MPEG2 section following the descriptor length.
+ internal virtual void Process(byte[] byteData, int index)
+ {
+ lastIndex = index;
+
+ if (Length != 0)
+ {
+ data = Utils.GetBytes(byteData, 0, Length);
+ lastIndex += Length;
+ }
+
+ isUndefined = true;
+ }
+
+ ///
+ /// Validate the record fields.
+ ///
+ ///
+ /// A record field is not valid.
+ ///
+ internal virtual void Validate() { }
+
+ ///
+ /// Log the descriptor fields.
+ ///
+ internal virtual void LogMessage()
+ {
+ if (DebugEntry.IsDefined(DebugName.LogUnknownRecords))
+ logMessage(Logger.Instance);
+ else
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ if (!TraceEntry.IsDefined(TraceName.GenericOpenTvRecord))
+ return;
+
+ logMessage(Logger.ProtocolLogger);
+ }
+ }
+
+ private void logMessage(Logger logger)
+ {
+ logger.Write(Logger.ProtocolIndent + "OPENTV GENERIC RECORD: Tag: " + Utils.ConvertToHex(tag) +
+ " Length: " + length);
+
+ if (length != 0)
+ logger.Dump("OpenTV Generic Record Data", data, data.Length);
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSeriesLinkRecord.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSeriesLinkRecord.cs
new file mode 100644
index 0000000..c22f4b0
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSeriesLinkRecord.cs
@@ -0,0 +1,111 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes an OpenTV series link record.
+ ///
+ internal class OpenTVSeriesLinkRecord : OpenTVRecordBase
+ {
+ ///
+ /// Get the tag value for this record.
+ ///
+ public const int TagValue = 0xc1;
+
+ ///
+ /// Get the series link.
+ ///
+ public int SeriesLink { get { return (seriesLink); } }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following the record.
+ ///
+ ///
+ /// The record has not been processed.
+ ///
+ public override int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("OpenTVSeriesLinkRecord: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private int seriesLink;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVSeriesLinkRecord class.
+ ///
+ internal OpenTVSeriesLinkRecord() { }
+
+ ///
+ /// Parse the record.
+ ///
+ /// The MPEG2 section containing the record.
+ /// Index of the first byte of the record data in the MPEG2 section.
+ internal override void Process(byte[] byteData, int index)
+ {
+ lastIndex = index;
+
+ try
+ {
+ seriesLink = Utils.Convert2BytesToInt(byteData, lastIndex);
+ lastIndex += 2;
+
+ Validate();
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw (new ArgumentOutOfRangeException("lastIndex = " + lastIndex));
+ }
+ }
+
+ ///
+ /// Validate the record data fields.
+ ///
+ ///
+ /// A record data field is not valid.
+ ///
+ internal override void Validate() { }
+
+ ///
+ /// Log the record data fields.
+ ///
+ internal override void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "");
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "OPENTV SERIES LINK RECORD: Series link: " + seriesLink);
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVShortDescriptionRecord.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVShortDescriptionRecord.cs
new file mode 100644
index 0000000..add3805
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVShortDescriptionRecord.cs
@@ -0,0 +1,116 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes an OpenTV short description record.
+ ///
+ internal class OpenTVShortDescriptionRecord : OpenTVRecordBase
+ {
+ ///
+ /// Get the tag value for this record.
+ ///
+ public const int TagValue = 0xb9;
+
+ ///
+ /// Get the short description.
+ ///
+ public string Description { get { return (SingleTreeDictionaryEntry.DecodeData(description)); } }
+
+ ///
+ /// Get the short description bytes.
+ ///
+ public byte[] DescriptionBytes { get { return (description); } }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following the record.
+ ///
+ ///
+ /// The record has not been processed.
+ ///
+ public override int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("OpenTVShortDescriptionRecord: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private byte[] description;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVShortDescriptionRecord class.
+ ///
+ internal OpenTVShortDescriptionRecord() { }
+
+ ///
+ /// Parse the record.
+ ///
+ /// The MPEG2 section containing the record.
+ /// Index of the first byte of the record data in the MPEG2 section.
+ internal override void Process(byte[] byteData, int index)
+ {
+ lastIndex = index;
+
+ try
+ {
+ description = Utils.GetBytes(byteData, lastIndex, Length);
+ lastIndex += Length;
+
+ Validate();
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw (new ArgumentOutOfRangeException("lastIndex = " + lastIndex));
+ }
+ }
+
+ ///
+ /// Validate the record data fields.
+ ///
+ ///
+ /// A record data field is not valid.
+ ///
+ internal override void Validate() { }
+
+ ///
+ /// Log the record data fields.
+ ///
+ internal override void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "");
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "OPENTV SHORT DESCRIPTION RECORD: Description: " + Utils.ConvertToHex(description));
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummaryData.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummaryData.cs
new file mode 100644
index 0000000..206da26
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummaryData.cs
@@ -0,0 +1,244 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.ObjectModel;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes Open TV summary data.
+ ///
+ public class OpenTVSummaryData
+ {
+ ///
+ /// Get the event identification.
+ ///
+ public int EventID { get { return (eventID); } }
+
+ ///
+ /// Get the short description of the event.
+ ///
+ public string ShortDescription
+ {
+ get
+ {
+ OpenTVShortDescriptionRecord record = (OpenTVShortDescriptionRecord)getRecord(OpenTVShortDescriptionRecord.TagValue);
+ if (record != null)
+ return (record.Description);
+ else
+ return null;
+ }
+ }
+
+ ///
+ /// Get the raw bytes of short description of the event.
+ ///
+ public byte[] ShortDescriptionBytes
+ {
+ get
+ {
+ OpenTVShortDescriptionRecord record = (OpenTVShortDescriptionRecord)getRecord(OpenTVShortDescriptionRecord.TagValue);
+ if (record != null)
+ return (record.DescriptionBytes);
+ else
+ return (new byte[] { 0x00 });
+ }
+ }
+
+ ///
+ /// Get the extended description of the event.
+ ///
+ public string ExtendedDescription
+ {
+ get
+ {
+ OpenTVExtendedDescriptionRecord record = (OpenTVExtendedDescriptionRecord)getRecord(OpenTVExtendedDescriptionRecord.TagValue);
+ if (record != null)
+ return (record.Description);
+ else
+ return (null);
+ }
+ }
+
+ ///
+ /// Get the series link of the event.
+ ///
+ public int SeriesLink
+ {
+ get
+ {
+ OpenTVSeriesLinkRecord record = (OpenTVSeriesLinkRecord)getRecord(OpenTVSeriesLinkRecord.TagValue);
+ if (record != null)
+ return (record.SeriesLink);
+ else
+ return (-1);
+ }
+ }
+
+ ///
+ /// Get the collection of records for this summary section.
+ ///
+ internal Collection Records
+ {
+ get
+ {
+ if (records == null)
+ records = new Collection();
+ return (records);
+ }
+ }
+
+ ///
+ /// Get the collection of undefined records for this summary section.
+ ///
+ internal Collection UndefinedRecords
+ {
+ get
+ {
+ if (records == null)
+ return (null);
+
+ Collection undefinedRecords = new Collection();
+
+ foreach (OpenTVRecordBase record in records)
+ {
+ if (record.IsUndefined)
+ undefinedRecords.Add(record);
+ }
+
+ return (undefinedRecords);
+ }
+ }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following the summary data.
+ ///
+ ///
+ /// The summary data has not been processed.
+ ///
+ public int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("OpenTVSummaryData: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private int eventID;
+ private int length;
+
+ private Collection records;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVSummaryData class.
+ ///
+ public OpenTVSummaryData() { }
+
+ ///
+ /// Parse the summary data.
+ ///
+ /// The MPEG2 section containing the summary data.
+ /// Index of the first byte of the summary data in the MPEG2 section.
+ /// The base date for the program events.
+ internal void Process(byte[] byteData, int index, DateTime baseDate)
+ {
+ lastIndex = index;
+
+ try
+ {
+ eventID = Utils.Convert2BytesToInt(byteData, lastIndex);
+ lastIndex += 2;
+
+ length = ((byteData[lastIndex] & 0x0f) * 256) + byteData[lastIndex + 1];
+ lastIndex += 2;
+
+ int recordLength = length;
+
+ while (recordLength != 0)
+ {
+ OpenTVRecordBase record = OpenTVRecordBase.Instance(byteData, lastIndex);
+ Records.Add(record);
+
+ lastIndex += record.TotalLength;
+ recordLength -= record.TotalLength;
+ }
+
+ Validate();
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw (new ArgumentOutOfRangeException("The Open TV Summary Data message is short"));
+ }
+ }
+
+ ///
+ /// Validate the summary data fields.
+ ///
+ ///
+ /// A summary data field is not valid.
+ ///
+ public void Validate() { }
+
+ ///
+ /// Log the summary data fields.
+ ///
+ public void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "OPENTV SUMMARY DATA: Event ID: " + eventID +
+ " Length: " + length);
+
+ if (records != null)
+ {
+ Logger.IncrementProtocolIndent();
+
+ foreach (OpenTVRecordBase record in records)
+ record.LogMessage();
+
+ Logger.DecrementProtocolIndent();
+ }
+ }
+
+ private OpenTVRecordBase getRecord(int tag)
+ {
+ if (records == null)
+ return (null);
+
+ foreach (OpenTVRecordBase record in records)
+ {
+ if (record.Tag == tag)
+ return (record);
+ }
+
+ return (null);
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummaryHeader.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummaryHeader.cs
new file mode 100644
index 0000000..53ed182
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummaryHeader.cs
@@ -0,0 +1,161 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.ObjectModel;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes an Open TV summary header.
+ ///
+ public class OpenTVSummaryHeader
+ {
+ ///
+ /// Get the channel identification.
+ ///
+ public int ChannelID { get { return (channelID); } }
+ ///
+ /// Get the title date base.
+ ///
+ public DateTime BaseDate { get { return (baseDate); } }
+ ///
+ /// Get the data collection related to this summary.
+ ///
+ public Collection SummaryData { get { return (summaryData); } }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following the summary header.
+ ///
+ ///
+ /// The summary header has not been processed.
+ ///
+ public int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("OpenTVSummaryHeader: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private int channelID;
+ private DateTime baseDate;
+ private Collection summaryData;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVSummaryHeader class.
+ ///
+ public OpenTVSummaryHeader() { }
+
+ ///
+ /// Parse the summary header.
+ ///
+ /// The MPEG2 section containing the summary header.
+ /// Index of the first byte of the summary header in the MPEG2 section.
+ /// The MPEG2 header of the section.
+ internal void Process(byte[] byteData, int index, Mpeg2ExtendedHeader mpeg2Header)
+ {
+ lastIndex = index;
+
+ channelID = mpeg2Header.TableIDExtension;
+
+ try
+ {
+ baseDate = getDate(Utils.Convert2BytesToInt(byteData, lastIndex));
+ lastIndex += 2;
+
+ while (lastIndex < byteData.Length - 4)
+ {
+ OpenTVSummaryData data = new OpenTVSummaryData();
+ data.Process(byteData, lastIndex, baseDate);
+
+ if (summaryData == null)
+ summaryData = new Collection();
+
+ summaryData.Add(data);
+
+ lastIndex = data.Index;
+ }
+
+ Validate();
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw (new ArgumentOutOfRangeException("The Open TV Summary Header message is short"));
+ }
+ }
+
+ private DateTime getDate(int mjd)
+ {
+ int j = mjd + 2400001 + 68569;
+ int c = 4 * j / 146097;
+ j = j - (146097 * c + 3) / 4;
+
+ int y = 4000 * (j + 1) / 1461001;
+ j = j - 1461 * y / 4 + 31;
+ int m = 80 * j / 2447;
+
+ int day = j - 2447 * m / 80;
+ j = m / 11;
+ int month = m + 2 - (12 * j);
+ int year = 100 * (c - 49) + y + j;
+
+ return (new DateTime(year, month, day) + new TimeSpan(1, 0, 0, 0));
+ }
+
+ ///
+ /// Validate the summary header fields.
+ ///
+ ///
+ /// A summary header field is not valid.
+ ///
+ public void Validate() { }
+
+ ///
+ /// Log the summary header fields.
+ ///
+ public void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "OPENTV SUMMARY HEADER: Channel ID: " + channelID +
+ " Base date : " + baseDate);
+
+ if (summaryData != null)
+ {
+ Logger.IncrementProtocolIndent();
+
+ foreach (OpenTVSummaryData data in summaryData)
+ data.LogMessage();
+
+ Logger.DecrementProtocolIndent();
+ }
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummarySection.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummarySection.cs
new file mode 100644
index 0000000..d7fa68d
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVSummarySection.cs
@@ -0,0 +1,151 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.ObjectModel;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes an Open TV Summary section.
+ ///
+ public class OpenTVSummarySection
+ {
+ ///
+ /// Get the collection of Open TV Title sections.
+ ///
+ public static Collection OpenTVSummarySections
+ {
+ get
+ {
+ if (openTVSummarySections == null)
+ openTVSummarySections = new Collection();
+ return (openTVSummarySections);
+ }
+ }
+
+ ///
+ /// Get the section number.
+ ///
+ public int SectionNumber { get { return (sectionNumber); } }
+ ///
+ /// Get the section number.
+ ///
+ public int LastSectionNumber { get { return (lastSectionNumber); } }
+ ///
+ /// Get the title header.
+ ///
+ public OpenTVSummaryHeader SummaryHeader { get { return (summaryHeader); } }
+
+ private int sectionNumber;
+ private int lastSectionNumber;
+ private OpenTVSummaryHeader summaryHeader;
+
+ private static Collection openTVSummarySections;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVSummarySection class.
+ ///
+ internal OpenTVSummarySection() { }
+
+ ///
+ /// Parse the section.
+ ///
+ /// The MPEG2 section containing the section.
+ /// The MPEG2 header that preceedes the section.
+ internal void Process(byte[] byteData, Mpeg2ExtendedHeader mpeg2Header)
+ {
+ lastIndex = mpeg2Header.Index;
+ sectionNumber = mpeg2Header.SectionNumber;
+ lastSectionNumber = mpeg2Header.LastSectionNumber;
+
+ summaryHeader = new OpenTVSummaryHeader();
+ summaryHeader.Process(byteData, lastIndex, mpeg2Header);
+ }
+
+ ///
+ /// Log the section fields.
+ ///
+ public void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ summaryHeader.LogMessage();
+ }
+
+ ///
+ /// Process an MPEG2 section from the Open TV Summary table.
+ ///
+ /// The MPEG2 section.
+ /// An Open TV Summary Section instance.
+ public static OpenTVSummarySection ProcessOpenTVSummaryTable(byte[] byteData)
+ {
+ Mpeg2ExtendedHeader mpeg2Header = new Mpeg2ExtendedHeader();
+
+ try
+ {
+ mpeg2Header.Process(byteData);
+
+ if (mpeg2Header.Current)
+ {
+ OpenTVSummarySection openTVSummarySection = new OpenTVSummarySection();
+ openTVSummarySection.Process(byteData, mpeg2Header);
+ openTVSummarySection.LogMessage();
+ return (openTVSummarySection);
+ }
+ else
+ return (null);
+ }
+ catch (ArgumentOutOfRangeException e)
+ {
+ Logger.Instance.Write(" Error processing Summary Section: " + e.Message);
+ return (null);
+ }
+ }
+
+ ///
+ /// Add a section to the collection.
+ ///
+ /// The section to be added.
+ public static void AddSection(OpenTVSummarySection newSection)
+ {
+ /*foreach (OpenTVSummarySection oldSection in OpenTVSummarySections)
+ {
+ if (oldSection.sectionNumber == newSection.sectionNumber)
+ return;
+
+ if (oldSection.SectionNumber > newSection.SectionNumber)
+ {
+ OpenTVSummarySections.Insert(OpenTVSummarySections.IndexOf(oldSection), newSection);
+ return;
+ }
+ }*/
+
+ OpenTVSummarySections.Add(newSection);
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleData.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleData.cs
new file mode 100644
index 0000000..e8e2967
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleData.cs
@@ -0,0 +1,289 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.ObjectModel;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes Open TV title data.
+ ///
+ public class OpenTVTitleData
+ {
+ ///
+ /// Get the event identification.
+ ///
+ public int EventID { get { return (eventID); } }
+
+ ///
+ /// Get the start time of the event.
+ ///
+ public DateTime StartTime
+ {
+ get
+ {
+ OpenTVTitleDataRecord record = (OpenTVTitleDataRecord)getRecord(OpenTVTitleDataRecord.TagValue);
+ return (baseDate + record.StartTimeOffset);
+ }
+ }
+
+ ///
+ /// Get the duration of the event.
+ ///
+ public TimeSpan Duration
+ {
+ get
+ {
+ OpenTVTitleDataRecord record = (OpenTVTitleDataRecord)getRecord(OpenTVTitleDataRecord.TagValue);
+ return (record.Duration);
+ }
+ }
+
+ ///
+ /// Get the theme identification of the event.
+ ///
+ public int CategoryID
+ {
+ get
+ {
+ OpenTVTitleDataRecord record = (OpenTVTitleDataRecord)getRecord(OpenTVTitleDataRecord.TagValue);
+ return (record.CategoryID);
+ }
+ }
+
+ ///
+ /// Get the name of the event.
+ ///
+ public string EventName
+ {
+ get
+ {
+ OpenTVTitleDataRecord record = (OpenTVTitleDataRecord)getRecord(OpenTVTitleDataRecord.TagValue);
+ return (record.DecodedEventName);
+ }
+ }
+
+ ///
+ /// Get the raw bytes of the event name.
+ ///
+ public byte[] EventNameBytes
+ {
+ get
+ {
+ OpenTVTitleDataRecord record = (OpenTVTitleDataRecord)getRecord(OpenTVTitleDataRecord.TagValue);
+ return (record.EventName);
+ }
+ }
+
+ ///
+ /// Get the flags field of the event.
+ ///
+ public byte[] Flags
+ {
+ get
+ {
+ OpenTVTitleDataRecord record = (OpenTVTitleDataRecord)getRecord(OpenTVTitleDataRecord.TagValue);
+ return (record.Flags);
+ }
+ }
+
+ ///
+ /// Get the collection of records for this title section.
+ ///
+ internal Collection Records
+ {
+ get
+ {
+ if (records == null)
+ records = new Collection();
+ return (records);
+ }
+ }
+
+ ///
+ /// Get the collection of undefined records for this title section.
+ ///
+ internal Collection UndefinedRecords
+ {
+ get
+ {
+ if (records == null)
+ return (null);
+
+ Collection undefinedRecords = new Collection();
+
+ foreach (OpenTVRecordBase record in records)
+ {
+ if (record.IsUndefined)
+ undefinedRecords.Add(record);
+ }
+
+ return (undefinedRecords);
+ }
+ }
+
+ ///
+ /// Return true if the entry is empty; false otherwise.
+ ///
+ public bool IsEmpty { get { return (records == null || records.Count == 0); } }
+
+ ///
+ /// Get the PID of the section containing the data.
+ ///
+ public int PID { get { return (pid); } }
+ ///
+ /// Get the table ID of the section containing the data.
+ ///
+ public int Table { get { return (table); } }
+ ///
+ /// Get the timestamp when the data arrived.
+ ///
+ public DateTime TimeStamp { get { return (timeStamp); } }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following the title data.
+ ///
+ ///
+ /// The title data has not been processed.
+ ///
+ public int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("OpenTVTitleData: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private int eventID;
+ private int length;
+
+ private DateTime baseDate;
+
+ private int pid;
+ private int table;
+ private DateTime timeStamp;
+
+ private Collection records;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVTitleData class.
+ ///
+ public OpenTVTitleData() { }
+
+ ///
+ /// Parse the title data.
+ ///
+ /// The MPEG2 section containing the title data.
+ /// Index of the first byte of the title data in the MPEG2 section.
+ /// The base date for the programs.
+ /// The channel for the data.
+ /// The PID of the section.
+ /// The table ID of the section.
+ internal void Process(byte[] byteData, int index, DateTime baseDate, int channel, int pid, int table)
+ {
+ lastIndex = index;
+
+ this.pid = pid;
+ this.table = table;
+ this.baseDate = baseDate;
+
+ try
+ {
+ eventID = Utils.Convert2BytesToInt(byteData, lastIndex);
+ lastIndex += 2;
+
+ length = ((byteData[lastIndex] & 0x0f) * 256) + byteData[lastIndex + 1];
+ lastIndex += 2;
+
+ int recordLength = length;
+
+ while (recordLength != 0)
+ {
+ OpenTVRecordBase record = OpenTVRecordBase.Instance(byteData, lastIndex);
+ Records.Add(record);
+
+ lastIndex += record.TotalLength;
+ recordLength -= record.TotalLength;
+ }
+
+ timeStamp = DateTime.Now;
+
+ Validate();
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw (new ArgumentOutOfRangeException("lastIndex = " + lastIndex));
+ }
+ }
+
+ ///
+ /// Validate the title data fields.
+ ///
+ ///
+ /// A title data field is not valid.
+ ///
+ public void Validate() { }
+
+ ///
+ /// Log the title data fields.
+ ///
+ public void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "OPENTV TITLE DATA: Event ID: " + eventID +
+ " Length: " + length);
+
+ if (records != null)
+ {
+ Logger.IncrementProtocolIndent();
+
+ foreach (OpenTVRecordBase record in records)
+ record.LogMessage();
+
+ Logger.DecrementProtocolIndent();
+ }
+ }
+
+ private OpenTVRecordBase getRecord(int tag)
+ {
+ if (records == null)
+ return(null);
+
+ foreach (OpenTVRecordBase record in records)
+ {
+ if (record.Tag == tag)
+ return(record);
+ }
+
+ return(null);
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleDataRecord.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleDataRecord.cs
new file mode 100644
index 0000000..6972784
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleDataRecord.cs
@@ -0,0 +1,164 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes an OpenTV title data record.
+ ///
+ internal class OpenTVTitleDataRecord : OpenTVRecordBase
+ {
+ ///
+ /// Get the tag value for this record.
+ ///
+ public const int TagValue = 0xb5;
+
+ ///
+ /// Get the start time of the event.
+ ///
+ public TimeSpan StartTimeOffset { get { return (startTimeOffset); } }
+ ///
+ /// Get the duration of the event.
+ ///
+ public TimeSpan Duration { get { return (duration); } }
+ ///
+ /// Get the theme identification of the event.
+ ///
+ public int CategoryID { get { return (categoryID); } }
+ ///
+ /// Get the flags field of the event.
+ ///
+ public byte[] Flags { get { return (flags); } }
+ ///
+ /// Get the name of the event.
+ ///
+ public byte[] EventName { get { return (eventName); } }
+
+ ///
+ /// Get the decompressed event name.
+ ///
+ public string DecodedEventName { get { return (SingleTreeDictionaryEntry.DecodeData(eventName)); } }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following the record.
+ ///
+ ///
+ /// The record has not been processed.
+ ///
+ public override int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("OpenTVTitleDataRecord: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private TimeSpan startTimeOffset;
+ private TimeSpan duration;
+ private int categoryID;
+ private byte[] flags;
+ private byte[] eventName;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVTitleDataRecord class.
+ ///
+ internal OpenTVTitleDataRecord() { }
+
+ ///
+ /// Parse the record.
+ ///
+ /// The MPEG2 section containing the record.
+ /// Index of the first byte of the record data in the MPEG2 section.
+ internal override void Process(byte[] byteData, int index)
+ {
+ lastIndex = index;
+
+ try
+ {
+ // Source value to 2 second resolution
+ startTimeOffset = getTime((byteData[lastIndex] * 512) + (byteData[lastIndex + 1] * 2));
+ lastIndex += 2;
+
+ duration = getTime(Utils.Convert2BytesToInt(byteData, lastIndex) * 2);
+ lastIndex += 2;
+
+ categoryID = (int)byteData[lastIndex];
+ lastIndex++;
+
+ flags = Utils.GetBytes(byteData, lastIndex, 2);
+ lastIndex += 2;
+
+ eventName = Utils.GetBytes(byteData, lastIndex, Length - 7);
+ lastIndex += Length - 7;
+
+ Validate();
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw (new ArgumentOutOfRangeException("lastIndex = " + lastIndex));
+ }
+ }
+
+ private TimeSpan getTime(int totalSeconds)
+ {
+ int days = totalSeconds / 86400;
+ int hours = (totalSeconds - (days * 86400)) / 3600;
+ int minutes = (totalSeconds - ((days * 86400) + (hours * 3600))) / 60;
+ int seconds = totalSeconds % 60;
+
+ return (new TimeSpan(days, hours, minutes, seconds));
+ }
+
+ ///
+ /// Validate the record data fields.
+ ///
+ ///
+ /// A record data field is not valid.
+ ///
+ internal override void Validate() { }
+
+ ///
+ /// Log the record data fields.
+ ///
+ internal override void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "");
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "OPENTV TITLE DATA RECORD: " +
+ "Start time: " + startTimeOffset +
+ " Duration: " + duration +
+ " Category: " + categoryID +
+ " Unknown: " + Utils.ConvertToHex(flags) +
+ " Name: " + Utils.ConvertToHex(eventName));
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleHeader.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleHeader.cs
new file mode 100644
index 0000000..141b22e
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleHeader.cs
@@ -0,0 +1,165 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.ObjectModel;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes an Open TV title header.
+ ///
+ public class OpenTVTitleHeader
+ {
+ ///
+ /// Get the channel identification.
+ ///
+ public int ChannelID { get { return (channelID); } }
+ ///
+ /// Get the title date base.
+ ///
+ public DateTime BaseDate { get { return (baseDate); } }
+ ///
+ /// Get the data collection related to this title.
+ ///
+ public Collection TitleData { get { return (titleData); } }
+
+ ///
+ /// Get the index of the next byte in the MPEG2 section following the title header.
+ ///
+ ///
+ /// The title header has not been processed.
+ ///
+ public int Index
+ {
+ get
+ {
+ if (lastIndex == -1)
+ throw (new InvalidOperationException("OpenTVTitleHeader: Index requested before block processed"));
+ return (lastIndex);
+ }
+ }
+
+ private int channelID;
+ private DateTime baseDate;
+ private Collection titleData;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVTitleHeader class.
+ ///
+ public OpenTVTitleHeader() { }
+
+ ///
+ /// Parse the title header.
+ ///
+ /// The MPEG2 section containing the title header.
+ /// Index of the first byte of the title header in the MPEG2 section.
+ /// The MPEG2 header of the section.
+ /// The PID of the section.
+ /// The table ID of the section.
+ internal void Process(byte[] byteData, int index, Mpeg2ExtendedHeader mpeg2Header, int pid, int tid)
+ {
+ lastIndex = index;
+
+ channelID = mpeg2Header.TableIDExtension;
+
+ try
+ {
+ baseDate = getDate(Utils.Convert2BytesToInt(byteData, lastIndex));
+ lastIndex += 2;
+
+ while (lastIndex < byteData.Length - 4)
+ {
+ OpenTVTitleData data = new OpenTVTitleData();
+ data.Process(byteData, lastIndex, baseDate, channelID, pid, tid);
+
+ if (!data.IsEmpty)
+ {
+ if (titleData == null)
+ titleData = new Collection();
+ titleData.Add(data);
+ }
+
+ lastIndex = data.Index;
+ }
+
+ Validate();
+ }
+ catch (IndexOutOfRangeException)
+ {
+ throw (new ArgumentOutOfRangeException("lastIndex = " + lastIndex));
+ }
+ }
+
+ private DateTime getDate(int mjd)
+ {
+ int j = mjd + 2400001 + 68569;
+ int c = 4 * j / 146097;
+ j = j - (146097 * c + 3) / 4;
+
+ int y = 4000 * (j + 1) / 1461001;
+ j = j - 1461 * y / 4 + 31;
+ int m = 80 * j / 2447;
+
+ int day = j - 2447 * m / 80;
+ j = m / 11;
+ int month = m + 2 - (12 * j);
+ int year = 100 * (c - 49) + y + j;
+
+ return (new DateTime(year, month, day));
+ }
+
+ ///
+ /// Validate the title header fields.
+ ///
+ ///
+ /// A title header field is not valid.
+ ///
+ public void Validate() { }
+
+ ///
+ /// Log the title header fields.
+ ///
+ public void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ Logger.ProtocolLogger.Write(Logger.ProtocolIndent + "OPENTV TITLE HEADER: Channel ID: " + channelID +
+ " Base date : " + baseDate);
+
+ if (titleData != null)
+ {
+ Logger.IncrementProtocolIndent();
+
+ foreach (OpenTVTitleData data in titleData)
+ data.LogMessage();
+
+ Logger.DecrementProtocolIndent();
+ }
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleSection.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleSection.cs
new file mode 100644
index 0000000..90a3405
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/OpenTV/OpenTVTitleSection.cs
@@ -0,0 +1,126 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+
+using DomainObjects;
+
+namespace DVBServices
+{
+ ///
+ /// The class that describes an Open TV Title section.
+ ///
+ public class OpenTVTitleSection
+ {
+ ///
+ /// Get the section number.
+ ///
+ public int SectionNumber { get { return (sectionNumber); } }
+ ///
+ /// Get the section number.
+ ///
+ public int LastSectionNumber { get { return (lastSectionNumber); } }
+ ///
+ /// Get the title header.
+ ///
+ public OpenTVTitleHeader TitleHeader { get { return (titleHeader); } }
+
+ private int sectionNumber;
+ private int lastSectionNumber;
+ private OpenTVTitleHeader titleHeader;
+
+ private int lastIndex = -1;
+
+ ///
+ /// Initialize a new instance of the OpenTVTitleSection class.
+ ///
+ internal OpenTVTitleSection() { }
+
+ ///
+ /// Parse the section.
+ ///
+ /// The MPEG2 section containing the section.
+ /// The MPEG2 header that preceedes the section.
+ /// The PID containing the section.
+ /// The table ID containing the section.
+ internal void Process(byte[] byteData, Mpeg2ExtendedHeader mpeg2Header, int pid, int tid)
+ {
+ lastIndex = mpeg2Header.Index;
+ sectionNumber = mpeg2Header.SectionNumber;
+ lastSectionNumber = mpeg2Header.LastSectionNumber;
+
+ titleHeader = new OpenTVTitleHeader();
+ titleHeader.Process(byteData, lastIndex, mpeg2Header, pid, tid);
+ }
+
+ ///
+ /// Log the section fields.
+ ///
+ public void LogMessage()
+ {
+ if (Logger.ProtocolLogger == null)
+ return;
+
+ titleHeader.LogMessage();
+ }
+
+ ///
+ /// Process an MPEG2 section from the Open TV Title table.
+ ///
+ /// The MPEG2 section.
+ /// The PID containing the section.
+ /// The table ID containing the section.
+ /// An Open TV Title Section instance or null if a section is not created.
+ public static OpenTVTitleSection ProcessOpenTVTitleTable(byte[] byteData, int pid, int table)
+ {
+ Mpeg2ExtendedHeader mpeg2Header = new Mpeg2ExtendedHeader();
+
+ try
+ {
+ mpeg2Header.Process(byteData);
+
+ if (mpeg2Header.Current)
+ {
+ OpenTVTitleSection openTVTitleSection = new OpenTVTitleSection();
+ openTVTitleSection.Process(byteData, mpeg2Header, pid, table);
+ openTVTitleSection.LogMessage();
+ return (openTVTitleSection);
+ }
+ else
+ return (null);
+ }
+ catch (ArgumentOutOfRangeException e)
+ {
+ Logger.Instance.Write(" Error processing Title Section: " + e.Message);
+
+ if (DebugEntry.IsDefined(DebugName.TitleSection))
+ {
+ Logger.Instance.Write(e.Message);
+ Logger.Instance.Write(e.StackTrace);
+ Logger.Instance.Dump("Title Section", byteData, byteData.Length);
+ }
+
+ return (null);
+ }
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Utils.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Utils.cs
index fb97cf3..0be70c1 100644
--- a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Utils.cs
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DVBServices/Utils.cs
@@ -138,5 +138,42 @@ namespace DVBServices
temp = "";
return temp;
}
+
+ ///
+ /// Convert an integer value to a hex string.
+ ///
+ /// The value to be converted.
+ /// The converted string.
+ public static string ConvertToHex(int value)
+ {
+ if (value == 0)
+ return ("0x00");
+
+ uint tempValue = (uint)value;
+
+ char[] outputChars = new char[8];
+
+ int outputIndex = 7;
+
+ for (int index = 3; index > -1; index--)
+ {
+ uint hexByte = (tempValue << 24) >> 24;
+ int hexByteLeft = (int)(hexByte >> 4);
+ int hexByteRight = (int)(hexByte & 0x0f);
+
+ outputChars[outputIndex] = getHex(hexByteRight);
+ outputChars[outputIndex - 1] = getHex(hexByteLeft);
+
+ outputIndex -= 2;
+ tempValue = tempValue >> 8;
+ }
+
+ string replyString = new string(outputChars).TrimStart(new char[] { '0' });
+
+ if (replyString.Length % 2 == 0)
+ return ("0x" + replyString);
+ else
+ return ("0x0" + replyString);
+ }
}
}
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DomainObjects/TraceEntry.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DomainObjects/TraceEntry.cs
new file mode 100644
index 0000000..9d5158a
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/EPGCollectorSide/DomainObjects/TraceEntry.cs
@@ -0,0 +1,266 @@
+//////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright © 2005-2020 nzsjb //
+// //
+// This Program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2, or (at your option) //
+// any later version. //
+// //
+// This Program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with GNU Make; see the file COPYING. If not, write to //
+// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections.ObjectModel;
+
+namespace DomainObjects
+{
+ ///
+ /// The class that describes a trace parameter entry.
+ ///
+ public class TraceEntry
+ {
+ ///
+ /// Get the last error message.
+ ///
+ public static string LastError { get { return (lastError); } }
+
+ ///
+ /// Get the entry name.
+ ///
+ public TraceName Name { get; private set; }
+
+ ///
+ /// Get or set the number entry parameter.
+ ///
+ public int NumberParameter
+ {
+ get
+ {
+ if (!numberParameterSet)
+ throw (new InvalidOperationException("TraceEntry number parameter not set"));
+
+ return (numberParameter);
+ }
+ set
+ {
+ numberParameter = value;
+ numberParameterSet = true;
+ }
+ }
+
+ ///
+ /// Get or set the string entry parameter.
+ ///
+ public string StringParameter
+ {
+ get
+ {
+ if (!stringParameterSet)
+ throw (new InvalidOperationException("TraceEntry string parameter not set"));
+
+ return (stringParameter);
+ }
+ set
+ {
+ stringParameter = value;
+ stringParameterSet = true;
+ }
+ }
+
+ ///
+ /// Return true if the entry number parameter has been set; false otherwise.
+ ///
+ public bool NumberParameterSet { get { return (numberParameterSet); } }
+ ///
+ /// Return true if the entry string parameter has been set; false otherwise.
+ ///
+ public bool StringParameterSet { get { return (stringParameterSet); } }
+
+ private int numberParameter;
+ private bool numberParameterSet;
+ private string stringParameter;
+ private bool stringParameterSet;
+
+ private static string lastError;
+
+ private TraceEntry() { }
+
+ ///
+ /// Initialize a new instance of the TraceEntry class with a name.
+ ///
+ /// The name of the entry.
+ public TraceEntry(TraceName name)
+ {
+ Name = name;
+ }
+
+ ///
+ /// Initialize a new entry of the TraceEntry class with a name and number parameter.
+ ///
+ ///
+ ///
+ public TraceEntry(TraceName name, int parameter) : this(name)
+ {
+ NumberParameter = parameter;
+ }
+
+ ///
+ /// Initialize a new entry of the TraceEntry class with a name and string parameter.
+ ///
+ ///
+ ///
+ public TraceEntry(TraceName name, string parameter) : this(name)
+ {
+ StringParameter = parameter;
+ }
+
+ ///
+ /// Get a string representation of the instance.
+ ///
+ /// A string representing the instance.
+ public override string ToString()
+ {
+ if (numberParameterSet)
+ return (Name.ToString() + "-" + NumberParameter);
+ else
+ {
+ if (stringParameterSet)
+ return (Name.ToString() + "-" + '"' + StringParameter + '"');
+ else
+ return (Name.ToString());
+ }
+ }
+
+ ///
+ /// Copy the instance.
+ ///
+ /// A new instance of the TraceEntry class with the same values as this instance.
+ public TraceEntry Clone()
+ {
+ TraceEntry newEntry = new TraceEntry(Name);
+
+ if (numberParameterSet)
+ newEntry.NumberParameter = NumberParameter;
+ if (stringParameterSet)
+ newEntry.StringParameter = StringParameter;
+
+ return (newEntry);
+ }
+
+ ///
+ /// Get an instance of the TraceEntry from a parameter file entry.
+ ///
+ /// The parameter file entry.
+ /// A new instance of the class.
+ public static TraceEntry GetInstance(string parameter)
+ {
+ string[] parameterParts = parameter.Split(new char[] { '-' });
+
+ if (parameterParts.Length == 2 && string.IsNullOrWhiteSpace(parameterParts[1]))
+ return(null);
+
+ try
+ {
+ TraceEntry traceEntry = new TraceEntry((TraceName)Enum.Parse(typeof(TraceName), parameterParts[0].Trim(), true));
+
+ if (parameterParts.Length == 2)
+ {
+ if (parameterParts[1].Trim()[0] != '"')
+ {
+ try
+ {
+ traceEntry.NumberParameter = Int32.Parse(parameterParts[1]);
+ }
+ catch (FormatException)
+ {
+ lastError = "The Trace name '" + parameterParts[0].Trim() + "' has a parameter in the wrong format.";
+ return (null);
+ }
+ catch (OverflowException)
+ {
+ lastError = "The Trace name '" + parameterParts[0].Trim() + "' has a parameter out of range.";
+ return (null);
+ }
+ }
+ else
+ {
+ if (parameterParts[1].Trim().Length < 3 || parameterParts[1].Trim()[parameterParts[1].Length - 1] != '"')
+ return (null);
+
+ traceEntry.StringParameter = parameterParts[1].Trim().Substring(1, parameterParts[1].Length - 2);
+ }
+ }
+
+ return (traceEntry);
+ }
+ catch (ArgumentException)
+ {
+ lastError = "The Trace ID '" + parameter.Trim() + "' is undefined and will be ignored.";
+ return (null);
+ }
+ }
+
+ ///
+ /// Check if a trace name is present.
+ ///
+ /// The name of the trace entry.
+ /// True if the trace name is present; false otherwise.
+ public static bool IsDefined(TraceName traceName)
+ {
+ return false;
+ }
+
+ ///
+ /// Find a trace entry.
+ ///
+ /// The name of the trace entry.
+ /// The trace entry if it is found; otherwise null
+ public static TraceEntry FindEntry(TraceName traceName)
+ {
+ return (FindEntry(traceName, false));
+ }
+
+ ///
+ /// Find a trace entry.
+ ///
+ /// The name of the trace entry.
+ /// True if a parameter must be present; false otherwise.
+ /// The trace entry if it is found; otherwise null
+ public static TraceEntry FindEntry(TraceName traceName, bool withParameter)
+ {
+ //feyris-tan: We don't use these in skyscraper, so we'll just always return null
+ return null;
+ }
+
+ ///
+ /// Find a trace entry.
+ ///
+ /// The list of trace entries to search.
+ /// The string representation of the debug entry.
+ /// The trace entry if it is found; otherwise null
+ public static TraceEntry FindEntry(Collection traceEntries, string identifier)
+ {
+ if (traceEntries == null)
+ return (null);
+
+ foreach (TraceEntry traceEntry in traceEntries)
+ {
+ if (traceEntry.ToString().ToUpperInvariant() == identifier.ToUpperInvariant())
+ return (traceEntry);
+ }
+
+ return (null);
+ }
+ }
+}
+
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvDataStorage.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvDataStorage.cs
new file mode 100644
index 0000000..a12b191
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvDataStorage.cs
@@ -0,0 +1,68 @@
+using skyscraper5.Data.PostgreSql;
+using skyscraper5.Skyscraper.Scraper.Storage.InMemory;
+using skyscraper8.EPGCollectorPort.SkyscraperSide.MediaHighway2;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace skyscraper8.EPGCollectorPort.SkyscraperSide.OpenTV
+{
+ internal interface IOpenTvDataStorage
+ {
+ bool TestForTitles(int skyscraperContextCurrentNetworkId, int skyscraperContextCurrentTransportStreamId, int titleDataEventId, DateTime titleDataStartTime);
+ }
+
+ internal class OpenTvDataStorageImpl : IOpenTvDataStorage
+ {
+ private IOpenTvDataStorage _storageEngine;
+
+ public OpenTvDataStorageImpl(object[] getPluginConnector)
+ {
+ object o = getPluginConnector[0];
+ switch (o)
+ {
+ case InMemoryPluginToken t1:
+ _storageEngine = new OpenTvDataStorageMemory();
+ break;
+ case PostgresqlToken t2:
+ _storageEngine = new OpenTvDataStoragePostgresql(t2);
+ break;
+ default:
+ throw new NotImplementedException(o.GetType().FullName);
+ }
+ }
+
+ public bool TestForTitles(int skyscraperContextCurrentNetworkId, int skyscraperContextCurrentTransportStreamId,
+ int titleDataEventId, DateTime titleDataStartTime)
+ {
+ return _storageEngine.TestForTitles(skyscraperContextCurrentNetworkId, skyscraperContextCurrentTransportStreamId, titleDataEventId, titleDataStartTime);
+ }
+ }
+
+ internal class OpenTvDataStorageMemory : IOpenTvDataStorage
+ {
+ public bool TestForTitles(int skyscraperContextCurrentNetworkId, int skyscraperContextCurrentTransportStreamId,
+ int titleDataEventId, DateTime titleDataStartTime)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ internal class OpenTvDataStoragePostgresql : IOpenTvDataStorage
+ {
+ private readonly PostgresqlToken _postgresql;
+
+ public OpenTvDataStoragePostgresql(PostgresqlToken postgresql)
+ {
+ _postgresql = postgresql;
+ }
+
+ public bool TestForTitles(int skyscraperContextCurrentNetworkId, int skyscraperContextCurrentTransportStreamId,
+ int titleDataEventId, DateTime titleDataStartTime)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvExpectedDataType.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvExpectedDataType.cs
new file mode 100644
index 0000000..32db809
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvExpectedDataType.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace skyscraper8.EPGCollectorPort.SkyscraperSide.OpenTV
+{
+ internal enum OpenTvExpectedDataType
+ {
+ Titles,
+ Summaries
+ }
+}
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvHandler.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvHandler.cs
new file mode 100644
index 0000000..10d8242
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvHandler.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DVBServices;
+
+namespace skyscraper8.EPGCollectorPort.SkyscraperSide.OpenTV
+{
+ internal interface OpenTvHandler
+ {
+ void OnNonOpenTvTraffic(int sourcePid, OpenTvExpectedDataType titles, int sectionTableId);
+ void OnTitles(int sourcePid, int sectionTableId, OpenTVTitleSection titleSection);
+ void OnSummaries(int sourcePid, int sectionTableId, OpenTVSummarySection summarySection);
+ }
+}
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvScraper.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvScraper.cs
new file mode 100644
index 0000000..5a22865
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvScraper.cs
@@ -0,0 +1,59 @@
+using DVBServices;
+using skyscraper5.Skyscraper.Scraper;
+using skyscraper8.Skyscraper.Plugins;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace skyscraper8.EPGCollectorPort.SkyscraperSide.OpenTV
+{
+ internal class OpenTvScraper : OpenTvHandler
+ {
+ private readonly SkyscraperContext _skyscraperContext;
+ private readonly IOpenTvDataStorage storage;
+ private static PluginLogger _logger;
+
+ public OpenTvScraper(SkyscraperContext skyscraperContext)
+ {
+ _skyscraperContext = skyscraperContext;
+ storage = new OpenTvDataStorageImpl(skyscraperContext.DataStorage.GetPluginConnector());
+ if (_logger == null)
+ {
+ _logger = PluginLogManager.GetLogger(GetType());
+ }
+ }
+
+ public void OnNonOpenTvTraffic(int sourcePid, OpenTvExpectedDataType titles, int sectionTableId)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnTitles(int sourcePid, int sectionTableId, OpenTVTitleSection titleSection)
+ {
+ if (!_skyscraperContext.CurrentNetworkId.HasValue)
+ return;
+ if (!_skyscraperContext.CurrentTransportStreamId.HasValue)
+ return;
+
+ foreach (OpenTVTitleData titleData in titleSection.TitleHeader.TitleData)
+ {
+ if (!storage.TestForTitles(_skyscraperContext.CurrentNetworkId.Value, _skyscraperContext.CurrentTransportStreamId.Value, titleData.EventID, titleData.StartTime))
+ {
+
+ }
+ }
+ }
+
+ public void OnSummaries(int sourcePid, int sectionTableId, OpenTVSummarySection summarySection)
+ {
+ if (!_skyscraperContext.CurrentNetworkId.HasValue)
+ return;
+ if (!_skyscraperContext.CurrentTransportStreamId.HasValue)
+ return;
+
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvSummaryContestant.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvSummaryContestant.cs
new file mode 100644
index 0000000..d959f45
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvSummaryContestant.cs
@@ -0,0 +1,68 @@
+using DVBServices;
+using skyscraper5.Mpeg2;
+using skyscraper5.Skyscraper.Plugins;
+using skyscraper5.Skyscraper.Scraper;
+using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
+using skyscraper8.EPGCollectorPort.SkyscraperSide.MediaHighway2;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace skyscraper8.EPGCollectorPort.SkyscraperSide.OpenTV
+{
+ ////Disabled due to the Huffmann Table being dynamically determined.
+ //[SkyscraperPlugin]
+ internal class OpenTvSummaryContestant : Contestant, OpenTvHandler
+ {
+ public OpenTvSummaryContestant(int pid)
+ : base("OpenTV Summaries", pid)
+ {
+ PacketProcessor = new PsiDecoder(pid, new OpenTvSummaryParser(this));
+ }
+
+ public override void Dispose()
+ {
+
+ }
+
+ public override void DeclareWinner(SkyscraperContext skyscraperContext, int pid, ProgramContext programContext)
+ {
+ OpenTvScraper openTvScraper = skyscraperContext.PluginContext.FirstOrDefault(x => x is OpenTvScraper) as OpenTvScraper;
+ if (openTvScraper == null)
+ {
+ openTvScraper = new OpenTvScraper(skyscraperContext);
+ skyscraperContext.PluginContext.Add(openTvScraper);
+ }
+
+ skyscraperContext.DvbContext.RegisterPacketProcessor(pid, new PsiDecoder(pid, new OpenTvSummaryParser(openTvScraper)));
+ }
+
+ public override void Introduce(ProgramContext programContext)
+ {
+
+ }
+
+ private byte[] nonTrafficMarkers;
+ public void OnNonOpenTvTraffic(int sourcePid, OpenTvExpectedDataType titles, int sectionTableId)
+ {
+ if (nonTrafficMarkers == null)
+ nonTrafficMarkers = new byte[byte.MaxValue];
+
+ nonTrafficMarkers[sectionTableId]++;
+ if (nonTrafficMarkers[sectionTableId] == 1)
+ Score++;
+ }
+
+ public void OnTitles(int sourcePid, int sectionTableId, OpenTVTitleSection titleSection)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnSummaries(int sourcePid, int sectionTableId, OpenTVSummarySection summarySection)
+ {
+ Score++;
+ }
+ }
+}
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvSummaryParser.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvSummaryParser.cs
new file mode 100644
index 0000000..9836ab9
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvSummaryParser.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DVBServices;
+using skyscraper5.Mpeg2;
+
+namespace skyscraper8.EPGCollectorPort.SkyscraperSide.OpenTV
+{
+ internal class OpenTvSummaryParser : IPsiProcessor
+ {
+ private readonly OpenTvHandler _openTvScraper;
+
+ public OpenTvSummaryParser(OpenTvHandler openTvScraper)
+ {
+ _openTvScraper = openTvScraper;
+ }
+
+ public void GatherPsi(PsiSection section, int sourcePid)
+ {
+ if (section.TableId >= 0xa8 && section.TableId <= 0xab)
+ {
+ OpenTVSummarySection summarySection = OpenTVSummarySection.ProcessOpenTVSummaryTable(section.GetData());
+ if (summarySection != null)
+ {
+ _openTvScraper.OnSummaries(sourcePid, section.TableId, summarySection);
+ }
+ }
+ else
+ {
+ if (section.TableId >= 0xa0 && section.TableId <= 0xa7)
+ {
+ //Titles
+ return;
+ }
+
+ _openTvScraper.OnNonOpenTvTraffic(sourcePid, OpenTvExpectedDataType.Summaries, section.TableId);
+ }
+ }
+ }
+}
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvTitleContestant.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvTitleContestant.cs
new file mode 100644
index 0000000..4720555
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvTitleContestant.cs
@@ -0,0 +1,62 @@
+using DVBServices;
+using skyscraper5.Mpeg2;
+using skyscraper5.Skyscraper.Plugins;
+using skyscraper5.Skyscraper.Scraper;
+using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
+using skyscraper8.EPGCollectorPort.SkyscraperSide.MediaHighway2;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace skyscraper8.EPGCollectorPort.SkyscraperSide.OpenTV
+{
+ //Disabled due to the Huffmann Table being dynamically determined.
+ //[SkyscraperPlugin]
+ internal class OpenTvTitleContestant : Contestant, OpenTvHandler
+ {
+ public OpenTvTitleContestant(int pid)
+ : base("OpenTV Titles", pid)
+ {
+ PacketProcessor = new PsiDecoder(pid, new OpenTvTitleParser(this));
+ }
+
+ public override void Dispose()
+ {
+
+ }
+
+ public override void DeclareWinner(SkyscraperContext skyscraperContext, int pid, ProgramContext programContext)
+ {
+ OpenTvScraper openTvScraper = skyscraperContext.PluginContext.FirstOrDefault(x => x is OpenTvScraper) as OpenTvScraper;
+ if (openTvScraper == null)
+ {
+ openTvScraper = new OpenTvScraper(skyscraperContext);
+ skyscraperContext.PluginContext.Add(openTvScraper);
+ }
+
+ skyscraperContext.DvbContext.RegisterPacketProcessor(pid, new PsiDecoder(pid, new OpenTvTitleParser(openTvScraper)));
+ }
+
+ public override void Introduce(ProgramContext programContext)
+ {
+
+ }
+
+ public void OnNonOpenTvTraffic(int sourcePid, OpenTvExpectedDataType titles, int sectionTableId)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void OnTitles(int sourcePid, int sectionTableId, OpenTVTitleSection titleSection)
+ {
+ Score++;
+ }
+
+ public void OnSummaries(int sourcePid, int sectionTableId, OpenTVSummarySection summarySection)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvTitleParser.cs b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvTitleParser.cs
new file mode 100644
index 0000000..0f2b165
--- /dev/null
+++ b/PrivateDataSpecifiers/skyscraper8.EPGCollectorPort/SkyscraperSide/OpenTV/OpenTvTitleParser.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DVBServices;
+using skyscraper5.Mpeg2;
+
+namespace skyscraper8.EPGCollectorPort.SkyscraperSide.OpenTV
+{
+ internal class OpenTvTitleParser : IPsiProcessor
+ {
+ private readonly OpenTvHandler _handler;
+
+ public OpenTvTitleParser(OpenTvHandler handler)
+ {
+ _handler = handler;
+ }
+
+ public void GatherPsi(PsiSection section, int sourcePid)
+ {
+ if (section.TableId >= 0xa0 && section.TableId <= 0xa7)
+ {
+ OpenTVTitleSection titleSection = OpenTVTitleSection.ProcessOpenTVTitleTable(section.GetData(),sourcePid,section.TableId);
+ if (titleSection != null)
+ {
+ _handler.OnTitles(sourcePid, section.TableId, titleSection);
+ }
+ }
+ else
+ {
+ if (section.TableId >= 0xa8 && section.TableId <= 0xab)
+ {
+ //Summaries.
+ return;
+ }
+
+ _handler.OnNonOpenTvTraffic(sourcePid,OpenTvExpectedDataType.Titles, section.TableId);
+ }
+ }
+ }
+}
diff --git a/skyscraper8/Program.cs b/skyscraper8/Program.cs
index d661098..375565a 100644
--- a/skyscraper8/Program.cs
+++ b/skyscraper8/Program.cs
@@ -40,6 +40,7 @@ namespace skyscraper5
private static void IntegrationTest()
{
+
}
static void Main(string[] args)
diff --git a/skyscraper8/Properties/launchSettings.json b/skyscraper8/Properties/launchSettings.json
index 412f243..11f87ae 100644
--- a/skyscraper8/Properties/launchSettings.json
+++ b/skyscraper8/Properties/launchSettings.json
@@ -2,7 +2,7 @@
"profiles": {
"skyscraper8": {
"commandName": "Project",
- "commandLineArgs": "cscan-live tcp://tetsuro:6969",
+ "commandLineArgs": "file-live \"C:\\Temp\\sky-uk-000000.ts\"",
"remoteDebugEnabled": false
},
"Container (Dockerfile)": {
diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs
index a2818cd..9631f33 100644
--- a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs
+++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs
@@ -633,12 +633,7 @@ namespace skyscraper5.Skyscraper.Scraper
interactionChannelDecoder.Handler = this;
DvbContext.RegisterPacketProcessor(mappingStream.ElementaryPid, new PsiDecoder(mappingStream.ElementaryPid, interactionChannelDecoder));
break;
- case StreamType.OpenTvPrivate:
- DvbContext.RegisterPacketProcessor(mappingStream.ElementaryPid, new OpenTvPrivate());
- break;
- case StreamType.BSkyBPrivate:
- DvbContext.RegisterPacketProcessor(mappingStream.ElementaryPid, new BSkyBPrivate());
- break;
+
case StreamType.Id3:
DvbContext.RegisterPacketProcessor(mappingStream.ElementaryPid, new PesDecoder(new Id3PesProcessor(this)));
break;
@@ -934,18 +929,6 @@ namespace skyscraper5.Skyscraper.Scraper
}
}
- if (stream.PrivateDataSpecifier == 0x00000002)
- {
- if (stream.UnknownUserDefines != null)
- {
- UserDefinedDescriptor userDefinedDescriptor = stream.UnknownUserDefines.Find(x => x.DescriptorTag == 0xb0);
- if (userDefinedDescriptor != null)
- {
- //BSkyB EPG Related descriptor
- return StreamType.BSkyBPrivate;
- }
- }
- }
if (stream.MetadataApplicationFormat == 0xffff && stream.MetadataApplicationFormatIdentifier == 0x49443320 && stream.MetadataFormat == 0xff && stream.MetadataFormatIdentifier == 0x49443320)
{