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 /skyscraper8/obj
/GUIs/skyscraper8.UI.ImGui/bin/Debug/net8.0/skyscraper5.ini /GUIs/skyscraper8.UI.ImGui/bin/Debug/net8.0/skyscraper5.ini
/.vs/skyscraper8/CopilotIndices/17.14.698.11175 /.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) public ArdVpsDescriptor(byte[] buffer)
{ {
if (buffer.Length != 13) if (buffer.Length != 13)
{
Valid = false;
return; return;
}
VpsString = Encoding.UTF8.GetString(buffer); VpsString = Encoding.UTF8.GetString(buffer);
Valid = true;
} }
public string VpsString { get; private set; } public string VpsString { get; private set; }

View File

@ -1,6 +1,7 @@
using skyscraper5.Mpeg2; using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.IO; using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants; using skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants;
using skyscraper8.Ses;
using skyscraper8.Tests.ClassDependencies.AsraBarkerTransponderTests; using skyscraper8.Tests.ClassDependencies.AsraBarkerTransponderTests;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -13,7 +14,7 @@ namespace skyscraper8.Tests
{ {
public class AstraBarkerTransponderTests 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() private Stream GetBarkerTransponder()
{ {
FileInfo fi = new FileInfo(BARKER_TRANSPONDER_FILE_PATH); FileInfo fi = new FileInfo(BARKER_TRANSPONDER_FILE_PATH);
@ -39,7 +40,6 @@ namespace skyscraper8.Tests
{ {
descriptorUnpacker.SetUserDefined(i, true); descriptorUnpacker.SetUserDefined(i, true);
} }
descriptorUnpacker.SetUserDefined(0xfe, true); descriptorUnpacker.SetUserDefined(0xfe, true);
TsContext tsContext = new TsContext(); TsContext tsContext = new TsContext();
@ -57,5 +57,46 @@ namespace skyscraper8.Tests
} }
stream.Close(); 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.IO;
using skyscraper5.Skyscraper.Scraper; using skyscraper5.Skyscraper.Scraper;
using skyscraper5.Skyscraper.Scraper.Utils; using skyscraper5.Skyscraper.Scraper.Utils;
using Tsubasa.IO;
namespace skyscraper5.Dvb.DataBroadcasting namespace skyscraper5.Dvb.DataBroadcasting
{ {
@ -210,7 +211,10 @@ namespace skyscraper5.Dvb.DataBroadcasting
vfs.DirectoriesCreated = 0; vfs.DirectoriesCreated = 0;
ObjectCarouselUtilities.ExtractBiopModule(module, assembledStream, vfs); ObjectCarouselUtilities.ExtractBiopModule(module, assembledStream, vfs);
if (vfs.DirectoriesCreated != 0) if (vfs.DirectoriesCreated != 0)
{
eventHandler.PreventDsmCcModuleRepetition(programMappingStream.ElementaryPid, module.ModuleId, module.ModuleVersion); eventHandler.PreventDsmCcModuleRepetition(programMappingStream.ElementaryPid, module.ModuleId, module.ModuleVersion);
eventHandler.ProcessVirtualFilesystem((IFilesystem)vfs, programMappingStream);
}
return; return;
} }
eventHandler.NotifyDownloadComplete(programMappingStream.ElementaryPid, module.ModuleId, module.ModuleVersion, assembledStream, isObjectCarousel); eventHandler.NotifyDownloadComplete(programMappingStream.ElementaryPid, module.ModuleId, module.ModuleVersion, assembledStream, isObjectCarousel);

View File

@ -6,7 +6,9 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using skyscraper5.DsmCc.Descriptors; using skyscraper5.DsmCc.Descriptors;
using skyscraper5.DsmCc.Message; using skyscraper5.DsmCc.Message;
using skyscraper5.Dvb.DataBroadcasting.Biop;
using skyscraper5.Mpeg2.Psi.Model; using skyscraper5.Mpeg2.Psi.Model;
using Tsubasa.IO;
namespace skyscraper5.Dvb.DataBroadcasting 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 NotifyDownloadComplete(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion, Stream result, bool isObjectCarousel);
void DsmCcDoItNowEvent(ProgramMapping programMapping, StreamEventDescriptor descriptorListStreamEventDescriptor, int sourcePid); void DsmCcDoItNowEvent(ProgramMapping programMapping, StreamEventDescriptor descriptorListStreamEventDescriptor, int sourcePid);
void PreventDsmCcModuleRepetition(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion); 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.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using skyscraper5.Mpeg2.Psi.Model; using skyscraper5.Mpeg2.Psi.Model;
using Tsubasa.IO;
namespace skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs namespace skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs
{ {
class ObjectCarouselMetadata class ObjectCarouselMetadata : IFilesystem
{ {
public ObjectCarouselMetadata(ObjectCarouselEventHandler eventHandler, int sourcePid, ProgramMapping programMapping) public ObjectCarouselMetadata(ObjectCarouselEventHandler eventHandler, int sourcePid, ProgramMapping programMapping)
{ {
@ -28,5 +29,53 @@ namespace skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs
public ProgramMapping ProgramMapping { get; private set; } public ProgramMapping ProgramMapping { get; private set; }
public int LastExtractions { get; set; } public int LastExtractions { get; set; }
public int DirectoriesCreated { 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 namespace skyscraper5.Dvb.Descriptors
{ {
[SkyscraperPlugin] [SkyscraperPlugin]
[TsDescriptor(0x48,"SDT")] [TsDescriptor(0x48,"SDT","Astra SGT")]
[BannedTable("TSDT","PMT")] [BannedTable("TSDT","PMT")]
public class ServiceDescriptor : TsDescriptor public class ServiceDescriptor : TsDescriptor
{ {
@ -68,6 +68,8 @@ namespace skyscraper5.Dvb.Descriptors
H264StereoscopicHdNvodRefence = 0x1e, H264StereoscopicHdNvodRefence = 0x1e,
TV_HEVC = 0x1f, TV_HEVC = 0x1f,
_4KTV_HEVC = 0x20, _4KTV_HEVC = 0x20,
VVC = 0x21,
AVS3 = 0x22
} }
public override byte[] Serialize() public override byte[] Serialize()

View File

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

View File

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

View File

@ -9,7 +9,7 @@ using skyscraper5.Skyscraper.Plugins;
namespace skyscraper5.Dvb.Descriptors namespace skyscraper5.Dvb.Descriptors
{ {
[SkyscraperPlugin] [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. [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 public class PrivateDataSpecifierDescriptor : TsDescriptor
{ {

View File

@ -49,7 +49,7 @@ namespace skyscraper5.Dvb
private IReadOnlyDictionary<UserDefinedDescriptorAttribute, ConstructorInfo> constructors; 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) if (constructors == null)
constructors = PluginManager.GetInstance().GetUserDefinedDescriptors(); constructors = PluginManager.GetInstance().GetUserDefinedDescriptors();
@ -69,6 +69,10 @@ namespace skyscraper5.Dvb
return (TsDescriptor)constructorInfo.Invoke(new object[] { userDefinedDescriptor.Data }); return (TsDescriptor)constructorInfo.Invoke(new object[] { userDefinedDescriptor.Data });
} }
WarnMissingDescriptor(userDefinedDescriptor.DescriptorTag, privateDataSpecifier); 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; 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": { "profiles": {
"skyscraper8": { "skyscraper8": {
"commandName": "Project", "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 "remoteDebugEnabled": false
}, },
"Container (Dockerfile)": { "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.Skyscraper.Scraper.StreamAutodetection;
using skyscraper5.src.Skyscraper.Scraper.Dns; using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.T2MI; using skyscraper5.T2MI;
using skyscraper8.yo3explorer;
namespace skyscraper5.Skyscraper.Plugins namespace skyscraper5.Skyscraper.Plugins
{ {
@ -150,6 +151,7 @@ namespace skyscraper5.Skyscraper.Plugins
private Type mpePluginType = typeof(ISkyscraperMpePlugin); private Type mpePluginType = typeof(ISkyscraperMpePlugin);
private Type gpsReceiverFactoryType = typeof(IGpsReceiverFactory); private Type gpsReceiverFactoryType = typeof(IGpsReceiverFactory);
private Type streamTypeAutodetectionContestantType = typeof(Contestant); private Type streamTypeAutodetectionContestantType = typeof(Contestant);
private Type filesystemProcessorType = typeof(FilesystemProcessorPlugin);
private PluginPrioritySorter sorter = new PluginPrioritySorter(); private PluginPrioritySorter sorter = new PluginPrioritySorter();
private List<IDnsParser> _dnsParsers; private List<IDnsParser> _dnsParsers;
@ -249,6 +251,11 @@ namespace skyscraper5.Skyscraper.Plugins
HandleDnsParser(type); HandleDnsParser(type);
continue; continue;
} }
else if (type.IsAssignableTo(filesystemProcessorType))
{
HandleFilesystemProcessor(type);
continue;
}
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -476,9 +483,30 @@ namespace skyscraper5.Skyscraper.Plugins
} }
#endregion #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 Ini Ini { get; private set; }
public IReadOnlyList<FilesystemProcessorPlugin> GetFilesystemProcessors()
{
if (filesystemProcessorPlugins == null)
return new List<FilesystemProcessorPlugin>();
return filesystemProcessorPlugins.AsReadOnly();
}
public IReadOnlyList<IDnsParser> GetDnsParsers() public IReadOnlyList<IDnsParser> GetDnsParsers()
{ {
if (_dnsParsers == null) if (_dnsParsers == null)

View File

@ -64,6 +64,9 @@ using skyscraper5.T2MI.Packets.AdressingFunctions;
using skyscraper5.Teletext; using skyscraper5.Teletext;
using skyscraper5.Teletext.Vps; using skyscraper5.Teletext.Vps;
using skyscraper5.Teletext.Wss; using skyscraper5.Teletext.Wss;
using skyscraper8.Ses;
using skyscraper8.yo3explorer;
using Tsubasa.IO;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
using RntParser = skyscraper5.Dvb.TvAnytime.RntParser; using RntParser = skyscraper5.Dvb.TvAnytime.RntParser;
@ -75,7 +78,7 @@ namespace skyscraper5.Skyscraper.Scraper
UpdateNotificationEventHandler, DataCarouselEventHandler, RdsEventHandler, IScte35EventHandler, UpdateNotificationEventHandler, DataCarouselEventHandler, RdsEventHandler, IScte35EventHandler,
IAutodetectionEventHandler, IRstEventHandler, IRntEventHandler, IMultiprotocolEncapsulationEventHandler, ObjectCarouselEventHandler, T2MIEventHandler, IAutodetectionEventHandler, IRstEventHandler, IRntEventHandler, IMultiprotocolEncapsulationEventHandler, ObjectCarouselEventHandler, T2MIEventHandler,
IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, IGsEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler, IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, IGsEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler,
InteractionChannelHandler InteractionChannelHandler, SgtEventHandler
{ {
public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true; public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true;
public const bool ALLOW_FFMPEG_FRAMEGRABBER = 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)); 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, TimCorrection,
TimContentionControl, TimContentionControl,
TimCorrectionControl, 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.Dns;
using skyscraper5.src.Skyscraper.Scraper.Storage.InMemory; using skyscraper5.src.Skyscraper.Scraper.Storage.InMemory;
using skyscraper5.Teletext; using skyscraper5.Teletext;
using skyscraper8.Ses;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
@ -1406,5 +1407,25 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
{ {
throw new NotImplementedException(); 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.FrequencyListGenerator;
using skyscraper5.src.Skyscraper.Scraper.Dns; using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.Teletext; using skyscraper5.Teletext;
using skyscraper8.Ses;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage namespace skyscraper5.Skyscraper.Scraper.Storage
@ -175,5 +176,9 @@ namespace skyscraper5.Skyscraper.Scraper.Storage
bool NetworkLayerInfoTim(PhysicalAddress mac, _0xa0_NetworkLayerInfoDescriptor nlid, DateTime timestamp); bool NetworkLayerInfoTim(PhysicalAddress mac, _0xa0_NetworkLayerInfoDescriptor nlid, DateTime timestamp);
IEnumerable<DbBlindscanJob> GetDbBlindscanJobs(); 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.Dns;
using skyscraper5.src.Skyscraper.Scraper.Storage.InMemory; using skyscraper5.src.Skyscraper.Scraper.Storage.InMemory;
using skyscraper5.Teletext; using skyscraper5.Teletext;
using skyscraper8.Ses;
using skyscraper8.Skyscraper.Scraper.Storage.InMemory.Model;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
@ -1012,37 +1014,54 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
throw new NotImplementedException(); throw new NotImplementedException();
} }
private HashSet<DbBlindscanJobContainer> jobs;
public void InsertBlindscanJob(DbBlindscanJob jobInDb) 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) public void UpdateJobState(DbBlindscanJob jobInDb)
{ {
throw new NotImplementedException();
} }
public void InsertSearchResult(DbBlindscanJob jobInDb, bool satellite, SearchResult searchResult, int polarityIndex, public void InsertSearchResult(DbBlindscanJob jobInDb, bool satellite, SearchResult searchResult, int polarityIndex,
SearchResult2 searchResult2) 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, public void UpdateTransponderState(DbBlindscanJob jobInDb, bool satellite, SearchResult searchResult,
BlindscanResultState blindscanResultState, SearchResult2 searchResult2) BlindscanResultState blindscanResultState, SearchResult2 searchResult2)
{ {
throw new NotImplementedException();
} }
public void InsertTransponderService(DbBlindscanJob jobInDb, bool resultSatellite, SearchResult resultSr1, public void InsertTransponderService(DbBlindscanJob jobInDb, bool resultSatellite, SearchResult resultSr1,
SearchResult2 resultSr2, HumanReadableService humanReadableService) 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) public DbBlindscanJob GetPastBlindscanJob(long offset)
@ -1236,5 +1255,39 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
dnsRecords.Add(record); 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.FrequencyListGenerator;
using skyscraper5.src.Skyscraper.Scraper.Dns; using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.Teletext; using skyscraper5.Teletext;
using skyscraper8.Ses;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage.Split namespace skyscraper5.Skyscraper.Scraper.Storage.Split
@ -160,5 +161,9 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Split
bool CorrectionControlTim(PhysicalAddress mac, _0xac_CorrectionControlDescriptor descriptor); bool CorrectionControlTim(PhysicalAddress mac, _0xac_CorrectionControlDescriptor descriptor);
bool NetworkLayerInfoTim(PhysicalAddress mac, _0xa0_NetworkLayerInfoDescriptor nlid, DateTime timestamp); bool NetworkLayerInfoTim(PhysicalAddress mac, _0xa0_NetworkLayerInfoDescriptor nlid, DateTime timestamp);
IEnumerable<DbBlindscanJob> GetDbBlindscanJobs(); 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.FrequencyListGenerator;
using skyscraper5.src.Skyscraper.Scraper.Dns; using skyscraper5.src.Skyscraper.Scraper.Dns;
using skyscraper5.Teletext; using skyscraper5.Teletext;
using skyscraper8.Ses;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper5.Skyscraper.Scraper.Storage.Split namespace skyscraper5.Skyscraper.Scraper.Storage.Split
@ -862,5 +863,29 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Split
{ {
dataStorage.RememberDnsRecord(record); 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;
using skyscraper5.Mpeg2.Psi.Model; using skyscraper5.Mpeg2.Psi.Model;
using skyscraper5.Skyscraper.Plugins; using skyscraper5.Skyscraper.Plugins;
using Tsubasa.IO;
namespace skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants 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) 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) public void DsmCcDoItNowEvent(ProgramMapping programMapping, StreamEventDescriptor descriptorListStreamEventDescriptor, int pid)
{ {
Score++;
} }
public void PreventDsmCcModuleRepetition(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion) 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))); 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" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="DvbI\Model\" />
</ItemGroup>
</Project> </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
{
}
}