Compare commits
No commits in common. "695ca5e69f47b570c83b1cc8e38acf8751af38ea" and "fe672a54f9e69d5eca99b628a9ad4c89a01d581f" have entirely different histories.
695ca5e69f
...
fe672a54f9
1
.gitignore
vendored
1
.gitignore
vendored
@ -134,4 +134,3 @@ imgui.ini
|
|||||||
/Documentation/TSDuck-Samples/experiment2/*.ts
|
/Documentation/TSDuck-Samples/experiment2/*.ts
|
||||||
/.vs/skyscraper8/CopilotIndices/17.14.1431.25910
|
/.vs/skyscraper8/CopilotIndices/17.14.1431.25910
|
||||||
/.vs
|
/.vs
|
||||||
/skyscraper8/bin/Debug/satip
|
|
||||||
|
|||||||
@ -120,11 +120,6 @@ namespace skyscraper8.GS.GSE_BFBS
|
|||||||
if (!startIndicator && endIndicator)
|
if (!startIndicator && endIndicator)
|
||||||
gseLength -= 4;
|
gseLength -= 4;
|
||||||
|
|
||||||
if (span.GetAvailableBytes() < gseLength)
|
|
||||||
{
|
|
||||||
//broken gse packet, invalid length
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gsePacket.GseDataBytes = span.ReadBytes(gseLength);
|
gsePacket.GseDataBytes = span.ReadBytes(gseLength);
|
||||||
|
|
||||||
if (!startIndicator && endIndicator)
|
if (!startIndicator && endIndicator)
|
||||||
|
|||||||
293
skyscraper8/Passing.cs
Normal file
293
skyscraper8/Passing.cs
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
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<SatellitePositionEntity> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,6 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"skyscraper8": {
|
"skyscraper8": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"commandLineArgs": "rotation-catalogue F:\\\\ F:\\\\rotate-us.csv",
|
|
||||||
"remoteDebugEnabled": false
|
"remoteDebugEnabled": false
|
||||||
},
|
},
|
||||||
"Container (Dockerfile)": {
|
"Container (Dockerfile)": {
|
||||||
|
|||||||
@ -1,329 +1,278 @@
|
|||||||
using log4net;
|
using log4net;
|
||||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||||
using skyscraper8.SatIp;
|
using skyscraper8.SatIp;
|
||||||
using skyscraper8.SatIp.RtspResponses;
|
using skyscraper8.SatIp.RtspResponses;
|
||||||
using skyscraper8.SimpleServiceDiscoveryProtocol;
|
using skyscraper8.SimpleServiceDiscoveryProtocol;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using skyscraper5.Mpeg2;
|
using skyscraper5.Mpeg2;
|
||||||
using skyscraper5.Skyscraper.Scraper;
|
using skyscraper5.Skyscraper.Scraper;
|
||||||
using skyscraper5.Skyscraper.Scraper.Storage.Filesystem;
|
using skyscraper5.Skyscraper.Scraper.Storage.Filesystem;
|
||||||
using skyscraper5.Skyscraper.Scraper.Storage.InMemory;
|
using skyscraper5.Skyscraper.Scraper.Storage.InMemory;
|
||||||
using skyscraper8.Skyscraper.Scraper.Storage;
|
using skyscraper8.Skyscraper.Scraper.Storage;
|
||||||
|
|
||||||
namespace skyscraper8
|
namespace skyscraper8
|
||||||
{
|
{
|
||||||
internal class QuickAndDirtySatIpClient
|
internal class QuickAndDirtySatIpClient
|
||||||
{
|
{
|
||||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||||
private const bool ENABLE_TS_WRITER = true;
|
private const bool ENABLE_TS_WRITER = true;
|
||||||
|
|
||||||
public QuickAndDirtySatIpClient(string[] args)
|
public QuickAndDirtySatIpClient(string[] args)
|
||||||
{
|
{
|
||||||
if (args.Length == 1)
|
if (args.Length == 1)
|
||||||
{
|
{
|
||||||
logger.Fatal("Hey, what's your SAT>IP Server's IP Address? You can also say \"autodetect\" here.");
|
logger.Fatal("Hey, what's your SAT>IP Server's IP Address? You can also say \"autodetect\" here.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (args[1].ToLowerInvariant().Contains("auto"))
|
if (args[1].ToLowerInvariant().Contains("auto"))
|
||||||
{
|
{
|
||||||
ipAddress = AutodetectIPAddress();
|
ipAddress = AutodetectIPAddress();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ipAddress = IPAddress.Parse(args[1]);
|
ipAddress = IPAddress.Parse(args[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.Length == 2)
|
if (args.Length == 2)
|
||||||
{
|
{
|
||||||
logger.Fatal("You didn't specify a DiSEqc setting. (Number between 1-4)");
|
logger.Fatal("You didn't specify a DiSEqc setting. (Number between 1-4)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
diseqcNumber = Int32.Parse(args[2]);
|
diseqcNumber = Int32.Parse(args[2]);
|
||||||
|
|
||||||
if (args.Length == 3)
|
if (args.Length == 3)
|
||||||
{
|
{
|
||||||
logger.Fatal("You didn't specify a polarity. Use H or V.");
|
logger.Fatal("You didn't specify a polarity. Use H or V.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
polarity = args[3].ToUpperInvariant()[0];
|
polarity = args[3].ToUpperInvariant()[0];
|
||||||
|
|
||||||
if (args.Length == 4)
|
if (args.Length == 4)
|
||||||
{
|
{
|
||||||
logger.Fatal("Please specify a frequency.");
|
logger.Fatal("Please specify a frequency.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
frequency = Int32.Parse(args[4]);
|
frequency = Int32.Parse(args[4]);
|
||||||
|
|
||||||
if (args.Length == 5)
|
if (args.Length == 5)
|
||||||
{
|
{
|
||||||
logger.Fatal("What DVB Standard do we have here? S or S2?");
|
logger.Fatal("What DVB Standard do we have here? S or S2?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isS2 = ParseDvbStandard(args[5]);
|
isS2 = ParseDvbStandard(args[5]);
|
||||||
|
|
||||||
if (args.Length == 6)
|
if (args.Length == 6)
|
||||||
{
|
{
|
||||||
logger.Fatal("What's the symbol rate?");
|
logger.Fatal("What's the symbol rate?");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
symbolRate = Int32.Parse(args[6]);
|
symbolRate = Int32.Parse(args[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPlayoutMode(string[] args)
|
private IPAddress AutodetectIPAddress()
|
||||||
{
|
{
|
||||||
if (args.Length == 7)
|
SsdpDevice firstSatIpServer = SsdpClient.GetFirstSatIpServer(1000, null);
|
||||||
{
|
if (firstSatIpServer == null)
|
||||||
logger.Fatal("What's the target port?");
|
{
|
||||||
return;
|
logger.WarnFormat("Didn't find any SAT>IP servers.");
|
||||||
}
|
return null;
|
||||||
destinationPort = int.Parse(args[7]);
|
}
|
||||||
playoutMode = true;
|
IPAddress ipAddress = firstSatIpServer.GetIpAddress();
|
||||||
if (args.Length == 10)
|
logger.InfoFormat("Found SAT>IP Server at {0}", ipAddress);
|
||||||
{
|
return ipAddress;
|
||||||
if (args[8].ToLowerInvariant().Equals("multicast"))
|
}
|
||||||
{
|
|
||||||
destinationIp = IPAddress.Parse(args[9]);
|
private int symbolRate;
|
||||||
multicastMode = true;
|
private bool isS2;
|
||||||
}
|
private int frequency;
|
||||||
else
|
private char polarity;
|
||||||
{
|
private int diseqcNumber;
|
||||||
logger.FatalFormat("Don't know what {0} means.", args[8]);
|
private IPAddress ipAddress;
|
||||||
return;
|
private RtspClient rtspClient;
|
||||||
}
|
public void Run()
|
||||||
}
|
{
|
||||||
}
|
rtspClient = new RtspClient(ipAddress, 554);
|
||||||
|
rtspClient.AutoReconnect = false;
|
||||||
private IPAddress AutodetectIPAddress()
|
Keepalive();
|
||||||
{
|
DiSEqC_Opcode opcode = BuildDiseqcOpcode();
|
||||||
SsdpDevice firstSatIpServer = SsdpClient.GetFirstSatIpServer(1000, null);
|
string url = RtspClient.MakeUrl(opcode, frequency, isS2, symbolRate, null, false);
|
||||||
if (firstSatIpServer == null)
|
RtspDescribeResponse describe = rtspClient.GetDescribe(url);
|
||||||
{
|
SessionDescriptionProtocol sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol();
|
||||||
logger.WarnFormat("Didn't find any SAT>IP servers.");
|
|
||||||
return null;
|
packetQueue = new Queue<byte[]>();
|
||||||
}
|
RtspSetupResponse setup = rtspClient.GetSetup(url);
|
||||||
IPAddress ipAddress = firstSatIpServer.GetIpAddress();
|
if (setup.RtspStatusCode == 404)
|
||||||
logger.InfoFormat("Found SAT>IP Server at {0}", ipAddress);
|
{
|
||||||
return ipAddress;
|
logger.Fatal("Your SAT>IP server doesn't have a tuner available that can talk to the requested frequency.");
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
private int symbolRate;
|
setup.OnRtcpPacket += Setup_OnRtcpPacket;
|
||||||
private bool isS2;
|
setup.OnRtpPacket += Setup_OnRtpPacket;
|
||||||
private int frequency;
|
|
||||||
private char polarity;
|
if (dataStorage == null)
|
||||||
private int diseqcNumber;
|
dataStorage = new InMemoryScraperStorage();
|
||||||
private IPAddress ipAddress;
|
if (objectStorage == null)
|
||||||
private RtspClient rtspClient;
|
objectStorage = new FilesystemStorage(new DirectoryInfo("."));
|
||||||
public void Run()
|
context = new SkyscraperContext(new TsContext(), dataStorage, objectStorage);
|
||||||
{
|
context.EnableTimeout = true;
|
||||||
rtspClient = new RtspClient(ipAddress, 554);
|
context.TimeoutSeconds = 60;
|
||||||
rtspClient.AutoReconnect = false;
|
context.InitalizeFilterChain();
|
||||||
Keepalive();
|
|
||||||
DiSEqC_Opcode opcode = BuildDiseqcOpcode();
|
RtspPlayResponse play = rtspClient.GetPlay(setup);
|
||||||
string url = RtspClient.MakeUrl(opcode, frequency, isS2, symbolRate, null, false);
|
DateTime lastTimestamp = DateTime.Now;
|
||||||
RtspDescribeResponse describe = rtspClient.GetDescribe(url);
|
|
||||||
SessionDescriptionProtocol sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol();
|
while (true)
|
||||||
|
{
|
||||||
packetQueue = new Queue<byte[]>();
|
if (packetQueue.Count >= 1)
|
||||||
RtspSetupResponse setup = rtspClient.GetSetup(url, destinationPort, multicastMode, destinationIp);
|
{
|
||||||
if (setup.RtspStatusCode == 404)
|
byte[] buffer;
|
||||||
{
|
lock (packetQueue)
|
||||||
logger.Fatal("Your SAT>IP server doesn't have a tuner available that can talk to the requested frequency.");
|
{
|
||||||
return;
|
buffer = packetQueue.Dequeue();
|
||||||
}
|
}
|
||||||
setup.OnRtcpPacket += Setup_OnRtcpPacket;
|
context.IngestSinglePacket(buffer);
|
||||||
setup.OnRtpPacket += Setup_OnRtpPacket;
|
}
|
||||||
|
else
|
||||||
if (dataStorage == null)
|
{
|
||||||
dataStorage = new InMemoryScraperStorage();
|
Thread.Sleep(1);
|
||||||
if (objectStorage == null)
|
}
|
||||||
objectStorage = new FilesystemStorage(new DirectoryInfo("."));
|
|
||||||
if (!playoutMode)
|
if (context.IsAbortConditionMet())
|
||||||
{
|
break;
|
||||||
context = new SkyscraperContext(new TsContext(), dataStorage, objectStorage);
|
|
||||||
context.EnableTimeout = true;
|
if (DateTime.Now.Second != lastTimestamp.Second)
|
||||||
context.TimeoutSeconds = 60;
|
{
|
||||||
context.InitalizeFilterChain();
|
Keepalive(url);
|
||||||
}
|
lastTimestamp = DateTime.Now;
|
||||||
|
}
|
||||||
RtspPlayResponse play = rtspClient.GetPlay(setup);
|
}
|
||||||
DateTime lastTimestamp = DateTime.Now;
|
|
||||||
bool initMessagePrinted = false;
|
rtspClient.GetTeardown(setup);
|
||||||
|
rtspClient.Dispose();
|
||||||
while (true)
|
}
|
||||||
{
|
|
||||||
if (playoutMode)
|
private FileStream fs;
|
||||||
{
|
private uint stuffingBytes;
|
||||||
Thread.Sleep(1000);
|
private Queue<byte[]> packetQueue;
|
||||||
Keepalive(url);
|
private ObjectStorage objectStorage;
|
||||||
if (!initMessagePrinted)
|
private DataStorage dataStorage;
|
||||||
{
|
private SkyscraperContext context;
|
||||||
logger.InfoFormat("Began SAT>IP playout to port {0}", destinationPort);
|
private void Setup_OnRtpPacket(byte[] data, int length)
|
||||||
initMessagePrinted = true;
|
{
|
||||||
}
|
for (int i = 12; i < length; i += 1)
|
||||||
}
|
{
|
||||||
else
|
if (data[i] == 'G')
|
||||||
{
|
{
|
||||||
if (packetQueue.Count >= 1)
|
byte[] buffer = new byte[188];
|
||||||
{
|
Array.Copy(data, i, buffer, 0, 188);
|
||||||
byte[] buffer;
|
lock (packetQueue)
|
||||||
lock (packetQueue)
|
{
|
||||||
{
|
packetQueue.Enqueue(buffer);
|
||||||
buffer = packetQueue.Dequeue();
|
}
|
||||||
}
|
|
||||||
context.IngestSinglePacket(buffer);
|
DumpPacket(buffer);
|
||||||
if (!initMessagePrinted)
|
i += 187;
|
||||||
{
|
}
|
||||||
logger.InfoFormat("Began SAT>IP stream.");
|
else if (data[i] == 0xff)
|
||||||
initMessagePrinted = true;
|
{
|
||||||
}
|
stuffingBytes++;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
Thread.Sleep(1);
|
|
||||||
}
|
private void DumpPacket(byte[] buffer)
|
||||||
|
{
|
||||||
if (context.IsAbortConditionMet())
|
if (!ENABLE_TS_WRITER)
|
||||||
break;
|
return;
|
||||||
|
|
||||||
if (DateTime.Now.Second != lastTimestamp.Second)
|
if (fs == null)
|
||||||
{
|
{
|
||||||
Keepalive(url);
|
string fname = String.Format("{0}.ts", DateTime.Now.Ticks);
|
||||||
lastTimestamp = DateTime.Now;
|
fs = File.OpenWrite(fname);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
fs.Write(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
rtspClient.GetTeardown(setup);
|
|
||||||
rtspClient.Dispose();
|
private int rtcps;
|
||||||
}
|
private void Setup_OnRtcpPacket(byte[] data, int length)
|
||||||
|
{
|
||||||
private FileStream fs;
|
//rtcps++;
|
||||||
private uint stuffingBytes;
|
}
|
||||||
private Queue<byte[]> packetQueue;
|
|
||||||
private ObjectStorage objectStorage;
|
private DiSEqC_Opcode BuildDiseqcOpcode()
|
||||||
private DataStorage dataStorage;
|
{
|
||||||
private SkyscraperContext context;
|
DiSEqC_Opcode opcode = DiSEqC_Opcode.DISEQC_HIGH_NIBBLE;
|
||||||
private void Setup_OnRtpPacket(byte[] data, int length)
|
switch (diseqcNumber)
|
||||||
{
|
{
|
||||||
for (int i = 12; i < length; i += 1)
|
case 1:
|
||||||
{
|
opcode |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
||||||
if (data[i] == 'G')
|
opcode |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
||||||
{
|
break;
|
||||||
byte[] buffer = new byte[188];
|
case 2:
|
||||||
Array.Copy(data, i, buffer, 0, 188);
|
opcode |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
||||||
lock (packetQueue)
|
opcode |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
||||||
{
|
break;
|
||||||
packetQueue.Enqueue(buffer);
|
case 3:
|
||||||
}
|
opcode |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
||||||
|
opcode |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
||||||
DumpPacket(buffer);
|
break;
|
||||||
i += 187;
|
case 4:
|
||||||
}
|
opcode |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
||||||
else if (data[i] == 0xff)
|
opcode |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
||||||
{
|
break;
|
||||||
stuffingBytes++;
|
default:
|
||||||
}
|
throw new ArgumentOutOfRangeException("Your DiSEqC position should be a number between 1 and 4.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
switch (polarity)
|
||||||
private void DumpPacket(byte[] buffer)
|
{
|
||||||
{
|
case 'H':
|
||||||
if (!ENABLE_TS_WRITER)
|
opcode |= DiSEqC_Opcode.DISEQC_HORIZONTAL;
|
||||||
return;
|
break;
|
||||||
|
case 'V':
|
||||||
if (fs == null)
|
opcode |= DiSEqC_Opcode.DISEQC_VERTICAL;
|
||||||
{
|
break;
|
||||||
string fname = String.Format("{0}.ts", DateTime.Now.Ticks);
|
default:
|
||||||
fs = File.OpenWrite(fname);
|
throw new ArgumentException("The polarity should be H or V.");
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.Write(buffer, 0, buffer.Length);
|
return opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int rtcps;
|
private bool ParseDvbStandard(string standard)
|
||||||
private IPAddress destinationIp;
|
{
|
||||||
private int destinationPort;
|
standard = standard.ToUpperInvariant();
|
||||||
private bool playoutMode;
|
if (standard.StartsWith("DVB"))
|
||||||
private bool multicastMode;
|
standard = standard.Substring(3);
|
||||||
|
if (standard.StartsWith("-"))
|
||||||
private void Setup_OnRtcpPacket(byte[] data, int length)
|
standard = standard.Substring(1);
|
||||||
{
|
|
||||||
//rtcps++;
|
switch (standard)
|
||||||
}
|
{
|
||||||
|
case "S":
|
||||||
private DiSEqC_Opcode BuildDiseqcOpcode()
|
return false;
|
||||||
{
|
case "S2":
|
||||||
DiSEqC_Opcode opcode = DiSEqC_Opcode.DISEQC_HIGH_NIBBLE;
|
return true;
|
||||||
switch (diseqcNumber)
|
case "S2X":
|
||||||
{
|
return true;
|
||||||
case 1:
|
default:
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
throw new ArgumentException(String.Format("I have no idea what kind of Standard {0} is supposed to be.", standard));
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
}
|
||||||
break;
|
}
|
||||||
case 2:
|
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
private void Keepalive(string url = "/")
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
{
|
||||||
break;
|
RtspOptionsResponse options = rtspClient.GetOptions("/");
|
||||||
case 3:
|
if (options.RtspStatusCode != 200)
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
{
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
throw new RtspException(String.Format("Unexpected RTSP Status code. Wanted {0}, got {1}", 200, options.RtspStatusCode));
|
||||||
break;
|
}
|
||||||
case 4:
|
}
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
}
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException("Your DiSEqC position should be a number between 1 and 4.");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (polarity)
|
|
||||||
{
|
|
||||||
case 'H':
|
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_HORIZONTAL;
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
opcode |= DiSEqC_Opcode.DISEQC_VERTICAL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentException("The polarity should be H or V.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return opcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ParseDvbStandard(string standard)
|
|
||||||
{
|
|
||||||
standard = standard.ToUpperInvariant();
|
|
||||||
if (standard.StartsWith("DVB"))
|
|
||||||
standard = standard.Substring(3);
|
|
||||||
if (standard.StartsWith("-"))
|
|
||||||
standard = standard.Substring(1);
|
|
||||||
|
|
||||||
switch (standard)
|
|
||||||
{
|
|
||||||
case "S":
|
|
||||||
return false;
|
|
||||||
case "S2":
|
|
||||||
return true;
|
|
||||||
case "S2X":
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
throw new ArgumentException(String.Format("I have no idea what kind of Standard {0} is supposed to be.", standard));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Keepalive(string url = "/")
|
|
||||||
{
|
|
||||||
RtspOptionsResponse options = rtspClient.GetOptions("/");
|
|
||||||
if (options.RtspStatusCode != 200)
|
|
||||||
{
|
|
||||||
throw new RtspException(String.Format("Unexpected RTSP Status code. Wanted {0}, got {1}", 200, options.RtspStatusCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,363 +1,347 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using skyscraper5.Skyscraper;
|
using skyscraper5.Skyscraper;
|
||||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||||
using skyscraper8.SatIp.RtspRequests;
|
using skyscraper8.SatIp.RtspRequests;
|
||||||
using skyscraper8.SatIp.RtspResponses;
|
using skyscraper8.SatIp.RtspResponses;
|
||||||
|
|
||||||
namespace skyscraper8.SatIp
|
namespace skyscraper8.SatIp
|
||||||
{
|
{
|
||||||
internal class RtspClient : Validatable, IDisposable
|
internal class RtspClient : Validatable, IDisposable
|
||||||
{
|
{
|
||||||
private uint cseqCounter;
|
private uint cseqCounter;
|
||||||
private const string USER_AGENT = "sophiaNetRtspClient/1.0";
|
private const string USER_AGENT = "sophiaNetRtspClient/1.0";
|
||||||
|
|
||||||
public RtspClient(string ip, int port)
|
public RtspClient(string ip, int port)
|
||||||
{
|
{
|
||||||
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
||||||
ConstructStep2(ipEndPoint);
|
ConstructStep2(ipEndPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RtspClient(IPAddress ip, int port)
|
public RtspClient(IPAddress ip, int port)
|
||||||
{
|
{
|
||||||
IPEndPoint ipEndPoint = new IPEndPoint(ip, port);
|
IPEndPoint ipEndPoint = new IPEndPoint(ip, port);
|
||||||
ConstructStep2(ipEndPoint);
|
ConstructStep2(ipEndPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConstructStep2(IPEndPoint ipEndPoint)
|
private void ConstructStep2(IPEndPoint ipEndPoint)
|
||||||
{
|
{
|
||||||
this.TcpClient = new TcpClient();
|
this.TcpClient = new TcpClient();
|
||||||
this.TcpClient.Connect(ipEndPoint);
|
this.TcpClient.Connect(ipEndPoint);
|
||||||
this.RootPath = string.Format("rtsp://{0}:{1}", ipEndPoint.Address.ToString(), ipEndPoint.Port.ToString());
|
this.RootPath = string.Format("rtsp://{0}:{1}", ipEndPoint.Address.ToString(), ipEndPoint.Port.ToString());
|
||||||
this.NetworkStream = TcpClient.GetStream();
|
this.NetworkStream = TcpClient.GetStream();
|
||||||
this.BufferedStream = new BufferedStream(this.NetworkStream);
|
this.BufferedStream = new BufferedStream(this.NetworkStream);
|
||||||
this.StreamReader = new StreamReader(this.BufferedStream);
|
this.StreamReader = new StreamReader(this.BufferedStream);
|
||||||
this.StreamWriter = new StreamWriter(this.BufferedStream);
|
this.StreamWriter = new StreamWriter(this.BufferedStream);
|
||||||
this.cseqCounter = 2;
|
this.cseqCounter = 2;
|
||||||
this.ListenIp = GetListenIp(this.TcpClient.Client.LocalEndPoint);
|
this.ListenIp = GetListenIp(this.TcpClient.Client.LocalEndPoint);
|
||||||
RtspOptionsResponse rtspOptionsResponse = GetOptions("/");
|
RtspOptionsResponse rtspOptionsResponse = GetOptions("/");
|
||||||
this.Valid = rtspOptionsResponse.Valid;
|
this.Valid = rtspOptionsResponse.Valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AutoReconnect { get; set; }
|
public bool AutoReconnect { get; set; }
|
||||||
public IPAddress ListenIp { get; set; }
|
public IPAddress ListenIp { get; set; }
|
||||||
|
|
||||||
private IPAddress GetListenIp(EndPoint clientLocalEndPoint)
|
private IPAddress GetListenIp(EndPoint clientLocalEndPoint)
|
||||||
{
|
{
|
||||||
IPEndPoint ipEndPoint = clientLocalEndPoint as IPEndPoint;
|
IPEndPoint ipEndPoint = clientLocalEndPoint as IPEndPoint;
|
||||||
if (ipEndPoint == null)
|
if (ipEndPoint == null)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException(clientLocalEndPoint.GetType().Name);
|
throw new NotImplementedException(clientLocalEndPoint.GetType().Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ipEndPoint.Address.AddressFamily == AddressFamily.InterNetwork)
|
if (ipEndPoint.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||||
{
|
{
|
||||||
return ipEndPoint.Address;
|
return ipEndPoint.Address;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ipEndPoint.Address.IsIPv4MappedToIPv6)
|
if (ipEndPoint.Address.IsIPv4MappedToIPv6)
|
||||||
{
|
{
|
||||||
return ipEndPoint.Address.MapToIPv4();
|
return ipEndPoint.Address.MapToIPv4();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotImplementedException(String.Format("Don't know whether I can listen on IP {0}", ipEndPoint.ToString()));
|
throw new NotImplementedException(String.Format("Don't know whether I can listen on IP {0}", ipEndPoint.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string RootPath { get; set; }
|
public string RootPath { get; set; }
|
||||||
|
|
||||||
private TcpClient TcpClient { get; set; }
|
private TcpClient TcpClient { get; set; }
|
||||||
private NetworkStream NetworkStream { get; set; }
|
private NetworkStream NetworkStream { get; set; }
|
||||||
private BufferedStream BufferedStream { get; set; }
|
private BufferedStream BufferedStream { get; set; }
|
||||||
private StreamReader StreamReader { get; set; }
|
private StreamReader StreamReader { get; set; }
|
||||||
private StreamWriter StreamWriter { get; set; }
|
private StreamWriter StreamWriter { get; set; }
|
||||||
|
|
||||||
public RtspOptionsResponse GetOptions(string url)
|
public RtspOptionsResponse GetOptions(string url)
|
||||||
{
|
{
|
||||||
RtspOptionsRequest request = new RtspOptionsRequest();
|
RtspOptionsRequest request = new RtspOptionsRequest();
|
||||||
request.RequestPath = url;
|
request.RequestPath = url;
|
||||||
request.CSeq = cseqCounter++;
|
request.CSeq = cseqCounter++;
|
||||||
request.UserAgent = USER_AGENT;
|
request.UserAgent = USER_AGENT;
|
||||||
RtspResponseHeader header = GetResponse(request.ListHeaders(RootPath));
|
RtspResponseHeader header = GetResponse(request.ListHeaders(RootPath));
|
||||||
RtspOptionsResponse result = new RtspOptionsResponse(header);
|
RtspOptionsResponse result = new RtspOptionsResponse(header);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RtspDescribeResponse GetDescribe(string url)
|
public RtspDescribeResponse GetDescribe(string url)
|
||||||
{
|
{
|
||||||
RtspDescribeRequest request = new RtspDescribeRequest();
|
RtspDescribeRequest request = new RtspDescribeRequest();
|
||||||
request.RequestPath = url;
|
request.RequestPath = url;
|
||||||
request.CSeq = cseqCounter++;
|
request.CSeq = cseqCounter++;
|
||||||
request.UserAgent = USER_AGENT;
|
request.UserAgent = USER_AGENT;
|
||||||
request.Accept = "application/sdp";
|
request.Accept = "application/sdp";
|
||||||
RtspResponseHeader header = GetResponse(request.ListHeaders(RootPath));
|
RtspResponseHeader header = GetResponse(request.ListHeaders(RootPath));
|
||||||
RtspDescribeResponse result = new RtspDescribeResponse(header);
|
RtspDescribeResponse result = new RtspDescribeResponse(header);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RtspSetupResponse GetSetup(string url, int destinationPort = 0, bool multicastMode = false, IPAddress multicastIp = null)
|
public RtspSetupResponse GetSetup(string url)
|
||||||
{
|
{
|
||||||
RtspSetupRequest request = new RtspSetupRequest();
|
RtspSetupRequest request = new RtspSetupRequest();
|
||||||
request.RequestPath = url;
|
request.RequestPath = url;
|
||||||
request.CSeq = cseqCounter++;
|
request.CSeq = cseqCounter++;
|
||||||
request.UserAgent = USER_AGENT;
|
request.UserAgent = USER_AGENT;
|
||||||
|
|
||||||
int rtpPort = 0;
|
Socket rtpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||||
Socket rtpSocket = null;
|
rtpSocket.Bind(new IPEndPoint(ListenIp, 0));
|
||||||
if (destinationPort == 0)
|
int rtpPort = GetPortFromEndPoint(rtpSocket.LocalEndPoint);
|
||||||
{
|
|
||||||
rtpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
Socket rtcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||||
rtpSocket.Bind(new IPEndPoint(ListenIp, 0));
|
rtcpSocket.Bind(new IPEndPoint(ListenIp, 0));
|
||||||
rtpPort = GetPortFromEndPoint(rtpSocket.LocalEndPoint);
|
int rtcpPort = GetPortFromEndPoint(rtcpSocket.LocalEndPoint);
|
||||||
}
|
|
||||||
else
|
request.SetRtpAvpUnicast(rtpPort, rtcpPort);
|
||||||
{
|
|
||||||
rtpPort = destinationPort;
|
RtspResponseHeader response = GetResponse(request.ListHeaders(RootPath));
|
||||||
}
|
RtspSetupResponse setupResponse = new RtspSetupResponse(response);
|
||||||
|
switch (response.statusCode)
|
||||||
Socket rtcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
{
|
||||||
rtcpSocket.Bind(new IPEndPoint(ListenIp, 0));
|
case 200:
|
||||||
int rtcpPort = GetPortFromEndPoint(rtcpSocket.LocalEndPoint);
|
setupResponse.RtpSocket = rtpSocket;
|
||||||
|
setupResponse.RtcpSocket = rtcpSocket;
|
||||||
if (multicastMode && multicastIp != null)
|
setupResponse.SetupListeners();
|
||||||
{
|
setupResponse.Valid = true;
|
||||||
request.SetRtpAvpMulticast(multicastIp, rtpPort, rtcpPort);
|
break;
|
||||||
}
|
case 404:
|
||||||
else
|
setupResponse.Valid = true;
|
||||||
{
|
break;
|
||||||
request.SetRtpAvpUnicast(rtpPort, rtcpPort);
|
default:
|
||||||
}
|
throw new NotImplementedException(setupResponse.RtspStatusCode.ToString());
|
||||||
|
}
|
||||||
RtspResponseHeader response = GetResponse(request.ListHeaders(RootPath));
|
return setupResponse;
|
||||||
RtspSetupResponse setupResponse = new RtspSetupResponse(response);
|
}
|
||||||
switch (response.statusCode)
|
|
||||||
{
|
public RtspPlayResponse GetPlay(RtspSetupResponse setupData)
|
||||||
case 200:
|
{
|
||||||
setupResponse.RtpSocket = rtpSocket;
|
RtspPlayRequest request = new RtspPlayRequest();
|
||||||
setupResponse.RtcpSocket = rtcpSocket;
|
request.RequestPath = string.Format("/stream={0}", setupData.StreamId);
|
||||||
setupResponse.SetupListeners();
|
request.Session = setupData.Session;
|
||||||
setupResponse.Valid = true;
|
request.UserAgent = USER_AGENT;
|
||||||
break;
|
|
||||||
case 404:
|
RtspPlayResponse response = new RtspPlayResponse(GetResponse(request.ListHeaders(RootPath)));
|
||||||
setupResponse.Valid = true;
|
return response;
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
throw new NotImplementedException(setupResponse.RtspStatusCode.ToString());
|
public RtspTeardownResponse GetTeardown(RtspSetupResponse setupData)
|
||||||
}
|
{
|
||||||
return setupResponse;
|
RtspTeardownRequest request = new RtspTeardownRequest();
|
||||||
}
|
request.RequestPath = string.Format("/stream={0}", setupData.StreamId);
|
||||||
|
request.Session = setupData.Session;
|
||||||
public RtspPlayResponse GetPlay(RtspSetupResponse setupData)
|
request.UserAgent = USER_AGENT;
|
||||||
{
|
|
||||||
RtspPlayRequest request = new RtspPlayRequest();
|
RtspTeardownResponse response = new RtspTeardownResponse(GetResponse(request.ListHeaders(RootPath)));
|
||||||
request.RequestPath = string.Format("/stream={0}", setupData.StreamId);
|
if (response.RtspStatusCode == 200)
|
||||||
request.Session = setupData.Session;
|
{
|
||||||
request.UserAgent = USER_AGENT;
|
setupData.InvokeCancellationTokens();
|
||||||
|
if (AutoReconnect)
|
||||||
RtspPlayResponse response = new RtspPlayResponse(GetResponse(request.ListHeaders(RootPath)));
|
{
|
||||||
return response;
|
Reconnect();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public RtspTeardownResponse GetTeardown(RtspSetupResponse setupData)
|
return response;
|
||||||
{
|
}
|
||||||
RtspTeardownRequest request = new RtspTeardownRequest();
|
|
||||||
request.RequestPath = string.Format("/stream={0}", setupData.StreamId);
|
private int GetPortFromEndPoint(EndPoint endpoint)
|
||||||
request.Session = setupData.Session;
|
{
|
||||||
request.UserAgent = USER_AGENT;
|
IPEndPoint ipEndPoint = endpoint as IPEndPoint;
|
||||||
|
if (ipEndPoint == null)
|
||||||
RtspTeardownResponse response = new RtspTeardownResponse(GetResponse(request.ListHeaders(RootPath)));
|
throw new NotImplementedException(endpoint.GetType().Name);
|
||||||
if (response.RtspStatusCode == 200)
|
return ipEndPoint.Port;
|
||||||
{
|
}
|
||||||
setupData.InvokeCancellationTokens();
|
|
||||||
if (AutoReconnect)
|
private RtspResponseHeader GetResponse(string request)
|
||||||
{
|
{
|
||||||
Reconnect();
|
StreamWriter.Write(request);
|
||||||
}
|
StreamWriter.Flush();
|
||||||
}
|
|
||||||
return response;
|
RtspResponseHeader result = new RtspResponseHeader();
|
||||||
}
|
|
||||||
|
string response = StreamReader.ReadLine();
|
||||||
private int GetPortFromEndPoint(EndPoint endpoint)
|
if (!response.StartsWith("RTSP/"))
|
||||||
{
|
throw new RtspException("Invalid RTSP response.");
|
||||||
IPEndPoint ipEndPoint = endpoint as IPEndPoint;
|
|
||||||
if (ipEndPoint == null)
|
response = response.Substring(5);
|
||||||
throw new NotImplementedException(endpoint.GetType().Name);
|
|
||||||
return ipEndPoint.Port;
|
string versionString = response.Substring(0, 3);
|
||||||
}
|
result.rtspVersion = Version.Parse(versionString);
|
||||||
|
response = response.Substring(4);
|
||||||
private RtspResponseHeader GetResponse(string request)
|
|
||||||
{
|
string statusCodeString = response.Substring(0,3);
|
||||||
StreamWriter.Write(request);
|
result.statusCode = ushort.Parse(statusCodeString);
|
||||||
StreamWriter.Flush();
|
|
||||||
|
response = response.Substring(4);
|
||||||
RtspResponseHeader result = new RtspResponseHeader();
|
result.statusLine = response;
|
||||||
|
|
||||||
string response = StreamReader.ReadLine();
|
long contentLength = 0;
|
||||||
if (!response.StartsWith("RTSP/"))
|
|
||||||
throw new RtspException("Invalid RTSP response.");
|
result.kv = new Dictionary<string, string>();
|
||||||
|
while (true)
|
||||||
response = response.Substring(5);
|
{
|
||||||
|
string lineIn = StreamReader.ReadLine();
|
||||||
string versionString = response.Substring(0, 3);
|
if (string.IsNullOrEmpty(lineIn))
|
||||||
result.rtspVersion = Version.Parse(versionString);
|
break;
|
||||||
response = response.Substring(4);
|
|
||||||
|
int indexOf = lineIn.IndexOf(": ");
|
||||||
string statusCodeString = response.Substring(0,3);
|
string key = lineIn.Substring(0, indexOf);
|
||||||
result.statusCode = ushort.Parse(statusCodeString);
|
string value = lineIn.Substring(indexOf + 2);
|
||||||
|
result.kv.Add(key, value);
|
||||||
response = response.Substring(4);
|
|
||||||
result.statusLine = response;
|
if (key.Equals("Content-Length"))
|
||||||
|
{
|
||||||
long contentLength = 0;
|
contentLength = long.Parse(value);
|
||||||
|
}
|
||||||
result.kv = new Dictionary<string, string>();
|
}
|
||||||
while (true)
|
|
||||||
{
|
if (contentLength > 0)
|
||||||
string lineIn = StreamReader.ReadLine();
|
{
|
||||||
if (string.IsNullOrEmpty(lineIn))
|
StreamReader.DiscardBufferedData();
|
||||||
break;
|
byte[] buffer = new byte[contentLength];
|
||||||
|
int sucessfullyRead = BufferedStream.Read(buffer, 0, (int)contentLength);
|
||||||
int indexOf = lineIn.IndexOf(": ");
|
if (sucessfullyRead != contentLength)
|
||||||
string key = lineIn.Substring(0, indexOf);
|
{
|
||||||
string value = lineIn.Substring(indexOf + 2);
|
throw new IOException("incomplete read");
|
||||||
result.kv.Add(key, value);
|
}
|
||||||
|
|
||||||
if (key.Equals("Content-Length"))
|
result.payload = buffer;
|
||||||
{
|
}
|
||||||
contentLength = long.Parse(value);
|
|
||||||
}
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contentLength > 0)
|
public void Reconnect()
|
||||||
{
|
{
|
||||||
StreamReader.DiscardBufferedData();
|
EndPoint clientRemoteEndPoint = this.TcpClient.Client.RemoteEndPoint;
|
||||||
byte[] buffer = new byte[contentLength];
|
IPEndPoint ipEndPoint = clientRemoteEndPoint as IPEndPoint;
|
||||||
int sucessfullyRead = BufferedStream.Read(buffer, 0, (int)contentLength);
|
if (ipEndPoint == null)
|
||||||
if (sucessfullyRead != contentLength)
|
{
|
||||||
{
|
throw new NotImplementedException(clientRemoteEndPoint.GetType().ToString());
|
||||||
throw new IOException("incomplete read");
|
}
|
||||||
}
|
|
||||||
|
this.TcpClient.Close();
|
||||||
result.payload = buffer;
|
this.TcpClient = new TcpClient();
|
||||||
}
|
this.TcpClient.Connect(ipEndPoint);
|
||||||
|
this.RootPath = string.Format("rtsp://{0}:{1}", ipEndPoint.Address, ipEndPoint.Port);
|
||||||
return result;
|
this.NetworkStream = TcpClient.GetStream();
|
||||||
}
|
this.BufferedStream = new BufferedStream(this.NetworkStream);
|
||||||
|
this.StreamReader = new StreamReader(this.BufferedStream);
|
||||||
public void Reconnect()
|
this.StreamWriter = new StreamWriter(this.BufferedStream);
|
||||||
{
|
this.cseqCounter = 2;
|
||||||
EndPoint clientRemoteEndPoint = this.TcpClient.Client.RemoteEndPoint;
|
this.ListenIp = GetListenIp(this.TcpClient.Client.LocalEndPoint);
|
||||||
IPEndPoint ipEndPoint = clientRemoteEndPoint as IPEndPoint;
|
}
|
||||||
if (ipEndPoint == null)
|
|
||||||
{
|
/// <summary>
|
||||||
throw new NotImplementedException(clientRemoteEndPoint.GetType().ToString());
|
/// Generates a SAT>IP Tuning string.
|
||||||
}
|
/// </summary>
|
||||||
|
/// <param name="diseqcChannel">The DiSEqC Command to send.</param>
|
||||||
this.TcpClient.Close();
|
/// <param name="freq">The frequency to tune to in MHz.</param>
|
||||||
this.TcpClient = new TcpClient();
|
/// <param name="isS2">Set this to true if tuning to DVB-S2/S2X, or false for DVB-S</param>
|
||||||
this.TcpClient.Connect(ipEndPoint);
|
/// <param name="symbolrate">The transponder's symbol rate in Ksyms.</param>
|
||||||
this.RootPath = string.Format("rtsp://{0}:{1}", ipEndPoint.Address, ipEndPoint.Port);
|
/// <param name="forceBbframeMode">Set this to true to force a STiD135 to BBFrame mode. Set this to false if you do not want this, or if the tuner isn't a STiD135. false is always safe here.</param>
|
||||||
this.NetworkStream = TcpClient.GetStream();
|
/// <returns>A SAT>IP Tuning String</returns>
|
||||||
this.BufferedStream = new BufferedStream(this.NetworkStream);
|
/// <exception cref="ArgumentOutOfRangeException">Thrown when an invalid DiSEqC Command is supplied.</exception>
|
||||||
this.StreamReader = new StreamReader(this.BufferedStream);
|
public static string MakeUrl(DiSEqC_Opcode diseqcChannel, int freq, bool isS2, int symbolrate, byte? mis = null, bool forceBbframeMode = false)
|
||||||
this.StreamWriter = new StreamWriter(this.BufferedStream);
|
{
|
||||||
this.cseqCounter = 2;
|
bool diseqcOk = false;
|
||||||
this.ListenIp = GetListenIp(this.TcpClient.Client.LocalEndPoint);
|
byte diseqc = 1;
|
||||||
}
|
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_A) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_A))
|
||||||
|
{
|
||||||
/// <summary>
|
diseqc = 1;
|
||||||
/// Generates a SAT>IP Tuning string.
|
diseqcOk = true;
|
||||||
/// </summary>
|
}
|
||||||
/// <param name="diseqcChannel">The DiSEqC Command to send.</param>
|
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_A) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_B))
|
||||||
/// <param name="freq">The frequency to tune to in MHz.</param>
|
{
|
||||||
/// <param name="isS2">Set this to true if tuning to DVB-S2/S2X, or false for DVB-S</param>
|
diseqc = 2;
|
||||||
/// <param name="symbolrate">The transponder's symbol rate in Ksyms.</param>
|
diseqcOk = true;
|
||||||
/// <param name="forceBbframeMode">Set this to true to force a STiD135 to BBFrame mode. Set this to false if you do not want this, or if the tuner isn't a STiD135. false is always safe here.</param>
|
}
|
||||||
/// <returns>A SAT>IP Tuning String</returns>
|
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_B) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_A))
|
||||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when an invalid DiSEqC Command is supplied.</exception>
|
{
|
||||||
public static string MakeUrl(DiSEqC_Opcode diseqcChannel, int freq, bool isS2, int symbolrate, byte? mis = null, bool forceBbframeMode = false)
|
diseqc = 3;
|
||||||
{
|
diseqcOk = true;
|
||||||
bool diseqcOk = false;
|
}
|
||||||
byte diseqc = 1;
|
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_B) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_B))
|
||||||
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_A) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_A))
|
{
|
||||||
{
|
diseqc = 4;
|
||||||
diseqc = 1;
|
diseqcOk = true;
|
||||||
diseqcOk = true;
|
}
|
||||||
}
|
if (!diseqcOk)
|
||||||
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_A) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_B))
|
{
|
||||||
{
|
throw new ArgumentOutOfRangeException(nameof(diseqcChannel));
|
||||||
diseqc = 2;
|
}
|
||||||
diseqcOk = true;
|
|
||||||
}
|
char pol;
|
||||||
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_B) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_A))
|
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_HORIZONTAL))
|
||||||
{
|
{
|
||||||
diseqc = 3;
|
pol = 'h';
|
||||||
diseqcOk = true;
|
}
|
||||||
}
|
else
|
||||||
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_OPTION_B) && diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_POSITION_B))
|
{
|
||||||
{
|
pol = 'v';
|
||||||
diseqc = 4;
|
}
|
||||||
diseqcOk = true;
|
|
||||||
}
|
StringBuilder sb = new StringBuilder();
|
||||||
if (!diseqcOk)
|
sb.AppendFormat("/?src={0}", diseqc);
|
||||||
{
|
sb.AppendFormat("&freq={0}", freq);
|
||||||
throw new ArgumentOutOfRangeException(nameof(diseqcChannel));
|
sb.AppendFormat("&pol={0}", pol);
|
||||||
}
|
sb.AppendFormat("&msys={0}", isS2 ? "dvbs2" : "dvbs");
|
||||||
|
sb.AppendFormat("&sr={0}", symbolrate);
|
||||||
char pol;
|
sb.AppendFormat("&pids=all");
|
||||||
if (diseqcChannel.HasFlag(DiSEqC_Opcode.DISEQC_HORIZONTAL))
|
|
||||||
{
|
//Thanks to the Digital Devices Customer Support for giving me this advice.
|
||||||
pol = 'h';
|
if (forceBbframeMode)
|
||||||
}
|
{
|
||||||
else
|
sb.Append("&x_isi=0x80000000");
|
||||||
{
|
}
|
||||||
pol = 'v';
|
else if (mis.HasValue)
|
||||||
}
|
{
|
||||||
|
sb.AppendFormat("&x_isi={0}", mis.Value);
|
||||||
StringBuilder sb = new StringBuilder();
|
}
|
||||||
sb.AppendFormat("/?src={0}", diseqc);
|
|
||||||
sb.AppendFormat("&freq={0}", freq);
|
return sb.ToString();
|
||||||
sb.AppendFormat("&pol={0}", pol);
|
}
|
||||||
sb.AppendFormat("&msys={0}", isS2 ? "dvbs2" : "dvbs");
|
|
||||||
sb.AppendFormat("&sr={0}", symbolrate);
|
private bool disposed;
|
||||||
sb.AppendFormat("&pids=all");
|
public void Dispose()
|
||||||
|
{
|
||||||
//Thanks to the Digital Devices Customer Support for giving me this advice.
|
if (disposed)
|
||||||
if (forceBbframeMode)
|
throw new ObjectDisposedException(nameof(RtspClient));
|
||||||
{
|
|
||||||
sb.Append("&x_isi=0x80000000");
|
ListenIp = null;
|
||||||
}
|
RootPath = null;
|
||||||
else if (mis.HasValue)
|
if (TcpClient.Connected)
|
||||||
{
|
{
|
||||||
sb.AppendFormat("&x_isi={0}", mis.Value);
|
TcpClient.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
TcpClient.Dispose();
|
||||||
}
|
NetworkStream = null;
|
||||||
|
BufferedStream = null;
|
||||||
private bool disposed;
|
StreamReader = null;
|
||||||
public void Dispose()
|
StreamWriter = null;
|
||||||
{
|
disposed = true;
|
||||||
if (disposed)
|
}
|
||||||
throw new ObjectDisposedException(nameof(RtspClient));
|
}
|
||||||
|
}
|
||||||
ListenIp = null;
|
|
||||||
RootPath = null;
|
|
||||||
if (TcpClient.Connected)
|
|
||||||
{
|
|
||||||
TcpClient.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
TcpClient.Dispose();
|
|
||||||
NetworkStream = null;
|
|
||||||
BufferedStream = null;
|
|
||||||
StreamReader = null;
|
|
||||||
StreamWriter = null;
|
|
||||||
disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,63 +1,57 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Text;
|
||||||
using System.Text;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
namespace skyscraper8.SatIp.RtspRequests
|
||||||
namespace skyscraper8.SatIp.RtspRequests
|
{
|
||||||
{
|
internal class RtspSetupRequest : RtspRequest
|
||||||
internal class RtspSetupRequest : RtspRequest
|
{
|
||||||
{
|
public RtspSetupRequest() : base("SETUP")
|
||||||
public RtspSetupRequest() : base("SETUP")
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
public uint CSeq
|
||||||
public uint CSeq
|
{
|
||||||
{
|
set
|
||||||
set
|
{
|
||||||
{
|
base.args["CSeq"] = Convert.ToString(value);
|
||||||
base.args["CSeq"] = Convert.ToString(value);
|
}
|
||||||
}
|
get
|
||||||
get
|
{
|
||||||
{
|
return uint.Parse(base.args["CSeq"]);
|
||||||
return uint.Parse(base.args["CSeq"]);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public string UserAgent
|
||||||
public string UserAgent
|
{
|
||||||
{
|
set
|
||||||
set
|
{
|
||||||
{
|
base.args["User-Agent"] = value;
|
||||||
base.args["User-Agent"] = value;
|
}
|
||||||
}
|
get
|
||||||
get
|
{
|
||||||
{
|
return base.args["User-Agent"];
|
||||||
return base.args["User-Agent"];
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public string Transport
|
||||||
public string Transport
|
{
|
||||||
{
|
set
|
||||||
set
|
{
|
||||||
{
|
base.args["Transport"] = value;
|
||||||
base.args["Transport"] = value;
|
}
|
||||||
}
|
get
|
||||||
get
|
{
|
||||||
{
|
return base.args["Transport"];
|
||||||
return base.args["Transport"];
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void SetRtpAvpUnicast(int rtpPort, int rtcpPort)
|
||||||
public void SetRtpAvpUnicast(int rtpPort, int rtcpPort)
|
{
|
||||||
{
|
Transport = String.Format("RTP/AVP;unicast;client_port={0}-{1}", rtpPort, rtcpPort);
|
||||||
Transport = String.Format("RTP/AVP;unicast;client_port={0}-{1}", rtpPort, rtcpPort);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetRtpAvpMulticast(IPAddress targetIp, int rtpPort, int rtcpPort)
|
}
|
||||||
{
|
|
||||||
Transport = String.Format("RTP/AVP;multicast;destination={2};port={0}-{1}", rtpPort, rtcpPort, targetIp.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@ -53,29 +53,23 @@ namespace skyscraper8.SatIp.RtspResponses
|
|||||||
if (listenersStarted)
|
if (listenersStarted)
|
||||||
throw new RtspException("Listener already started.");
|
throw new RtspException("Listener already started.");
|
||||||
|
|
||||||
if (RtpSocket != null)
|
rtpCancellation = new CancellationTokenSource();
|
||||||
{
|
|
||||||
rtpCancellation = new CancellationTokenSource();
|
|
||||||
}
|
|
||||||
rtcpCancellation = new CancellationTokenSource();
|
rtcpCancellation = new CancellationTokenSource();
|
||||||
|
|
||||||
if (RtpSocket != null)
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
byte[] buffer = new byte[2048];
|
||||||
{
|
|
||||||
byte[] buffer = new byte[2048];
|
while (!rtpCancellation.IsCancellationRequested)
|
||||||
|
{
|
||||||
while (!rtpCancellation.IsCancellationRequested)
|
Array.Clear(buffer);
|
||||||
{
|
int result = await RtpSocket.ReceiveAsync(buffer, rtpCancellation.Token);
|
||||||
Array.Clear(buffer);
|
OnRtpPacket?.Invoke(buffer, result);
|
||||||
int result = await RtpSocket.ReceiveAsync(buffer, rtpCancellation.Token);
|
}
|
||||||
OnRtpPacket?.Invoke(buffer, result);
|
|
||||||
}
|
exitedThread++;
|
||||||
|
}
|
||||||
exitedThread++;
|
);
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@ -98,8 +92,8 @@ namespace skyscraper8.SatIp.RtspResponses
|
|||||||
|
|
||||||
internal void InvokeCancellationTokens()
|
internal void InvokeCancellationTokens()
|
||||||
{
|
{
|
||||||
rtpCancellation?.Cancel();
|
rtpCancellation.Cancel();
|
||||||
rtcpCancellation?.Cancel();
|
rtcpCancellation.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public event OnRtpPacket OnRtpPacket;
|
public event OnRtpPacket OnRtpPacket;
|
||||||
|
|||||||
20
skyscraper8/Skyscraper/Equipment/BaseEquipment.cs
Normal file
20
skyscraper8/Skyscraper/Equipment/BaseEquipment.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace skyscraper5.Skyscraper.Equipment
|
||||||
|
{
|
||||||
|
public class BaseEquipment
|
||||||
|
{
|
||||||
|
[XmlIgnore]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public string Manufacturer { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[XmlIgnore]
|
||||||
|
public DateTime DateAdded { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
57
skyscraper8/Skyscraper/Equipment/Dish.cs
Normal file
57
skyscraper8/Skyscraper/Equipment/Dish.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace skyscraper5.Skyscraper.Equipment
|
||||||
|
{
|
||||||
|
public class DishEntity : BaseEquipment
|
||||||
|
{
|
||||||
|
public DishEntity(string manufac, string name, int diameter, DishShape shape)
|
||||||
|
{
|
||||||
|
this.Manufacturer = manufac;
|
||||||
|
this.Name = name;
|
||||||
|
this.Diameter = diameter;
|
||||||
|
this.Shape = shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DishEntity()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public int Diameter { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public DishShape Shape { get; set; }
|
||||||
|
|
||||||
|
protected bool Equals(DishEntity other)
|
||||||
|
{
|
||||||
|
return Diameter == other.Diameter && Shape == other.Shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
if (obj.GetType() != this.GetType()) return false;
|
||||||
|
return Equals((DishEntity)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(Diameter, (int)Shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return this.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DishShape : int
|
||||||
|
{
|
||||||
|
Offset,
|
||||||
|
PrimeFocus,
|
||||||
|
Mesh,
|
||||||
|
Other
|
||||||
|
}
|
||||||
|
}
|
||||||
20
skyscraper8/Skyscraper/Equipment/EquipmentCollection.cs
Normal file
20
skyscraper8/Skyscraper/Equipment/EquipmentCollection.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace skyscraper5.Skyscraper.Equipment;
|
||||||
|
|
||||||
|
public class EquipmentCollection
|
||||||
|
{
|
||||||
|
public EquipmentCollection()
|
||||||
|
{
|
||||||
|
Dishes = new List<DishEntity>();
|
||||||
|
LNBs = new List<LnbEntity>();
|
||||||
|
SatellitePositions = new List<SatellitePositionEntity>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DishEntity> Dishes { get; set; }
|
||||||
|
public List<LnbEntity> LNBs { get; set; }
|
||||||
|
public List<SatellitePositionEntity> SatellitePositions { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return String.Format("{0} dishes, {1} LNBs, {2} satellite positions", Dishes.Count, LNBs.Count, SatellitePositions.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
57
skyscraper8/Skyscraper/Equipment/EquipmentUtilities.cs
Normal file
57
skyscraper8/Skyscraper/Equipment/EquipmentUtilities.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using skyscraper5.Skyscraper.Scraper.Storage;
|
||||||
|
using skyscraper8.Skyscraper.Scraper.Storage;
|
||||||
|
|
||||||
|
namespace skyscraper5.Skyscraper.Equipment
|
||||||
|
{
|
||||||
|
public static class EquipmentUtilities
|
||||||
|
{
|
||||||
|
public static void InsertDefaultLnbTypes(DataStorage storage)
|
||||||
|
{
|
||||||
|
List<LnbEntity> knownLnbTypes = storage.UiLnbTypesListAll();
|
||||||
|
foreach (LnbEntity defaultLnbType in GetDefaultLnbTypes())
|
||||||
|
{
|
||||||
|
if (!knownLnbTypes.Contains(defaultLnbType))
|
||||||
|
storage.UiLnbTypesAdd(defaultLnbType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<LnbEntity> GetDefaultLnbTypes()
|
||||||
|
{
|
||||||
|
LnbEntity lnbType = new LnbEntity();
|
||||||
|
lnbType.Lof1 = 9750;
|
||||||
|
lnbType.Lof2 = 10600;
|
||||||
|
lnbType.LofSw = 11700;
|
||||||
|
lnbType.MinimumFrequency = 10700;
|
||||||
|
lnbType.MaximumFrequency = 12750;
|
||||||
|
lnbType.Manufacturer = "Generic";
|
||||||
|
lnbType.Name = "Universal LNB";
|
||||||
|
yield return lnbType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void InsertDefaultDishTypes(DataStorage storage)
|
||||||
|
{
|
||||||
|
List<DishEntity> knownDishTypes = storage.UiDishTypesListAll();
|
||||||
|
foreach (DishEntity defaultDishType in GetDefaultDishTypes())
|
||||||
|
{
|
||||||
|
if (!knownDishTypes.Contains(defaultDishType))
|
||||||
|
storage.UiDishTypesAdd(defaultDishType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<DishEntity> GetDefaultDishTypes()
|
||||||
|
{
|
||||||
|
int[] commonSizes = new int[] { 60, 80, 85, 100 };
|
||||||
|
foreach (int commonSize in commonSizes)
|
||||||
|
{
|
||||||
|
DishEntity dishType = new DishEntity();
|
||||||
|
dishType.Diameter = commonSize;
|
||||||
|
dishType.Shape = DishShape.Offset;
|
||||||
|
dishType.Manufacturer = "Generic";
|
||||||
|
dishType.Name = String.Format("{0} cm Offset dish antenna", commonSize);
|
||||||
|
yield return dishType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
skyscraper8/Skyscraper/Equipment/LNB.cs
Normal file
59
skyscraper8/Skyscraper/Equipment/LNB.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace skyscraper5.Skyscraper.Equipment
|
||||||
|
{
|
||||||
|
public class LnbEntity : BaseEquipment
|
||||||
|
{
|
||||||
|
public LnbEntity() { }
|
||||||
|
|
||||||
|
public LnbEntity(string manufac, string name, int lof1, int lof2, int lofSw, int minFreq, int maxFreq)
|
||||||
|
{
|
||||||
|
this.Manufacturer = manufac;
|
||||||
|
this.Name = name;
|
||||||
|
this.Lof1 = lof1;
|
||||||
|
this.Lof2 = lof2;
|
||||||
|
this.LofSw = lofSw;
|
||||||
|
this.MinimumFrequency = minFreq;
|
||||||
|
this.MaximumFrequency = maxFreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public int Lof1 { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public int Lof2 { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public int LofSw { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public int MinimumFrequency { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public int MaximumFrequency { get; set; }
|
||||||
|
|
||||||
|
protected bool Equals(LnbEntity other)
|
||||||
|
{
|
||||||
|
return Lof1 == other.Lof1 && Lof2 == other.Lof2 && LofSw == other.LofSw && MinimumFrequency == other.MinimumFrequency && MaximumFrequency == other.MaximumFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
if (obj.GetType() != this.GetType()) return false;
|
||||||
|
return Equals((LnbEntity)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(Lof1, Lof2, LofSw, MinimumFrequency, MaximumFrequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return String.Format("{0} {1}", Manufacturer, Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
108
skyscraper8/Skyscraper/Equipment/SatellitePositionEntity.cs
Normal file
108
skyscraper8/Skyscraper/Equipment/SatellitePositionEntity.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace skyscraper5.Skyscraper
|
||||||
|
{
|
||||||
|
public class SatellitePositionEntity
|
||||||
|
{
|
||||||
|
public SatellitePositionEntity()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SatellitePositionEntity(float angle, string name)
|
||||||
|
{
|
||||||
|
this.angle = angle;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float angle;
|
||||||
|
public string name;
|
||||||
|
|
||||||
|
public int Checksum => GetChecksum(angle);
|
||||||
|
|
||||||
|
public static int GetChecksum(float angle)
|
||||||
|
{
|
||||||
|
int result = (int)(angle * 10.0f);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (angle > 0)
|
||||||
|
{
|
||||||
|
return String.Format("{0}°E {1}", angle, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float tmpAngle = angle;
|
||||||
|
tmpAngle *= -1;
|
||||||
|
return String.Format("{0}°W {1}", tmpAngle, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SatellitePositionEntity FromChecksum(int checksum)
|
||||||
|
{
|
||||||
|
float newAngle = checksum;
|
||||||
|
newAngle /= 10.0f;
|
||||||
|
return new SatellitePositionEntity(newAngle, "???");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool Equals(SatellitePositionEntity other)
|
||||||
|
{
|
||||||
|
return angle.Equals(other.angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
if (obj.GetType() != this.GetType()) return false;
|
||||||
|
return Equals((SatellitePositionEntity)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an integer value for the cardinal direction.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns 0 for east, 1 for west, 2 if satellite is at 0.0</returns>
|
||||||
|
public int GetCardinalDirectionAsInt()
|
||||||
|
{
|
||||||
|
if (angle > 0)
|
||||||
|
return 0;
|
||||||
|
else if (angle < 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the letter matching the cardinal direction of the satellite.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns either 'E' or 'W' depending on the angle.</returns>
|
||||||
|
public char GetCardinalDirectionAsChar()
|
||||||
|
{
|
||||||
|
int cardinalDirectionAsInt = GetCardinalDirectionAsInt();
|
||||||
|
return cardinalDirectionAsInt == 0 ? 'E' : 'W';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a filename-safe number of the angle. Meaning the angle stripped of its sign and decimal separator.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>For example: For 19.2°E, this will return 192, For 34.5°W, this will return 345</returns>
|
||||||
|
public int GetCleanAngle()
|
||||||
|
{
|
||||||
|
int cleanAngle = (int)(angle * 10.0f);
|
||||||
|
if (cleanAngle < 0)
|
||||||
|
cleanAngle /= -1;
|
||||||
|
return cleanAngle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,6 +13,7 @@ using skyscraper5.src.Mpeg2.PacketFilter;
|
|||||||
using skyscraper5.Skyscraper.IO;
|
using skyscraper5.Skyscraper.IO;
|
||||||
using skyscraper5.Skyscraper.Scraper;
|
using skyscraper5.Skyscraper.Scraper;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using skyscraper5.Skyscraper.Equipment;
|
||||||
|
|
||||||
namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
||||||
{
|
{
|
||||||
@ -93,12 +94,12 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
SearchResult sr1 = default;
|
SearchResult sr1 = default;
|
||||||
int tpNum = default;
|
int tpNum = default;
|
||||||
|
|
||||||
int lof1 = config.Lof1 * 1000;
|
int lof1 = config.LnbType.Lof1 * 1000;
|
||||||
int lof2 = config.Lof2 * 1000;
|
int lof2 = config.LnbType.Lof2 * 1000;
|
||||||
int lofSw = config.LofSw * 1000;
|
int lofSw = config.LnbType.LofSw * 1000;
|
||||||
int diseqc = config.TunerMetadata.DiseqcType;
|
int diseqc = config.TunerMetadata.DiseqcType;
|
||||||
int startFreq = config.MinimumFrequency * 1000;
|
int startFreq = config.LnbType.MinimumFrequency * 1000;
|
||||||
int endFreq = config.MaximumFrequency * 1000;
|
int endFreq = config.LnbType.MaximumFrequency * 1000;
|
||||||
bool anythingSuceeded = false;
|
bool anythingSuceeded = false;
|
||||||
nint allocHGlobal = Marshal.AllocHGlobal(ushort.MaxValue);
|
nint allocHGlobal = Marshal.AllocHGlobal(ushort.MaxValue);
|
||||||
|
|
||||||
@ -394,15 +395,15 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
foundFrequencies.Add(blindscanSearchResult);
|
foundFrequencies.Add(blindscanSearchResult);
|
||||||
}
|
}
|
||||||
config.DataStorage.InsertSearchResult(jobInDb, true, searchResult, polarityIndex, new SearchResult2());
|
config.DataStorage.InsertSearchResult(jobInDb, true, searchResult, polarityIndex, new SearchResult2());
|
||||||
config.Ui.OnBlindscanSearchResult1Callback(blindscanSearchResult, polarityIndex, config.MinimumFrequency, config.MaximumFrequency);
|
config.Ui.OnBlindscanSearchResult1Callback(blindscanSearchResult, polarityIndex, config.LnbType.MinimumFrequency, config.LnbType.MaximumFrequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void RunScrape()
|
public void RunScrape()
|
||||||
{
|
{
|
||||||
int lof1 = config.Lof1 * 1000;
|
int lof1 = config.LnbType.Lof1 * 1000;
|
||||||
int lof2 = config.Lof2 * 1000;
|
int lof2 = config.LnbType.Lof2 * 1000;
|
||||||
int lofSw = config.LofSw * 1000;
|
int lofSw = config.LnbType.LofSw * 1000;
|
||||||
|
|
||||||
|
|
||||||
foreach (BlindscanSearchResult blindscanResult in foundFrequencies)
|
foreach (BlindscanSearchResult blindscanResult in foundFrequencies)
|
||||||
@ -411,7 +412,7 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
|
|
||||||
blindscanResult.State = BlindscanResultState.Tuning;
|
blindscanResult.State = BlindscanResultState.Tuning;
|
||||||
config.DataStorage.UpdateTransponderState(jobInDb, blindscanResult.IsSatellite(), blindscanResult.SearchResult, blindscanResult.State, blindscanResult.SearchResult2);
|
config.DataStorage.UpdateTransponderState(jobInDb, blindscanResult.IsSatellite(), blindscanResult.SearchResult, blindscanResult.State, blindscanResult.SearchResult2);
|
||||||
config.Ui.OnBlindscanBeforeSetChannel(blindscanResult);
|
config.Ui.OnBlindscanBeforeSetChannel(blindscanResult, config.LnbType);
|
||||||
bool channel = config.StreamReader.SetChannel(blindscanResult.SearchResult.Freq, blindscanResult.SearchResult.SR, blindscanResult.SearchResult.Pol, blindscanResult.SearchResult.FEC, lof1, lof2, lofSw);
|
bool channel = config.StreamReader.SetChannel(blindscanResult.SearchResult.Freq, blindscanResult.SearchResult.SR, blindscanResult.SearchResult.Pol, blindscanResult.SearchResult.FEC, lof1, lof2, lofSw);
|
||||||
if (!channel)
|
if (!channel)
|
||||||
{
|
{
|
||||||
@ -444,11 +445,11 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
|
|
||||||
config.Ui.OnBlindscanBeginRfSpectrum();
|
config.Ui.OnBlindscanBeginRfSpectrum();
|
||||||
|
|
||||||
int lof1 = config.Lof1 * 1000;
|
int lof1 = config.LnbType.Lof1 * 1000;
|
||||||
int lof2 = config.Lof2 * 1000;
|
int lof2 = config.LnbType.Lof2 * 1000;
|
||||||
int lofSw = config.LofSw * 1000;
|
int lofSw = config.LnbType.LofSw * 1000;
|
||||||
int startFreq = config.MinimumFrequency * 1000;
|
int startFreq = config.LnbType.MinimumFrequency * 1000;
|
||||||
int endFreq = config.MaximumFrequency * 1000;
|
int endFreq = config.LnbType.MaximumFrequency * 1000;
|
||||||
|
|
||||||
RfSpectrumData spectrumData = RfSpectrumData.Create();
|
RfSpectrumData spectrumData = RfSpectrumData.Create();
|
||||||
|
|
||||||
@ -573,14 +574,14 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
{
|
{
|
||||||
int polarity = result.SearchResult.Pol;
|
int polarity = result.SearchResult.Pol;
|
||||||
int freq = result.SearchResult.Freq;
|
int freq = result.SearchResult.Freq;
|
||||||
bool isHighBand = freq > config.LofSw * 1000;
|
bool isHighBand = freq > config.LnbType.LofSw * 1000;
|
||||||
bool isHorizontal = polarity == 0;
|
bool isHorizontal = polarity == 0;
|
||||||
|
|
||||||
SendDiseqcCommand(isHighBand, isHorizontal);
|
SendDiseqcCommand(isHighBand, isHorizontal);
|
||||||
logger.Log(PluginLogLevel.Info, string.Format("Trying to BLScanEx..."), 8);
|
logger.Log(PluginLogLevel.Info, string.Format("Trying to BLScanEx..."), 8);
|
||||||
if (!config.StreamReader.BLScanEx(result.SearchResult.Freq, 5000, result.SearchResult.Pol,
|
if (!config.StreamReader.BLScanEx(result.SearchResult.Freq, 5000, result.SearchResult.Pol,
|
||||||
config.Lof1 * 1000, config.Lof2 * 1000,
|
config.LnbType.Lof1 * 1000, config.LnbType.Lof2 * 1000,
|
||||||
config.LofSw * 1000, 1000000, (STD_TYPE)result.SearchResult.StdType,
|
config.LnbType.LofSw * 1000, 1000000, (STD_TYPE)result.SearchResult.StdType,
|
||||||
ref satelliteSr))
|
ref satelliteSr))
|
||||||
{
|
{
|
||||||
//No blindscan? No problem! Try anyway!
|
//No blindscan? No problem! Try anyway!
|
||||||
@ -599,7 +600,7 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
result.State = BlindscanResultState.Retrying;
|
result.State = BlindscanResultState.Retrying;
|
||||||
logger.Log(PluginLogLevel.Info, string.Format("Retrying BLScanEx... ({0}/{1})", i + 1, attempts + 1), 8);
|
logger.Log(PluginLogLevel.Info, string.Format("Retrying BLScanEx... ({0}/{1})", i + 1, attempts + 1), 8);
|
||||||
bool retryResult = config.StreamReader.BLScanEx(result.SearchResult.Freq, 5000, result.SearchResult.Pol, config.Lof1 * 1000, config.Lof2 * 1000, config.LofSw * 1000, 1000000, (STD_TYPE)result.SearchResult.StdType,ref satelliteSr);
|
bool retryResult = config.StreamReader.BLScanEx(result.SearchResult.Freq, 5000, result.SearchResult.Pol, config.LnbType.Lof1 * 1000, config.LnbType.Lof2 * 1000, config.LnbType.LofSw * 1000, 1000000, (STD_TYPE)result.SearchResult.StdType,ref satelliteSr);
|
||||||
if (!retryResult)
|
if (!retryResult)
|
||||||
{
|
{
|
||||||
result.State = BlindscanResultState.BlScanFailure;
|
result.State = BlindscanResultState.BlScanFailure;
|
||||||
@ -675,7 +676,7 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
if (plot != null)
|
if (plot != null)
|
||||||
{
|
{
|
||||||
result.State = BlindscanResultState.IqSaving;
|
result.State = BlindscanResultState.IqSaving;
|
||||||
config.ObjectStorage.StoreIqGraph(jobInDb.JobGuid, result.GetFrequency(), result.GetPolarity(config.LofSw), plot);
|
config.ObjectStorage.StoreIqGraph(jobInDb.JobGuid, result.GetFrequency(), result.GetPolarity(config.LnbType.LofSw), plot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,19 +707,22 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
if (tsRecorder.PrepareRecording())
|
if (tsRecorder.PrepareRecording())
|
||||||
{
|
{
|
||||||
DateTime now = DateTime.Now;
|
DateTime now = DateTime.Now;
|
||||||
|
|
||||||
|
int cardinalDirection = 0;
|
||||||
|
int angle = config.SatellitePosition.Checksum;
|
||||||
|
if (angle < 0)
|
||||||
|
{
|
||||||
|
angle *= -1;
|
||||||
|
cardinalDirection = 1;
|
||||||
|
}
|
||||||
|
|
||||||
string recordingFilename = string.Format(
|
string recordingFilename = string.Format(
|
||||||
"skyscraper_{0:D4}{1:D2}{2:D2}_{3:D2}{4:D2}_{8}_{5}_{6}_{7}.ts",
|
"skyscraper_{0:D4}{1:D2}{2:D2}_{3:D2}{4:D2}_{8:D4}{9}_{5}_{6}_{7}.ts",
|
||||||
now.Year, //0
|
now.Year, now.Month, now.Day, now.Hour, now.Minute, result.GetFrequency() / 1000,
|
||||||
now.Month, //1
|
result.GetPolarity(config.LnbType.LofSw), result.GetSymbolRate() / 1000,
|
||||||
now.Day, //2
|
config.SatellitePosition.GetCleanAngle(),
|
||||||
now.Hour, //3
|
config.SatellitePosition.GetCardinalDirectionAsChar());
|
||||||
now.Minute, //4
|
tsRecorder.SetNextFilename(recordingFilename);
|
||||||
result.GetFrequency() / 1000, //5
|
|
||||||
result.GetPolarity(config.LofSw), //6
|
|
||||||
result.GetSymbolRate() / 1000, //7
|
|
||||||
config.GetFiveLetterSattelitePosition()); //8
|
|
||||||
tsRecorder.SetNextFilename(recordingFilename);
|
|
||||||
tsRecorder.CreateBufferedStream();
|
tsRecorder.CreateBufferedStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using skyscraper5.Skyscraper;
|
using skyscraper5.Skyscraper;
|
||||||
|
using skyscraper5.Skyscraper.Equipment;
|
||||||
using skyscraper5.Skyscraper.Gps;
|
using skyscraper5.Skyscraper.Gps;
|
||||||
using skyscraper5.Skyscraper.IO;
|
using skyscraper5.Skyscraper.IO;
|
||||||
using skyscraper5.Skyscraper.Scraper;
|
using skyscraper5.Skyscraper.Scraper;
|
||||||
@ -17,7 +18,7 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
public TunerMetadata TunerMetadata { get; set; }
|
public TunerMetadata TunerMetadata { get; set; }
|
||||||
public int DiseqcIndex { get; set; }
|
public int DiseqcIndex { get; set; }
|
||||||
public IGpsReceiver Gps { get; set; }
|
public IGpsReceiver Gps { get; set; }
|
||||||
public double SatellitePosition { get; set; }
|
public SatellitePositionEntity SatellitePosition { get; set; }
|
||||||
|
|
||||||
public bool DoHorizontalHigh { get; set; }
|
public bool DoHorizontalHigh { get; set; }
|
||||||
public bool DoHorizontalLow { get; set; }
|
public bool DoHorizontalLow { get; set; }
|
||||||
@ -28,27 +29,9 @@ namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
|||||||
public ObjectStorage ObjectStorage { get; set; }
|
public ObjectStorage ObjectStorage { get; set; }
|
||||||
public ISkyscraperUiJunction Ui { get; set; }
|
public ISkyscraperUiJunction Ui { get; set; }
|
||||||
public bool DoCollectRfSpectrum { get; set; }
|
public bool DoCollectRfSpectrum { get; set; }
|
||||||
|
public LnbEntity LnbType { get; set; }
|
||||||
public bool DoCollectIqGraphs { get; set; }
|
public bool DoCollectIqGraphs { get; set; }
|
||||||
public bool DoRecordTs { get; set; }
|
public bool DoRecordTs { get; set; }
|
||||||
public Ini Ini { get; set; }
|
public Ini Ini { get; set; }
|
||||||
public int Lof1 { get; internal set; }
|
}
|
||||||
public int Lof2 { get; internal set; }
|
|
||||||
public int LofSw { get; internal set; }
|
|
||||||
public int MinimumFrequency { get; internal set; }
|
|
||||||
public int MaximumFrequency { get; internal set; }
|
|
||||||
|
|
||||||
internal string GetFiveLetterSattelitePosition()
|
|
||||||
{
|
|
||||||
if (SatellitePosition >= 0)
|
|
||||||
{
|
|
||||||
return String.Format("{0:D4}E", (int)(SatellitePosition * 10));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int westerner = (int)(SatellitePosition * 10);
|
|
||||||
westerner /= -1;
|
|
||||||
return String.Format("{0:D4}W", westerner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ namespace skyscraper5.src.Skyscraper.FrequencyListGenerator
|
|||||||
public class DbBlindscanJob
|
public class DbBlindscanJob
|
||||||
{
|
{
|
||||||
public DbBlindscanJob(Guid jobGuid, PhysicalAddress tunerMac, STD_TYPE tunerStandard, int diseqCIndex,
|
public DbBlindscanJob(Guid jobGuid, PhysicalAddress tunerMac, STD_TYPE tunerStandard, int diseqCIndex,
|
||||||
IGpsReceiver jobContextGps, double satellitePosition)
|
IGpsReceiver jobContextGps, SatellitePositionEntity satellitePosition)
|
||||||
{
|
{
|
||||||
this.JobGuid = jobGuid;
|
this.JobGuid = jobGuid;
|
||||||
this.TunerMAC = tunerMac;
|
this.TunerMAC = tunerMac;
|
||||||
@ -37,7 +37,7 @@ namespace skyscraper5.src.Skyscraper.FrequencyListGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public double SatPosition { get; private set; }
|
public SatellitePositionEntity SatPosition { get; private set; }
|
||||||
|
|
||||||
public GpsCoordinate? GpsCoordinate { get; private set; }
|
public GpsCoordinate? GpsCoordinate { get; private set; }
|
||||||
|
|
||||||
@ -68,15 +68,8 @@ namespace skyscraper5.src.Skyscraper.FrequencyListGenerator
|
|||||||
switch(mode)
|
switch(mode)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
if (SatPosition >= 0.0)
|
if (SatPosition != null)
|
||||||
{
|
return String.Format("{0:0.0}° {1}", SatPosition.angle, SatPosition.GetCardinalDirectionAsChar());
|
||||||
return String.Format("{0}°E", SatPosition);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double westerner = SatPosition /= -1;
|
|
||||||
return String.Format("{0}°W", westerner);
|
|
||||||
}
|
|
||||||
return TunerStandard.ToString();
|
return TunerStandard.ToString();
|
||||||
case 2:
|
case 2:
|
||||||
return String.Format("({0}/{1}/{2}/{3})", (int)HorizontalLowState, (int)HorizontalHighState, (int)VerticalLowState, (int)VerticalHighState);
|
return String.Format("({0}/{1}/{2}/{3})", (int)HorizontalLowState, (int)HorizontalHighState, (int)VerticalLowState, (int)VerticalHighState);
|
||||||
@ -85,19 +78,6 @@ namespace skyscraper5.src.Skyscraper.FrequencyListGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetFiveLetterOrbitalPosition()
|
|
||||||
{
|
|
||||||
if (SatPosition >= 0)
|
|
||||||
{
|
|
||||||
return String.Format("{0:4}E", (int)(SatPosition * 10));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double westerner = SatPosition /= -1;
|
|
||||||
return String.Format("{0:4}W", (int)(westerner * 10));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DbBlindscanJobPolarizationStatus : int
|
public enum DbBlindscanJobPolarizationStatus : int
|
||||||
|
|||||||
@ -513,10 +513,7 @@ namespace skyscraper5.Skyscraper.IO.RemoteStreamReader
|
|||||||
{
|
{
|
||||||
case RemoteStreamReaderConstants.COMMAND_SUCCESSFUL:
|
case RemoteStreamReaderConstants.COMMAND_SUCCESSFUL:
|
||||||
pRFLevel = NetworkStreamExtensions.ReadDouble(TcpStream);
|
pRFLevel = NetworkStreamExtensions.ReadDouble(TcpStream);
|
||||||
return true;
|
return true;
|
||||||
case RemoteStreamReaderConstants.COMMAND_FAILED:
|
|
||||||
pRFLevel = NetworkStreamExtensions.ReadDouble(TcpStream);
|
|
||||||
return false;
|
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException(result.ToString());
|
throw new NotImplementedException(result.ToString());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ namespace skyscraper5.Skyscraper.IO.TunerInterface
|
|||||||
{
|
{
|
||||||
[SkyscraperPlugin]
|
[SkyscraperPlugin]
|
||||||
[TunerFactoryId(2,"skyscraper5 Remote Stream Reader")]
|
[TunerFactoryId(2,"skyscraper5 Remote Stream Reader")]
|
||||||
public class RemoteStreamReaderTunerFactory : ITunerFactory
|
internal class RemoteStreamReaderTunerFactory : ITunerFactory
|
||||||
{
|
{
|
||||||
public string Hostname { get; set; }
|
public string Hostname { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ using skyscraper5.Mhp.Si.Model;
|
|||||||
using skyscraper5.Mpeg2.Descriptors;
|
using skyscraper5.Mpeg2.Descriptors;
|
||||||
using skyscraper5.Mpeg2.Psi.Model;
|
using skyscraper5.Mpeg2.Psi.Model;
|
||||||
using skyscraper5.Scte35;
|
using skyscraper5.Scte35;
|
||||||
|
using skyscraper5.Skyscraper.Equipment;
|
||||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||||
using skyscraper5.Skyscraper.Net;
|
using skyscraper5.Skyscraper.Net;
|
||||||
using skyscraper5.src.InteractionChannel.Model;
|
using skyscraper5.src.InteractionChannel.Model;
|
||||||
@ -97,7 +98,7 @@ namespace skyscraper5.Skyscraper.Scraper
|
|||||||
/// Called before a SetChannel operation is performed.
|
/// Called before a SetChannel operation is performed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="blindscanResult"></param>
|
/// <param name="blindscanResult"></param>
|
||||||
void OnBlindscanBeforeSetChannel(BlindscanSearchResult blindscanResult);
|
void OnBlindscanBeforeSetChannel(BlindscanSearchResult blindscanResult, LnbEntity lnbType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called after a band (meaning e.g. Horizontal High) has been scraped.
|
/// Called after a band (meaning e.g. Horizontal High) has been scraped.
|
||||||
|
|||||||
@ -12,11 +12,13 @@ using skyscraper5.Mpeg2.Psi.Model;
|
|||||||
using skyscraper5.Rds.Messages;
|
using skyscraper5.Rds.Messages;
|
||||||
using skyscraper5.Scte35;
|
using skyscraper5.Scte35;
|
||||||
using skyscraper5.Skyscraper;
|
using skyscraper5.Skyscraper;
|
||||||
|
using skyscraper5.Skyscraper.Equipment;
|
||||||
using skyscraper5.Skyscraper.Gps;
|
using skyscraper5.Skyscraper.Gps;
|
||||||
using skyscraper5.Skyscraper.Headless;
|
using skyscraper5.Skyscraper.Headless;
|
||||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||||
using skyscraper5.Skyscraper.Scraper.Storage.Utilities;
|
using skyscraper5.Skyscraper.Scraper.Storage.Utilities;
|
||||||
using skyscraper5.src.InteractionChannel.Model;
|
using skyscraper5.src.InteractionChannel.Model;
|
||||||
|
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;
|
||||||
@ -28,6 +30,8 @@ using System.Net.NetworkInformation;
|
|||||||
using skyscraper5.src.InteractionChannel.Model2;
|
using skyscraper5.src.InteractionChannel.Model2;
|
||||||
using skyscraper8.InteractionChannel.Model;
|
using skyscraper8.InteractionChannel.Model;
|
||||||
using skyscraper8.InteractionChannel.Model2;
|
using skyscraper8.InteractionChannel.Model2;
|
||||||
|
using skyscraper8.InteractionChannel.Model2.Descriptors;
|
||||||
|
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
|
||||||
|
|
||||||
namespace skyscraper8.Skyscraper.Scraper.Storage
|
namespace skyscraper8.Skyscraper.Scraper.Storage
|
||||||
{
|
{
|
||||||
@ -81,6 +85,9 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
|
|||||||
void T2MiSetTimestamp(int currentNetworkId, int currentTransportStreamId, int pid, DateTime resolveTime);
|
void T2MiSetTimestamp(int currentNetworkId, int currentTransportStreamId, int pid, DateTime resolveTime);
|
||||||
bool TestForRelatedContent(EitEvent lEvent, RctLinkInfo rctLinkInfo);
|
bool TestForRelatedContent(EitEvent lEvent, RctLinkInfo rctLinkInfo);
|
||||||
void SetRelatedContent(EitEvent lEvent, RctLinkInfo rctLinkInfo);
|
void SetRelatedContent(EitEvent lEvent, RctLinkInfo rctLinkInfo);
|
||||||
|
List<SatellitePositionEntity> UiSatellitesListAll();
|
||||||
|
void UiSatellitesAdd(SatellitePositionEntity newPosition);
|
||||||
|
void UiSatellitesDelete(SatellitePositionEntity satellitePosition);
|
||||||
bool UiTunerTestFor(TunerMetadata tuner);
|
bool UiTunerTestFor(TunerMetadata tuner);
|
||||||
void UiTunerUpdate(TunerMetadata tuner);
|
void UiTunerUpdate(TunerMetadata tuner);
|
||||||
void UiTunerInsert(TunerMetadata tuner);
|
void UiTunerInsert(TunerMetadata tuner);
|
||||||
@ -100,6 +107,11 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
|
|||||||
bool T2MiTestForTransmitter(int? currentNetworkId, int? currentTransportStreamId, int relatedPid, ushort txIdentifier);
|
bool T2MiTestForTransmitter(int? currentNetworkId, int? currentTransportStreamId, int relatedPid, ushort txIdentifier);
|
||||||
void T2MiRememberTransmitter(int? currentNetworkId, int? currentTransportStreamId, int relatedPid, ushort txIdentifier);
|
void T2MiRememberTransmitter(int? currentNetworkId, int? currentTransportStreamId, int relatedPid, ushort txIdentifier);
|
||||||
void T2MiSetTransmitterTimeOffset(int? currentNetworkId, int? currentTransportStreamId, int relatedPid, ushort txIdentifier, ushort timeOffset);
|
void T2MiSetTransmitterTimeOffset(int? currentNetworkId, int? currentTransportStreamId, int relatedPid, ushort txIdentifier, ushort timeOffset);
|
||||||
|
List<LnbEntity> UiLnbTypesListAll();
|
||||||
|
void UiLnbTypesAdd(LnbEntity defaultLnbType);
|
||||||
|
List<DishEntity> UiDishTypesListAll();
|
||||||
|
void UiDishTypesAdd(DishEntity defaultDishType);
|
||||||
|
|
||||||
IEnumerable<Tuple<int, int, ProgramMapping>> SelectAllPmt();
|
IEnumerable<Tuple<int, int, ProgramMapping>> SelectAllPmt();
|
||||||
SdtService SelectSdtById(int networkId, int tsId, ushort programMappingProgramNumber);
|
SdtService SelectSdtById(int networkId, int tsId, ushort programMappingProgramNumber);
|
||||||
IEnumerable<Tuple<int, int, SdtService>> SelectAllSdt();
|
IEnumerable<Tuple<int, int, SdtService>> SelectAllSdt();
|
||||||
|
|||||||
@ -13,6 +13,7 @@ using skyscraper5.Mpeg2.Descriptors;
|
|||||||
using skyscraper5.Mpeg2.Psi.Model;
|
using skyscraper5.Mpeg2.Psi.Model;
|
||||||
using skyscraper5.Rds.Messages;
|
using skyscraper5.Rds.Messages;
|
||||||
using skyscraper5.Scte35;
|
using skyscraper5.Scte35;
|
||||||
|
using skyscraper5.Skyscraper.Equipment;
|
||||||
using skyscraper5.Skyscraper.Gps;
|
using skyscraper5.Skyscraper.Gps;
|
||||||
using skyscraper5.Skyscraper.Headless;
|
using skyscraper5.Skyscraper.Headless;
|
||||||
using skyscraper5.Skyscraper.IO;
|
using skyscraper5.Skyscraper.IO;
|
||||||
@ -788,6 +789,48 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<SatellitePositionEntity> UiSatellitesListAll()
|
||||||
|
{
|
||||||
|
string path = Path.Combine(rootDirectory.FullName, "satellites.json");
|
||||||
|
FileInfo fi = new FileInfo(path);
|
||||||
|
if (!fi.Exists)
|
||||||
|
return new List<SatellitePositionEntity>();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return JsonConvert.DeserializeObject<List<SatellitePositionEntity>>(File.ReadAllText(fi.FullName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UiSatellitesAdd(SatellitePositionEntity newPosition)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(rootDirectory.FullName, "satellites.json");
|
||||||
|
FileInfo fi = new FileInfo(path);
|
||||||
|
List<SatellitePositionEntity> satellites;
|
||||||
|
if (!fi.Exists)
|
||||||
|
{
|
||||||
|
satellites = new List<SatellitePositionEntity>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
satellites = JsonConvert.DeserializeObject<List<SatellitePositionEntity>>(File.ReadAllText(fi.FullName));
|
||||||
|
}
|
||||||
|
|
||||||
|
satellites.Add(newPosition);
|
||||||
|
EnsureDirectoryExists(fi.Directory);
|
||||||
|
File.WriteAllText(fi.FullName, JsonConvert.SerializeObject(satellites, Formatting.Indented));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UiSatellitesDelete(SatellitePositionEntity satellitePosition)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(rootDirectory.FullName, "satellites.json");
|
||||||
|
FileInfo fi = new FileInfo(path);
|
||||||
|
List<SatellitePositionEntity> satellites = JsonConvert.DeserializeObject<List<SatellitePositionEntity>>(File.ReadAllText(fi.FullName));
|
||||||
|
|
||||||
|
satellites.RemoveAll(x => x.Checksum == satellitePosition.Checksum);
|
||||||
|
|
||||||
|
File.WriteAllText(fi.FullName, JsonConvert.SerializeObject(satellites, Formatting.Indented));
|
||||||
|
}
|
||||||
|
|
||||||
public bool UiTunerTestFor(TunerMetadata tuner)
|
public bool UiTunerTestFor(TunerMetadata tuner)
|
||||||
{
|
{
|
||||||
string fname = BitConverter.ToString(tuner.MacAddress.GetAddressBytes());
|
string fname = BitConverter.ToString(tuner.MacAddress.GetAddressBytes());
|
||||||
@ -892,6 +935,35 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
|||||||
File.WriteAllText(path, timeOffset.ToString());
|
File.WriteAllText(path, timeOffset.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<LnbEntity> UiLnbTypesListAll()
|
||||||
|
{
|
||||||
|
string path = Path.Combine(rootDirectory.FullName, "0-UI", "LnbTypes");
|
||||||
|
DirectoryInfo di = new DirectoryInfo(path);
|
||||||
|
if (!di.Exists)
|
||||||
|
{
|
||||||
|
return new List<LnbEntity>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LnbEntity> result = new List<LnbEntity>();
|
||||||
|
FileInfo[] fileInfos = di.GetFiles("*.json");
|
||||||
|
foreach (FileInfo fileInfo in fileInfos)
|
||||||
|
{
|
||||||
|
string fid = Path.GetFileNameWithoutExtension(fileInfo.Name);
|
||||||
|
if (!fid.IsNaturalNumeric())
|
||||||
|
continue;
|
||||||
|
int iid = int.Parse(fid);
|
||||||
|
|
||||||
|
string json = File.ReadAllText(fileInfo.FullName);
|
||||||
|
LnbEntity deserializeObject = JsonConvert.DeserializeObject<LnbEntity>(json);
|
||||||
|
if (deserializeObject.Id != iid)
|
||||||
|
continue;
|
||||||
|
if (result.Contains(deserializeObject))
|
||||||
|
continue;
|
||||||
|
result.Add(deserializeObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private int GetNextJsonFileNumber(DirectoryInfo di)
|
private int GetNextJsonFileNumber(DirectoryInfo di)
|
||||||
{
|
{
|
||||||
@ -916,6 +988,61 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UiLnbTypesAdd(LnbEntity defaultLnbType)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(rootDirectory.FullName, "0-UI", "LnbTypes");
|
||||||
|
DirectoryInfo di = new DirectoryInfo(path);
|
||||||
|
int fileId = GetNextJsonFileNumber(di);
|
||||||
|
defaultLnbType.Id = fileId;
|
||||||
|
defaultLnbType.DateAdded = DateTime.Now;
|
||||||
|
|
||||||
|
path = Path.Combine(rootDirectory.FullName, "0-UI", "LnbTypes", fileId.ToString() + ".json");
|
||||||
|
string json = JsonConvert.SerializeObject(defaultLnbType, jsonSerializerSettings);
|
||||||
|
File.WriteAllText(path, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DishEntity> UiDishTypesListAll()
|
||||||
|
{
|
||||||
|
string path = Path.Combine(rootDirectory.FullName, "0-UI", "DishTypes");
|
||||||
|
DirectoryInfo di = new DirectoryInfo(path);
|
||||||
|
if (!di.Exists)
|
||||||
|
{
|
||||||
|
return new List<DishEntity>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DishEntity> result = new List<DishEntity>();
|
||||||
|
FileInfo[] fileInfos = di.GetFiles("*.json");
|
||||||
|
foreach (FileInfo fileInfo in fileInfos)
|
||||||
|
{
|
||||||
|
string fid = Path.GetFileNameWithoutExtension(fileInfo.Name);
|
||||||
|
if (!fid.IsNaturalNumeric())
|
||||||
|
continue;
|
||||||
|
int iid = int.Parse(fid);
|
||||||
|
|
||||||
|
string json = File.ReadAllText(fileInfo.FullName);
|
||||||
|
DishEntity deserializeObject = JsonConvert.DeserializeObject<DishEntity>(json);
|
||||||
|
if (deserializeObject.Id != iid)
|
||||||
|
continue;
|
||||||
|
if (result.Contains(deserializeObject))
|
||||||
|
continue;
|
||||||
|
result.Add(deserializeObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UiDishTypesAdd(DishEntity defaultDishType)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(rootDirectory.FullName, "0-UI", "DishTypes");
|
||||||
|
DirectoryInfo di = new DirectoryInfo(path);
|
||||||
|
int fileId = GetNextJsonFileNumber(di);
|
||||||
|
defaultDishType.Id = fileId;
|
||||||
|
defaultDishType.DateAdded = DateTime.Now;
|
||||||
|
|
||||||
|
path = Path.Combine(rootDirectory.FullName, "0-UI", "DishTypes", fileId.ToString() + ".json");
|
||||||
|
string json = JsonConvert.SerializeObject(defaultDishType, jsonSerializerSettings);
|
||||||
|
File.WriteAllText(path, json);
|
||||||
|
}
|
||||||
|
|
||||||
public object[] GetPluginConnector()
|
public object[] GetPluginConnector()
|
||||||
{
|
{
|
||||||
@ -1116,7 +1243,7 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
|||||||
{
|
{
|
||||||
if (jobInDb.DateAdded == DateTime.MinValue)
|
if (jobInDb.DateAdded == DateTime.MinValue)
|
||||||
jobInDb.DateAdded = DateTime.Now;
|
jobInDb.DateAdded = DateTime.Now;
|
||||||
string path = Path.Combine(rootDirectory.FullName, "0-Blindscan",jobInDb.GetFiveLetterOrbitalPosition(), jobInDb.JobGuid.ToString(), "index.json");
|
string path = Path.Combine(rootDirectory.FullName, "0-Blindscan",jobInDb.SatPosition.Checksum.ToString(), jobInDb.JobGuid.ToString(), "index.json");
|
||||||
FileInfo fi = new FileInfo(path);
|
FileInfo fi = new FileInfo(path);
|
||||||
EnsureDirectoryExists(fi.Directory);
|
EnsureDirectoryExists(fi.Directory);
|
||||||
|
|
||||||
@ -1133,7 +1260,7 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
|||||||
SearchResult2 searchResult2)
|
SearchResult2 searchResult2)
|
||||||
{
|
{
|
||||||
string freq = satellite ? String.Format("{0}_{1}", searchResult.Freq, searchResult.Pol) : String.Format("{0}", searchResult2);
|
string freq = satellite ? String.Format("{0}_{1}", searchResult.Freq, searchResult.Pol) : String.Format("{0}", searchResult2);
|
||||||
string path = Path.Combine(rootDirectory.FullName, "0-Blindscan", jobInDb.GetFiveLetterOrbitalPosition(), jobInDb.JobGuid.ToString(), freq + ".json");
|
string path = Path.Combine(rootDirectory.FullName, "0-Blindscan", jobInDb.SatPosition.Checksum.ToString(), jobInDb.JobGuid.ToString(), freq + ".json");
|
||||||
string json = JsonConvert.SerializeObject(satellite ? searchResult : searchResult2, jsonSerializerSettings);
|
string json = JsonConvert.SerializeObject(satellite ? searchResult : searchResult2, jsonSerializerSettings);
|
||||||
File.WriteAllText(path, json);
|
File.WriteAllText(path, json);
|
||||||
}
|
}
|
||||||
@ -1149,7 +1276,7 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
|||||||
{
|
{
|
||||||
string freq = resultSatellite ? String.Format("{0}_{1}", resultSr1.Freq, resultSr1.Pol) : String.Format("{0}", resultSr2);
|
string freq = resultSatellite ? String.Format("{0}_{1}", resultSr1.Freq, resultSr1.Pol) : String.Format("{0}", resultSr2);
|
||||||
string jsonName = String.Format("{0}.json", humanReadableService.ServiceId);
|
string jsonName = String.Format("{0}.json", humanReadableService.ServiceId);
|
||||||
string path = Path.Combine(rootDirectory.FullName, "0-Blindscan", jobInDb.GetFiveLetterOrbitalPosition(), jobInDb.JobGuid.ToString(), freq, jsonName);
|
string path = Path.Combine(rootDirectory.FullName, "0-Blindscan", jobInDb.SatPosition.Checksum.ToString(), jobInDb.JobGuid.ToString(), freq, jsonName);
|
||||||
FileInfo fi = new FileInfo(path);
|
FileInfo fi = new FileInfo(path);
|
||||||
EnsureDirectoryExists(fi.Directory);
|
EnsureDirectoryExists(fi.Directory);
|
||||||
string json = JsonConvert.SerializeObject(humanReadableService, jsonSerializerSettings);
|
string json = JsonConvert.SerializeObject(humanReadableService, jsonSerializerSettings);
|
||||||
|
|||||||
@ -12,6 +12,7 @@ using skyscraper5.Mpeg2.Descriptors;
|
|||||||
using skyscraper5.Mpeg2.Psi.Model;
|
using skyscraper5.Mpeg2.Psi.Model;
|
||||||
using skyscraper5.Rds.Messages;
|
using skyscraper5.Rds.Messages;
|
||||||
using skyscraper5.Scte35;
|
using skyscraper5.Scte35;
|
||||||
|
using skyscraper5.Skyscraper.Equipment;
|
||||||
using skyscraper5.Skyscraper.Gps;
|
using skyscraper5.Skyscraper.Gps;
|
||||||
using skyscraper5.Skyscraper.Headless;
|
using skyscraper5.Skyscraper.Headless;
|
||||||
using skyscraper5.Skyscraper.IO;
|
using skyscraper5.Skyscraper.IO;
|
||||||
@ -770,6 +771,27 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<SatellitePositionEntity> satellitePositions;
|
||||||
|
|
||||||
|
public List<SatellitePositionEntity> UiSatellitesListAll()
|
||||||
|
{
|
||||||
|
if (satellitePositions == null)
|
||||||
|
satellitePositions = new List<SatellitePositionEntity>();
|
||||||
|
return satellitePositions.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UiSatellitesAdd(SatellitePositionEntity newPosition)
|
||||||
|
{
|
||||||
|
if (satellitePositions == null)
|
||||||
|
satellitePositions = new List<SatellitePositionEntity>();
|
||||||
|
satellitePositions.Add(newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UiSatellitesDelete(SatellitePositionEntity satellitePosition)
|
||||||
|
{
|
||||||
|
satellitePositions.RemoveAll(x => x.Checksum == satellitePosition.Checksum);
|
||||||
|
}
|
||||||
|
|
||||||
private List<TunerMetadata> uiTuners;
|
private List<TunerMetadata> uiTuners;
|
||||||
|
|
||||||
public bool UiTunerTestFor(TunerMetadata tuner)
|
public bool UiTunerTestFor(TunerMetadata tuner)
|
||||||
@ -883,6 +905,40 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
|
|||||||
t2miTransmitters[t2miTransmitterId].TimeOffset = timeOffset;
|
t2miTransmitters[t2miTransmitterId].TimeOffset = timeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<LnbEntity> _lnbTypes;
|
||||||
|
|
||||||
|
public List<LnbEntity> UiLnbTypesListAll()
|
||||||
|
{
|
||||||
|
if (_lnbTypes == null)
|
||||||
|
_lnbTypes = new List<LnbEntity>();
|
||||||
|
return _lnbTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UiLnbTypesAdd(LnbEntity defaultLnbType)
|
||||||
|
{
|
||||||
|
if (_lnbTypes == null)
|
||||||
|
_lnbTypes = new List<LnbEntity>();
|
||||||
|
if (!_lnbTypes.Contains(defaultLnbType))
|
||||||
|
_lnbTypes.Add(defaultLnbType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DishEntity> _dishTypes;
|
||||||
|
|
||||||
|
public List<DishEntity> UiDishTypesListAll()
|
||||||
|
{
|
||||||
|
if (_dishTypes == null)
|
||||||
|
_dishTypes = new List<DishEntity>();
|
||||||
|
return _dishTypes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UiDishTypesAdd(DishEntity defaultDishType)
|
||||||
|
{
|
||||||
|
if (_dishTypes == null)
|
||||||
|
_dishTypes = new List<DishEntity>();
|
||||||
|
if (!_dishTypes.Contains(defaultDishType))
|
||||||
|
_dishTypes.Add(defaultDishType);
|
||||||
|
}
|
||||||
|
|
||||||
public object[] GetPluginConnector()
|
public object[] GetPluginConnector()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,112 +0,0 @@
|
|||||||
using log4net;
|
|
||||||
using log4net.Repository.Hierarchy;
|
|
||||||
using skyscraper5.Docsis.MacManagement;
|
|
||||||
using skyscraper5.Skyscraper;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace skyscraper8.Skyscraper
|
|
||||||
{
|
|
||||||
internal class TsRotationToCsv
|
|
||||||
{
|
|
||||||
public DirectoryInfo SourceDir { get; set; }
|
|
||||||
public FileInfo DestinationCsv { get; set; }
|
|
||||||
|
|
||||||
private List<FileInfo> files;
|
|
||||||
private ILog logger;
|
|
||||||
public void Run()
|
|
||||||
{
|
|
||||||
logger = LogManager.GetLogger(typeof(TsRotationToCsv));
|
|
||||||
files = new List<FileInfo>();
|
|
||||||
ScrapeDirectory(SourceDir);
|
|
||||||
files.Sort(new FileInfoComparerByDate(logger));
|
|
||||||
DumpCsv();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DumpCsv()
|
|
||||||
{
|
|
||||||
StreamWriter sw = new StreamWriter(DestinationCsv.FullName);
|
|
||||||
foreach (FileInfo file in files)
|
|
||||||
{
|
|
||||||
sw.WriteLine(String.Format("\"{0}\";{1};{2}", file.FullName, file.Length, file.LastWriteTime));
|
|
||||||
}
|
|
||||||
sw.Flush();
|
|
||||||
sw.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ScrapeDirectory(DirectoryInfo di)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (FileSystemInfo fsi in di.GetFileSystemInfos())
|
|
||||||
{
|
|
||||||
switch (fsi)
|
|
||||||
{
|
|
||||||
case FileInfo fi:
|
|
||||||
if (fi.Extension.ToLowerInvariant().Equals(".ts"))
|
|
||||||
{
|
|
||||||
files.Add(fi);
|
|
||||||
if (files.Count % 100 == 0)
|
|
||||||
logger.InfoFormat("Listed {0} files.", files.Count);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DirectoryInfo subdirectory:
|
|
||||||
ScrapeDirectory(subdirectory);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException(di.GetType().Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
logger.WarnFormat(e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FileInfoComparerByDate : Comparer<FileInfo>
|
|
||||||
{
|
|
||||||
private ILog logger;
|
|
||||||
private int ups, downs, stands;
|
|
||||||
|
|
||||||
public FileInfoComparerByDate(ILog logger)
|
|
||||||
{
|
|
||||||
this.logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Compare(FileInfo? x, FileInfo? y)
|
|
||||||
{
|
|
||||||
long xTime = x.LastWriteTime.ToUnixTime();
|
|
||||||
long yTime = y.LastWriteTime.ToUnixTime();
|
|
||||||
|
|
||||||
int ops;
|
|
||||||
int v = xTime.CompareTo(yTime);
|
|
||||||
switch(v)
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
ups++;
|
|
||||||
ops = ups;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
stands++;
|
|
||||||
ops = stands;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
downs++;
|
|
||||||
ops = downs;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException(v.ToString());
|
|
||||||
}
|
|
||||||
if (ops % 1000 == 0)
|
|
||||||
{
|
|
||||||
logger.InfoFormat("Sort progress: {0} up, {1} down, {2} stand.", ups, downs, stands);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user