skyscraper8/skyscraper8/DvbI/DvbIFilesystemProcessor.cs

120 lines
4.1 KiB
C#

using log4net;
using moe.yo3explorer.skyscraper8.DVBI.Model;
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;
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 static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private XmlSerializer serviceListEntryPointSerializer;
public void ProcessFilesystem(IFilesystem vfs, yo3explorerToSkyscraperContextBridge context, yo3explorerState state)
{
if (!vfs.FileExists(INDEX_FILENAME))
return;
if (context.Source == ServiceListEntryPointSource.TransportStream)
{
if (!context.TransportStreamId.HasValue)
return;
if (!context.OriginalNetworkId.HasValue)
return;
}
else
{
throw new NotImplementedException(context.Source.ToString());
}
if (context.CurrentTime == DateTime.MinValue)
return;
DvbIDataStorage dataStorage = (DvbIDataStorage)context.DataStorage;
long sourceHash = context.GetSourceHash();
if (dataStorage.TestForDvbiServiceListEntryPoints(sourceHash))
{
DateTime lastChecked = dataStorage.GetLastDvbiServiceListEntryPointUpdateDate(sourceHash);
TimeSpan sinceLastChecked = context.CurrentTime - lastChecked;
if (sinceLastChecked.TotalDays < 1.0)
return;
}
else
{
logger.InfoFormat("New DVB-I Service List Entry Point: {0}", context.ToHumanReadableSourceString());
dataStorage.InsertDvbiServiceListEntryPoint(sourceHash);
}
byte[] slepBytes = vfs.GetFile(INDEX_FILENAME);
ServiceListEntryPoints serviceListEntryPoints = DvbIUtils.UnpackServiceListEntryPoints(slepBytes);
IEnumerable<DvbiServiceList> enumerable = DvbIUtils.FlattenServiceListEntryPoints(serviceListEntryPoints);
foreach(DvbiServiceList serviceList in enumerable)
{
DateTime serviceListLastChecked;
if (dataStorage.TestForDvbiServiceList(serviceList.Id))
{
serviceListLastChecked = dataStorage.GetDvbiServiceListLastUpdateDate(serviceList.Id);
}
else
{
logger.InfoFormat("New DVB-I Service List: {0}", serviceList.Name);
dataStorage.InsertDvbiServiceList(serviceList);
dataStorage.AddDvbiServiceListToServiceListEntryPoint(serviceList, sourceHash);
serviceListLastChecked = new DateTime(1970, 1, 1);
}
TimeSpan sinceLastServiceListCheck = context.CurrentTime - serviceListLastChecked;
if (sinceLastServiceListCheck.TotalDays < 1.0)
continue;
if (vfs.FileExists(serviceList.URI))
{
byte[] serviceListBytes = vfs.GetFile(serviceList.URI);
ServiceListType serviceListData = DvbIUtils.UnpackServiceList(serviceListBytes);
HandleServiceList(serviceListData, dataStorage, serviceList.Id);
dataStorage.UpdateDvbiServiceListLastCheckedDate(serviceList.Id, context.CurrentTime);
}
}
dataStorage.UpdateDvbiServiceListEntryPointUpdateDate(sourceHash, context.CurrentTime);
}
private void HandleServiceList(ServiceListType serviceListData, DvbIDataStorage dataStorage, string serviceListId)
{
IEnumerable<DvbIService> services = DvbIUtils.FlattenServiceList(serviceListData);
foreach(DvbIService service in services)
{
if (dataStorage.TestForDvbiService(service.Id))
{
int versionInDb = dataStorage.GetDvbiServiceVersion(service.Id);
if (service.Version > versionInDb)
{
dataStorage.UpdateDvbiService(service);
}
}
else
{
logger.InfoFormat("New DVB-I Service: {0}", service.ServiceName);
dataStorage.InsertDvbiService(service);
dataStorage.AddDvbiServiceToServiceList(service.Id, serviceListId);
}
}
}
}
}