Additions for Astra's SGT.

This commit is contained in:
feyris-tan 2025-06-03 11:48:18 +02:00
parent bc4562cd52
commit 58e6dc00d2
39 changed files with 1551 additions and 25 deletions

1
.gitignore vendored
View File

@ -108,3 +108,4 @@ imgui.ini
/skyscraper8/obj
/GUIs/skyscraper8.UI.ImGui/bin/Debug/net8.0/skyscraper5.ini
/.vs/skyscraper8/CopilotIndices/17.14.698.11175
/GUIs/skyscraper8.UI.ImGui/bin/Debug/net8.0

View File

@ -18,9 +18,13 @@ namespace skyscraper5.Ard
public ArdVpsDescriptor(byte[] buffer)
{
if (buffer.Length != 13)
{
Valid = false;
return;
}
VpsString = Encoding.UTF8.GetString(buffer);
Valid = true;
}
public string VpsString { get; private set; }

View File

@ -1,6 +1,7 @@
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants;
using skyscraper8.Ses;
using skyscraper8.Tests.ClassDependencies.AsraBarkerTransponderTests;
using System;
using System.Collections.Generic;
@ -13,7 +14,7 @@ namespace skyscraper8.Tests
{
public class AstraBarkerTransponderTests
{
private const string BARKER_TRANSPONDER_FILE_PATH = "Z:\\Freebies\\Datasets\\SkyscraperLibrarian\\DVB-S Mai 2025\\sgt-000000.ts";
private const string BARKER_TRANSPONDER_FILE_PATH = "C:\\Temp\\Astra1_12604_v_SGT-000000.ts";
private Stream GetBarkerTransponder()
{
FileInfo fi = new FileInfo(BARKER_TRANSPONDER_FILE_PATH);
@ -39,7 +40,6 @@ namespace skyscraper8.Tests
{
descriptorUnpacker.SetUserDefined(i, true);
}
descriptorUnpacker.SetUserDefined(0xfe, true);
TsContext tsContext = new TsContext();
@ -57,5 +57,46 @@ namespace skyscraper8.Tests
}
stream.Close();
}
[Fact]
public void TestAstraLcn()
{
Stream stream = GetBarkerTransponder();
if (stream == null)
return;
SgtCandidate contestant = new SgtCandidate(0x0777);
SgtCandidate contestant2 = new SgtCandidate(0x0776);
TsDescriptorUnpacker descriptorUnpacker = TsDescriptorUnpacker.GetInstance();
for (byte i = 0x80; i < 0xfe; i++)
{
descriptorUnpacker.SetUserDefined(i, true);
}
descriptorUnpacker.SetUserDefined(0xfe, true);
TsContext tsContext = new TsContext();
tsContext.FilterChain = new List<skyscraper5.src.Mpeg2.PacketFilter.IPacketFilter>();
tsContext.FilterChain.Add(new DummyFilter());
tsContext.RegisterPacketProcessor(0x0777, contestant.PacketProcessor);
tsContext.RegisterPacketProcessor(0x0776, contestant2.PacketProcessor);
byte[] buffer = new byte[188];
while (stream.GetAvailableBytes() >= 188)
{
stream.Read(buffer, 0, 188);
tsContext.PushPacket(buffer);
bool winnerA = contestant.Score >= 10;
bool winnerB = contestant2.Score >= 10;
if (winnerA)
{
if (winnerB)
{
return;
}
}
}
stream.Close();
}
}
}

View File

@ -16,6 +16,7 @@ using skyscraper5.Mpeg2.Psi.Model;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Scraper;
using skyscraper5.Skyscraper.Scraper.Utils;
using Tsubasa.IO;
namespace skyscraper5.Dvb.DataBroadcasting
{
@ -210,7 +211,10 @@ namespace skyscraper5.Dvb.DataBroadcasting
vfs.DirectoriesCreated = 0;
ObjectCarouselUtilities.ExtractBiopModule(module, assembledStream, vfs);
if (vfs.DirectoriesCreated != 0)
{
eventHandler.PreventDsmCcModuleRepetition(programMappingStream.ElementaryPid, module.ModuleId, module.ModuleVersion);
eventHandler.ProcessVirtualFilesystem((IFilesystem)vfs, programMappingStream);
}
return;
}
eventHandler.NotifyDownloadComplete(programMappingStream.ElementaryPid, module.ModuleId, module.ModuleVersion, assembledStream, isObjectCarousel);

View File

@ -6,7 +6,9 @@ using System.Text;
using System.Threading.Tasks;
using skyscraper5.DsmCc.Descriptors;
using skyscraper5.DsmCc.Message;
using skyscraper5.Dvb.DataBroadcasting.Biop;
using skyscraper5.Mpeg2.Psi.Model;
using Tsubasa.IO;
namespace skyscraper5.Dvb.DataBroadcasting
{
@ -19,5 +21,6 @@ namespace skyscraper5.Dvb.DataBroadcasting
void NotifyDownloadComplete(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion, Stream result, bool isObjectCarousel);
void DsmCcDoItNowEvent(ProgramMapping programMapping, StreamEventDescriptor descriptorListStreamEventDescriptor, int sourcePid);
void PreventDsmCcModuleRepetition(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion);
}
void ProcessVirtualFilesystem(IFilesystem vfs, ProgramMappingStream programMappingStream);
}
}

View File

@ -4,10 +4,11 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Mpeg2.Psi.Model;
using Tsubasa.IO;
namespace skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs
{
class ObjectCarouselMetadata
class ObjectCarouselMetadata : IFilesystem
{
public ObjectCarouselMetadata(ObjectCarouselEventHandler eventHandler, int sourcePid, ProgramMapping programMapping)
{
@ -28,5 +29,53 @@ namespace skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs
public ProgramMapping ProgramMapping { get; private set; }
public int LastExtractions { get; set; }
public int DirectoriesCreated { get; set; }
#region yo3explorer Driver
private string[] _wrappedFileList;
public string[] FileList
{
get
{
if (_wrappedFileList == null)
{
_wrappedFileList = vfsFiles.Select(x => x.ToString()).ToArray();
}
return _wrappedFileList;
}
}
public string FilesystemName
{
get
{
return string.Format("DSM-CC Object Carousel;{0};", SourcePid);
}
}
public bool FileExists(string filename)
{
foreach (VfsFile file in vfsFiles)
{
if (file.ToString().Equals(filename))
return true;
}
return false;
}
public byte[] GetFile(string filename)
{
foreach (VfsFile file in vfsFiles)
{
if (file.ToString().Equals(filename))
return file.FileContent;
}
throw new FileNotFoundException(filename);
}
public void Dispose()
{
}
#endregion
}
}

View File

@ -12,7 +12,7 @@ using skyscraper5.Skyscraper.Text;
namespace skyscraper5.Dvb.Descriptors
{
[SkyscraperPlugin]
[TsDescriptor(0x48,"SDT")]
[TsDescriptor(0x48,"SDT","Astra SGT")]
[BannedTable("TSDT","PMT")]
public class ServiceDescriptor : TsDescriptor
{
@ -68,6 +68,8 @@ namespace skyscraper5.Dvb.Descriptors
H264StereoscopicHdNvodRefence = 0x1e,
TV_HEVC = 0x1f,
_4KTV_HEVC = 0x20,
VVC = 0x21,
AVS3 = 0x22
}
public override byte[] Serialize()

View File

@ -10,9 +10,9 @@ using skyscraper5.Skyscraper.Plugins;
namespace skyscraper5.Dvb.Descriptors
{
[SkyscraperPlugin]
[TsDescriptor(0x49,"BAT","SDT")]
[TsDescriptor(0x49,"BAT","SDT","Astra SGT")]
[BannedTable("PMT","TSDT")]
class CountryAvailabilityDescriptor : TsDescriptor
public class CountryAvailabilityDescriptor : TsDescriptor
{
public CountryAvailabilityDescriptor(byte[] buffer)
{

View File

@ -11,7 +11,7 @@ using skyscraper5.Skyscraper.Plugins;
namespace skyscraper5.Dvb.Descriptors
{
[SkyscraperPlugin]
[TsDescriptor(0x53,"BAT","SDT","EIT")]
[TsDescriptor(0x53,"BAT","SDT","EIT","Astra SGT")]
[BannedTable("TSDT")]
class CaIdentifierDescriptor : TsDescriptor
{

View File

@ -9,7 +9,7 @@ using skyscraper5.Skyscraper.Plugins;
namespace skyscraper5.Dvb.Descriptors
{
[SkyscraperPlugin]
[TsDescriptor(0x5f,"NIT","BAT","SDT","EIT","PMT")]
[TsDescriptor(0x5f,"NIT","BAT","SDT","EIT","PMT", "Astra SGT")]
[BannedTable("CAT")] // <-- Scientific Atlanta is known to put private_data_specifier_descriptors into the CAT, however this is a private extension.
public class PrivateDataSpecifierDescriptor : TsDescriptor
{

View File

@ -49,7 +49,7 @@ namespace skyscraper5.Dvb
private IReadOnlyDictionary<UserDefinedDescriptorAttribute, ConstructorInfo> constructors;
public TsDescriptor UnpackUserDefinedDescriptor(UserDefinedDescriptor userDefinedDescriptor, uint privateDataSpecifier, string lookupTable)
public TsDescriptor UnpackUserDefinedDescriptor(UserDefinedDescriptor userDefinedDescriptor, uint privateDataSpecifier, string lookupTable, bool crashOnMissingDescriptor = false)
{
if (constructors == null)
constructors = PluginManager.GetInstance().GetUserDefinedDescriptors();
@ -69,6 +69,10 @@ namespace skyscraper5.Dvb
return (TsDescriptor)constructorInfo.Invoke(new object[] { userDefinedDescriptor.Data });
}
WarnMissingDescriptor(userDefinedDescriptor.DescriptorTag, privateDataSpecifier);
if (crashOnMissingDescriptor)
{
throw new NotImplementedException(String.Format("Missing Descriptor 0x{0:X2} from private data specifier 0x{1:X8} in {2}", userDefinedDescriptor.DescriptorTag, privateDataSpecifier, lookupTable));
}
return null;
}

View File

@ -0,0 +1,37 @@
using skyscraper5.Skyscraper.Plugins;
using skyscraper8.yo3explorer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Tsubasa.IO;
using moe.yo3explorer.skyscraper8.DVBI.Model;
namespace skyscraper8.DvbI
{
/// <summary>
/// See https://www.tara-systems.de/wp-content/uploads/2024/08/DVB-I_Instant_Channel_List_Setup_IBC2024.pdf
/// There is no official specification for this.
/// This is a best guess reverse engineering of the DVB-I link found on 12,604/H on Astra 19,2°
/// </summary>
[SkyscraperPlugin]
internal class DvbIFilesystemProcessor : FilesystemProcessorPlugin
{
private const string INDEX_FILENAME = "\\DVB-I_slep.xml";
private XmlSerializer serviceListEntryPointSerializer;
public void ProcessFilesystem(IFilesystem vfs, yo3explorerToSkyscraperContextBridge context, yo3explorerState state)
{
if (!vfs.FileExists(INDEX_FILENAME))
return;
byte[] slepBytes = vfs.GetFile(INDEX_FILENAME);
ServiceListEntryPoints serviceListEntryPoints = DvbIUtils.UnpackServiceListEntryPoints(slepBytes);
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,28 @@
using moe.yo3explorer.skyscraper8.DVBI.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace skyscraper8.DvbI
{
internal class DvbIUtils
{
private DvbIUtils() { }
private static XmlSerializer serviceListEntryPointSerializer;
public static ServiceListEntryPoints UnpackServiceListEntryPoints(byte[] buffer)
{
if (serviceListEntryPointSerializer == null)
serviceListEntryPointSerializer = new XmlSerializer(typeof(ServiceListEntryPoints));
MemoryStream slepStream = new MemoryStream(buffer, false);
object slepWrapped = serviceListEntryPointSerializer.Deserialize(slepStream);
ServiceListEntryPoints serviceListEntryPoint = (ServiceListEntryPoints)slepWrapped;
return serviceListEntryPoint;
}
}
}

View File

@ -0,0 +1,446 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
//
// This source code was auto-generated by xsd, Version=4.8.9037.0.
//
namespace moe.yo3explorer.skyscraper8.DVBI.Model {
using System.Xml.Serialization;
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicelistdiscovery:2024")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:dvb:metadata:servicelistdiscovery:2024", IsNullable=false)]
public partial class ServiceListEntryPoints {
private ServiceListEntryPointsServiceListRegistryEntity[] serviceListRegistryEntityField;
private ServiceListEntryPointsProviderOffering[] providerOfferingField;
private string langField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ServiceListRegistryEntity")]
public ServiceListEntryPointsServiceListRegistryEntity[] ServiceListRegistryEntity {
get {
return this.serviceListRegistryEntityField;
}
set {
this.serviceListRegistryEntityField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ProviderOffering")]
public ServiceListEntryPointsProviderOffering[] ProviderOffering {
get {
return this.providerOfferingField;
}
set {
this.providerOfferingField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="http://www.w3.org/XML/1998/namespace")]
public string lang {
get {
return this.langField;
}
set {
this.langField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicelistdiscovery:2024")]
public partial class ServiceListEntryPointsServiceListRegistryEntity {
private string nameField;
/// <remarks/>
public string Name {
get {
return this.nameField;
}
set {
this.nameField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicelistdiscovery:2024")]
public partial class ServiceListEntryPointsProviderOffering {
private ServiceListEntryPointsProviderOfferingProvider[] providerField;
private ServiceListEntryPointsProviderOfferingServiceListOffering[] serviceListOfferingField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Provider")]
public ServiceListEntryPointsProviderOfferingProvider[] Provider {
get {
return this.providerField;
}
set {
this.providerField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ServiceListOffering")]
public ServiceListEntryPointsProviderOfferingServiceListOffering[] ServiceListOffering {
get {
return this.serviceListOfferingField;
}
set {
this.serviceListOfferingField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicelistdiscovery:2024")]
public partial class ServiceListEntryPointsProviderOfferingProvider {
private string nameField;
/// <remarks/>
public string Name {
get {
return this.nameField;
}
set {
this.nameField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicelistdiscovery:2024")]
public partial class ServiceListEntryPointsProviderOfferingServiceListOffering {
private string serviceListNameField;
private string serviceListIdField;
private ServiceListEntryPointsProviderOfferingServiceListOfferingServiceListURI[] serviceListURIField;
private ServiceListEntryPointsProviderOfferingServiceListOfferingDelivery[] deliveryField;
private RelatedMaterial relatedMaterialField;
/// <remarks/>
public string ServiceListName {
get {
return this.serviceListNameField;
}
set {
this.serviceListNameField = value;
}
}
/// <remarks/>
public string ServiceListId {
get {
return this.serviceListIdField;
}
set {
this.serviceListIdField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ServiceListURI")]
public ServiceListEntryPointsProviderOfferingServiceListOfferingServiceListURI[] ServiceListURI {
get {
return this.serviceListURIField;
}
set {
this.serviceListURIField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Delivery")]
public ServiceListEntryPointsProviderOfferingServiceListOfferingDelivery[] Delivery {
get {
return this.deliveryField;
}
set {
this.deliveryField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="urn:dvb:metadata:servicediscovery-types:2023")]
public RelatedMaterial RelatedMaterial {
get {
return this.relatedMaterialField;
}
set {
this.relatedMaterialField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicelistdiscovery:2024")]
public partial class ServiceListEntryPointsProviderOfferingServiceListOfferingServiceListURI {
private string uRIField;
private string contentTypeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="urn:dvb:metadata:servicediscovery-types:2023")]
public string URI {
get {
return this.uRIField;
}
set {
this.uRIField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string contentType {
get {
return this.contentTypeField;
}
set {
this.contentTypeField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicelistdiscovery:2024")]
public partial class ServiceListEntryPointsProviderOfferingServiceListOfferingDelivery {
private string dASHDeliveryField;
private ServiceListEntryPointsProviderOfferingServiceListOfferingDeliveryDVBSDelivery[] dVBSDeliveryField;
/// <remarks/>
public string DASHDelivery {
get {
return this.dASHDeliveryField;
}
set {
this.dASHDeliveryField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DVBSDelivery")]
public ServiceListEntryPointsProviderOfferingServiceListOfferingDeliveryDVBSDelivery[] DVBSDelivery {
get {
return this.dVBSDeliveryField;
}
set {
this.dVBSDeliveryField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicelistdiscovery:2024")]
public partial class ServiceListEntryPointsProviderOfferingServiceListOfferingDeliveryDVBSDelivery {
private string orbitalPositionField;
/// <remarks/>
public string OrbitalPosition {
get {
return this.orbitalPositionField;
}
set {
this.orbitalPositionField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicediscovery-types:2023")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:dvb:metadata:servicediscovery-types:2023", IsNullable=false)]
public partial class RelatedMaterial {
private HowRelated howRelatedField;
private MediaLocatorMediaUri[] mediaLocatorField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="urn:tva:metadata:2024")]
public HowRelated HowRelated {
get {
return this.howRelatedField;
}
set {
this.howRelatedField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayAttribute(Namespace="urn:tva:metadata:2024")]
[System.Xml.Serialization.XmlArrayItemAttribute("MediaUri")]
public MediaLocatorMediaUri[] MediaLocator {
get {
return this.mediaLocatorField;
}
set {
this.mediaLocatorField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:tva:metadata:2024")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:tva:metadata:2024", IsNullable=false)]
public partial class HowRelated {
private string hrefField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string href {
get {
return this.hrefField;
}
set {
this.hrefField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:tva:metadata:2024")]
public partial class MediaLocatorMediaUri {
private string contentTypeField;
private string valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string contentType {
get {
return this.contentTypeField;
}
set {
this.contentTypeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Value {
get {
return this.valueField;
}
set {
this.valueField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:dvb:metadata:servicelistdiscovery:2024")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:dvb:metadata:servicelistdiscovery:2024", IsNullable=false)]
public partial class NewDataSet {
private ServiceListEntryPoints[] itemsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ServiceListEntryPoints")]
public ServiceListEntryPoints[] Items {
get {
return this.itemsField;
}
set {
this.itemsField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.9037.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:tva:metadata:2024")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:tva:metadata:2024", IsNullable=false)]
public partial class MediaLocator {
private MediaLocatorMediaUri[] mediaUriField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("MediaUri", IsNullable=true)]
public MediaLocatorMediaUri[] MediaUri {
get {
return this.mediaUriField;
}
set {
this.mediaUriField = value;
}
}
}
}

View File

@ -2,7 +2,7 @@
"profiles": {
"skyscraper8": {
"commandName": "Project",
"commandLineArgs": "\"Z:\\Freebies\\Datasets\\SkyscraperLibrarian\\DVB-S Mai 2025\\sgt-000000.ts\"",
"commandLineArgs": "\"C:\\Temp\\Astra1_12604_v_SGT-000000.ts\"",
"remoteDebugEnabled": false
},
"Container (Dockerfile)": {

View File

@ -0,0 +1,27 @@
using skyscraper5.Dvb;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.Plugins;
using skyscraper5.Skyscraper.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Ses.Descriptors
{
[SkyscraperPlugin]
[UserDefinedDescriptor(0x01, 0x88, "Astra SGT")]
internal class _0x88_ServiceListNameDescriptor : TsDescriptor
{
public _0x88_ServiceListNameDescriptor(byte[] buffer)
{
LanguageCode = Encoding.ASCII.GetString(buffer, 0, 3);
TextualDescription = En300468AnnexATextDecoder.GetInstance().Decode(buffer, 3, buffer.Length - 3);
Valid = true;
}
public string LanguageCode { get; }
public string TextualDescription { get; }
}
}

View File

@ -0,0 +1,46 @@
using skyscraper5.Dvb;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Plugins;
using skyscraper5.Skyscraper.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Ses.Descriptors
{
[SkyscraperPlugin]
[UserDefinedDescriptor(0x01, 0x93, "Astra SGT")]
internal class _0x93_BouquetListDescriptor : TsDescriptor
{
public _0x93_BouquetListDescriptor(byte[] buffer)
{
MemoryStream ms = new MemoryStream(buffer, false);
while (ms.GetAvailableBytes() >= 1)
{
byte bouquetNameLength = ms.ReadUInt8();
if (bouquetNameLength != 0)
{
byte[] chars = ms.ReadBytes(bouquetNameLength);
string chars2 = En300468AnnexATextDecoder.GetInstance().Decode(chars);
if (!string.IsNullOrEmpty(chars2))
{
if (string.IsNullOrEmpty(Name))
{
Name = chars2;
}
else
{
throw new NotImplementedException("multiple bouquet names");
}
}
}
}
Valid = true;
}
public string Name { get; private set; }
}
}

View File

@ -0,0 +1,31 @@
using skyscraper5.Dvb;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.Plugins;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Ses.Descriptors
{
[SkyscraperPlugin]
[UserDefinedDescriptor(0x01, 0xD1, "Astra SGT")]
internal class _0xD1_VirtualServiceIdDescriptor : TsDescriptor
{
public _0xD1_VirtualServiceIdDescriptor(byte[] buffer)
{
if (buffer.Length < 2)
{
Valid = false;
return;
}
(buffer[1], buffer[0]) = (buffer[0], buffer[1]);
VirtualServiceId = BitConverter.ToUInt16(buffer, 0);
Valid = true;
}
public ushort VirtualServiceId { get; }
}
}

View File

@ -0,0 +1,48 @@
using skyscraper5.Mhp.Si;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.Plugins;
using skyscraper5.Skyscraper.Scraper;
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Ses
{
[SkyscraperPlugin]
public class SgtCandidate : Contestant, SgtEventHandler, IDisposable
{
public SgtCandidate(int pid)
: base("Asta SGT",pid)
{
PacketProcessor = new PsiDecoder(pid, new SgtParser(this));
}
public override void DeclareWinner(SkyscraperContext skyscraperContext, int pid, ProgramContext programContext)
{
skyscraperContext.DvbContext.RegisterPacketProcessor(pid, new PsiDecoder(pid, new SgtParser(skyscraperContext)));
}
public override void Dispose()
{
}
void SgtEventHandler.AnnounceSgtList(SgtList list)
{
if (list.CountryAvailabilities.Count > 0 || list.Names != null || list.PrivateDataSpecifier != 0x01)
Score++;
}
void SgtEventHandler.OnSgtError(SgtError invalidTableId)
{
Score--;
}
void SgtEventHandler.OnSgtService(SgtService child)
{
Score++;
}
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Ses
{
internal enum SgtError
{
InvalidTableId,
NoSectionSyntax
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Ses
{
internal interface SgtEventHandler
{
void AnnounceSgtList(SgtList list);
void OnSgtError(SgtError invalidTableId);
void OnSgtService(SgtService child);
}
}

View File

@ -0,0 +1,46 @@
using skyscraper5.Dvb.Descriptors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Ses
{
public class SgtList
{
public SgtList(ushort serviceListId, uint v)
{
ServiceListId = serviceListId;
PrivateDataSpecifier = v;
CountryAvailabilities = new Dictionary<string, bool>();
}
public ushort ServiceListId { get; }
public uint PrivateDataSpecifier { get; internal set; }
public Dictionary<string,string> Names { get; internal set; }
public Dictionary<string,bool> CountryAvailabilities { get; internal set; }
public string GetName()
{
if (Names == null)
return "???";
if (Names.Count == 0)
return "???";
foreach (KeyValuePair<string,string> name in Names)
{
if (!string.IsNullOrEmpty(name.Value))
{
return name.Value;
}
}
return "???";
{
}
}
}
}

View File

@ -0,0 +1,184 @@
using skyscraper5.Dvb;
using skyscraper5.Dvb.Descriptors;
using skyscraper5.Mpeg2;
using skyscraper5.Mpeg2.Descriptors;
using skyscraper5.Skyscraper.IO;
using skyscraper8.Ses.Descriptors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static skyscraper5.Dvb.Descriptors.ContentIdentifierDescriptor;
namespace skyscraper8.Ses
{
internal class SgtParser : IPsiProcessor
{
public SgtParser(SgtEventHandler eventHandler)
{
this.EventHandler = eventHandler;
}
public SgtEventHandler EventHandler { get; }
public void GatherPsi(PsiSection section, int sourcePid)
{
byte[] buffer = section.GetData();
MemoryStream ms = new MemoryStream(buffer, false);
byte table_id = ms.ReadUInt8();
if (table_id != 0x91)
{
EventHandler.OnSgtError(SgtError.InvalidTableId);
return;
}
byte byteA = ms.ReadUInt8();
bool sectionSyntaxIndicator = (byteA & 0x80) != 0;
if (!sectionSyntaxIndicator)
{
EventHandler.OnSgtError(SgtError.NoSectionSyntax);
return;
}
bool reservedFutureUse = (byteA & 0x40) != 0;
int reserved = (byteA & 0x30) >> 4;
int sectionLength = (byteA & 0x0f);
sectionLength <<= 4;
sectionLength += ms.ReadUInt8();
ushort serviceListId = ms.ReadUInt16BE();
byte byteB = ms.ReadUInt8();
int reservedB = (byteA & 0xc0) >> 6;
int versionNumber = (byteA & 0x3e) >> 1;
bool currentNextIndicator = (byteB & 0x01) != 0;
byte sectionNumber = ms.ReadUInt8();
byte lastSectionNumber = ms.ReadUInt8();
ushort ReservedC = ms.ReadUInt16BE();
ushort uint16 = ms.ReadUInt16BE();
int reservedFutureUseB = (uint16 & 0xf000) >> 12;
int serviceListDescriptorsLength = (uint16 & 0x0fff);
byte[] descriptorBuffer = ms.ReadBytes(serviceListDescriptorsLength);
IEnumerable<TsDescriptor> descriptors = TsDescriptorUnpacker.GetInstance().UnpackDescriptors(descriptorBuffer, "Astra SGT");
SgtList list = new SgtList(serviceListId, 0x01);
foreach (TsDescriptor rawDescriptor in descriptors)
{
switch (rawDescriptor.GetType().Name)
{
case nameof(PrivateDataSpecifierDescriptor):
PrivateDataSpecifierDescriptor pdsd = (PrivateDataSpecifierDescriptor)rawDescriptor;
list.PrivateDataSpecifier = pdsd.PrivateDataSpecifier;
break;
case nameof(UserDefinedDescriptor):
TsDescriptor userDefinedDescriptor = UserDefinedDescriptorUnpacker.GetInstance().UnpackUserDefinedDescriptor((UserDefinedDescriptor)rawDescriptor, list.PrivateDataSpecifier, "Astra SGT", true);
switch (userDefinedDescriptor.GetType().Name)
{
case nameof(_0x88_ServiceListNameDescriptor):
_0x88_ServiceListNameDescriptor slnd = (_0x88_ServiceListNameDescriptor)userDefinedDescriptor;
if (list.Names == null)
list.Names = new Dictionary<string, string>();
list.Names.Add(slnd.LanguageCode, slnd.TextualDescription);
break;
default:
throw new NotImplementedException(rawDescriptor.GetType().Name);
}
continue;
case nameof(CountryAvailabilityDescriptor):
CountryAvailabilityDescriptor cad = (CountryAvailabilityDescriptor)rawDescriptor;
foreach(string countryFlag in cad.CountryCodes)
{
list.CountryAvailabilities.Add(countryFlag, cad.CountryAvailabilityFlag);
}
break;
default:
throw new NotImplementedException(rawDescriptor.GetType().Name);
}
}
EventHandler.AnnounceSgtList(list);
ushort uint16b = ms.ReadUInt16BE();
int reservedFutureUseC = (uint16b & 0xf000) >> 12;
int serviceLoopLength = (uint16b & 0x0fff);
byte[] serviceLoopBuffer = ms.ReadBytes(serviceLoopLength);
ParseServiceLoop(serviceListId, serviceLoopBuffer,list.PrivateDataSpecifier);
uint crc32 = ms.ReadUInt32BE();
}
private void ParseServiceLoop(ushort serviceListId, byte[] serviceLoopBuffer, uint? privateDataSpecifier)
{
MemoryStream ms = new MemoryStream(serviceLoopBuffer, false);
while (ms.GetAvailableBytes() > 6)
{
SgtService child = new SgtService(serviceListId);
child.ServiceId = ms.ReadUInt16BE();
child.TransportStreamId = ms.ReadUInt16BE();
child.OriginalNetworkId = ms.ReadUInt16BE();
ushort ushortA = ms.ReadUInt16BE();
child.Lcn = (ushortA & 0xfc) >> 2;
child.VisibleServiceFlag = (ushortA & 0x02) != 0;
child.NewServiceFlag = (ushortA & 0x01) != 0;
child.GenreCode = ms.ReadUInt16BE();
ushort ushortB = ms.ReadUInt16BE();
int reservedFutureUseB = (ushortB & 0xf000) >> 12;
int serviceListDescriptorsLength = (ushortB & 0x0fff);
byte[] descriptorBuffer = ms.ReadBytes(serviceListDescriptorsLength);
IEnumerable<TsDescriptor> descriptors = TsDescriptorUnpacker.GetInstance().UnpackDescriptors(descriptorBuffer, "Astra SGT");
child.PrivateDataSpecifier = privateDataSpecifier != null ? privateDataSpecifier.Value : 0x01;
foreach (TsDescriptor rawDescriptor in descriptors)
{
switch (rawDescriptor.GetType().Name)
{
case nameof(CaIdentifierDescriptor):
CaIdentifierDescriptor cid = (CaIdentifierDescriptor)rawDescriptor;
if (child.CaSystemIds != null)
throw new NotImplementedException("Multiple CA Identifier descriptors");
child.CaSystemIds = cid.CaSystemIds;
continue;
case nameof(ServiceDescriptor):
ServiceDescriptor sd = (ServiceDescriptor)rawDescriptor;
if (child.ServiceDescriptor != null)
throw new NotImplementedException("Multiple Service descriptors");
child.ServiceDescriptor = sd;
continue;
case nameof(UserDefinedDescriptor):
TsDescriptor userDefinedDescriptor = UserDefinedDescriptorUnpacker.GetInstance().UnpackUserDefinedDescriptor((UserDefinedDescriptor)rawDescriptor, child.PrivateDataSpecifier, "Astra SGT", true);
switch(userDefinedDescriptor.GetType().Name)
{
case nameof(_0xD1_VirtualServiceIdDescriptor):
_0xD1_VirtualServiceIdDescriptor vsid = (_0xD1_VirtualServiceIdDescriptor)userDefinedDescriptor;
if (child.VirtualServiceIds == null)
child.VirtualServiceIds = new List<uint>();
child.VirtualServiceIds.Add(vsid.VirtualServiceId);
continue;
case nameof(_0x93_BouquetListDescriptor):
_0x93_BouquetListDescriptor bld = (_0x93_BouquetListDescriptor)userDefinedDescriptor;
if (!string.IsNullOrEmpty(child.BouquetList))
throw new NotImplementedException("Multiple bouquets in child.");
child.BouquetList = bld.Name;
continue;
default:
throw new NotImplementedException(rawDescriptor.GetType().Name);
}
continue;
case nameof(PrivateDataSpecifierDescriptor):
PrivateDataSpecifierDescriptor pds = (PrivateDataSpecifierDescriptor)rawDescriptor;
if (pds.PrivateDataSpecifier != child.PrivateDataSpecifier)
throw new NotImplementedException("Multiple private data specifiers?");
continue;
default:
throw new NotImplementedException(rawDescriptor.GetType().Name);
}
}
EventHandler.OnSgtService(child);
}
}
}
}

View File

@ -0,0 +1,57 @@
using skyscraper5.Dvb.Descriptors;
using skyscraper8.Ses.Descriptors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Ses
{
public class SgtService
{
public SgtService(ushort serviceListId)
{
ServiceListId = serviceListId;
}
public ushort ServiceListId { get; }
public ushort ServiceId { get; internal set; }
public ushort TransportStreamId { get; internal set; }
public ushort OriginalNetworkId { get; internal set; }
public int Lcn { get; internal set; }
public bool VisibleServiceFlag { get; internal set; }
public bool NewServiceFlag { get; internal set; }
public ushort GenreCode { get; internal set; }
//In SGT this is mandatory and defaults to 0x01
public uint PrivateDataSpecifier { get; internal set; }
public ushort[] CaSystemIds { get; internal set; }
public ServiceDescriptor ServiceDescriptor { get; internal set; }
public List<uint> VirtualServiceIds { get; internal set; }
public string? BouquetList { get; internal set; }
public override bool Equals(object? obj)
{
return obj is SgtService service &&
ServiceListId == service.ServiceListId &&
ServiceId == service.ServiceId &&
TransportStreamId == service.TransportStreamId &&
OriginalNetworkId == service.OriginalNetworkId;
}
public override int GetHashCode()
{
return HashCode.Combine(ServiceListId, ServiceId, TransportStreamId, OriginalNetworkId);
}
internal string GetName()
{
if (ServiceDescriptor == null)
return "???";
return ServiceDescriptor.ServiceName;
}
}
}

View File

@ -15,6 +15,7 @@ using skyscraper5.Skyscraper.Scraper.Storage;
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.T2MI;
using skyscraper8.yo3explorer;
namespace skyscraper5.Skyscraper.Plugins
{
@ -150,6 +151,7 @@ namespace skyscraper5.Skyscraper.Plugins
private Type mpePluginType = typeof(ISkyscraperMpePlugin);
private Type gpsReceiverFactoryType = typeof(IGpsReceiverFactory);
private Type streamTypeAutodetectionContestantType = typeof(Contestant);
private Type filesystemProcessorType = typeof(FilesystemProcessorPlugin);
private PluginPrioritySorter sorter = new PluginPrioritySorter();
private List<IDnsParser> _dnsParsers;
@ -249,6 +251,11 @@ namespace skyscraper5.Skyscraper.Plugins
HandleDnsParser(type);
continue;
}
else if (type.IsAssignableTo(filesystemProcessorType))
{
HandleFilesystemProcessor(type);
continue;
}
throw new NotImplementedException();
}
@ -476,9 +483,30 @@ namespace skyscraper5.Skyscraper.Plugins
}
#endregion
#region yo3explorers
private List<FilesystemProcessorPlugin> filesystemProcessorPlugins;
private void HandleFilesystemProcessor(Type t)
{
if (filesystemProcessorPlugins == null)
filesystemProcessorPlugins = new List<FilesystemProcessorPlugin>();
FilesystemProcessorPlugin child = (FilesystemProcessorPlugin)Activator.CreateInstance(t);
filesystemProcessorPlugins.Add(child);
}
#endregion
public Ini Ini { get; private set; }
public IReadOnlyList<FilesystemProcessorPlugin> GetFilesystemProcessors()
{
if (filesystemProcessorPlugins == null)
return new List<FilesystemProcessorPlugin>();
return filesystemProcessorPlugins.AsReadOnly();
}
public IReadOnlyList<IDnsParser> GetDnsParsers()
{
if (_dnsParsers == null)

View File

@ -64,6 +64,9 @@ using skyscraper5.T2MI.Packets.AdressingFunctions;
using skyscraper5.Teletext;
using skyscraper5.Teletext.Vps;
using skyscraper5.Teletext.Wss;
using skyscraper8.Ses;
using skyscraper8.yo3explorer;
using Tsubasa.IO;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
using RntParser = skyscraper5.Dvb.TvAnytime.RntParser;
@ -75,7 +78,7 @@ namespace skyscraper5.Skyscraper.Scraper
UpdateNotificationEventHandler, DataCarouselEventHandler, RdsEventHandler, IScte35EventHandler,
IAutodetectionEventHandler, IRstEventHandler, IRntEventHandler, IMultiprotocolEncapsulationEventHandler, ObjectCarouselEventHandler, T2MIEventHandler,
IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, IGsEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler,
InteractionChannelHandler
InteractionChannelHandler, SgtEventHandler
{
public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true;
public const bool ALLOW_FFMPEG_FRAMEGRABBER = true;
@ -2389,5 +2392,43 @@ namespace skyscraper5.Skyscraper.Scraper
{
LogEvent(SkyscraperContextEvent.StreamTypeAutodetection, String.Format("PID 0x{0:X4} probably isn't a {1}", pid, contestant.Tag));
}
}
void SgtEventHandler.AnnounceSgtList(SgtList list)
{
if (!ScraperStorage.TestForSgtList(list))
{
LogEvent(SkyscraperContextEvent.SgtList, String.Format("List #{0} ({1})", list.ServiceListId, list.GetName()));
ScraperStorage.InsertSgtList(list);
}
}
void SgtEventHandler.OnSgtError(SgtError invalidTableId)
{
throw new NotImplementedException();
}
void SgtEventHandler.OnSgtService(SgtService child)
{
if (!ScraperStorage.TestForSgtService(child))
{
LogEvent(SkyscraperContextEvent.SgtService, String.Format("LCN #{0} in List #{1} ({2})", child.Lcn, child.ServiceListId, child.GetName()));
ScraperStorage.InsertSgtService(child);
}
}
public void ProcessVirtualFilesystem(IFilesystem vfs, ProgramMappingStream programMappingStream)
{
yo3explorerState state = yo3explorerState.GetInstance();
yo3explorerToSkyscraperContextBridge context = new yo3explorerToSkyscraperContextBridge();
PluginManager pluginManager = PluginManager.GetInstance();
IReadOnlyList<skyscraper8.yo3explorer.FilesystemProcessorPlugin> processors = pluginManager.GetFilesystemProcessors();
foreach(FilesystemProcessorPlugin processor in processors)
{
processor.ProcessFilesystem(vfs, context, state);
}
}
}
}

View File

@ -70,6 +70,8 @@
TimCorrection,
TimContentionControl,
TimCorrectionControl,
TimNetworkLayerInfo
TimNetworkLayerInfo,
SgtList,
SgtService
}
}

View File

@ -33,6 +33,7 @@ using skyscraper5.src.Skyscraper.FrequencyListGenerator;
using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.src.Skyscraper.Scraper.Storage.InMemory;
using skyscraper5.Teletext;
using skyscraper8.Ses;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
@ -1406,5 +1407,25 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
{
throw new NotImplementedException();
}
public bool TestForSgtList(SgtList list)
{
throw new NotImplementedException();
}
public void InsertSgtList(SgtList list)
{
throw new NotImplementedException();
}
public bool TestForSgtService(SgtService child)
{
throw new NotImplementedException();
}
public void InsertSgtService(SgtService child)
{
throw new NotImplementedException();
}
}
}

View File

@ -28,6 +28,7 @@ using skyscraper5.src.InteractionChannel.Model.Descriptors;
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.Teletext;
using skyscraper8.Ses;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage
@ -175,5 +176,9 @@ namespace skyscraper5.Skyscraper.Scraper.Storage
bool NetworkLayerInfoTim(PhysicalAddress mac, _0xa0_NetworkLayerInfoDescriptor nlid, DateTime timestamp);
IEnumerable<DbBlindscanJob> GetDbBlindscanJobs();
bool TestForSgtList(SgtList list);
void InsertSgtList(SgtList list);
bool TestForSgtService(SgtService child);
void InsertSgtService(SgtService child);
}
}

View File

@ -31,6 +31,8 @@ using skyscraper5.src.Skyscraper.FrequencyListGenerator;
using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.src.Skyscraper.Scraper.Storage.InMemory;
using skyscraper5.Teletext;
using skyscraper8.Ses;
using skyscraper8.Skyscraper.Scraper.Storage.InMemory.Model;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
@ -1012,37 +1014,54 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
throw new NotImplementedException();
}
private HashSet<DbBlindscanJobContainer> jobs;
public void InsertBlindscanJob(DbBlindscanJob jobInDb)
{
throw new NotImplementedException();
if (jobs == null)
jobs = new HashSet<DbBlindscanJobContainer>();
DbBlindscanJobContainer jobContainer = new DbBlindscanJobContainer(jobInDb);
jobs.Add(jobContainer);
}
public void UpdateJobState(DbBlindscanJob jobInDb)
{
throw new NotImplementedException();
}
public void InsertSearchResult(DbBlindscanJob jobInDb, bool satellite, SearchResult searchResult, int polarityIndex,
SearchResult2 searchResult2)
{
throw new NotImplementedException();
DbBlindscanJobContainer dbBlindscanJobContainer = jobs.First(x => x.JobGuid.Equals(jobInDb.JobGuid));
if (dbBlindscanJobContainer == null)
throw new Exception("Failed to find the job.");
dbBlindscanJobContainer.AddSearchResult(satellite, searchResult, polarityIndex, searchResult2);
}
public void UpdateTransponderState(DbBlindscanJob jobInDb, bool satellite, SearchResult searchResult,
BlindscanResultState blindscanResultState, SearchResult2 searchResult2)
{
throw new NotImplementedException();
}
public void InsertTransponderService(DbBlindscanJob jobInDb, bool resultSatellite, SearchResult resultSr1,
SearchResult2 resultSr2, HumanReadableService humanReadableService)
{
throw new NotImplementedException();
}
DbBlindscanJobContainer jobContainer = jobs.First(x => x.JobGuid.Equals(jobInDb.JobGuid));
if (jobContainer == null)
throw new Exception("Failed to find the job.");
public bool TestForIncompleteJob()
DbBlindscanJobContainer.SearchResultContainer searchResultContainer = jobContainer.GetSearchResult(resultSatellite, resultSr1, resultSr2);
if (searchResultContainer == null)
throw new Exception("Failed to find the search result.");
searchResultContainer.AddService(humanReadableService);
}
public bool TestForIncompleteJob()
{
throw new NotImplementedException();
return false;
}
public DbBlindscanJob GetPastBlindscanJob(long offset)
@ -1236,5 +1255,39 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
dnsRecords.Add(record);
}
private SgtList[] sgtLists;
public bool TestForSgtList(SgtList list)
{
if (sgtLists == null)
return false;
return sgtLists[list.ServiceListId] != null;
}
public void InsertSgtList(SgtList list)
{
if (sgtLists == null)
sgtLists = new SgtList[ushort.MaxValue];
sgtLists[list.ServiceListId] = list;
}
private HashSet<SgtService> sgtServices;
public bool TestForSgtService(SgtService child)
{
if (sgtServices == null)
return false;
return sgtServices.Contains(child);
}
public void InsertSgtService(SgtService child)
{
if (sgtServices == null)
sgtServices = new HashSet<SgtService>();
sgtServices.Add(child);
}
}
}

View File

@ -0,0 +1,122 @@
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Scraper.Storage.InMemory.Model
{
internal class DbBlindscanJobContainer
{
private DbBlindscanJob jobInDb;
private List<SearchResultContainer> searchResults;
public DbBlindscanJobContainer(DbBlindscanJob jobInDb)
{
this.jobInDb = jobInDb;
}
public override bool Equals(object? obj)
{
return obj is DbBlindscanJobContainer container &&
EqualityComparer<DbBlindscanJob>.Default.Equals(jobInDb, container.jobInDb);
}
public override int GetHashCode()
{
return HashCode.Combine(jobInDb);
}
internal void AddSearchResult(bool satellite, SearchResult searchResult, int polarityIndex, SearchResult2 searchResult2)
{
if (searchResults == null)
searchResults = new List<SearchResultContainer>();
searchResults.Add(new SearchResultContainer(satellite, searchResult, polarityIndex, searchResult2));
}
internal SearchResultContainer GetSearchResult(bool satellit, SearchResult searchResult, int polarityIndex, SearchResult2 searchResult2)
{
SearchResultContainer searchResultContainer = searchResults.First(x => x.Matches(satellit, searchResult, polarityIndex, searchResult2));
return searchResultContainer;
}
internal SearchResultContainer GetSearchResult(bool satellit, SearchResult searchResult, SearchResult2 searchResult2)
{
SearchResultContainer searchResultContainer = searchResults.First(x => x.Matches(satellit, searchResult, searchResult2));
return searchResultContainer;
}
public Guid JobGuid
{
get
{
return jobInDb.JobGuid;
}
}
internal class SearchResultContainer
{
private bool satellite;
private SearchResult searchResult;
private int polarityIndex;
private SearchResult2 searchResult2;
private List<HumanReadableService> services;
public SearchResultContainer(bool satellite, SearchResult searchResult, int polarityIndex, SearchResult2 searchResult2)
{
this.satellite = satellite;
this.searchResult = searchResult;
this.polarityIndex = polarityIndex;
this.searchResult2 = searchResult2;
}
public override bool Equals(object? obj)
{
return obj is SearchResultContainer container &&
satellite == container.satellite &&
EqualityComparer<SearchResult>.Default.Equals(searchResult, container.searchResult) &&
polarityIndex == container.polarityIndex &&
EqualityComparer<SearchResult2>.Default.Equals(searchResult2, container.searchResult2);
}
public override int GetHashCode()
{
return HashCode.Combine(satellite, searchResult, polarityIndex, searchResult2);
}
public bool Matches(bool satellite, SearchResult searchResult, int polarityIndex, SearchResult2 searchResult2)
{
if (this.satellite != satellite)
return false;
if (!EqualityComparer<SearchResult>.Default.Equals(searchResult, this.searchResult))
return false;
if (this.polarityIndex != polarityIndex)
return false;
if (!EqualityComparer<SearchResult2>.Default.Equals(searchResult2, this.searchResult2))
return false;
return true;
}
public bool Matches(bool satellite, SearchResult searchResult,SearchResult2 searchResult2)
{
if (this.satellite != satellite)
return false;
if (!EqualityComparer<SearchResult>.Default.Equals(searchResult, this.searchResult))
return false;
if (!EqualityComparer<SearchResult2>.Default.Equals(searchResult2, this.searchResult2))
return false;
return true;
}
internal void AddService(HumanReadableService humanReadableService)
{
if (services == null)
services = new List<HumanReadableService>();
services.Add(humanReadableService);
}
}
}
}

View File

@ -31,6 +31,7 @@ using skyscraper5.src.InteractionChannel.Model.Descriptors;
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.Teletext;
using skyscraper8.Ses;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage.Split
@ -160,5 +161,9 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Split
bool CorrectionControlTim(PhysicalAddress mac, _0xac_CorrectionControlDescriptor descriptor);
bool NetworkLayerInfoTim(PhysicalAddress mac, _0xa0_NetworkLayerInfoDescriptor nlid, DateTime timestamp);
IEnumerable<DbBlindscanJob> GetDbBlindscanJobs();
bool TestForSgtList(SgtList list);
void InsertSgtList(SgtList list);
bool TestForSgtService(SgtService child);
void InsertSgtService(SgtService child);
}
}

View File

@ -28,6 +28,7 @@ using skyscraper5.src.InteractionChannel.Model.Descriptors;
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.Teletext;
using skyscraper8.Ses;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage.Split
@ -862,5 +863,29 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Split
{
dataStorage.RememberDnsRecord(record);
}
[DebuggerStepThrough]
public bool TestForSgtList(SgtList list)
{
return dataStorage.TestForSgtList(list);
}
[DebuggerStepThrough]
public void InsertSgtList(SgtList list)
{
dataStorage.InsertSgtList(list);
}
[DebuggerStepThrough]
public bool TestForSgtService(SgtService child)
{
return dataStorage.TestForSgtService(child);
}
[DebuggerStepThrough]
public void InsertSgtService(SgtService child)
{
dataStorage.InsertSgtService(child);
}
}
}

View File

@ -14,6 +14,7 @@ using skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs;
using skyscraper5.Mpeg2;
using skyscraper5.Mpeg2.Psi.Model;
using skyscraper5.Skyscraper.Plugins;
using Tsubasa.IO;
namespace skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants
{
@ -60,12 +61,11 @@ namespace skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants
public void NotifyDownloadComplete(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion, Stream result, bool isObjectCarousel)
{
Score += 2;
Score++;
}
public void DsmCcDoItNowEvent(ProgramMapping programMapping, StreamEventDescriptor descriptorListStreamEventDescriptor, int pid)
{
Score++;
}
public void PreventDsmCcModuleRepetition(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion)
@ -106,5 +106,9 @@ namespace skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants
}
skyscraperContext.DvbContext.RegisterPacketProcessor(pid, new PsiDecoder(pid, new DataCarouselDecoder(programContext.Stream, programContext.Program, DataCarouselIntention.NoIntention, skyscraperContext)));
}
}
public void ProcessVirtualFilesystem(IFilesystem vfs, ProgramMappingStream pmtPid)
{
}
}
}

View File

@ -13,4 +13,8 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<Folder Include="DvbI\Model\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,67 @@
using skyscraper5.Dvb.DataBroadcasting.Biop;
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Tsubasa.IO
{
/// <summary>
/// Represents a simple interface to a virtual filesystem.
///
/// This interface is here as a memento to remember where Skyscraper originated from.
/// It was copied 1:1 from the source code of yo3explorer, a project I abandoned a long time ago, but is still dear to me.
///yo3explorer was designed to extract game assets of Yu-Gi-Oh! ONLINE 3, a long defunct online game with a fully automatic simulation of the Yu-Gi-Oh! Trading Card Game.
///The GUI of yo3explorer used this interface to talk to Archive Format parsers.
///Eventually, yo3explorer grew to not only support Yu-Gi-Oh! ONLINE 3, but other games as well.
///Some notable ones:
/// - Artificial Girl 3
/// - Ever17: The out of infinity
/// - Jokei Kazoku III ~Himitsu~
/// - Hyperdimension Neptunia Re; Birth
/// - Steins;Gate
/// - Yu-Gi-Oh! Power of Chaos
/// - Spelunky
/// - Super Heroine Chronicle
/// - Spocon! ~Sports Wear-Complex ~
///This interface is, at the time of adding this comment, over 10 years old. It was written on 24.12.2013
/// </summary>
public interface IFilesystem : IDisposable
{
/// <summary>
/// Checks whether a file by a specified name is present in a virtual filesystem.
/// </summary>
/// <param name="filename">The filename to check for.</param>
/// <returns>true if the file is present in the virtual filesystem, false if not. If filename appears in FileList this should return true.</returns>
bool FileExists(string filename);
/// <summary>
/// Returns the contents of a file in a virtual filesystem.
/// </summary>
/// <param name="filename">The filename of the file you want the contents of.</param>
/// <returns>The file contents as a byte array.</returns>
byte[] GetFile(string filename);
/// <summary>
/// All the names of the files contained in this virtual filesystem.
/// </summary>
string[] FileList
{
get;
}
/// <summary>
/// A human readable name for this virutal filesystem.
/// </summary>
string FilesystemName
{
get;
}
}
}

View File

@ -0,0 +1,24 @@
using skyscraper5.Skyscraper.Scraper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tsubasa.IO;
namespace skyscraper8.yo3explorer
{
/// <summary>
/// This interface is intended to describe a Skyscraper plugin that processes a yo3explorer compatible filesystem.
/// </summary>
internal interface FilesystemProcessorPlugin
{
/// <summary>
/// Lets this Skyscraper plugin process a yo3explorer compatible filesystem.
/// </summary>
/// <param name="vfs">A yo3explorer compatible filesystem.</param>
/// <param name="context">Data that might be useful to the plugin.</param>
/// <param name="state">Data that is supposed to be kept spanning multiple yo3explorer sessions. One could argue that this object simulates the GUI of yo3explorer.</param>
void ProcessFilesystem(IFilesystem vfs, yo3explorerToSkyscraperContextBridge context, yo3explorerState state);
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.yo3explorer
{
internal class yo3explorerState
{
private static yo3explorerState instance;
private yo3explorerState()
{
}
public static yo3explorerState GetInstance()
{
if (instance == null)
{
instance = new yo3explorerState();
}
return instance;
}
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.yo3explorer
{
internal class yo3explorerToSkyscraperContextBridge
{
}
}