294 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using log4net;
using skyscraper5.Dvb.Psi.Model;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper;
using skyscraper5.Skyscraper.Headless;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
using skyscraper5.Skyscraper.IO.TunerInterface;
using skyscraper5.Skyscraper.Plugins;
using skyscraper5.Skyscraper.Scraper;
using skyscraper5.Skyscraper.Scraper.Storage;
using skyscraper8.Skyscraper.Scraper.Storage;
namespace skyscraper5
{
public class Passing
{
public DataStorage DataStorage { get; set; }
public ObjectStorage ObjectStorage { get; set; }
private IStreamReader streamReader;
private List<TunerMetadata> tuners;
private List<SatellitePosition> satellitePositions;
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
public Passing()
{
}
public bool Boot()
{
Ini ini = PluginManager.GetInstance().Ini;
StorageConnectionManager connectionManager = StorageConnectionManager.GetInstance();
IEnumerable<Tuple<int, bool, string>> allKnownFactoryNames = connectionManager.GetAllKnownFactoryNames();
foreach (Tuple<int, bool, string> knownFactoryName in allKnownFactoryNames)
{
logger.InfoFormat("Found {0} Storage Factory #{1}, {2}",knownFactoryName.Item2 ? "Data" : "Object",knownFactoryName.Item1,knownFactoryName.Item3);
}
logger.Debug("Acquiring Default Data Storage...");
DataStorageFactory dataStorageFactory = connectionManager.GetDefaultDataStorageFactory();
logger.Debug("Acquiring Default Object Storage...");
ObjectStorageFactory objectStorageFactory = connectionManager.GetDefaultObjectStorageFactory();
logger.Debug("Acquiring Data Storage...");
DataStorage = dataStorageFactory.CreateDataStorage();
if (DataStorage == null)
{
logger.FatalFormat("The data storage factory didn't create a data storage.");
return false;
}
bool isEquivalent = objectStorageFactory.IsEquivalent(dataStorageFactory);
if (isEquivalent)
{
logger.Debug("Using the Data Storage as Object Storage.");
ObjectStorage = (ObjectStorage)DataStorage;
}
else
{
logger.Debug("Acquiring Object Storage...");
ObjectStorage = objectStorageFactory.CreateObjectStorage();
if (ObjectStorage == null)
{
logger.FatalFormat("The object storage factory didn't create an object storage.");
return false;
}
}
TunerFactoryConnectionManager tunerFactoryConnectionManager = TunerFactoryConnectionManager.GetInstance();
ReadOnlyCollection<KeyValuePair<TunerFactoryIdAttribute, ITunerFactory>> tunerFactories = tunerFactoryConnectionManager.GetKnownFactories();
int tunerFactory = ini.ReadValue("startup", "tunerFactory", 0);
KeyValuePair<TunerFactoryIdAttribute, ITunerFactory> bootingTuner = tunerFactories.First(x => x.Key.Id == tunerFactory);
if (bootingTuner.Value == null)
{
Console.WriteLine("The tuner factory #{0} didn't load.", tunerFactory);
return false;
}
TunerFactoryConnectionManager.ConfigureFactoryFromIni(bootingTuner, ini);
streamReader = bootingTuner.Value.CreateStreamReader();
if (streamReader == null)
{
Console.WriteLine("The tuner factory #{0} didn't create a stream reader.");
return false;
}
try
{
streamReader.CheckForDVB();
}
catch (BadImageFormatException e)
{
Console.WriteLine("The configured tuner factory is not suitable for the current processor architecture. Tuning won't work, therefore functionality will be severely limited. Please configure a Tuner Factory Class suitable for this processor architecture in order to get the best experience. If you need to run crazycat69's StreamReader.dll on 64-bit machines, try RemoteStreamReader.");
streamReader = new NullTunerFactory().CreateStreamReader();
}
List<TunerMetadata> foundTuners = new List<TunerMetadata>();
bool checkForDvbExEx = streamReader.CheckForDVBExEx((index, name, type) =>
{
TunerMetadata tuner = new TunerMetadata(index, name, type);
foundTuners.Add(tuner);
});
foreach (TunerMetadata foundTuner in foundTuners)
{
streamReader.StopDVB();
bool startDvbEx = streamReader.StartDvbEx(foundTuner.Index);
if (!startDvbEx)
{
Console.WriteLine("Failed to start {0}", foundTuner.Name);
Thread.Sleep(1000);
continue;
}
foundTuner.Caps = streamReader.GetCaps();
byte[] macBuffer = new byte[6];
bool mac = streamReader.GetMAC(macBuffer);
if (!mac)
{
Console.WriteLine("Failed to read MAC Address of {0}", foundTuner.Name);
Thread.Sleep(1000);
}
else
{
foundTuner.MacAddress = new PhysicalAddress(macBuffer);
}
bool stopDvb = streamReader.StopDVB();
if (!stopDvb)
{
Console.WriteLine("Failed to stop {0}", foundTuner.Name);
Thread.Sleep(1000);
continue;
}
;
if (DataStorage.UiTunerTestFor(foundTuner))
{
DataStorage.UiTunerGetConfiguration(foundTuner);
}
if (tuners == null)
tuners = new List<TunerMetadata>();
tuners.Add(foundTuner);
}
satellitePositions = DataStorage.UiSatellitesListAll();
return true;
}
private HeadlessJob GetNextJob()
{
HeadlessJob headlessJob = DataStorage.GetQueuedJob();
if (headlessJob != null)
{
return headlessJob;
}
return new HeadlessJob(HeadlessJobType.BlindscanEverything);
}
public void Run()
{
while (true)
{
HeadlessJob headlessJob = GetNextJob();
Run(headlessJob);
if (!headlessJob.isSynthetic)
{
DataStorage.SetQueuedJobComplete(headlessJob);
}
}
}
private void Run(HeadlessJob job)
{
switch (job.jobType)
{
case HeadlessJobType.Sleep:
Thread.Sleep(job.iArg1);
break;
case HeadlessJobType.MassImport:
DirectoryInfo di = new DirectoryInfo(job.sArg1);
MassImportDirectory(di);
break;
case HeadlessJobType.BlindscanEverything:
PerformBlindscanEverything();
break;
case HeadlessJobType.ReimportByTag1:
ReimportTag(job.iArg1);
break;
default:
throw new NotImplementedException(job.jobType.ToString());
}
}
private void PerformBlindscanEverything()
{
if (tuners == null)
tuners = new List<TunerMetadata>();
if (tuners.Count == 0)
throw new ApplicationException("I'd need to blindscan everything, but I don't have any tuners I could use!");
throw new NotImplementedException(nameof(PerformBlindscanEverything));
}
private void ReimportTag(int tag1)
{
IReadOnlyList<string> queue = DataStorage.ListImportFileByTag1(tag1);
foreach(string filename in queue)
{
FileInfo fi = new FileInfo(filename);
if (!fi.Exists)
continue;
ScrapeStream(fi);
}
}
public void MassImportDirectory(DirectoryInfo sourceDir)
{
foreach (FileSystemInfo fileSystemInfo in sourceDir.GetFileSystemInfos())
{
DirectoryInfo di = fileSystemInfo as DirectoryInfo;
FileInfo fi = fileSystemInfo as FileInfo;
if (di != null)
{
MassImportDirectory(di);
}
else if (fi != null)
{
if (fi.Length == 0)
continue;
if (!fi.Extension.ToLowerInvariant().Equals(".ts"))
continue;
if (DataStorage.ImportFileKnown(fi))
continue;
FileStream fileStream = fi.OpenRead();
Stopwatch stopwatch = Stopwatch.StartNew();
int tstype;
ScrapeStream(fileStream,true, out tstype);
stopwatch.Stop();
Console.WriteLine("Importing {0} took {1}",fi.Name, stopwatch.Elapsed);
DataStorage.WaitForCompletion();
DataStorage.ImportMarkFileAsKnown(fi, stopwatch.Elapsed, tstype);
fileStream.Close();
}
else
{
throw new NotImplementedException(fileSystemInfo.GetType().ToString());
}
}
}
private void ScrapeStream(FileInfo fi)
{
FileStream fileStream = fi.OpenRead();
ScrapeStream(fileStream, true, out _);
fileStream.Close();
fileStream.Dispose();
}
private void ScrapeStream(Stream inStream, bool disk, out int tstype)
{
SkyscraperContext skyscraperContext = new SkyscraperContext(new TsContext(), DataStorage,ObjectStorage);
skyscraperContext.SourceIsDisk = disk;
skyscraperContext.InitalizeFilterChain();
skyscraperContext.IngestFromStream(inStream);
skyscraperContext.Dispose();
tstype = skyscraperContext.SpecialTsType;
}
}
}