Rewrote the complete blindscanning engine.
This commit is contained in:
parent
1d7c9c3807
commit
03d827df44
@ -168,7 +168,62 @@ namespace skyscraper5.Data.PostgreSql
|
||||
return new object[] { pluginToken };
|
||||
}
|
||||
|
||||
|
||||
public void InsertUiBlindscanSettingHistory(int settingsWindowBlScanTunerSelection,
|
||||
bool settingsWindowUseDifferentTunerForSetFilter, int settingsWindowSetFilterTunerSelection,
|
||||
int settingsWindowDiseqc, bool settingsWindowCollectIqGraphs, bool settingsWindowCollectRfSpectrum,
|
||||
bool settingsWindowCaptureFile, int settingsWindowSatellite, int settingsWindowLnb, int dish,
|
||||
bool settingsWindowScanHorizontalLow, bool settingsWindowScanHorizontalHigh, bool settingsWindowScanVerticalLow,
|
||||
bool settingsWindowScanVerticalHigh)
|
||||
{
|
||||
using (NpgsqlConnection connection = new NpgsqlConnection(connectionStringBuilder.ToString()))
|
||||
{
|
||||
connection.Open();
|
||||
NpgsqlCommand command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
"INSERT INTO ui_blindscan_setting_history VALUES (DEFAULT,@bstselection,@ustfsfilter,@sftselection,@diseqc,@cigraphs,@crspectrum,@cfilters,@satellite,@lnb,@dish,@hl,@hh,@vl,@vh);";
|
||||
command.Parameters.AddWithValue("@bstselection", NpgsqlDbType.Integer, settingsWindowBlScanTunerSelection);
|
||||
command.Parameters.AddWithValue("@ustfsfilter", NpgsqlDbType.Boolean, settingsWindowUseDifferentTunerForSetFilter);
|
||||
command.Parameters.AddWithValue("@sftselection", NpgsqlDbType.Integer, settingsWindowSetFilterTunerSelection);
|
||||
command.Parameters.AddWithValue("@diseqc", NpgsqlDbType.Integer, settingsWindowDiseqc);
|
||||
command.Parameters.AddWithValue("@cigraphs", NpgsqlDbType.Boolean, settingsWindowCollectIqGraphs);
|
||||
command.Parameters.AddWithValue("@crspectrum", NpgsqlDbType.Boolean, settingsWindowCollectRfSpectrum);
|
||||
command.Parameters.AddWithValue("@cfilters", NpgsqlDbType.Boolean, settingsWindowCaptureFile);
|
||||
command.Parameters.AddWithValue("@satellite", NpgsqlDbType.Integer, settingsWindowSatellite);
|
||||
command.Parameters.AddWithValue("@lnb", NpgsqlDbType.Integer, settingsWindowLnb);
|
||||
command.Parameters.AddWithValue("@dish", NpgsqlDbType.Integer, dish);
|
||||
command.Parameters.AddWithValue("@hl", NpgsqlDbType.Boolean, settingsWindowScanHorizontalLow);
|
||||
command.Parameters.AddWithValue("@hh", NpgsqlDbType.Boolean, settingsWindowScanHorizontalHigh);
|
||||
command.Parameters.AddWithValue("@vl", NpgsqlDbType.Boolean, settingsWindowScanVerticalLow);
|
||||
command.Parameters.AddWithValue("@vh", NpgsqlDbType.Boolean, settingsWindowScanVerticalHigh);
|
||||
command.ExecuteNonQuery();
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public object[] GetLastUiBlindscanSettings()
|
||||
{
|
||||
using (NpgsqlConnection connection = new NpgsqlConnection(connectionStringBuilder.ToString()))
|
||||
{
|
||||
connection.Open();
|
||||
NpgsqlCommand command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT * FROM ui_blindscan_setting_history WHERE dateadded = (SELECT MAX(dateadded) FROM ui_blindscan_setting_history)";
|
||||
NpgsqlDataReader dataReader = command.ExecuteReader();
|
||||
object[] result = null;
|
||||
if (dataReader.Read())
|
||||
{
|
||||
int fields = dataReader.FieldCount;
|
||||
result = new object[fields];
|
||||
for (int i = 0; i < fields; i++)
|
||||
{
|
||||
result[i] = dataReader.GetValue(i);
|
||||
}
|
||||
}
|
||||
dataReader.Close();
|
||||
command.Dispose();
|
||||
connection.Close();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SDL2Demo.Jobs;
|
||||
using skyscraper8.Skyscraper.FrequencyListGenerator;
|
||||
using static SDL2Demo.Jobs.Blindscan;
|
||||
|
||||
namespace SDL2Demo.Forms
|
||||
@ -98,6 +100,19 @@ namespace SDL2Demo.Forms
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(BlindscanSearchResult searchResult, int polarityIndex, int lnbTypeMinimumFrequency, int i)
|
||||
{
|
||||
if (searchResult.IsSatellite())
|
||||
_blindscanResults.Add(new Blindscan.BlindscanResult(searchResult.SearchResult, lnbTypeMinimumFrequency, i));
|
||||
else
|
||||
_blindscanResults.Add(new BlindscanResult(searchResult.SearchResult2, lnbTypeMinimumFrequency, i));
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_blindscanResults.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
93
GUIs/skyscraper8.UI.ImGui/Forms/FoundFrequenciesWindow2.cs
Normal file
93
GUIs/skyscraper8.UI.ImGui/Forms/FoundFrequenciesWindow2.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using SDL2Demo;
|
||||
using skyscraper8.Skyscraper.FrequencyListGenerator;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ImGuiNET;
|
||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||
|
||||
namespace SDL2Demo
|
||||
{
|
||||
internal class FoundFrequenciesWindow2 : IRenderable
|
||||
{
|
||||
private readonly List<BlindscanSearchResult> _foundFrequencies;
|
||||
public bool doNotAutoZap;
|
||||
public bool allowZapNow;
|
||||
public bool zapNowRequested;
|
||||
private string tableUuid;
|
||||
public long statusPacketsInTotal;
|
||||
public long statusPacketsInQueue;
|
||||
|
||||
public FoundFrequenciesWindow2(List<BlindscanSearchResult> foundFrequencies)
|
||||
{
|
||||
_foundFrequencies = foundFrequencies;
|
||||
tableUuid = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
if (_foundFrequencies.Count == 0)
|
||||
return;
|
||||
|
||||
if (ImGui.Begin("Blind-Scan Results"))
|
||||
{
|
||||
ImGui.Checkbox("Do not Auto-Zap", ref doNotAutoZap);
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginDisabled(!allowZapNow);
|
||||
if (ImGui.Button("Zap now"))
|
||||
{
|
||||
zapNowRequested = true;
|
||||
}
|
||||
ImGui.EndDisabled();
|
||||
|
||||
if (allowZapNow)
|
||||
{
|
||||
ImGui.Text(String.Format("{0} packets received in total, {1} queued.", statusPacketsInTotal, statusPacketsInQueue));
|
||||
}
|
||||
|
||||
if (ImGui.BeginTable(tableUuid, 5,
|
||||
ImGuiTableFlags.NoSavedSettings | ImGuiTableFlags.SizingFixedFit))
|
||||
{
|
||||
for (int i = 0; i < _foundFrequencies.Count; i++)
|
||||
{
|
||||
BlindscanSearchResult blindscanResult = _foundFrequencies[i];
|
||||
ImGui.TableNextRow();
|
||||
if (blindscanResult.IsSatellite())
|
||||
{
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.Text(String.Format("{0} {1} ", blindscanResult.SearchResult.Freq / 1000,
|
||||
blindscanResult.SearchResult.Pol == 0 ? "H" : "V"));
|
||||
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
ImGui.Text((blindscanResult.SearchResult.SR / 1000).ToString());
|
||||
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
ImGui.Text(((MOD_TYPE)blindscanResult.SearchResult.ModType).ToString());
|
||||
|
||||
ImGui.TableSetColumnIndex(3);
|
||||
ImGui.Text((blindscanResult.SearchResult.MIS + 1).ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.Text((blindscanResult.SearchResult.Freq / 1000).ToString());
|
||||
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
ImGui.Text((blindscanResult.SearchResult.SR / 10).ToString());
|
||||
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
ImGui.Text(((MOD_TYPE)blindscanResult.SearchResult.ModType).ToString());
|
||||
}
|
||||
|
||||
ImGui.TableSetColumnIndex(4);
|
||||
ImGui.Text(blindscanResult.State.ToString());
|
||||
}
|
||||
ImGui.EndTable();
|
||||
}
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -21,10 +21,14 @@ using skyscraper5.Mpeg2;
|
||||
using skyscraper5.Mpeg2.Descriptors;
|
||||
using skyscraper5.Mpeg2.Psi.Model;
|
||||
using skyscraper5.Scte35;
|
||||
using skyscraper5.Skyscraper.Equipment;
|
||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||
using skyscraper5.Skyscraper.Net;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
|
||||
using skyscraper5.Teletext.Wss;
|
||||
using skyscraper8.Skyscraper.Drawing;
|
||||
using skyscraper8.Skyscraper.FrequencyListGenerator;
|
||||
using testdrid.SdlWrapper;
|
||||
|
||||
namespace SDL2Demo.Forms
|
||||
@ -2060,6 +2064,126 @@ namespace SDL2Demo.Forms
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void OnBlindscanOpenFoundFrquenciesWindow(List<BlindscanSearchResult> foundFrequencies, STD_TYPE tunerMetadataType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanJobDone(bool success)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanErrorMessage(string blindscanningLowHorizontalAreaFailed)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanBandComplete()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanBeforeBLScan(int minimum, int currentProgress, int maximum)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanAfterBLScan()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanSearchResult1Callback(BlindscanSearchResult searchResult, int polarityIndex,
|
||||
int lnbTypeMinimumFrequency, int lnbTypeMaximumFrequency)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanBeforeSetChannel(BlindscanSearchResult blindscanResult,LnbType lnbType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnScrapeBandComplete()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanScrapeTransponderComplete(BlindscanSearchResult blindscanResult)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanBeginRfSpectrum()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanRfSpectrumEnqueueSample(SatelliteDeliverySystemDescriptor.PolarizationEnum polarization, int frequency, double rf)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanEndRfSpectrum()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanBeginIqSpectrum(IqChartData result)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanEndIq()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanLockFail(SearchResult satelliteSr, BlindscanResultState resultState)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanFilterSetUp()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanScrapeStopCondition()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanAfterPacketDrain()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanPacketError(int errorCount, int length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnBlindscanPacketOk(int numPackets, int packetsQueueCount)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsZapNowRequested()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool MayAutoZap()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TaskQueue Tasks { get; set; }
|
||||
|
||||
private ushort? ResolveCaId(ProgramMapping patValuePmt, SdtCoordinate sdt)
|
||||
{
|
||||
if (patValuePmt != null)
|
||||
@ -2082,8 +2206,6 @@ namespace SDL2Demo.Forms
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||
using Echo.UserInterface.Backend;
|
||||
using ImGuiNET;
|
||||
using SDL2;
|
||||
using skyscraper8.Skyscraper.FrequencyListGenerator;
|
||||
using testdrid.SdlWrapper;
|
||||
|
||||
namespace SDL2Demo.Forms
|
||||
@ -60,12 +61,22 @@ namespace SDL2Demo.Forms
|
||||
ImGui.End();
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private bool disposed;
|
||||
public void Dispose()
|
||||
{
|
||||
_texture.Dispose();
|
||||
_surface.Dispose();
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
tasks.EnqueueTask(() =>
|
||||
{
|
||||
renderables.Remove(this);
|
||||
_texture.Dispose();
|
||||
_surface.Dispose();
|
||||
});
|
||||
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
internal static Renderer Renderer { get; set; }
|
||||
@ -75,5 +86,13 @@ namespace SDL2Demo.Forms
|
||||
position.X = x;
|
||||
position.Y = y;
|
||||
}
|
||||
|
||||
private TaskQueue tasks;
|
||||
private List<IRenderable> renderables;
|
||||
public void SetTaskQueue(TaskQueue tasks, List<IRenderable> jobContextRenderables)
|
||||
{
|
||||
this.tasks = tasks;
|
||||
this.renderables = jobContextRenderables;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,6 +59,7 @@ namespace skyscraper8.UI.ImGui.Forms
|
||||
_plot.Dispose();
|
||||
_skBitmap.Dispose();
|
||||
_skCanvas.Dispose();
|
||||
_texture.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,7 +314,7 @@ namespace SDL2Demo.Jobs
|
||||
public BlindscanResult(SearchResult searchResult, int satPositionMinFreq, int satPositionMaxFreq)
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
|
||||
|
||||
if (searchResult.Pol == 0)
|
||||
{
|
||||
//Horizontal
|
||||
|
||||
247
GUIs/skyscraper8.UI.ImGui/Jobs/InheritedBlindscanConfigWindow.cs
Normal file
247
GUIs/skyscraper8.UI.ImGui/Jobs/InheritedBlindscanConfigWindow.cs
Normal file
@ -0,0 +1,247 @@
|
||||
using ImGuiNET;
|
||||
using skyscraper5.Skyscraper;
|
||||
using skyscraper5.Skyscraper.Equipment;
|
||||
using skyscraper5.Skyscraper.Gps;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
using skyscraper8.Skyscraper.FrequencyListGenerator;
|
||||
using skyscraper8.Skyscraper.Scraper.Storage;
|
||||
using skyscraper8.UI.SDL2.Jobs;
|
||||
|
||||
namespace SDL2Demo.Jobs
|
||||
{
|
||||
internal class InheritedBlindscanConfigWindow : IRenderable
|
||||
{
|
||||
private bool windowOpen;
|
||||
private List<TunerMetadata> tuners;
|
||||
private List<SatellitePosition> satellites;
|
||||
private List<LnbType> lnbs;
|
||||
private List<DishType> dishes;
|
||||
private readonly TaskQueue _taskQueue;
|
||||
|
||||
public int settingsWindowBLScanTunerSelection;
|
||||
public bool settingsWindowUseDifferentTunerForSetFilter;
|
||||
public int settingsWindowSetFilterTunerSelection;
|
||||
public int settingsWindowDiseqc;
|
||||
public bool settingsWindowCollectIqGraphs;
|
||||
public bool settingsWindowCollectRfSpectrum;
|
||||
public bool settingsWindowCaptureFile;
|
||||
public int settingsWindowSatellite;
|
||||
public int settingsWindowLNB;
|
||||
public int settingsWindowDish;
|
||||
|
||||
public bool settingsWindowScanHorizontalLow;
|
||||
public bool settingsWindowScanHorizontalHigh;
|
||||
public bool settingsWindowScanVerticalLow;
|
||||
public bool settingsWindowScanVerticalHigh;
|
||||
|
||||
private DataStorage dataStorage;
|
||||
private ObjectStorage objectStorage;
|
||||
private IGpsReceiver gpsReceiver;
|
||||
private Ini ini;
|
||||
private IStreamReader streamReader;
|
||||
|
||||
private void StoreSettings()
|
||||
{
|
||||
dataStorage.InsertUiBlindscanSettingHistory(settingsWindowBLScanTunerSelection,
|
||||
settingsWindowUseDifferentTunerForSetFilter, settingsWindowSetFilterTunerSelection,
|
||||
settingsWindowDiseqc, settingsWindowCollectIqGraphs,
|
||||
settingsWindowCollectRfSpectrum, settingsWindowCaptureFile, settingsWindowSatellite, settingsWindowLNB,
|
||||
settingsWindowDish, settingsWindowScanHorizontalLow, settingsWindowScanHorizontalHigh,
|
||||
settingsWindowScanVerticalLow, settingsWindowScanVerticalHigh);
|
||||
}
|
||||
public InheritedBlindscanConfigWindow(List<TunerMetadata> tunerMetadatas,
|
||||
List<SatellitePosition> satellitePositions, List<LnbType> lnbTypes, List<DishType> dishTypes,
|
||||
DataStorage dataStorage, ObjectStorage objectStorage, IGpsReceiver gps, Ini ini, IStreamReader streamReader,
|
||||
TaskQueue taskQueue)
|
||||
{
|
||||
tuners = tunerMetadatas;
|
||||
satellites = satellitePositions;
|
||||
lnbs = lnbTypes;
|
||||
dishes = dishTypes;
|
||||
windowOpen = true;
|
||||
settingsWindowDiseqc = 1;
|
||||
this.dataStorage = dataStorage;
|
||||
this.objectStorage = objectStorage;
|
||||
this.gpsReceiver = gps;
|
||||
this.ini = ini;
|
||||
this.streamReader = streamReader;
|
||||
_taskQueue = taskQueue;
|
||||
|
||||
object[] previousSettings = dataStorage.GetLastUiBlindscanSettings();
|
||||
if (previousSettings != null)
|
||||
{
|
||||
settingsWindowBLScanTunerSelection = (int)previousSettings[1];
|
||||
settingsWindowUseDifferentTunerForSetFilter = (bool)previousSettings[2];
|
||||
settingsWindowSetFilterTunerSelection = (int)previousSettings[3];
|
||||
settingsWindowDiseqc = (int)previousSettings[4];
|
||||
settingsWindowCollectIqGraphs = (bool)previousSettings[5];
|
||||
settingsWindowCollectRfSpectrum = (bool)previousSettings[6];
|
||||
settingsWindowCaptureFile = (bool)previousSettings[7];
|
||||
settingsWindowSatellite = (int)previousSettings[8];
|
||||
settingsWindowLNB = (int)previousSettings[9];
|
||||
settingsWindowDish = (int)previousSettings[10];
|
||||
|
||||
settingsWindowScanHorizontalLow = (bool)previousSettings[11];
|
||||
settingsWindowScanHorizontalHigh = (bool)previousSettings[12];
|
||||
settingsWindowScanVerticalLow = (bool)previousSettings[13];
|
||||
settingsWindowScanVerticalHigh = (bool)previousSettings[14];
|
||||
}
|
||||
}
|
||||
public bool IsWindowOpen()
|
||||
{
|
||||
return windowOpen;
|
||||
}
|
||||
public BlindscanJobConfiguration GetConfiguration()
|
||||
{
|
||||
if (!okButtonClicked)
|
||||
return null;
|
||||
|
||||
BlindscanJobConfiguration bjc = new BlindscanJobConfiguration();
|
||||
bjc.DataStorage = dataStorage;
|
||||
bjc.DiseqcIndex = settingsWindowDiseqc;
|
||||
bjc.DoHorizontalLow = settingsWindowScanHorizontalLow;
|
||||
bjc.DoHorizontalHigh = settingsWindowScanHorizontalHigh;
|
||||
bjc.DoVerticalLow = settingsWindowScanVerticalLow;
|
||||
bjc.DoVerticalHigh = settingsWindowScanHorizontalHigh;
|
||||
bjc.DoCollectIqGraphs = settingsWindowCollectIqGraphs;
|
||||
bjc.DoCollectRfSpectrum = settingsWindowCollectRfSpectrum;
|
||||
bjc.DoRecordTs = settingsWindowCaptureFile;
|
||||
bjc.Gps = gpsReceiver;
|
||||
bjc.Ini = ini;
|
||||
bjc.LnbType = lnbs[settingsWindowLNB];
|
||||
bjc.ObjectStorage = objectStorage;
|
||||
bjc.SatellitePosition = satellites[settingsWindowSatellite];
|
||||
|
||||
if (settingsWindowUseDifferentTunerForSetFilter)
|
||||
bjc.StreamReader = new CoopBlindscanStreamReader(streamReader, settingsWindowBLScanTunerSelection, settingsWindowSetFilterTunerSelection);
|
||||
else
|
||||
bjc.StreamReader = streamReader;
|
||||
|
||||
bjc.TunerMetadata = tuners[settingsWindowBLScanTunerSelection];
|
||||
bjc.Ui = new InheritedBlindscanUiJunction();
|
||||
bjc.Ui.Tasks = _taskQueue;
|
||||
return bjc;
|
||||
}
|
||||
|
||||
private bool okButtonClicked;
|
||||
public void Render()
|
||||
{
|
||||
if (ImGui.Begin("Blindscan", ref windowOpen, ImGuiWindowFlags.AlwaysAutoResize))
|
||||
{
|
||||
ImGui.PushID("tunerA");
|
||||
if (ImGui.BeginCombo("Tuner for BLScanEx and RFScan", tuners[settingsWindowBLScanTunerSelection].Name))
|
||||
{
|
||||
for (int i = 0; i < tuners.Count; i++)
|
||||
{
|
||||
bool isSelected = settingsWindowBLScanTunerSelection == i;
|
||||
if (ImGui.Selectable(tuners[i].Name, isSelected))
|
||||
{
|
||||
settingsWindowBLScanTunerSelection = i;
|
||||
}
|
||||
}
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
ImGui.PopID();
|
||||
|
||||
if (tuners[settingsWindowBLScanTunerSelection].IsSatellite())
|
||||
{
|
||||
ImGui.Checkbox("Use different Tuner for IQScan and SetFilter", ref settingsWindowUseDifferentTunerForSetFilter);
|
||||
|
||||
if (settingsWindowUseDifferentTunerForSetFilter)
|
||||
{
|
||||
ImGui.Text("This assumes that both tuners are connected to the same antenna set-up, using e.g. a splitter.");
|
||||
|
||||
ImGui.PushID("tunerB");
|
||||
if (ImGui.BeginCombo("Tuner for BLScanEx and RFScan", tuners[settingsWindowSetFilterTunerSelection].Name))
|
||||
{
|
||||
for (int i = 0; i < tuners.Count; i++)
|
||||
{
|
||||
bool isSelected = settingsWindowSetFilterTunerSelection == i;
|
||||
if (ImGui.Selectable(tuners[i].Name, isSelected))
|
||||
{
|
||||
settingsWindowSetFilterTunerSelection = i;
|
||||
}
|
||||
}
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
ImGui.Text("DiSEqC");
|
||||
ImGui.SameLine();
|
||||
ImGui.RadioButton("A", ref settingsWindowDiseqc, 1);
|
||||
ImGui.SameLine();
|
||||
ImGui.RadioButton("B", ref settingsWindowDiseqc, 2);
|
||||
ImGui.SameLine();
|
||||
ImGui.RadioButton("C", ref settingsWindowDiseqc, 3);
|
||||
ImGui.SameLine();
|
||||
ImGui.RadioButton("D", ref settingsWindowDiseqc, 4);
|
||||
|
||||
|
||||
if (ImGui.BeginCombo("Target Satellite", satellites[settingsWindowSatellite].name))
|
||||
{
|
||||
for (int i = 0; i < satellites.Count; i++)
|
||||
{
|
||||
bool isSelected = settingsWindowSatellite == i;
|
||||
if (ImGui.Selectable(satellites[i].name, isSelected))
|
||||
{
|
||||
settingsWindowSatellite = i;
|
||||
}
|
||||
}
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui.BeginCombo("LNB", lnbs[settingsWindowLNB].Name))
|
||||
{
|
||||
for (int i = 0; i < lnbs.Count; i++)
|
||||
{
|
||||
bool isSelected = settingsWindowLNB == i;
|
||||
if (ImGui.Selectable(lnbs[i].Name, isSelected))
|
||||
{
|
||||
settingsWindowLNB = i;
|
||||
}
|
||||
}
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui.BeginCombo("Dish", dishes[settingsWindowDish].Name))
|
||||
{
|
||||
for (int i = 0; i < dishes.Count; i++)
|
||||
{
|
||||
bool isSelected = settingsWindowDish == i;
|
||||
if (ImGui.Selectable(dishes[i].Name, isSelected))
|
||||
{
|
||||
settingsWindowDish = i;
|
||||
}
|
||||
}
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
if (lnbs[settingsWindowLNB].LofSw != 0)
|
||||
{
|
||||
ImGui.Checkbox("Scan Horizontal Low Band", ref settingsWindowScanHorizontalLow);
|
||||
ImGui.Checkbox("Scan Horizontal High Band", ref settingsWindowScanHorizontalHigh);
|
||||
ImGui.Checkbox("Scan Vertical Low Band", ref settingsWindowScanVerticalLow);
|
||||
ImGui.Checkbox("Scan Vertical High Band", ref settingsWindowScanVerticalHigh);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.Checkbox("Scan Left circular Band", ref settingsWindowScanHorizontalLow);
|
||||
ImGui.Checkbox("Scan Right circular Band", ref settingsWindowScanVerticalLow);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.Checkbox("Capture Packets to files", ref settingsWindowCaptureFile);
|
||||
ImGui.Checkbox("Collect IQ Graphs", ref settingsWindowCollectIqGraphs);
|
||||
ImGui.Checkbox("Collect RF Spectrum", ref settingsWindowCollectRfSpectrum);
|
||||
|
||||
if (ImGui.Button("OK"))
|
||||
{
|
||||
windowOpen = false;
|
||||
okButtonClicked = true;
|
||||
StoreSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
43
GUIs/skyscraper8.UI.ImGui/Jobs/InheritedBlindscanJob.cs
Normal file
43
GUIs/skyscraper8.UI.ImGui/Jobs/InheritedBlindscanJob.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SDL2Demo;
|
||||
using SDL2Demo.Jobs;
|
||||
using skyscraper8.Skyscraper.FrequencyListGenerator;
|
||||
|
||||
namespace skyscraper8.UI.SDL2.Jobs
|
||||
{
|
||||
internal class InheritedBlindscanJob : IJob
|
||||
{
|
||||
private readonly BlindscanJobConfiguration _jobConfiguration;
|
||||
|
||||
public InheritedBlindscanJob(BlindscanJobConfiguration jobConfiguration)
|
||||
{
|
||||
_jobConfiguration = jobConfiguration;
|
||||
}
|
||||
|
||||
private BaseBlindscanJob baseBlindscanJob;
|
||||
public void Run()
|
||||
{
|
||||
if (JobContext == null)
|
||||
{
|
||||
throw new NullReferenceException(nameof(JobContext));
|
||||
}
|
||||
|
||||
InheritedBlindscanUiJunction inherited = (InheritedBlindscanUiJunction)_jobConfiguration.Ui;
|
||||
inherited.jobContext = JobContext;
|
||||
|
||||
baseBlindscanJob = new BaseBlindscanJob(_jobConfiguration);
|
||||
baseBlindscanJob.Run();
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public JobContext JobContext { get; set; }
|
||||
}
|
||||
}
|
||||
1786
GUIs/skyscraper8.UI.ImGui/Jobs/InheritedBlindscanUiJunction.cs
Normal file
1786
GUIs/skyscraper8.UI.ImGui/Jobs/InheritedBlindscanUiJunction.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -23,9 +23,11 @@ using skyscraper5.Skyscraper.Scraper.Storage;
|
||||
using skyscraper5.Skyscraper.Scraper.Storage.Filesystem;
|
||||
using skyscraper5.Skyscraper.Scraper.Storage.InMemory;
|
||||
using skyscraper5.src.Skyscraper;
|
||||
using skyscraper8.Skyscraper.FrequencyListGenerator;
|
||||
using skyscraper8.Skyscraper.Plugins;
|
||||
using skyscraper8.Skyscraper.Scraper.Storage;
|
||||
using skyscraper8.UI.ImGui.Forms;
|
||||
using skyscraper8.UI.SDL2.Jobs;
|
||||
using Color = ScottPlot.Color;
|
||||
using Exception = System.Exception;
|
||||
using Version = System.Version;
|
||||
@ -201,6 +203,7 @@ namespace SkyscraperUI
|
||||
private DataStorage dataStorage;
|
||||
private ObjectStorage objectStorage;
|
||||
private IGpsReceiver gps;
|
||||
private TaskQueue tasks;
|
||||
|
||||
|
||||
private List<MessageWindow> messageWindows;
|
||||
@ -223,6 +226,7 @@ namespace SkyscraperUI
|
||||
private ConfigureGpsWindow configureGpsWindow;
|
||||
private GpsDisplay gpsDisplayWindow;
|
||||
private BlindscanJobDeleter jobDeleter;
|
||||
private InheritedBlindscanConfigWindow inheritedBlindscanWindow;
|
||||
|
||||
private ScreenHack[] allScreenHacks;
|
||||
private ScreenHack currentScreenHack;
|
||||
@ -243,7 +247,11 @@ namespace SkyscraperUI
|
||||
|
||||
|
||||
private void BeforeRenderFrame()
|
||||
{
|
||||
{
|
||||
if (tasks == null)
|
||||
tasks = new TaskQueue();
|
||||
tasks.ProcessTasks();
|
||||
|
||||
if (jobContext != null)
|
||||
{
|
||||
if (jobContext.MessageQueue.Count != 0)
|
||||
@ -473,6 +481,8 @@ namespace SkyscraperUI
|
||||
blindscanWindow = new Blindscan(tuners, satellitePositions, lnbTypes, dataStorage);
|
||||
if (ImGui.MenuItem("Perform Cooperative Blindscan", CanPerformBlindscan()))
|
||||
coopBlindscanWindow = new CoopBlindscan(tuners, satellitePositions, lnbTypes, dataStorage);
|
||||
if (ImGui.MenuItem("Perform inherited Blindscan", CanPerformBlindscan()))
|
||||
inheritedBlindscanWindow = new InheritedBlindscanConfigWindow(tuners, satellitePositions, lnbTypes, dishTypes, dataStorage, objectStorage, gps, ini, streamReader, tasks);
|
||||
if (ImGui.MenuItem("Cancel current job", CanCancelJob()))
|
||||
jobContext.Job.Cancel();
|
||||
if (ImGui.MenuItem("Quit"))
|
||||
@ -722,15 +732,32 @@ namespace SkyscraperUI
|
||||
|
||||
if (coopBlindscanWindow != null)
|
||||
{
|
||||
coopBlindscanWindow.Render();
|
||||
if (!coopBlindscanWindow.WindowOpen)
|
||||
coopBlindscanWindow.Render();
|
||||
if (!coopBlindscanWindow.WindowOpen)
|
||||
{
|
||||
if (coopBlindscanWindow.Configuration != null)
|
||||
{
|
||||
EnrollJob(coopBlindscanWindow);
|
||||
}
|
||||
|
||||
coopBlindscanWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (inheritedBlindscanWindow != null)
|
||||
{
|
||||
inheritedBlindscanWindow.Render();
|
||||
if (!inheritedBlindscanWindow.IsWindowOpen())
|
||||
{
|
||||
if (coopBlindscanWindow.Configuration != null)
|
||||
{
|
||||
EnrollJob(coopBlindscanWindow);
|
||||
}
|
||||
coopBlindscanWindow = null;
|
||||
BlindscanJobConfiguration jobConfiguration = inheritedBlindscanWindow.GetConfiguration();
|
||||
if (jobConfiguration != null)
|
||||
{
|
||||
InheritedBlindscanJob inheritedBlindscanJob = new InheritedBlindscanJob(jobConfiguration);
|
||||
EnrollJob(inheritedBlindscanJob);
|
||||
inheritedBlindscanWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (aboutWindow != null)
|
||||
|
||||
@ -38,6 +38,7 @@ namespace skyscraper5
|
||||
private static void IntegrationTest()
|
||||
{
|
||||
RtspClient rtspClient = new RtspClient("172.20.20.121", 554);
|
||||
rtspClient.AutoReconnect = true;
|
||||
RtspOptionsResponse options = rtspClient.GetOptions("/");
|
||||
string url = RtspClient.MakeUrl(DiSEqC_Opcode.DISEQC_OPTION_A | DiSEqC_Opcode.DISEQC_POSITION_A | DiSEqC_Opcode.DISEQC_HORIZONTAL, 11954, true, 27500);
|
||||
RtspDescribeResponse describe = rtspClient.GetDescribe(url);
|
||||
@ -59,6 +60,31 @@ namespace skyscraper5
|
||||
rtspClient.GetTeardown(setup);
|
||||
Console.WriteLine("{0} RTCPs",rtcps);
|
||||
Console.WriteLine("{0} RTPs",rtps);
|
||||
|
||||
Thread.Sleep(1000);
|
||||
|
||||
url = RtspClient.MakeUrl(DiSEqC_Opcode.DISEQC_OPTION_A | DiSEqC_Opcode.DISEQC_POSITION_A | DiSEqC_Opcode.DISEQC_VERTICAL, 10758, true, 22000);
|
||||
describe = rtspClient.GetDescribe(url);
|
||||
sessionDescriptionProtocol = describe.GetSessionDescriptionProtocol();
|
||||
|
||||
rtcps = 0;
|
||||
rtps = 0;
|
||||
|
||||
setup = rtspClient.GetSetup(url);
|
||||
setup.OnRtcpPacket += ((data, length) =>
|
||||
rtcps++);
|
||||
setup.OnRtpPacket += (data, length) =>
|
||||
rtps++;
|
||||
|
||||
play = rtspClient.GetPlay(setup);
|
||||
|
||||
Thread.Sleep(5000);
|
||||
|
||||
rtspClient.AutoReconnect = false;
|
||||
rtspClient.GetTeardown(setup);
|
||||
Console.WriteLine("{0} RTCPs", rtcps);
|
||||
Console.WriteLine("{0} RTPs", rtps);
|
||||
rtspClient.Dispose();
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
@ -212,13 +238,7 @@ namespace skyscraper5
|
||||
GpsManager.GpsTest();
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[0].ToLowerInvariant().Equals("mk-cable-csv"))
|
||||
{
|
||||
new CableFrequencyListGenerator().Run();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (args[0].ToLowerInvariant().Equals("what-can-i-receive"))
|
||||
{
|
||||
WhatCanIReceive.StandaloneProgram();
|
||||
@ -247,27 +267,7 @@ namespace skyscraper5
|
||||
}
|
||||
passing.Run();
|
||||
}
|
||||
|
||||
private static void StreamReaderTest(IStreamReader streamReader)
|
||||
{
|
||||
List<StreamReaderScanController.StreamReaderTuner> streamReaderTuners = StreamReaderScanController.GetTuners(streamReader);
|
||||
if (streamReaderTuners.Count == 0)
|
||||
{
|
||||
Console.WriteLine("No tuners, lmao.");
|
||||
return;
|
||||
}
|
||||
|
||||
//FileInfo fi = new FileInfo("blindscan.json");
|
||||
StreamReaderScanController srsc = new StreamReaderScanController(streamReader, streamReaderTuners[0]);
|
||||
//srsc.SetDefaultDvbCParameters();
|
||||
srsc.SetDefaultKuBandParameters();
|
||||
srsc.SetParameter(StreamReaderScanController.StreamReaderParameter.ScanDiseqcType, 2);
|
||||
srsc.SetParameter(StreamReaderScanController.StreamReaderParameter.DiseqcSwitchPosition, 1);
|
||||
srsc.RunBlindscan();
|
||||
srsc.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
private static void ProcessDirectory(DirectoryInfo di)
|
||||
{
|
||||
DataStorage dataStorage = new InMemoryScraperStorage();
|
||||
|
||||
@ -1,168 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using skyscraper5.Dvb.Psi.Model;
|
||||
using skyscraper5.Mpeg2.Psi.Model;
|
||||
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 skyscraper5.Skyscraper.Scraper.Storage.InMemory;
|
||||
using skyscraper8.Skyscraper.Scraper.Storage;
|
||||
using Console = System.Console;
|
||||
|
||||
namespace skyscraper5.Skyscraper
|
||||
{
|
||||
internal class CableFrequencyListGenerator
|
||||
{
|
||||
public CableFrequencyListGenerator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
Ini ini = PluginManager.GetInstance().Ini;
|
||||
TunerFactoryConnectionManager tunerFactoryConnectionManager = TunerFactoryConnectionManager.GetInstance();
|
||||
ITunerFactory tunerFactory = tunerFactoryConnectionManager.AutoGetConfiguredTunerFactory();
|
||||
IStreamReader streamReader = tunerFactory.CreateStreamReader();
|
||||
int usableTuner = -1;
|
||||
if (!streamReader.CheckForDVBExEx((x, y, z) =>
|
||||
{
|
||||
if (usableTuner == -1 && z == STD_TYPE.STD_DVBC)
|
||||
usableTuner = x;
|
||||
}))
|
||||
{
|
||||
Console.WriteLine("Failed to check for tuners.");
|
||||
return;
|
||||
}
|
||||
if (usableTuner == -1)
|
||||
{
|
||||
Console.WriteLine("no dvb-c tuner present, quitting.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!streamReader.StartDvbEx(usableTuner))
|
||||
{
|
||||
Console.WriteLine("Failed to start the tuner.");
|
||||
streamReader.StopDVB();
|
||||
if (!streamReader.StartDvbEx(usableTuner))
|
||||
{
|
||||
Console.WriteLine("Giving up...");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IntPtr pSearchResult = Marshal.AllocHGlobal(ushort.MaxValue);
|
||||
int tpNum = 0;
|
||||
SearchResult2 sr2 = default;
|
||||
if (!streamReader.AirScan(48000, 1000000, 3000, 8000, (int)STD_TYPE.STD_DVBC, pSearchResult, ref tpNum, (ref SearchResult2 searchResult) => SearchResult2Callback(searchResult)))
|
||||
{
|
||||
Console.WriteLine("Failed to run AirScan...");
|
||||
return;
|
||||
}
|
||||
|
||||
string filename = String.Format("dvb-c_{0}.csv", DateTime.Now.ToUnixTime());
|
||||
FileStream fileStream = File.OpenWrite(filename);
|
||||
StreamWriter streamWriter = new StreamWriter(fileStream);
|
||||
|
||||
foreach (SearchResult2 searchResult2 in searchResults)
|
||||
{
|
||||
double outFreq = searchResult2.Freq;
|
||||
outFreq = Math.Round((double)outFreq / (double)1000.0, 0) * 1000;
|
||||
outFreq /= 1000;
|
||||
|
||||
Console.WriteLine("Tuning to {0} Mhz", outFreq);
|
||||
if (!streamReader.SetChannel2((uint)searchResult2.Freq, (uint)searchResult2.BW))
|
||||
{
|
||||
Console.WriteLine("Failed to tune.");
|
||||
continue;
|
||||
}
|
||||
|
||||
SearchResult2 recheck = default;
|
||||
if (!streamReader.SignalInfo2(ref recheck))
|
||||
{
|
||||
Console.WriteLine("Failed to get signal info.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!recheck.Lock)
|
||||
{
|
||||
Console.WriteLine("No lock.");
|
||||
continue;
|
||||
}
|
||||
|
||||
double outSymRate = searchResult2.SR;
|
||||
outSymRate = Math.Round((double)outSymRate / (double)10000.0, 0) * 10000;
|
||||
outSymRate /= 1000;
|
||||
string outModType = ((MOD_TYPE)searchResult2.ModType).ToString();
|
||||
string outLine = String.Format("{0} Mhz;{1} kSym/s;{2}", outFreq, outSymRate, outModType);
|
||||
streamWriter.WriteLine(outLine);
|
||||
|
||||
StreamReaderScraperController scraper = new StreamReaderScraperController(streamReader);
|
||||
scraper.DataStorage = new InMemoryScraperStorage();
|
||||
scraper.Recording = false;
|
||||
Console.Write("Running PSI acquisition...");
|
||||
scraper.Run();
|
||||
Console.WriteLine(".DONE");
|
||||
|
||||
DataStorage data = scraper.DataStorage;
|
||||
IEnumerable<Tuple<int, int, ProgramMapping>> pmtEntries = data.SelectAllPmt().ToList();
|
||||
List<Tuple<int, int, SdtService>> tuples = data.SelectAllSdt().ToList();
|
||||
foreach (var (tsId, networkId, programMapping) in pmtEntries)
|
||||
{
|
||||
SdtService sdt = data.SelectSdtById(networkId, tsId, programMapping.ProgramNumber);
|
||||
if (sdt == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
outLine = String.Format("{0};{1};{2};{3};{4}", programMapping.ProgramNumber,sdt.ServiceProviderName,sdt.ServiceName,GetCaSystemName(programMapping,sdt),sdt.ServiceType);
|
||||
streamWriter.WriteLine(outLine);
|
||||
streamWriter.Flush();
|
||||
}
|
||||
streamWriter.WriteLine("");
|
||||
|
||||
}
|
||||
|
||||
if (!streamReader.StopDVB())
|
||||
{
|
||||
Console.WriteLine("Failed to properly close the tuner!");
|
||||
return;
|
||||
}
|
||||
streamWriter.Flush();
|
||||
streamWriter.Close();
|
||||
}
|
||||
|
||||
private string GetCaSystemName(ProgramMapping pmt, SdtService sdt)
|
||||
{
|
||||
if (pmt.CaSystemId.HasValue)
|
||||
{
|
||||
return CaSystemNames.GetHumanReadableName(pmt.CaSystemId.Value);
|
||||
}
|
||||
|
||||
if (sdt.CaIdentifiers != null)
|
||||
{
|
||||
if (sdt.CaIdentifiers.Length > 0)
|
||||
{
|
||||
return CaSystemNames.GetHumanReadableName(sdt.CaIdentifiers[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private List<SearchResult2> searchResults;
|
||||
private void SearchResult2Callback(SearchResult2 searchResult)
|
||||
{
|
||||
if (searchResults == null)
|
||||
searchResults = new List<SearchResult2>();
|
||||
searchResults.Add(searchResult);
|
||||
Console.WriteLine("Heard something at {0}", searchResult.Freq / 1000);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,904 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
|
||||
using skyscraper8.Skyscraper.Plugins;
|
||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||
using skyscraper8.Skyscraper.Drawing;
|
||||
using skyscraper5.Dvb.Descriptors;
|
||||
using skyscraper5.src.Mpeg2.PacketFilter;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using System.Runtime.InteropServices;
|
||||
using skyscraper5.Skyscraper.Equipment;
|
||||
|
||||
namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
||||
{
|
||||
public class BaseBlindscanJob
|
||||
{
|
||||
private static PluginLogger logger = PluginLogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public BaseBlindscanJob(BlindscanJobConfiguration config)
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(config));
|
||||
}
|
||||
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
private BlindscanJobConfiguration config;
|
||||
private DbBlindscanJob jobInDb;
|
||||
private List<BlindscanSearchResult> foundFrequencies;
|
||||
|
||||
public void Run()
|
||||
{
|
||||
if (config == null)
|
||||
throw new NullReferenceException("No config? Dude, what?");
|
||||
if (config.StreamReader == null)
|
||||
throw new NullReferenceException("No StreamReader available");
|
||||
|
||||
|
||||
jobInDb = new DbBlindscanJob(Guid.NewGuid(), config.TunerMetadata.MacAddress, config.TunerMetadata.Type, config.DiseqcIndex, config.Gps, config.SatellitePosition);
|
||||
jobInDb.HorizontalHighState = config.DoHorizontalHigh ? DbBlindscanJobPolarizationStatus.SELECTED_WAITING : DbBlindscanJobPolarizationStatus.NOT_SELECTED;
|
||||
jobInDb.HorizontalLowState = config.DoHorizontalLow ? DbBlindscanJobPolarizationStatus.SELECTED_WAITING : DbBlindscanJobPolarizationStatus.NOT_SELECTED;
|
||||
jobInDb.VerticalLowState = config.DoVerticalLow ? DbBlindscanJobPolarizationStatus.SELECTED_WAITING : DbBlindscanJobPolarizationStatus.NOT_SELECTED;
|
||||
jobInDb.VerticalHighState = config.DoVerticalHigh ? DbBlindscanJobPolarizationStatus.SELECTED_WAITING : DbBlindscanJobPolarizationStatus.NOT_SELECTED;
|
||||
config.DataStorage.InsertBlindscanJob(jobInDb);
|
||||
|
||||
foundFrequencies = new List<BlindscanSearchResult>();
|
||||
config.Ui.OnBlindscanOpenFoundFrquenciesWindow(foundFrequencies, config.TunerMetadata.Type);
|
||||
|
||||
if (!config.StreamReader.StartDvbEx(config.TunerMetadata.Index))
|
||||
{
|
||||
throw new Exception("Failed to start DVB");
|
||||
}
|
||||
if (!RunBlindscan())
|
||||
{
|
||||
config.StreamReader.StopDVB();
|
||||
config.Ui.OnBlindscanJobDone(false);
|
||||
return;
|
||||
}
|
||||
|
||||
config.Ui.OnBlindscanJobDone(true);
|
||||
logger.Log(PluginLogLevel.Info,"Blindscan Job done!");
|
||||
return;
|
||||
}
|
||||
|
||||
public bool RunBlindscan()
|
||||
{
|
||||
Caps caps = config.TunerMetadata.Caps;
|
||||
|
||||
if (config.DoCollectRfSpectrum)
|
||||
{
|
||||
RfSpectrumData rfSpectrum = GatherRfSpectrum();
|
||||
if (rfSpectrum != null)
|
||||
{
|
||||
config.ObjectStorage.StoreRfSpectrum(jobInDb.JobGuid, rfSpectrum);
|
||||
}
|
||||
}
|
||||
if (caps.HasFlag(Caps.SR_BLSCAN2))
|
||||
{
|
||||
SearchResult sr1 = default;
|
||||
int tpNum = default;
|
||||
|
||||
int lof1 = config.LnbType.Lof1 * 1000;
|
||||
int lof2 = config.LnbType.Lof2 * 1000;
|
||||
int lofSw = config.LnbType.LofSw * 1000;
|
||||
int diseqc = config.TunerMetadata.DiseqcType;
|
||||
int startFreq = config.LnbType.MinimumFrequency * 1000;
|
||||
int endFreq = config.LnbType.MaximumFrequency * 1000;
|
||||
bool anythingSuceeded = false;
|
||||
nint allocHGlobal = Marshal.AllocHGlobal(ushort.MaxValue);
|
||||
|
||||
if (lofSw != 0)
|
||||
{
|
||||
if (config.DoHorizontalLow)
|
||||
{
|
||||
if (SendDiseqcCommand(false, true))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info,"Scanning low horizontal band...");
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_BLINDSCANNING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
bool hLower = BlScan2Wrap(startFreq, lofSw, 0, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult sr1) => SearchResult1Callback(sr1, 1));
|
||||
config.Ui.OnBlindscanBandComplete();
|
||||
if (!hLower)
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("Blindscanning low horizontal area failed.");
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
else
|
||||
{
|
||||
anythingSuceeded = true;
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_SCRAPING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
SendDiseqcCommand(false, true);
|
||||
RunScrape();
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_DONE;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
foundFrequencies.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("DiSEqC Switch to low horizontal area failed.");
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED_DISEQC;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.DoHorizontalHigh)
|
||||
{
|
||||
if (SendDiseqcCommand(true, true))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info,"Scanning high horizontal band...");
|
||||
jobInDb.HorizontalHighState = DbBlindscanJobPolarizationStatus.SELECTED_BLINDSCANNING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
bool hUpper = BlScan2Wrap(lofSw, endFreq, 0, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult sr1) => SearchResult1Callback(sr1, 2));
|
||||
config.Ui.OnBlindscanBandComplete();
|
||||
if (!hUpper)
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("Blindscanning high horizontal area failed.");
|
||||
jobInDb.HorizontalHighState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
else
|
||||
{
|
||||
anythingSuceeded = true;
|
||||
jobInDb.HorizontalHighState = DbBlindscanJobPolarizationStatus.SELECTED_SCRAPING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
SendDiseqcCommand(true, true);
|
||||
RunScrape();
|
||||
jobInDb.HorizontalHighState = DbBlindscanJobPolarizationStatus.SELECTED_DONE;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
foundFrequencies.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("DiSEqC Switch to high horizontal area failed.");
|
||||
jobInDb.HorizontalHighState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED_DISEQC;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.DoVerticalLow)
|
||||
{
|
||||
if (SendDiseqcCommand(false, false))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info,"Scanning low vertical band...");
|
||||
jobInDb.VerticalLowState = DbBlindscanJobPolarizationStatus.SELECTED_BLINDSCANNING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
bool vLower = BlScan2Wrap(startFreq, lofSw, 1, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult sr1) => SearchResult1Callback(sr1, 3));
|
||||
config.Ui.OnBlindscanBandComplete();
|
||||
if (!vLower)
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("Blindscanning low vertical area failed.");
|
||||
jobInDb.VerticalLowState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
else
|
||||
{
|
||||
anythingSuceeded = true;
|
||||
jobInDb.VerticalLowState = DbBlindscanJobPolarizationStatus.SELECTED_SCRAPING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
SendDiseqcCommand(false, false);
|
||||
RunScrape();
|
||||
jobInDb.VerticalLowState = DbBlindscanJobPolarizationStatus.SELECTED_DONE;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
foundFrequencies.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("DiSEqC Switch to low vertical area failed.");
|
||||
jobInDb.VerticalLowState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED_DISEQC;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.DoVerticalHigh)
|
||||
{
|
||||
if (SendDiseqcCommand(true, false))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info,"Scanning high vertical band...");
|
||||
jobInDb.VerticalHighState = DbBlindscanJobPolarizationStatus.SELECTED_BLINDSCANNING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
bool vUpper = BlScan2Wrap(lofSw, endFreq, 1, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult sr1) => SearchResult1Callback(sr1, 4));
|
||||
config.Ui.OnBlindscanBandComplete();
|
||||
if (!vUpper)
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("Blindscanning high vertical area failed.");
|
||||
jobInDb.VerticalHighState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
else
|
||||
{
|
||||
anythingSuceeded = true;
|
||||
jobInDb.VerticalHighState = DbBlindscanJobPolarizationStatus.SELECTED_SCRAPING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
SendDiseqcCommand(true, false);
|
||||
RunScrape();
|
||||
jobInDb.VerticalHighState = DbBlindscanJobPolarizationStatus.SELECTED_DONE;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
foundFrequencies.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("DiSEqC Switch to high vertical area failed.");
|
||||
jobInDb.VerticalHighState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED_DISEQC;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SendDiseqcCommand(false, true))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Scanning left circular band..."));
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_BLINDSCANNING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
bool lCirc = BlScan2Wrap(startFreq, endFreq, 0, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult sr1) => SearchResult1Callback(sr1, 1));
|
||||
config.Ui.OnBlindscanBandComplete();
|
||||
if (!lCirc)
|
||||
{
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
config.Ui.OnBlindscanErrorMessage("Blindscanning left circular area failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
anythingSuceeded = true;
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_SCRAPING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
SendDiseqcCommand(false, true);
|
||||
RunScrape();
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_DONE;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
foundFrequencies.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("DiSEqC Switch to left circulation failed.");
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED_DISEQC;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
if (SendDiseqcCommand(false, false))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Scanning right circular band..."));
|
||||
jobInDb.VerticalLowState = DbBlindscanJobPolarizationStatus.SELECTED_BLINDSCANNING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
bool rCirc = BlScan2Wrap(startFreq, endFreq, 1, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult sr1) => SearchResult1Callback(sr1, 3));
|
||||
config.Ui.OnBlindscanBandComplete();
|
||||
if (!rCirc)
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("Blindscanning right circular area failed.");
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_FAILED;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
else
|
||||
{
|
||||
anythingSuceeded = true;
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_SCRAPING;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
SendDiseqcCommand(false, false);
|
||||
RunScrape();
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_DONE;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
foundFrequencies.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
config.Ui.OnBlindscanErrorMessage("DiSEqC Switch to right circulation failed.");
|
||||
jobInDb.HorizontalLowState = DbBlindscanJobPolarizationStatus.SELECTED_DONE;
|
||||
config.DataStorage.UpdateJobState(jobInDb);
|
||||
}
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(allocHGlobal);
|
||||
return anythingSuceeded;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("Don't know how to blindscan with this tuner.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool BlScan2Wrap(int freq_start, int freq_stop, int pol, int lof1, int lof2, int lofSw, nint pSearchResult, ref int pTpNum, BlScanCallback lpFunc)
|
||||
{
|
||||
config.Ui.OnBlindscanBeforeBLScan(freq_start, freq_start, freq_stop);
|
||||
|
||||
bool result = config.StreamReader.BLScan2(freq_start, freq_stop, pol, lof1, lof2, lofSw, pSearchResult, ref pTpNum, lpFunc);
|
||||
|
||||
config.Ui.OnBlindscanAfterBLScan();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool SendDiseqcCommand(bool highBand, bool horizontal)
|
||||
{
|
||||
DiSEqC_Opcode myOpcode = DiSEqC_Opcode.DISEQC_HIGH_NIBBLE;
|
||||
if (highBand)
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_HIGH_BAND;
|
||||
else
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_LOW_BAND;
|
||||
|
||||
if (horizontal)
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_HORIZONTAL;
|
||||
else
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_VERTICAL;
|
||||
|
||||
int parameter = config.DiseqcIndex;
|
||||
switch (parameter)
|
||||
{
|
||||
case 1:
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
||||
break;
|
||||
case 2:
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
||||
break;
|
||||
case 3:
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
||||
break;
|
||||
case 4:
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("DiSEqC Switch Position");
|
||||
}
|
||||
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Send DiSEqC Command {0:X2}", (byte)myOpcode), 8);
|
||||
|
||||
DateTime started = DateTime.Now;
|
||||
bool result = config.StreamReader.SendDiSEqC(2, myOpcode);
|
||||
TimeSpan timeTaken = DateTime.Now - started;
|
||||
logger.Log(PluginLogLevel.Debug, string.Format("DiSEqC Comannd sent in {0:F1} seconds.", timeTaken.TotalSeconds));
|
||||
if (timeTaken.TotalSeconds > 10)
|
||||
{
|
||||
logger.Log(PluginLogLevel.Warn, string.Format("Something went wrong while performing the DiSEqC operation, trying again..."), 8);
|
||||
Thread.Sleep(1000);
|
||||
return SendDiseqcCommand(highBand, horizontal);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SearchResult1Callback(SearchResult searchResult, int polarityIndex)
|
||||
{
|
||||
BlindscanSearchResult blindscanSearchResult = new BlindscanSearchResult();
|
||||
blindscanSearchResult.SearchResult = searchResult;
|
||||
blindscanSearchResult.Standard = (STD_TYPE)searchResult.StdType;
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Found frequency: {0}, {1}", searchResult.Freq / 1000, searchResult.Pol == 0 ? "H" : "V"));
|
||||
lock (foundFrequencies)
|
||||
{
|
||||
foundFrequencies.Add(blindscanSearchResult);
|
||||
}
|
||||
config.DataStorage.InsertSearchResult(jobInDb, true, searchResult, polarityIndex, new SearchResult2());
|
||||
config.Ui.OnBlindscanSearchResult1Callback(blindscanSearchResult, polarityIndex, config.LnbType.MinimumFrequency, config.LnbType.MaximumFrequency);
|
||||
}
|
||||
|
||||
|
||||
public void RunScrape()
|
||||
{
|
||||
int lof1 = config.LnbType.Lof1 * 1000;
|
||||
int lof2 = config.LnbType.Lof2 * 1000;
|
||||
int lofSw = config.LnbType.LofSw * 1000;
|
||||
|
||||
|
||||
foreach (BlindscanSearchResult blindscanResult in foundFrequencies)
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
blindscanResult.State = BlindscanResultState.Tuning;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, blindscanResult.IsSatellite(), blindscanResult.SearchResult, blindscanResult.State, blindscanResult.SearchResult2);
|
||||
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);
|
||||
if (!channel)
|
||||
{
|
||||
blindscanResult.State = BlindscanResultState.TuningFailed;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, blindscanResult.IsSatellite(), blindscanResult.SearchResult, blindscanResult.State, blindscanResult.SearchResult2);
|
||||
continue;
|
||||
}
|
||||
|
||||
RunSkyscraper(blindscanResult);
|
||||
config.Ui.OnBlindscanScrapeTransponderComplete(blindscanResult);
|
||||
}
|
||||
|
||||
config.Ui.OnScrapeBandComplete();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private RfSpectrumData GatherRfSpectrum()
|
||||
{
|
||||
Caps caps = config.TunerMetadata.Caps;
|
||||
if (caps.HasFlag(Caps.SR_RFSCAN2))
|
||||
{
|
||||
return GatherRfSpectrumCable();
|
||||
}
|
||||
else if (!caps.HasFlag(Caps.SR_RFSCAN))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Error, "Couldn't figure out whether to use RFScan or RFScan2!");
|
||||
return null;
|
||||
}
|
||||
|
||||
config.Ui.OnBlindscanBeginRfSpectrum();
|
||||
|
||||
int lof1 = config.LnbType.Lof1 * 1000;
|
||||
int lof2 = config.LnbType.Lof2 * 1000;
|
||||
int lofSw = config.LnbType.LofSw * 1000;
|
||||
int startFreq = config.LnbType.MinimumFrequency * 1000;
|
||||
int endFreq = config.LnbType.MaximumFrequency * 1000;
|
||||
|
||||
RfSpectrumData spectrumData = RfSpectrumData.Create();
|
||||
|
||||
void RunRfScan(RfSpectrumData spectrum, int startFreq, int endFreq, SatelliteDeliverySystemDescriptor.PolarizationEnum polarization, DiSEqC_Opcode diseqcCmd, int lof1, int lof2, int lofSw)
|
||||
{
|
||||
const int STEP = 1000;
|
||||
config.StreamReader.SendDiSEqC(2, diseqcCmd);
|
||||
RfSpectrumDataBlock block = spectrumData.CreateBlock(startFreq, endFreq, STEP, polarization);
|
||||
for (int i = startFreq; i <= endFreq; i += STEP)
|
||||
{
|
||||
double rf = double.NaN;
|
||||
config.StreamReader.RFScan(i, diseqcCmd.HasFlag(DiSEqC_Opcode.DISEQC_HORIZONTAL) ? 0 : 1, lof1, lof2, lofSw, out rf);
|
||||
logger.Log(PluginLogLevel.Debug,"{0} {1}, {2}", i, polarization.ToString().Substring(0, 1), rf);
|
||||
block.Push(i, rf);
|
||||
config.Ui.OnBlindscanRfSpectrumEnqueueSample(polarization, i, rf);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (DiSEqC_Opcode opcode in GetIqGraphDiseqcOpcodes())
|
||||
{
|
||||
RunRfScan(spectrumData, startFreq, endFreq,
|
||||
opcode.HasFlag(DiSEqC_Opcode.DISEQC_HORIZONTAL) ? SatelliteDeliverySystemDescriptor.PolarizationEnum.HorizontalLinear : SatelliteDeliverySystemDescriptor.PolarizationEnum.VerticalLinear,
|
||||
opcode, lof1, lof2, lofSw);
|
||||
}
|
||||
|
||||
config.Ui.OnBlindscanEndRfSpectrum();
|
||||
|
||||
return spectrumData;
|
||||
}
|
||||
|
||||
private RfSpectrumData GatherRfSpectrumCable()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private IEnumerable<DiSEqC_Opcode> GetIqGraphDiseqcOpcodes()
|
||||
{
|
||||
DiSEqC_Opcode baseDiseqc = DiSEqC_Opcode.DISEQC_HIGH_NIBBLE;
|
||||
|
||||
int parameter = config.DiseqcIndex;
|
||||
switch (parameter)
|
||||
{
|
||||
case 1:
|
||||
baseDiseqc |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
||||
baseDiseqc |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
||||
break;
|
||||
case 2:
|
||||
baseDiseqc |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
||||
baseDiseqc |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
||||
break;
|
||||
case 3:
|
||||
baseDiseqc |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
||||
baseDiseqc |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
||||
break;
|
||||
case 4:
|
||||
baseDiseqc |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
||||
baseDiseqc |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("DiSEqC Switch Position");
|
||||
}
|
||||
|
||||
if (config.DoHorizontalLow || config.DoHorizontalHigh)
|
||||
yield return baseDiseqc | DiSEqC_Opcode.DISEQC_HORIZONTAL | DiSEqC_Opcode.DISEQC_LOW_BAND;
|
||||
if (config.DoVerticalLow || config.DoVerticalHigh)
|
||||
yield return baseDiseqc | DiSEqC_Opcode.DISEQC_VERTICAL | DiSEqC_Opcode.DISEQC_LOW_BAND;
|
||||
yield break;
|
||||
}
|
||||
private IqChartData GatherIqGraph()
|
||||
{
|
||||
Caps caps = config.TunerMetadata.Caps;
|
||||
if (caps.HasFlag(Caps.SR_IQSCAN2))
|
||||
{
|
||||
return GatherIQGraphCable();
|
||||
|
||||
}
|
||||
else if (!caps.HasFlag(Caps.SR_IQSCAN))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Error, "Couldn't figure out whether to use IQScan or IQScan2!");
|
||||
return null;
|
||||
}
|
||||
|
||||
IqChartData result = IqChartData.Create();
|
||||
config.Ui.OnBlindscanBeginIqSpectrum(result);
|
||||
|
||||
|
||||
sbyte[] buffer = new sbyte[400];
|
||||
DateTime started = DateTime.Now;
|
||||
while (!result.IsComplete)
|
||||
{
|
||||
bool iqScan = config.StreamReader.IQScan(0, buffer, (uint)(buffer.Length / 2));
|
||||
if (!iqScan)
|
||||
{
|
||||
result = null;
|
||||
logger.Log(PluginLogLevel.Error, "IQScan failed");
|
||||
break;
|
||||
}
|
||||
result.PushPacket(buffer);
|
||||
}
|
||||
TimeSpan finished = DateTime.Now - started;
|
||||
logger.Log(PluginLogLevel.Debug, "Finished IQ acquisiton in {0} ({1} samples per call)", finished.ToString(), buffer.Length / 2);
|
||||
|
||||
config.Ui.OnBlindscanEndIq();
|
||||
|
||||
return result;
|
||||
}
|
||||
private IqChartData GatherIQGraphCable()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void RunSkyscraper(BlindscanSearchResult result)
|
||||
{
|
||||
int misCounter = 1;
|
||||
bool misMode = false;
|
||||
bool cableTvMode = false;
|
||||
Caps caps = config.TunerMetadata.Caps;
|
||||
SearchResult satelliteSr = new SearchResult();
|
||||
SearchResult2 cableSr = new SearchResult2();
|
||||
|
||||
if (caps.HasFlag(Caps.SR_SIGINFO))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Trying to BLScanEx..."), 8);
|
||||
if (!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))
|
||||
{
|
||||
//No blindscan? No problem! Try anyway!
|
||||
satelliteSr = result.SearchResult;
|
||||
satelliteSr.Lock = false;
|
||||
result.State = BlindscanResultState.BlScanFailure;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
}
|
||||
|
||||
if (!satelliteSr.Lock)
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Trying to SetChannel..."), 8);
|
||||
bool channel = config.StreamReader.SetChannel(result.SearchResult.Freq, result.SearchResult.SR, result.SearchResult.Freq, result.SearchResult.FEC, config.LnbType.Lof1 * 1000, config.LnbType.Lof2 * 1000, config.LnbType.LofSw * 1000);
|
||||
if (!channel)
|
||||
{
|
||||
result.State = BlindscanResultState.TuningFailed;
|
||||
config.Ui.OnBlindscanLockFail(satelliteSr, result.State);
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Trying to get SignalInfo..."), 8);
|
||||
bool signalInfo = config.StreamReader.SignalInfo(ref satelliteSr);
|
||||
if (!signalInfo)
|
||||
{
|
||||
result.State = BlindscanResultState.TuningFailed;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
config.Ui.OnBlindscanLockFail(satelliteSr, result.State);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!satelliteSr.Lock)
|
||||
{
|
||||
result.State = BlindscanResultState.NoLock;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
config.Ui.OnBlindscanLockFail(satelliteSr, result.State);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (caps.HasFlag(Caps.SR_MISSEL))
|
||||
{
|
||||
if (satelliteSr.MIS > 16)
|
||||
satelliteSr.MIS = 1;
|
||||
|
||||
if (satelliteSr.MIS == 0)
|
||||
satelliteSr.MIS = 1;
|
||||
|
||||
if (satelliteSr.MIS != 1)
|
||||
misMode = true;
|
||||
|
||||
misCounter = satelliteSr.MIS;
|
||||
}
|
||||
}
|
||||
else if (caps.HasFlag(Caps.SR_SIGINFO2))
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Trying to SetChannel2..."), 8);
|
||||
bool channel2 = config.StreamReader.SetChannel2((uint)result.SearchResult2.Freq, (uint)result.SearchResult2.BW);
|
||||
if (!channel2)
|
||||
{
|
||||
result.State = BlindscanResultState.TuningFailed;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
config.Ui.OnBlindscanLockFail(result.SearchResult, result.State);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Trying to get SignalInfo2..."), 8);
|
||||
bool signalInfo2 = config.StreamReader.SignalInfo2(ref cableSr);
|
||||
if (!signalInfo2)
|
||||
{
|
||||
result.State = BlindscanResultState.TuningFailed;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
config.Ui.OnBlindscanLockFail(result.SearchResult, result.State);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cableSr.Lock)
|
||||
{
|
||||
result.State = BlindscanResultState.NoLock;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
config.Ui.OnBlindscanLockFail(result.SearchResult, result.State);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("Couldn't figure out what signal info to use.");
|
||||
}
|
||||
|
||||
if (config.DoCollectIqGraphs)
|
||||
{
|
||||
result.State = BlindscanResultState.IqCollecting;
|
||||
IqChartData plot = GatherIqGraph();
|
||||
if (plot != null)
|
||||
{
|
||||
result.State = BlindscanResultState.IqSaving;
|
||||
config.ObjectStorage.StoreIqGraph(jobInDb.JobGuid, result.GetFrequency(), result.GetPolarity(config.LnbType.LofSw), plot);
|
||||
}
|
||||
}
|
||||
|
||||
for (int mis = 0; mis < misCounter; mis++)
|
||||
{
|
||||
if (misMode)
|
||||
{
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Selecting MIS IS {0}", satelliteSr.IS[mis]), 8);
|
||||
bool misSel = config.StreamReader.MISSel(misMode, satelliteSr.IS[mis], 0xff);
|
||||
if (!misSel)
|
||||
{
|
||||
result.State = BlindscanResultState.MisFailure;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
config.Ui.OnBlindscanLockFail(result.SearchResult, result.State);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Start Filter
|
||||
TsRecorder tsRecorder = null;
|
||||
if (config.DoRecordTs)
|
||||
{
|
||||
tsRecorder = new TsRecorder();
|
||||
tsRecorder.Recording = true;
|
||||
string outputDirName = config.Ini.ReadValue("recording", "output_dir", "recording_output");
|
||||
tsRecorder.RecordingOutputDirectory = new DirectoryInfo(outputDirName);
|
||||
tsRecorder.RecordingOutputDirectory.EnsureExists();
|
||||
if (tsRecorder.PrepareRecording())
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
string recordingFilename = string.Format(
|
||||
"skyscraper_{0:D4}{1:D2}{2:D2}_{3:D2}{4:D2}_{8:D4}{9}_{5}_{6}_{7}.ts",
|
||||
now.Year, now.Month, now.Day, now.Hour, now.Minute, result.GetFrequency() / 1000,
|
||||
result.GetPolarity(config.LnbType.LofSw), result.GetSymbolRate() / 1000,
|
||||
(int)(config.SatellitePosition.angle * 10),
|
||||
config.SatellitePosition.cardinalDirection == 0 ? "E" : "W");
|
||||
tsRecorder.SetNextFilename(recordingFilename);
|
||||
tsRecorder.CreateBufferedStream();
|
||||
}
|
||||
}
|
||||
|
||||
nint filterReference = nint.MaxValue;
|
||||
logger.Log(PluginLogLevel.Info, string.Format("Set-Up filter..."), 8);
|
||||
packetsQueue = new Queue<byte[]>();
|
||||
|
||||
bool filter = config.StreamReader.SetFilter(8192, DvbCallback, 0x02, 2, ref filterReference);
|
||||
if (!filter)
|
||||
{
|
||||
result.State = BlindscanResultState.FilterFailure;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
config.Ui.OnBlindscanLockFail(result.SearchResult, result.State);
|
||||
return;
|
||||
}
|
||||
logger.Log(PluginLogLevel.Debug, string.Format("Filter set-up complete!"), 8);
|
||||
|
||||
//Use the Filter
|
||||
result.State = BlindscanResultState.Scraping;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
config.Ui.OnBlindscanFilterSetUp();
|
||||
|
||||
SkipFilter skipper = new SkipFilter(SkipFilter.CRAZYSCAN_BUFFER * 8);
|
||||
skyscraperContext = SkyscraperContextFactory.CreateSkyscraper(config.DataStorage, config.ObjectStorage);
|
||||
skyscraperContext.TcpProxyEnabled = true;
|
||||
skyscraperContext.UiJunction = config.Ui;
|
||||
IPacketFilter[] packetFilters = new IPacketFilter[0];
|
||||
if (tsRecorder != null)
|
||||
packetFilters = new IPacketFilter[] { tsRecorder, skipper };
|
||||
skyscraperContext.InitalizeFilterChain(packetFilters);
|
||||
|
||||
|
||||
byte[] singlePacketBuffer = new byte[188];
|
||||
packetsReceivedInTotal = 0;
|
||||
startedAt = DateTime.Now;
|
||||
|
||||
//The actual scraping happens in this loop
|
||||
while (!StopConditionMet())
|
||||
{
|
||||
if (!HasPackets())
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] packetBuffer = null;
|
||||
lock (packetsQueue)
|
||||
{
|
||||
packetBuffer = packetsQueue.Dequeue();
|
||||
}
|
||||
|
||||
for (int i = 0; i < packetBuffer.Length; i += 188)
|
||||
{
|
||||
Array.Copy(packetBuffer, i, singlePacketBuffer, 0, 188);
|
||||
skyscraperContext.IngestSinglePacket(singlePacketBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
config.Ui.OnBlindscanScrapeStopCondition();
|
||||
//Stop Filter
|
||||
logger.Log(PluginLogLevel.Debug, string.Format("Deleting Filter..."), 8);
|
||||
bool stopped = config.StreamReader.DelFilter(filterReference);
|
||||
if (!stopped)
|
||||
{
|
||||
result.State = BlindscanResultState.DelFilterFailed;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
return;
|
||||
}
|
||||
logger.Log(PluginLogLevel.Debug, string.Format("Deleted filter!"), 8);
|
||||
DrainPackets();
|
||||
skyscraperContext.Dispose();
|
||||
|
||||
if (tsRecorder != null)
|
||||
tsRecorder.Dispose();
|
||||
|
||||
result.State = BlindscanResultState.DataSaving;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
|
||||
foreach (HumanReadableService humanReadableService in config.Ui.GetServices())
|
||||
{
|
||||
config.DataStorage.InsertTransponderService(jobInDb, result.IsSatellite(), result.SearchResult, result.SearchResult2, humanReadableService);
|
||||
}
|
||||
|
||||
result.State = BlindscanResultState.Done;
|
||||
config.DataStorage.UpdateTransponderState(jobInDb, result.IsSatellite(), result.SearchResult, result.State, result.SearchResult2);
|
||||
config.Ui.OnBlindscanAfterPacketDrain();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Queue<byte[]> packetsQueue;
|
||||
private void DvbCallback(nint data, int length)
|
||||
{
|
||||
if (length % 188 == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] buffer = new byte[length];
|
||||
Marshal.Copy(data, buffer, 0, length);
|
||||
|
||||
lock (packetsQueue)
|
||||
{
|
||||
packetsQueue.Enqueue(buffer);
|
||||
}
|
||||
|
||||
packetsReceivedInTotal += (uint)(buffer.Length / 188);
|
||||
config.Ui.OnBlindscanPacketOk(buffer.Length / 188, packetsQueue.Count);
|
||||
}
|
||||
catch (OutOfMemoryException e)
|
||||
{
|
||||
config.Ui.OnBlindscanPacketError(2, length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Log(PluginLogLevel.Warn, string.Format("odd packet size!"), 8);
|
||||
config.Ui.OnBlindscanPacketError(1, length);
|
||||
}
|
||||
}
|
||||
|
||||
private ISkyscraperContext skyscraperContext;
|
||||
private ulong packetsReceivedInTotal;
|
||||
private DateTime startedAt;
|
||||
private bool StopConditionMet()
|
||||
{
|
||||
if (startedAt == DateTime.MinValue)
|
||||
startedAt = DateTime.Now;
|
||||
|
||||
if (config.Ui.IsZapNowRequested())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!config.Ui.MayAutoZap())
|
||||
return false;
|
||||
|
||||
if (packetsReceivedInTotal == 0 && (DateTime.Now - startedAt).TotalSeconds > 5)
|
||||
return true;
|
||||
|
||||
if (skyscraperContext.GetIpCommunicationParties() > 1000)
|
||||
return true;
|
||||
|
||||
if (!skyscraperContext.EnableTimeout)
|
||||
{
|
||||
skyscraperContext.TimeoutSeconds = 10;
|
||||
skyscraperContext.EnableTimeout = true;
|
||||
}
|
||||
|
||||
if (packetsReceivedInTotal > 0 && skyscraperContext.IsAbortConditionMet())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private bool HasPackets()
|
||||
{
|
||||
lock (packetsQueue)
|
||||
{
|
||||
return packetsQueue.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrainPackets()
|
||||
{
|
||||
if (packetsQueue.Count == 0)
|
||||
return;
|
||||
|
||||
logger.Log(PluginLogLevel.Warn, string.Format("{0} packets left after switching off the filter.", packetsQueue.Count), 8);
|
||||
|
||||
DateTime startedAt = DateTime.Now;
|
||||
byte[] singlePacketBuffer = new byte[188];
|
||||
byte[] packetBuffer = null;
|
||||
DateTime drainTickerPrevious = DateTime.Now, drainTickerNow = DateTime.Now;
|
||||
while (packetsQueue.Count > 0)
|
||||
{
|
||||
packetBuffer = packetsQueue.Dequeue();
|
||||
if (packetBuffer == null)
|
||||
continue;
|
||||
for (int i = 0; i < packetBuffer.Length; i += 188)
|
||||
{
|
||||
Array.Copy(packetBuffer, i, singlePacketBuffer, 0, 188);
|
||||
skyscraperContext.IngestSinglePacket(singlePacketBuffer);
|
||||
}
|
||||
|
||||
drainTickerPrevious = drainTickerNow;
|
||||
drainTickerNow = DateTime.Now;
|
||||
if (drainTickerNow.Second != drainTickerPrevious.Second)
|
||||
{
|
||||
logger.Log(PluginLogLevel.Warn, string.Format("{0} packets left ({1}).", packetsQueue.Count, drainTickerNow.ToLongTimeString()), 8);
|
||||
}
|
||||
}
|
||||
|
||||
logger.Log(PluginLogLevel.Warn, string.Format("Packets drained in {0} seconds.", (DateTime.Now - startedAt).TotalSeconds), 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper;
|
||||
using skyscraper5.Skyscraper.Equipment;
|
||||
using skyscraper5.Skyscraper.Gps;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper8.Skyscraper.Scraper.Storage;
|
||||
|
||||
namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
||||
{
|
||||
public class BlindscanJobConfiguration
|
||||
{
|
||||
public IStreamReader StreamReader { get; set; }
|
||||
public TunerMetadata TunerMetadata { get; set; }
|
||||
public int DiseqcIndex { get; set; }
|
||||
public IGpsReceiver Gps { get; set; }
|
||||
public SatellitePosition SatellitePosition { get; set; }
|
||||
|
||||
public bool DoHorizontalHigh { get; set; }
|
||||
public bool DoHorizontalLow { get; set; }
|
||||
public bool DoVerticalHigh { get; set; }
|
||||
public bool DoVerticalLow { get; set; }
|
||||
|
||||
public DataStorage DataStorage { get; set; }
|
||||
public ObjectStorage ObjectStorage { get; set; }
|
||||
public ISkyscraperUiJunction Ui { get; set; }
|
||||
public bool DoCollectRfSpectrum { get; set; }
|
||||
public LnbType LnbType { get; set; }
|
||||
public bool DoCollectIqGraphs { get; set; }
|
||||
public bool DoRecordTs { get; set; }
|
||||
public Ini Ini { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
|
||||
|
||||
namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
||||
{
|
||||
public class BlindscanSearchResult
|
||||
{
|
||||
public SearchResult SearchResult;
|
||||
public STD_TYPE Standard { get; set; }
|
||||
public BlindscanResultState State { get; set; }
|
||||
public SearchResult2 SearchResult2;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the data is in SearchResult.
|
||||
/// If false, the data is in SearchResult2.
|
||||
/// </summary>
|
||||
public bool IsSatellite()
|
||||
{
|
||||
switch (Standard)
|
||||
{
|
||||
case STD_TYPE.STD_DVBS2: return true;
|
||||
case STD_TYPE.STD_DVBS: return true;
|
||||
case STD_TYPE.STD_DVBC: return false;
|
||||
case STD_TYPE.STD_DVBC2: return false;
|
||||
case STD_TYPE.STD_DVBT: return false;
|
||||
case STD_TYPE.STD_DVBT2: return false;
|
||||
default: throw new NotImplementedException(Standard.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public long GetFrequency()
|
||||
{
|
||||
if (IsSatellite())
|
||||
return SearchResult.Freq;
|
||||
else
|
||||
return SearchResult2.Freq;
|
||||
}
|
||||
|
||||
public char GetPolarity(int lnbTypeLofSw)
|
||||
{
|
||||
if (IsSatellite())
|
||||
{
|
||||
if (lnbTypeLofSw == 0 && SearchResult.Pol == 0)
|
||||
return 'L';
|
||||
else if (lnbTypeLofSw == 0 && SearchResult.Pol == 1)
|
||||
return 'R';
|
||||
else if (lnbTypeLofSw != 0 && SearchResult.Pol == 0)
|
||||
return 'H';
|
||||
else if (lnbTypeLofSw != 0 && SearchResult.Pol == 1)
|
||||
return 'V';
|
||||
else
|
||||
throw new NotImplementedException("Couldn't figure out signal polarity.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return 'T';
|
||||
}
|
||||
}
|
||||
|
||||
public int GetSymbolRate()
|
||||
{
|
||||
if (IsSatellite())
|
||||
return SearchResult.SR;
|
||||
else
|
||||
return SearchResult2.SR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,306 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||
|
||||
namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
||||
{
|
||||
public class CoopBlindscanStreamReader : IStreamReader
|
||||
{
|
||||
private readonly IStreamReader _proxiedStreamReader;
|
||||
private readonly int _blindScanTuner;
|
||||
private readonly int _setFilterTuner;
|
||||
|
||||
public CoopBlindscanStreamReader(IStreamReader proxiedStreamReader, int blindScanTuner, int setFilterTuner)
|
||||
{
|
||||
_proxiedStreamReader = proxiedStreamReader;
|
||||
_blindScanTuner = blindScanTuner;
|
||||
_setFilterTuner = setFilterTuner;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CheckForDVB()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CheckForDVBEx(DvbEnumCallback func)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CheckForDVBExEx(DvbEnumCallbackEx func)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool StartDVB()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool StartDvbEx(int index)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool StopDVB()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool GetTunerType(ref STD_TYPE type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SendDiSEqC(uint diseqcType, DiSEqC_Opcode data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SendDiseqCmd(byte[] buffer, int length)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SendDiseqCmdEx(nint pCmd, int length, nint reply, int replyLength)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetChannel(int freq, int symbrate, int pol, VITERBIRATE_TYPE fec, int lof1, int lof2, int lofsw)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetChannelEx(int freq, int symbrate, int pol, VITERBIRATE_TYPE fec, int lof1, int lof2, int lofsw, MOD_TYPE mod)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetChannelExEx(int freq, int symbrate, int pol, VITERBIRATE_TYPE fec, int lof1, int lof2, int lofsw, MOD_TYPE mod,
|
||||
int inv, int pilot, ROLLOFF_TYPE rolloff)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetFilter(int pid, StdcallDvbCallback func, int callbackType, int size, ref nint lpFilterNum)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetFilterEx(int pid, StdcallDvbCallbackEx lpFunc, int callbackType, int size, ref nint lpFilterNum)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetBitFilter(int pid, nint filterData, nint filterMask, byte filterLength, StdcallDvbCallback lpFunc,
|
||||
ref nint lpFilterNum)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetRemoteControl(int irtype, short devAddr, StdcallDvbCallback func, ref nint lpFilterNum)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool DelFilter(nint filterNum)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool GetSignal(ref int pStrength, ref int pQuality)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool GetSignalStrength(ref float pStrength, ref float pQuality)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool GetSignalEx(ref float pSNR, ref float pBER)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool GetSignalExEx(ref bool pPresent, ref bool pLock, ref int pRFLevel, ref float pSNR, ref float pBER)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Statistic(int[] pStat)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool GetMAC(byte[] pMac)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Caps GetCaps()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool RFScan(int freq, int pol, int lof1, int lof2, int lofsw, out double pRFLevel)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool FFTInit()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool FFTScan(int freq, int pol, int lof1, int lof2, int lofsw, uint range, byte mode, byte nb_acc, nint pTab,
|
||||
nint pBegin, nint pNum)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool BLScan(int freq, int freq_range, int pol, int lof1, int lof2, int lofsw, int minsr,
|
||||
ref SearchResult pSearchResult)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool BLScanEx(int freq, int freq_range, int pol, int lof1, int lof2, int lofsw, int minsr, STD_TYPE std,
|
||||
ref SearchResult pSearchResult)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool BLScan2(int freq_start, int freq_stop, int pol, int lof1, int lof2, int lofsw, nint pSearchResult, ref int pTpNum,
|
||||
BlScanCallback lpFunc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SignalInfo(ref SearchResult pSearchResult)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IQScan(uint input, sbyte[] pIQ, uint num)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IQScan2(uint point, short[] pIQ, uint num)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IQScan2Range(byte input, ref ushort pMinPoint, ref ushort pMaxPoint)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CIRScanRange(bool bHiRes, ref ushort pMinCnum, ref ushort pMaxCnum, ref int pMinDelayNs, ref int pMaxDelayNs)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CIRScan(bool bHiRes, int[] pPowers, int[] pDelays)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CarRange(ref ushort pMinCnum, ref ushort pMaxCnum)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CarEsNo(ref ushort cnum, ref double pEsNo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool MISSel(bool bEnable, byte misFilter, byte misFilterMask)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool PLSSel(byte plsMode, uint code)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool PLSGet(byte pMode, ref uint pCode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool ModSel(ref S2Mode ps2Modes, uint num)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool ModInv(uint WaitMs, ref S2Mode pS2Modes, ref uint pNum)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetChannel2(uint freq, uint bandwidth)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetChannel2Ex(uint freq, uint bandwidth, STD_TYPE std, int stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetChannel2ExEx(uint freq, uint bandwidth, uint symbrate, STD_TYPE std, int stream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SignalInfo2(ref SearchResult2 si2)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool RFScan2(uint freq, STD_TYPE std, ref double pRFLevel)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool AirScan(int freq_start, int freq_stop, uint step, uint bandwidth, int std, nint pSearchResult, ref int pTpNum,
|
||||
AirScanCallback lpFunc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool GetEEPROM(byte[] buffer, int offset, int len)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool SetEEPROM(byte[] buffer, int offset, int len)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Version GetEngineVersion()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetEngineName()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,203 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Docsis;
|
||||
using skyscraper5.Dvb.DataBroadcasting.SkyscraperVfs;
|
||||
using skyscraper5.Dvb.Descriptors;
|
||||
using skyscraper5.Dvb.Psi.Model;
|
||||
using skyscraper5.Mhp.Si.Model;
|
||||
using skyscraper5.Mpeg2.Descriptors;
|
||||
using skyscraper5.Mpeg2.Psi.Model;
|
||||
using skyscraper5.Scte35;
|
||||
using skyscraper5.Skyscraper.Net;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper5.Teletext.Wss;
|
||||
|
||||
namespace skyscraper5.src.Skyscraper.FrequencyListGenerator
|
||||
{
|
||||
internal class FrequencyListGeneratorJunction : ISkyscraperUiJunction
|
||||
{
|
||||
public FrequencyListGeneratorJunction()
|
||||
{
|
||||
sdtServices = new Dictionary<ushort, SdtService>();
|
||||
}
|
||||
|
||||
private Dictionary<ushort, SdtService> sdtServices;
|
||||
private Dictionary<ushort, ProgramMapping> programMappings;
|
||||
|
||||
public void NotifyEvent(EitEvent eitEvent)
|
||||
{
|
||||
}
|
||||
|
||||
public void NotifySdtService(SdtService sdtService)
|
||||
{
|
||||
if (!sdtServices.ContainsKey(sdtService.ServiceId))
|
||||
sdtServices.Add(sdtService.ServiceId, sdtService);
|
||||
}
|
||||
|
||||
public void NotifyPatProgram(int pmtPid, ushort programId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyPmtProgram(ProgramMapping result, int pmtPid)
|
||||
{
|
||||
if (!programMappings.ContainsKey(result.ProgramNumber))
|
||||
programMappings.Add(result.ProgramNumber, result);
|
||||
}
|
||||
|
||||
public void NotifyNit(NitTransportStream transportStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyMpeTraffic(IpTrafficInfo iti, int ipv4PacketLength)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyAit(AitApplication aitApplication)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DsmCcModuleAdd(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DsmCcModuleProgress(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion,
|
||||
double moduleInfoDownloadProgress)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DsmCcModuleComplete(int elementaryPid, ushort moduleModuleId, byte moduleModuleVersion)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyWss(ushort programNumber, WssDataBlock wssDataBlock)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyStreamTypeDetection(string contestantTag, int pid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyBat(BatBouquet batBouquet)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyBatTs(ushort batBouquetBouquetId, BatTransportStream child)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void DsmCcVfs(VfsFile vfsFile)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyTot(DateTime utcTime, LocalTimeOffsetDescriptor ltod)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyTdt(DateTime utcTime)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyCat(CaDescriptor caDescriptor)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyScte35(ushort programNumber, SpliceInsert spliceInsert)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyScte35(ushort programNumber, TimeSignal spliceInsert)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SetMemorySaverMode(bool saveMemory)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyDocsisCarrier(DocsisEnvironment docsisEnvironment)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyDocsisFrequency(uint? frequency, bool isUpstream, object mmm)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void SetGseMode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ShowFramegrab(int currentNetworkId, int transportStreamId, ushort mappingProgramNumber,
|
||||
int mappingStreamElementaryPid, byte[] imageData)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void NotifyBlockstreamCarrier()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public IEnumerable<HumanReadableService> GetServices()
|
||||
{
|
||||
foreach (var (pmtPid, pmt) in programMappings)
|
||||
{
|
||||
ushort serviceId = pmt.ProgramNumber;
|
||||
if (!sdtServices.ContainsKey(serviceId))
|
||||
continue;
|
||||
SdtService service = sdtServices[serviceId];
|
||||
string providerName = service.ServiceProviderName;
|
||||
string serviceName = service.ServiceName;
|
||||
ushort? caId = GetCaId(pmt, service);
|
||||
ServiceDescriptor.ServiceTypeCoding serviceType = service.ServiceType.GetValueOrDefault();
|
||||
yield return new HumanReadableService(serviceId, providerName, serviceName, caId, serviceType);
|
||||
}
|
||||
}
|
||||
|
||||
private ushort? GetCaId(ProgramMapping pmt, SdtService sdt)
|
||||
{
|
||||
if (pmt.CaSystemId.HasValue)
|
||||
{
|
||||
return pmt.CaSystemId.Value;
|
||||
}
|
||||
|
||||
foreach (ProgramMappingStream stream in pmt.Streams)
|
||||
{
|
||||
if (stream.CaSystemId.HasValue)
|
||||
return stream.CaSystemId.Value;
|
||||
}
|
||||
|
||||
if (sdt.CaIdentifiers != null)
|
||||
{
|
||||
if (sdt.CaIdentifiers.Length > 0)
|
||||
{
|
||||
return sdt.CaIdentifiers[0];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
skyscraper8/Skyscraper/FrequencyListGenerator/TaskQueue.cs
Normal file
38
skyscraper8/Skyscraper/FrequencyListGenerator/TaskQueue.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Skyscraper.FrequencyListGenerator
|
||||
{
|
||||
public class TaskQueue
|
||||
{
|
||||
public TaskQueue()
|
||||
{
|
||||
tasks = new Queue<Action>();
|
||||
}
|
||||
|
||||
private Queue<Action> tasks;
|
||||
|
||||
public void EnqueueTask(Action a)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
tasks.Enqueue(a);
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessTasks()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
while (tasks.Count > 0)
|
||||
{
|
||||
Action dequeue = tasks.Dequeue();
|
||||
dequeue.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,469 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper5.Skyscraper.Scraper.Storage.Filesystem;
|
||||
using skyscraper8.Skyscraper.Scraper.Storage;
|
||||
|
||||
namespace skyscraper5.Skyscraper.IO
|
||||
{
|
||||
internal class StreamReaderScanController : IDisposable
|
||||
{
|
||||
private readonly IStreamReader streamReader;
|
||||
|
||||
public static List<StreamReaderTuner> GetTuners(IStreamReader streamReader)
|
||||
{
|
||||
List<StreamReaderTuner> result = new List<StreamReaderTuner>();
|
||||
bool checkForDvbExEx = streamReader.CheckForDVBExEx((index, name, type) =>
|
||||
{
|
||||
result.Add(new StreamReaderTuner(index, name, type));
|
||||
});
|
||||
if (!checkForDvbExEx)
|
||||
{
|
||||
return new List<StreamReaderTuner>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<StreamReaderTuner> GetTunersByStandard(STD_TYPE stdType)
|
||||
{
|
||||
return GetTuners(streamReader).Where(x => x.Type == stdType).ToList();
|
||||
}
|
||||
|
||||
public StreamReaderTuner GetTunerByStandard(STD_TYPE stdType)
|
||||
{
|
||||
List<StreamReaderTuner> streamReaderTuners = GetTunersByStandard(stdType);
|
||||
if (streamReaderTuners.Count == 0)
|
||||
return null;
|
||||
else
|
||||
return streamReaderTuners[0];
|
||||
}
|
||||
|
||||
private bool busy;
|
||||
private PhysicalAddress physicalAddress;
|
||||
private STD_TYPE stdType;
|
||||
private Caps caps;
|
||||
private StreamReaderTuner tunerMetadata;
|
||||
private static int instances = 0;
|
||||
private bool disposed;
|
||||
|
||||
public StreamReaderScanController(IStreamReader streamReader, StreamReaderTuner tuner)
|
||||
{
|
||||
this.streamReader = streamReader;
|
||||
|
||||
if (instances > 0)
|
||||
{
|
||||
throw new StreamReaderException("Only one StreamReader may be active, dispose the other one first.");
|
||||
}
|
||||
|
||||
if (tuner != null)
|
||||
{
|
||||
tunerMetadata = tuner;
|
||||
if (!streamReader.StartDvbEx(tuner.Index))
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.StartDvbEx)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!streamReader.StartDVB())
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.StartDVB)));
|
||||
}
|
||||
}
|
||||
|
||||
caps = streamReader.GetCaps();
|
||||
if (!streamReader.GetTunerType(ref stdType))
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.GetTunerType)));
|
||||
}
|
||||
|
||||
if (caps.HasFlag(Caps.SR_GETMAC))
|
||||
{
|
||||
byte[] macBuffer = new byte[6];
|
||||
if (streamReader.GetMAC(macBuffer))
|
||||
{
|
||||
physicalAddress = new PhysicalAddress(macBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
string[] strings = Enum.GetNames(typeof(StreamReaderParameter));
|
||||
parameters = new uint[strings.Length];
|
||||
paramsSet = new bool[strings.Length];
|
||||
|
||||
if (stdType == STD_TYPE.STD_DVBC)
|
||||
SetDefaultDvbCParameters();
|
||||
}
|
||||
|
||||
private bool[] paramsSet;
|
||||
private uint[] parameters;
|
||||
public enum StreamReaderParameter : int
|
||||
{
|
||||
ScanStartFreq,
|
||||
ScanEndFreq,
|
||||
ScanStep,
|
||||
ScanBandwidth,
|
||||
ScanStdType,
|
||||
ScanLof1,
|
||||
ScanLofSwitch,
|
||||
ScanLof2,
|
||||
ScanDiseqcType,
|
||||
DiseqcSwitchPosition
|
||||
}
|
||||
|
||||
public void SetParameter(StreamReaderParameter key, uint value)
|
||||
{
|
||||
parameters[(int)key] = value;
|
||||
paramsSet[(int)key] = true;
|
||||
}
|
||||
|
||||
public uint GetParameter(StreamReaderParameter key)
|
||||
{
|
||||
if (!paramsSet[(int)key])
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} was not set.", key.ToString()));
|
||||
}
|
||||
return parameters[(int)key];
|
||||
}
|
||||
|
||||
public void SetDefaultDvbCParameters()
|
||||
{
|
||||
SetParameter(StreamReaderParameter.ScanStartFreq, 48000);
|
||||
SetParameter(StreamReaderParameter.ScanEndFreq, 1000000);
|
||||
SetParameter(StreamReaderParameter.ScanStep, 3000);
|
||||
SetParameter(StreamReaderParameter.ScanBandwidth, 8000);
|
||||
SetParameter(StreamReaderParameter.ScanStdType, (uint)STD_TYPE.STD_DVBC);
|
||||
}
|
||||
|
||||
public void SetDefaultKuBandParameters()
|
||||
{
|
||||
SetParameter(StreamReaderParameter.ScanLof1, 9750000);
|
||||
SetParameter(StreamReaderParameter.ScanLofSwitch, 11700000);
|
||||
SetParameter(StreamReaderParameter.ScanLof2, 10600000);
|
||||
SetParameter(StreamReaderParameter.ScanStartFreq, 10700000);
|
||||
SetParameter(StreamReaderParameter.ScanEndFreq, 12750000);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (busy)
|
||||
{
|
||||
throw new StreamReaderException("TunerMetadata is busy.");
|
||||
}
|
||||
|
||||
streamReader.StopDVB();
|
||||
instances--;
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
public class StreamReaderTuner
|
||||
{
|
||||
public int Index { get; }
|
||||
public string Name { get; }
|
||||
public STD_TYPE Type { get; }
|
||||
|
||||
public StreamReaderTuner(int index, string name, STD_TYPE type)
|
||||
{
|
||||
Index = index;
|
||||
Name = name;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Tune(BlindScanResult blindScanResult)
|
||||
{
|
||||
switch (stdType)
|
||||
{
|
||||
case STD_TYPE.STD_DVBC:
|
||||
Console.WriteLine("Tuning to {0} Mhz", blindScanResult.SearchResult2.Freq / 1000.0);
|
||||
bool channel2 = streamReader.SetChannel2((uint)blindScanResult.SearchResult2.Freq, (uint)blindScanResult.SearchResult2.BW);
|
||||
if (!channel2)
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.SetChannel2)));
|
||||
}
|
||||
|
||||
SearchResult2 sr2 = default;
|
||||
bool signalInfo2 = streamReader.SignalInfo2(ref sr2);
|
||||
if (!signalInfo2)
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.SetChannel2)));
|
||||
}
|
||||
|
||||
return sr2.Lock;
|
||||
case STD_TYPE.STD_DVBS:
|
||||
Console.WriteLine("Tuning to {0} Mhz", blindScanResult.SearchResult1.Freq / 1000.0);
|
||||
SearchResult searchResult1 = blindScanResult.SearchResult1;
|
||||
uint lof1 = GetParameter(StreamReaderParameter.ScanLof1);
|
||||
uint lof2 = GetParameter(StreamReaderParameter.ScanLof2);
|
||||
uint lofSw = GetParameter(StreamReaderParameter.ScanLofSwitch);
|
||||
if (!streamReader.SetChannel(searchResult1.Freq, searchResult1.SR, searchResult1.Pol, searchResult1.FEC, (int)lof1, (int)lof2, (int)lofSw))
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.SetChannel)));
|
||||
}
|
||||
|
||||
SearchResult cmp = default;
|
||||
bool signalInfo = streamReader.SignalInfo(ref cmp);
|
||||
if (!signalInfo)
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.SignalInfo)));
|
||||
}
|
||||
return cmp.Lock;
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchResult2Callback(BlindScanResults results, SearchResult2 sr2Ptr)
|
||||
{
|
||||
BlindScanResult bbsr = new BlindScanResult();
|
||||
bbsr.System = stdType;
|
||||
bbsr.SearchResult2 = sr2Ptr;
|
||||
results.Transponders.Add(bbsr);
|
||||
|
||||
Console.WriteLine("{0} Mhz, {1} ksyms, {2}", sr2Ptr.Freq / 1000.0, sr2Ptr.SR / 1000, (MOD_TYPE)sr2Ptr.ModType);
|
||||
}
|
||||
|
||||
private void SearchResult2Callback(BlindScanResults results, SearchResult sr2Ptr)
|
||||
{
|
||||
BlindScanResult bbsr = new BlindScanResult();
|
||||
bbsr.SearchResult1 = sr2Ptr;
|
||||
bbsr.System = stdType;
|
||||
results.Transponders.Add(bbsr);
|
||||
|
||||
Console.WriteLine("{0} Mhz, {1} ksyms, {2}", sr2Ptr.Freq / 1000.0, sr2Ptr.SR / 1000, (MOD_TYPE)sr2Ptr.ModType);
|
||||
}
|
||||
|
||||
private void SendDiseqcCommand(int diseqcType, bool highBand, bool horizontal)
|
||||
{
|
||||
DiSEqC_Opcode myOpcode = DiSEqC_Opcode.DISEQC_HIGH_NIBBLE;
|
||||
if (highBand)
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_HIGH_BAND;
|
||||
else
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_LOW_BAND;
|
||||
|
||||
if (horizontal)
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_HORIZONTAL;
|
||||
else
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_VERTICAL;
|
||||
|
||||
if (diseqcType == 2)
|
||||
{
|
||||
uint parameter = GetParameter(StreamReaderParameter.DiseqcSwitchPosition);
|
||||
switch (parameter)
|
||||
{
|
||||
case 1:
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
||||
break;
|
||||
case 2:
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_OPTION_A;
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
||||
break;
|
||||
case 3:
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_POSITION_A;
|
||||
break;
|
||||
case 4:
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_OPTION_B;
|
||||
myOpcode |= DiSEqC_Opcode.DISEQC_POSITION_B;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(StreamReaderParameter.DiseqcSwitchPosition));
|
||||
}
|
||||
}
|
||||
|
||||
bool sendDiSEqC = streamReader.SendDiSEqC((uint)diseqcType, myOpcode);
|
||||
if (!sendDiSEqC)
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.SendDiSEqC)));
|
||||
}
|
||||
}
|
||||
|
||||
public void RunBlindscan()
|
||||
{
|
||||
if (busy)
|
||||
throw new StreamReaderException("TunerMetadata is busy");
|
||||
|
||||
int startFreq = (int)GetParameter(StreamReaderParameter.ScanStartFreq);
|
||||
int endFreq = (int)GetParameter(StreamReaderParameter.ScanEndFreq);
|
||||
|
||||
BlindScanResults result = new BlindScanResults();
|
||||
result.Standard = stdType;
|
||||
switch (stdType)
|
||||
{
|
||||
case STD_TYPE.STD_DVBC:
|
||||
if (caps.HasFlag(Caps.SR_AIRSCAN))
|
||||
{
|
||||
|
||||
uint step = GetParameter(StreamReaderParameter.ScanStep);
|
||||
uint bandwidth = GetParameter(StreamReaderParameter.ScanBandwidth);
|
||||
STD_TYPE stdType = (STD_TYPE)GetParameter(StreamReaderParameter.ScanStdType);
|
||||
SearchResult2 sr2 = default;
|
||||
int tpNum = default;
|
||||
IntPtr pSearchResult = Marshal.AllocHGlobal(ushort.MaxValue);
|
||||
busy = true;
|
||||
bool airScan = streamReader.AirScan(startFreq, endFreq, step, bandwidth, (int)stdType, pSearchResult, ref tpNum, (ref SearchResult2 searchResult) => SearchResult2Callback(result, searchResult));
|
||||
if (airScan)
|
||||
{
|
||||
Scrape(result);
|
||||
}
|
||||
busy = false;
|
||||
Marshal.FreeHGlobal(pSearchResult);
|
||||
if (!airScan)
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.GetTunerType)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("Don't know how to blindscan with this tuner.");
|
||||
}
|
||||
|
||||
break;
|
||||
case STD_TYPE.STD_DVBS:
|
||||
if (caps.HasFlag(Caps.SR_BLSCAN2))
|
||||
{
|
||||
SearchResult sr1 = default;
|
||||
int tpNum = default;
|
||||
|
||||
int lof1 = (int)GetParameter(StreamReaderParameter.ScanLof1);
|
||||
int lof2 = (int)GetParameter(StreamReaderParameter.ScanLof2);
|
||||
int lofSw = (int)GetParameter(StreamReaderParameter.ScanLofSwitch);
|
||||
int diseqc = (int)GetParameter(StreamReaderParameter.ScanDiseqcType);
|
||||
|
||||
IntPtr allocHGlobal = Marshal.AllocHGlobal(ushort.MaxValue);
|
||||
|
||||
if (lofSw != 0)
|
||||
{
|
||||
busy = true;
|
||||
|
||||
result.Transponders.Clear();
|
||||
SendDiseqcCommand(diseqc, false, true);
|
||||
bool hLower = streamReader.BLScan2(startFreq, lofSw, 0, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult searchResult) => SearchResult2Callback(result, searchResult));
|
||||
if (hLower)
|
||||
{
|
||||
Scrape(result);
|
||||
}
|
||||
|
||||
result.Transponders.Clear();
|
||||
SendDiseqcCommand(diseqc, true, true);
|
||||
bool hUpper = streamReader.BLScan2(lofSw, endFreq, 0, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult searchResult) => SearchResult2Callback(result, searchResult));
|
||||
if (hUpper)
|
||||
{
|
||||
Scrape(result);
|
||||
}
|
||||
|
||||
result.Transponders.Clear();
|
||||
SendDiseqcCommand(diseqc, false, false);
|
||||
bool vLower = streamReader.BLScan2(startFreq, lofSw, 1, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult searchResult) => SearchResult2Callback(result, searchResult));
|
||||
if (vLower)
|
||||
{
|
||||
Scrape(result);
|
||||
}
|
||||
|
||||
result.Transponders.Clear();
|
||||
SendDiseqcCommand(diseqc, true, false);
|
||||
bool vUpper = streamReader.BLScan2(lofSw, endFreq, 1, lof1, lof2, lofSw, allocHGlobal, ref tpNum, (ref SearchResult searchResult) => SearchResult2Callback(result, searchResult));
|
||||
if (vUpper)
|
||||
{
|
||||
Scrape(result);
|
||||
}
|
||||
|
||||
busy = false;
|
||||
if (!hLower && !hUpper && !vLower && !vUpper)
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.BLScan2)));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("non switching lnb");
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(allocHGlobal);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("Don't know how to blindscan with this tuner.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException(stdType.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private StreamReaderScraperController srsc2;
|
||||
private void Scrape(BlindScanResults blindScanResults)
|
||||
{
|
||||
if (srsc2 == null)
|
||||
{
|
||||
srsc2 = new StreamReaderScraperController(streamReader);
|
||||
srsc2.RecordingOutputDirectory = new DirectoryInfo("recordings");
|
||||
srsc2.Recording = true;
|
||||
srsc2.DataStorage = new FilesystemStorage(new DirectoryInfo("srtest_results"));
|
||||
srsc2.ObjectStorage = (ObjectStorage)srsc2.DataStorage;
|
||||
}
|
||||
|
||||
foreach (BlindScanResult blindScanResult in blindScanResults.Transponders)
|
||||
{
|
||||
if (Tune(blindScanResult))
|
||||
{
|
||||
srsc2.SetNamingHint(blindScanResult);
|
||||
srsc2.Run();
|
||||
}
|
||||
else
|
||||
Console.WriteLine("Lock failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
class StreamReaderException : SkyscraperIOException
|
||||
{
|
||||
//
|
||||
// For guidelines regarding the creation of new exception types, see
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
|
||||
// and
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
|
||||
//
|
||||
|
||||
public StreamReaderException()
|
||||
{
|
||||
}
|
||||
|
||||
public StreamReaderException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public StreamReaderException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
|
||||
protected StreamReaderException(
|
||||
SerializationInfo info,
|
||||
StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class BlindScanResults
|
||||
{
|
||||
public BlindScanResults()
|
||||
{
|
||||
Transponders = new List<BlindScanResult>();
|
||||
}
|
||||
|
||||
public List<BlindScanResult> Transponders { get; private set; }
|
||||
public STD_TYPE Standard { get; set; }
|
||||
}
|
||||
|
||||
class BlindScanResult
|
||||
{
|
||||
public SearchResult2 SearchResult2 { get; set; }
|
||||
public SearchResult SearchResult1 { get; set; }
|
||||
public STD_TYPE System { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,324 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using skyscraper5.Mpeg2;
|
||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper5.Skyscraper.Scraper.Storage;
|
||||
using skyscraper8.Skyscraper.Scraper.Storage;
|
||||
|
||||
namespace skyscraper5.Skyscraper.IO
|
||||
{
|
||||
internal class StreamReaderScraperController
|
||||
{
|
||||
private readonly IStreamReader streamReader;
|
||||
|
||||
public StreamReaderScraperController(IStreamReader streamReader)
|
||||
{
|
||||
this.streamReader = streamReader;
|
||||
}
|
||||
|
||||
|
||||
private const string RECORDING_FILENAME_MASK = "skyscraper_{0}.ts";
|
||||
|
||||
public DataStorage DataStorage { get; set; }
|
||||
public ObjectStorage ObjectStorage { get; set; }
|
||||
|
||||
public bool Recording { get; set; }
|
||||
|
||||
public DirectoryInfo RecordingOutputDirectory { get; set; }
|
||||
|
||||
private bool PrepareRecording()
|
||||
{
|
||||
if (!Recording)
|
||||
return false;
|
||||
|
||||
if (RecordingOutputDirectory == null)
|
||||
return false;
|
||||
|
||||
DirectoryInfo rootDirectory = RecordingOutputDirectory.Root;
|
||||
DriveInfo driveInfo = new DriveInfo(rootDirectory.FullName);
|
||||
long driveFreeSpace = driveInfo.TotalFreeSpace;
|
||||
long driveTotalSize = driveInfo.TotalSize;
|
||||
long tenPercentOfDriveTotal = driveTotalSize / 10;
|
||||
if (driveFreeSpace > tenPercentOfDriveTotal)
|
||||
return true;
|
||||
|
||||
FileInfo[] fileInfos = RecordingOutputDirectory.GetFiles(string.Format(RECORDING_FILENAME_MASK, "*"));
|
||||
Array.Sort(fileInfos, (x, y) => DateTime.Compare(x.CreationTimeUtc, y.CreationTimeUtc));
|
||||
long sizeOfAllKnown = fileInfos.Select(x => x.Length).Sum();
|
||||
long driveFreeSpaceAfterDeleting = driveFreeSpace + sizeOfAllKnown;
|
||||
if (driveFreeSpaceAfterDeleting < tenPercentOfDriveTotal)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < fileInfos.Length; i++)
|
||||
{
|
||||
fileInfos[i].Delete();
|
||||
Console.WriteLine("Deleted for rotation: {0}", fileInfos[i].Name);
|
||||
fileInfos[i] = null;
|
||||
driveInfo = new DriveInfo(rootDirectory.FullName);
|
||||
driveFreeSpace = driveInfo.TotalFreeSpace;
|
||||
if (driveFreeSpace > tenPercentOfDriveTotal)
|
||||
return true;
|
||||
}
|
||||
driveInfo = new DriveInfo(rootDirectory.FullName);
|
||||
driveFreeSpace = driveInfo.TotalFreeSpace;
|
||||
if (driveFreeSpace > tenPercentOfDriveTotal)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool HasLock(bool cableTv)
|
||||
{
|
||||
if (cableTv)
|
||||
{
|
||||
SearchResult2 sr2 = new SearchResult2();
|
||||
if (!streamReader.SignalInfo2(ref sr2))
|
||||
return false;
|
||||
return sr2.Lock;
|
||||
}
|
||||
else
|
||||
{
|
||||
SearchResult sr = new SearchResult();
|
||||
if (!streamReader.SignalInfo(ref sr))
|
||||
return false;
|
||||
return sr.Lock;
|
||||
}
|
||||
}
|
||||
|
||||
private ulong packetsReceivedInTotal;
|
||||
private Queue<byte[]> packetsQueue;
|
||||
private void DvbCallback(IntPtr data, int length)
|
||||
{
|
||||
if (length % 188 == 0)
|
||||
{
|
||||
byte[] buffer = new byte[length];
|
||||
Marshal.Copy(data, buffer, 0, length);
|
||||
lock (packetsQueue)
|
||||
{
|
||||
packetsQueue.Enqueue(buffer);
|
||||
}
|
||||
packetsReceivedInTotal++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("odd packet size!");
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasPackets()
|
||||
{
|
||||
lock (packetsQueue)
|
||||
{
|
||||
return packetsQueue.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime startedAt;
|
||||
private bool StopConditionMet()
|
||||
{
|
||||
if (startedAt == DateTime.MinValue)
|
||||
startedAt = DateTime.Now;
|
||||
|
||||
if (packetsReceivedInTotal == 0 && (DateTime.Now - startedAt).TotalSeconds > 5)
|
||||
return true;
|
||||
|
||||
if (!skyscraperContext.EnableTimeout)
|
||||
{
|
||||
skyscraperContext.TimeoutSeconds = 10;
|
||||
skyscraperContext.EnableTimeout = true;
|
||||
}
|
||||
|
||||
if (packetsReceivedInTotal > 0 && skyscraperContext.IsAbortConditionMet())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DrainPackets()
|
||||
{
|
||||
if (packetsQueue.Count == 0)
|
||||
return;
|
||||
|
||||
DateTime startedAt = DateTime.Now;
|
||||
byte[] singlePacketBuffer = new byte[188];
|
||||
byte[] packetBuffer = null;
|
||||
while (packetsQueue.Count > 0)
|
||||
{
|
||||
packetBuffer = packetsQueue.Dequeue();
|
||||
if (recordingBufferedStream != null)
|
||||
recordingBufferedStream.Write(packetBuffer, 0, packetBuffer.Length);
|
||||
for (int i = 0; i < packetBuffer.Length; i += 188)
|
||||
{
|
||||
Array.Copy(packetBuffer, i, singlePacketBuffer, 0, 188);
|
||||
skyscraperContext.IngestSinglePacket(singlePacketBuffer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private BufferedStream recordingBufferedStream;
|
||||
private FileStream recordingFileStream;
|
||||
private SkyscraperContext skyscraperContext;
|
||||
public void Run()
|
||||
{
|
||||
bool cableTvMode = false;
|
||||
Caps caps = streamReader.GetCaps();
|
||||
if (caps.HasFlag(Caps.SR_SIGINFO))
|
||||
{
|
||||
cableTvMode = false;
|
||||
}
|
||||
else if (caps.HasFlag(Caps.SR_SIGINFO2))
|
||||
{
|
||||
cableTvMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException("Couldn't figure out what signal info to use.");
|
||||
}
|
||||
|
||||
if (!HasLock(cableTvMode))
|
||||
{
|
||||
throw new NotImplementedException("No lock.");
|
||||
}
|
||||
|
||||
int misCounter = 1;
|
||||
int misMode = 0;
|
||||
byte[] s2_is = null;
|
||||
if (!cableTvMode)
|
||||
{
|
||||
SearchResult sr = default;
|
||||
if (!streamReader.SignalInfo(ref sr))
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.SignalInfo)));
|
||||
}
|
||||
|
||||
if (!sr.Lock)
|
||||
return;
|
||||
|
||||
misMode = sr.MIS;
|
||||
s2_is = sr.IS;
|
||||
}
|
||||
|
||||
for (int mis = 0; mis < misCounter; mis++)
|
||||
{
|
||||
if (misMode != 0)
|
||||
{
|
||||
Console.WriteLine("Selecting MIS IS {0}", s2_is[mis]);
|
||||
bool misSel = streamReader.MISSel(misMode != 0, s2_is[mis], 0xff);
|
||||
if (!misSel)
|
||||
{
|
||||
throw new StreamReaderException(string.Format("{0} failed", nameof(streamReader.MISSel)));
|
||||
}
|
||||
}
|
||||
|
||||
//Start Filter
|
||||
if (PrepareRecording())
|
||||
{
|
||||
string recordingFileName = GenerateRecordingFilename(mis, misMode);
|
||||
FileInfo recordingFileInfo = new FileInfo(recordingFileName);
|
||||
recordingFileInfo.Directory.EnsureExists();
|
||||
recordingFileStream = recordingFileInfo.OpenWrite();
|
||||
recordingBufferedStream = new BufferedStream(recordingFileStream);
|
||||
}
|
||||
|
||||
IntPtr filterReference = IntPtr.MaxValue;
|
||||
packetsQueue = new Queue<byte[]>();
|
||||
bool filter = streamReader.SetFilter(8192, DvbCallback, 0x02, 2, ref filterReference);
|
||||
if (!filter)
|
||||
{
|
||||
throw new Exception("failed to set filter");
|
||||
}
|
||||
|
||||
//Use the Filter
|
||||
skyscraperContext = new SkyscraperContext(new TsContext(), DataStorage,ObjectStorage);
|
||||
skyscraperContext.TcpProxyEnabled = true;
|
||||
byte[] singlePacketBuffer = new byte[188];
|
||||
while (!StopConditionMet())
|
||||
{
|
||||
if (!HasPackets())
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] packetBuffer = null;
|
||||
lock (packetsQueue)
|
||||
{
|
||||
packetBuffer = packetsQueue.Dequeue();
|
||||
}
|
||||
|
||||
if (recordingBufferedStream != null)
|
||||
recordingBufferedStream.Write(packetBuffer, 0, packetBuffer.Length);
|
||||
|
||||
|
||||
for (int i = 0; i < packetBuffer.Length; i += 188)
|
||||
{
|
||||
Array.Copy(packetBuffer, i, singlePacketBuffer, 0, 188);
|
||||
skyscraperContext.IngestSinglePacket(singlePacketBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
//Stop Filter
|
||||
bool stopped = streamReader.DelFilter(filterReference);
|
||||
if (!stopped)
|
||||
{
|
||||
throw new Exception("failed to stop filter");
|
||||
}
|
||||
|
||||
DrainPackets();
|
||||
if (recordingBufferedStream != null)
|
||||
{
|
||||
recordingBufferedStream.Flush();
|
||||
recordingBufferedStream.Close();
|
||||
recordingBufferedStream.Dispose();
|
||||
recordingBufferedStream = null;
|
||||
recordingFileStream.Close();
|
||||
recordingFileStream.Dispose();
|
||||
recordingFileStream = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GenerateRecordingFilename(int mis, int misMode)
|
||||
{
|
||||
DateTime dt = DateTime.Now;
|
||||
string dateFmt = string.Format("{0:D4}{1:D2}{2:D2}_{3:D2}{4:D2}", dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);
|
||||
if (namingHint != null)
|
||||
{
|
||||
switch (namingHint.System)
|
||||
{
|
||||
case STD_TYPE.STD_DVBS:
|
||||
string resultS = null;
|
||||
if (misMode == 0)
|
||||
{
|
||||
resultS = string.Format("{0}_{1}_{2}_{3}.ts", dateFmt, namingHint.SearchResult1.Freq / 1000, namingHint.SearchResult1.Pol == 0 ? "H" : "V", namingHint.SearchResult1.SR / 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultS = string.Format("{0}_{1}_{2}_{3}_MIS{4}.ts", dateFmt, namingHint.SearchResult1.Freq / 1000, namingHint.SearchResult1.Pol == 0 ? "H" : "V", namingHint.SearchResult1.SR / 1000, mis);
|
||||
}
|
||||
|
||||
return Path.Combine(RecordingOutputDirectory.FullName, resultS);
|
||||
default:
|
||||
throw new NotImplementedException(namingHint.System.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return Path.Combine(RecordingOutputDirectory.FullName, string.Format(RECORDING_FILENAME_MASK, dateFmt));
|
||||
}
|
||||
}
|
||||
|
||||
private BlindScanResult namingHint;
|
||||
public void SetNamingHint(BlindScanResult blindScanResult)
|
||||
{
|
||||
namingHint = blindScanResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -25,5 +25,6 @@ namespace skyscraper5.Skyscraper.Scraper
|
||||
|
||||
public void InitalizeFilterChain(params IPacketFilter[] args);
|
||||
|
||||
}
|
||||
int GetIpCommunicationParties();
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,9 +12,13 @@ using skyscraper5.Mhp.Si.Model;
|
||||
using skyscraper5.Mpeg2.Descriptors;
|
||||
using skyscraper5.Mpeg2.Psi.Model;
|
||||
using skyscraper5.Scte35;
|
||||
using skyscraper5.Skyscraper.Equipment;
|
||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||
using skyscraper5.Skyscraper.Net;
|
||||
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
|
||||
using skyscraper5.Teletext.Wss;
|
||||
using skyscraper8.Skyscraper.Drawing;
|
||||
using skyscraper8.Skyscraper.FrequencyListGenerator;
|
||||
|
||||
namespace skyscraper5.Skyscraper.Scraper
|
||||
{
|
||||
@ -48,5 +52,143 @@ namespace skyscraper5.Skyscraper.Scraper
|
||||
void NotifyBlockstreamCarrier();
|
||||
|
||||
IEnumerable<HumanReadableService> GetServices();
|
||||
void OnBlindscanOpenFoundFrquenciesWindow(List<BlindscanSearchResult> foundFrequencies, STD_TYPE tunerMetadataType);
|
||||
void OnBlindscanJobDone(bool success);
|
||||
void OnBlindscanErrorMessage(string blindscanningLowHorizontalAreaFailed);
|
||||
|
||||
/// <summary>
|
||||
/// Called after the part of a band (e.g. Horizontal High) has completed blindscanning.
|
||||
/// Is supposed to move the puppets in the SDL2 based UI to their home position.
|
||||
/// </summary>
|
||||
void OnBlindscanBandComplete();
|
||||
|
||||
/// <summary>
|
||||
/// Called before a BLScan operation begins.
|
||||
/// </summary>
|
||||
/// <param name="minimum">The minimum frequency to scan</param>
|
||||
/// <param name="currentProgress">The Frequency on which we're starting.</param>
|
||||
/// <param name="maximum">The maximum frequency to scan</param>
|
||||
void OnBlindscanBeforeBLScan(int minimum, int currentProgress, int maximum);
|
||||
|
||||
/// <summary>
|
||||
/// Called before a BLScan operation ends.
|
||||
/// </summary>
|
||||
void OnBlindscanAfterBLScan();
|
||||
|
||||
/// <summary>
|
||||
/// Called when a transponder is found during a BLScan2.
|
||||
/// </summary>
|
||||
/// <param name="searchResult"></param>
|
||||
/// <param name="polarityIndex"></param>
|
||||
/// <param name="lnbTypeMinimumFrequency"></param>
|
||||
/// <param name="lnbTypeMaximumFrequency"></param>
|
||||
void OnBlindscanSearchResult1Callback(BlindscanSearchResult searchResult, int polarityIndex, int lnbTypeMinimumFrequency, int lnbTypeMaximumFrequency);
|
||||
|
||||
/// <summary>
|
||||
/// Called before a SetChannel operation is performed.
|
||||
/// </summary>
|
||||
/// <param name="blindscanResult"></param>
|
||||
void OnBlindscanBeforeSetChannel(BlindscanSearchResult blindscanResult, LnbType lnbType);
|
||||
|
||||
/// <summary>
|
||||
/// Called after a band (meaning e.g. Horizontal High) has been scraped.
|
||||
/// In the SDL2 version, this is supposed to move the puppets back to their home position.
|
||||
/// </summary>
|
||||
void OnScrapeBandComplete();
|
||||
|
||||
/// <summary>
|
||||
/// Called after a single transponder has been scraped.
|
||||
/// In the SDL2 version, this is supposed to hide the pressure plate representing the transponder.
|
||||
/// </summary>
|
||||
/// <param name="blindscanResult"></param>
|
||||
void OnBlindscanScrapeTransponderComplete(BlindscanSearchResult blindscanResult);
|
||||
|
||||
/// <summary>
|
||||
/// Called when beginning to gather the RF Spectrum.
|
||||
/// In the SDL2 version, this is supposed to create the ScottPlot window.
|
||||
/// </summary>
|
||||
void OnBlindscanBeginRfSpectrum();
|
||||
|
||||
/// <summary>
|
||||
/// Called when a data point for the RF Spectrum is available.
|
||||
/// </summary>
|
||||
/// <param name="polarization"></param>
|
||||
/// <param name="frequency"></param>
|
||||
/// <param name="rf"></param>
|
||||
void OnBlindscanRfSpectrumEnqueueSample(SatelliteDeliverySystemDescriptor.PolarizationEnum polarization, int frequency, double rf);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the gathering of the RF Spectrum has been completed.
|
||||
/// In the SDL2 version, this is supposed to close the ScottPlotWindow.
|
||||
/// </summary>
|
||||
void OnBlindscanEndRfSpectrum();
|
||||
|
||||
/// <summary>
|
||||
/// Called when beginning to gather an IQ Spectrum.
|
||||
/// In the SDL2 version, this is supposed to create a Surface for Pixel drawing.
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
void OnBlindscanBeginIqSpectrum(IqChartData result);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the gathering of an IQ Spectrum has been completed.
|
||||
/// In the SDL2 version, this is supposed to remove the Surface for Pixel drawing.
|
||||
/// </summary>
|
||||
void OnBlindscanEndIq();
|
||||
|
||||
/// <summary>
|
||||
/// Called when a lock couldn't be acquired.
|
||||
/// In the SDL2 version, this is supposed to play the fail.wav sound.
|
||||
/// </summary>
|
||||
/// <param name="satelliteSr"></param>
|
||||
/// <param name="resultState"></param>
|
||||
void OnBlindscanLockFail(SearchResult satelliteSr, BlindscanResultState resultState);
|
||||
|
||||
/// <summary>
|
||||
/// Called before SetFilter is called.
|
||||
/// In the SDL2 version, this is supposed to:
|
||||
/// 1) Spawn all these nice windows about PAT, CAT, PMT, EIT, etc...
|
||||
/// 2) Play the Success1.wav
|
||||
/// 3) Set the packet counters in foundFrequenciesWindow to 0.
|
||||
/// 4) Enable the Zap now button in the foundFrequenciesWindow.
|
||||
/// </summary>
|
||||
void OnBlindscanFilterSetUp();
|
||||
|
||||
/// <summary>
|
||||
/// Called after we're done collecting packets from a transponder.
|
||||
/// In the SDL2 version, this is supposed to:
|
||||
/// 1) Disable the Zap now button in the foundFrequenciesWindow.
|
||||
/// </summary>
|
||||
void OnBlindscanScrapeStopCondition();
|
||||
|
||||
/// <summary>
|
||||
/// Called after the packets collected from the transponder have all been processed.
|
||||
/// In the SDL2 version, this is supposed to:
|
||||
/// 1) Hide all the windows about DVB Tables
|
||||
/// </summary>
|
||||
void OnBlindscanAfterPacketDrain();
|
||||
|
||||
/// <summary>
|
||||
/// Called when StreamReader has invoked a DvbCallback.
|
||||
/// </summary>
|
||||
/// <param name="errorCount">1 when the packet size is odd. 2 when out of memory</param>
|
||||
/// <param name="length">The size of the data StreamReader gave to the DvbCallback</param>
|
||||
void OnBlindscanPacketError(int errorCount, int length);
|
||||
|
||||
void OnBlindscanPacketOk(int numPackets, int packetsQueueCount);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the user asks to abort scraping and switch to the next transponder.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the button has been pressed.</returns>
|
||||
bool IsZapNowRequested();
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the user asks not to zap automatically.
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the "Do not auto-zap" checkbox is checked in the FoundFrequenciesWIndow</returns>
|
||||
bool MayAutoZap();
|
||||
|
||||
TaskQueue Tasks { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,6 +229,14 @@ namespace skyscraper5.Skyscraper.Scraper
|
||||
logger.DebugFormat("Built filter chain: {0}", stringBuilder.ToString());
|
||||
}
|
||||
|
||||
public int GetIpCommunicationParties()
|
||||
{
|
||||
if (trafficInfos == null)
|
||||
return 0;
|
||||
else
|
||||
return trafficInfos.Count;
|
||||
}
|
||||
|
||||
public void IngestFromStream(Stream stream)
|
||||
{
|
||||
byte[] buffer = new byte[188];
|
||||
|
||||
@ -191,5 +191,7 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
|
||||
|
||||
void Ping();
|
||||
IEnumerable<Tuple<int, SatelliteDeliverySystemDescriptor.PolarizationEnum>> GetBlindscanResultFrequencies(Guid selectedGuid);
|
||||
void InsertUiBlindscanSettingHistory(int settingsWindowBlScanTunerSelection, bool settingsWindowUseDifferentTunerForSetFilter, int settingsWindowSetFilterTunerSelection, int settingsWindowDiseqc, bool settingsWindowCollectIqGraphs, bool settingsWindowCollectRfSpectrum, bool settingsWindowCaptureFile, int settingsWindowSatellite, int settingsWindowLnb, int dish, bool settingsWindowScanHorizontalLow, bool settingsWindowScanHorizontalHigh, bool settingsWindowScanVerticalLow, bool settingsWindowScanVerticalHigh);
|
||||
object[] GetLastUiBlindscanSettings();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1121,6 +1121,21 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void InsertUiBlindscanSettingHistory(int settingsWindowBlScanTunerSelection,
|
||||
bool settingsWindowUseDifferentTunerForSetFilter, int settingsWindowSetFilterTunerSelection,
|
||||
int settingsWindowDiseqc, bool settingsWindowCollectIqGraphs, bool settingsWindowCollectRfSpectrum,
|
||||
bool settingsWindowCaptureFile, int settingsWindowSatellite, int settingsWindowLnb, int dish,
|
||||
bool settingsWindowScanHorizontalLow, bool settingsWindowScanHorizontalHigh, bool settingsWindowScanVerticalLow,
|
||||
bool settingsWindowScanVerticalHigh)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object[] GetLastUiBlindscanSettings()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<int, int, ProgramMapping>> SelectAllPmt()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
@ -929,6 +929,21 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void InsertUiBlindscanSettingHistory(int settingsWindowBlScanTunerSelection,
|
||||
bool settingsWindowUseDifferentTunerForSetFilter, int settingsWindowSetFilterTunerSelection,
|
||||
int settingsWindowDiseqc, bool settingsWindowCollectIqGraphs, bool settingsWindowCollectRfSpectrum,
|
||||
bool settingsWindowCaptureFile, int settingsWindowSatellite, int settingsWindowLnb, int dish,
|
||||
bool settingsWindowScanHorizontalLow, bool settingsWindowScanHorizontalHigh, bool settingsWindowScanVerticalLow,
|
||||
bool settingsWindowScanVerticalHigh)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object[] GetLastUiBlindscanSettings()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<int, int, ProgramMapping>> SelectAllPmt()
|
||||
{
|
||||
for (int x = 0; x < pmtEntries.Length; x++)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.InteropServices;
|
||||
using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
|
||||
|
||||
namespace skyscraper5.Skyscraper
|
||||
@ -43,5 +44,19 @@ namespace skyscraper5.Skyscraper
|
||||
default: throw new NotImplementedException(String.Format("{0} {1}", nameof(DiseqcType), DiseqcType));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSatellite()
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case STD_TYPE.STD_DVBS: return true;
|
||||
case STD_TYPE.STD_DVBS2: return true;
|
||||
case STD_TYPE.STD_DVBT: return false;
|
||||
case STD_TYPE.STD_DVBT2: return false;
|
||||
case STD_TYPE.STD_DVBC: return false;
|
||||
case STD_TYPE.STD_DVBC2: return false;
|
||||
default: throw new NotImplementedException(Type.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user