Can now create RF Spectrums in the ImGui.

This commit is contained in:
feyris-tan 2025-08-06 22:05:22 +02:00
parent e091c3469d
commit 5eff90d0de
14 changed files with 273 additions and 15 deletions

View File

@ -11,6 +11,7 @@ using skyscraper8.Skyscraper.Scraper.Storage;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
@ -314,5 +315,20 @@ namespace skyscraper5.Data
WriteObject(fullName, ms);
}
public void StoreRfSpectrum(Guid jobGuid, RfSpectrumData rfSpectrum)
{
if (definetlyKnownFiles == null)
definetlyKnownFiles = new HashSet<string>();
if (definetlyMissingFiles == null)
definetlyMissingFiles = new HashSet<string>();
string fullName = String.Format("/rf/{0}.rf", jobGuid.ToString("D"));
MemoryStream ms = new MemoryStream();
rfSpectrum.SaveTo(ms);
ms.Position = 0;
WriteObject(fullName, ms);
}
}
}

View File

@ -14,9 +14,9 @@ using testdrid.SdlWrapper;
namespace skyscraper8.UI.ImGui.Forms
{
internal class SdlScottPlotWindow : SdlWindow
internal class SdlScottPlotWindow : SdlWindow, IDisposable
{
private readonly Plot _plot;
protected readonly Plot _plot;
private readonly SKBitmap _skBitmap;
private readonly SKCanvas _skCanvas;
@ -32,6 +32,7 @@ namespace skyscraper8.UI.ImGui.Forms
private int dataLength;
protected override void RenderInternal(Texture surface)
{
BeforeRender();
_plot.Render(_skCanvas, (int)this._size.X, (int)this._size.Y);
nint data0 = surface.GetData0();
@ -47,5 +48,17 @@ namespace skyscraper8.UI.ImGui.Forms
Marshal.Copy(tempBuffer, 0, data0, dataLength);
}
protected virtual void BeforeRender()
{
}
public void Dispose()
{
_plot.Dispose();
_skBitmap.Dispose();
_skCanvas.Dispose();
}
}
}

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Echo.UserInterface.Backend;
using ScottPlot;
using ScottPlot.Plottables;
using skyscraper5.Dvb.Descriptors;
using skyscraper5.src.InteractionChannel.Model;
using Color = System.Drawing.Color;
namespace skyscraper8.UI.ImGui.Forms
{
internal class SdlScottPlotWindowRfSpectrum : SdlScottPlotWindow
{
private DataLogger[] loggers;
private Color[] colors = new Color[]
{
System.Drawing.Color.FromArgb(52, 152, 152),
System.Drawing.Color.FromArgb(252, 52, 52),
System.Drawing.Color.FromArgb(152, 52, 152),
System.Drawing.Color.FromArgb(52, 52, 252),
};
public SdlScottPlotWindowRfSpectrum(ImGuiDevice imGuiDevice)
: base(imGuiDevice, new Plot(), 1000, 200, "RF Spectrum")
{
locakable = new object();
}
protected override void BeforeRender()
{
if (_queuedSamples == null)
return;
lock (locakable)
{
while (_queuedSamples.Count > 0)
{
Tuple<SatelliteDeliverySystemDescriptor.PolarizationEnum, int, double> value = _queuedSamples.Dequeue();
if (loggers == null)
loggers = new DataLogger[4];
if (loggers[(int)value.Item1] == null)
{
loggers[(int)value.Item1] = _plot.Add.DataLogger();
loggers[(int)value.Item1].LegendText = value.Item1.ToString();
loggers[(int)value.Item1].Color = ScottPlot.Color.FromColor(colors[(int)value.Item1]);
}
loggers[(int)value.Item1].Add(value.Item2, value.Item3);
}
}
}
private Queue<Tuple<SatelliteDeliverySystemDescriptor.PolarizationEnum, int, double>> _queuedSamples;
private object locakable;
public void EnqueueSample(SatelliteDeliverySystemDescriptor.PolarizationEnum polarization, int frequency, double sample)
{
if (_queuedSamples == null)
_queuedSamples = new Queue<Tuple<SatelliteDeliverySystemDescriptor.PolarizationEnum, int, double>>();
lock (locakable)
{
_queuedSamples.Enqueue(new Tuple<SatelliteDeliverySystemDescriptor.PolarizationEnum, int, double>(polarization, frequency, sample));
}
}
}
}

View File

@ -1,6 +1,7 @@
using ImGuiNET;
using SDL2Demo.Forms;
using SDL2Demo.SdlWrapper;
using skyscraper5.Dvb.Descriptors;
using skyscraper5.Skyscraper;
using skyscraper5.Skyscraper.Equipment;
using skyscraper5.Skyscraper.IO;
@ -8,7 +9,9 @@ using skyscraper5.Skyscraper.IO.CrazycatStreamReader;
using skyscraper5.Skyscraper.Scraper;
using skyscraper5.src.Mpeg2.PacketFilter;
using skyscraper5.src.Skyscraper.FrequencyListGenerator;
using skyscraper8.Skyscraper.Drawing;
using skyscraper8.Skyscraper.Plugins;
using skyscraper8.UI.ImGui.Forms;
using System;
using System.Collections.Generic;
using System.Drawing;
@ -17,7 +20,7 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Skyscraper.Drawing;
using testdrid.SdlWrapper;
using static SDL2Demo.Jobs.Blindscan;
namespace SDL2Demo.Jobs
@ -71,6 +74,7 @@ namespace SDL2Demo.Jobs
private int settingsWindowDiseqc;
private int settingsWindowSatellite;
private bool settingsWindowCollectIqGraphs;
private bool settingsWindowCollectRfSpectrum;
public void Render()
{
@ -136,6 +140,7 @@ namespace SDL2Demo.Jobs
ImGui.Checkbox("Scan Low Vertical Region", ref settingsWindowScanVerticalLow);
ImGui.Checkbox("Scan High Vertical Region", ref settingsWindowScanVerticalHigh);
ImGui.Checkbox("Collect IQ Graphs", ref settingsWindowCollectIqGraphs);
ImGui.Checkbox("Collect RF Spectrum", ref settingsWindowCollectRfSpectrum);
ImGui.PushID("diseqc");
ImGui.Text("DiSEqC");
@ -264,6 +269,15 @@ namespace SDL2Demo.Jobs
{
Caps caps = Configuration.TunerA.Caps;
if (settingsWindowCollectRfSpectrum)
{
SetTuner(1);
RfSpectrumData rfSpectrum = GatherRfSpectrum();
if (rfSpectrum != null)
{
jobContext.ObjectStorage.StoreRfSpectrum(jobInDb.JobGuid, rfSpectrum);
}
}
if (caps.HasFlag(Caps.SR_BLSCAN2))
{
SearchResult sr1 = default;
@ -513,7 +527,7 @@ namespace SDL2Demo.Jobs
throw new NotImplementedException("Don't know how to blindscan with this tuner.");
}
}
private bool somethingStarted;
private int lastTuner;
private bool SetTuner(int mode)
@ -689,10 +703,102 @@ namespace SDL2Demo.Jobs
JobContext.Puppets[3].AutoMoveToHome();
}
private IqChartData GatherIQGraphCable()
private RfSpectrumData GatherRfSpectrum()
{
Caps caps = streamReader.GetCaps();
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;
}
SdlScottPlotWindowRfSpectrum window = new SdlScottPlotWindowRfSpectrum(jobContext.ImgUiDevice);
jobContext.Renderables.Add(window);
int lof1 = Configuration.LnbType.Lof1 * 1000;
int lof2 = Configuration.LnbType.Lof2 * 1000;
int lofSw = Configuration.LnbType.LofSw * 1000;
int startFreq = Configuration.LnbType.MinimumFrequency * 1000;
int endFreq = Configuration.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;
streamReader.SendDiSEqC(2, diseqcCmd);
RfSpectrumDataBlock block = spectrumData.CreateBlock(startFreq, endFreq, STEP, polarization);
for (int i = startFreq; i <= endFreq; i += STEP)
{
double rf = Double.NaN;
streamReader.RFScan(i, diseqcCmd.HasFlag(DiSEqC_Opcode.DISEQC_HORIZONTAL) ? 0 : 1, lof1, lof2, lofSw, out rf);
Console.WriteLine("{0} {1}, {2}", i, polarization.ToString().Substring(0, 1), rf);
block.Push(i, rf);
window.EnqueueSample(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);
}
lock (jobContext.Renderables)
{
JobContext.Renderables.Remove(window);
window.Dispose();
window = null;
}
return spectrumData;
}
private RfSpectrumData GatherRfSpectrumCable()
{
throw new NotImplementedException();
}
private IEnumerable<DiSEqC_Opcode> GetIqGraphDiseqcOpcodes()
{
DiSEqC_Opcode baseDiseqc = DiSEqC_Opcode.DISEQC_HIGH_NIBBLE;
int parameter = Configuration.Diseqc;
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 (settingsWindowScanHorizontalLow || settingsWindowScanHorizontalHigh)
yield return baseDiseqc | DiSEqC_Opcode.DISEQC_HORIZONTAL | DiSEqC_Opcode.DISEQC_LOW_BAND;
if (settingsWindowScanVerticalLow || settingsWindowScanVerticalHigh)
yield return baseDiseqc | DiSEqC_Opcode.DISEQC_VERTICAL | DiSEqC_Opcode.DISEQC_LOW_BAND;
yield break;
}
private IqChartData GatherIqGraph()
{
Caps caps = streamReader.GetCaps();
@ -707,13 +813,17 @@ namespace SDL2Demo.Jobs
return null;
}
/*
*
*/
IqChartData result = IqChartData.Create();
IqWindow iqWindow = new IqWindow(JobContext.ImgUiDevice, result);
JobContext.Renderables.Add(iqWindow);
sbyte[] buffer = new sbyte[200];
sbyte[] buffer = new sbyte[400];
DateTime started = DateTime.Now;
while (!result.IsComplete)
{
bool iqScan = streamReader.IQScan(0, buffer, 100);
bool iqScan = streamReader.IQScan(0, buffer, (uint)(buffer.Length / 2));
if (!iqScan)
{
result = null;
@ -722,6 +832,8 @@ namespace SDL2Demo.Jobs
}
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);
lock (jobContext.Renderables)
{
@ -732,6 +844,10 @@ namespace SDL2Demo.Jobs
return result;
}
private IqChartData GatherIQGraphCable()
{
throw new NotImplementedException();
}
private void RunSkyscraper(BlindscanResult result)
{

View File

@ -777,7 +777,7 @@ namespace SkyscraperUI
ImGui.Render();
}
private void TestdridClass_Quit(SDL.SDL_QuitEvent qe)
{
quit = true;

View File

@ -39,6 +39,10 @@ namespace skyscraper8.DvbI
string s = Encoding.UTF8.GetString(buffer);
s = s.Replace("<dvbi-types:URI>", "<URI>");
s = s.Replace("</dvbi-types:URI>", "</URI>");
if (s.Contains("urn:dvb:metadata:servicediscovery:2025"))
{
s = s.Replace("urn:dvb:metadata:servicediscovery:2025", "urn:dvb:metadata:servicediscovery:2024");
}
object slWrapped = serviceListSerializer.Deserialize(new StringReader(s));
ServiceListType slt = (ServiceListType)slWrapped;
@ -270,6 +274,10 @@ namespace skyscraper8.DvbI
if (serviceListEntryPointSerializer == null)
serviceListEntryPointSerializer = new XmlSerializer(typeof(ServiceListEntryPoints));
if (rawSlepString.Contains("urn:dvb:metadata:servicelistdiscovery:2025"))
{
rawSlepString = rawSlepString.Replace("urn:dvb:metadata:servicelistdiscovery:2025", "urn:dvb:metadata:servicelistdiscovery:2024");
}
StringReader stringReader = new StringReader(rawSlepString);
object slepWrapped = serviceListEntryPointSerializer.Deserialize(stringReader);
ServiceListEntryPoints serviceListEntryPoint = (ServiceListEntryPoints)slepWrapped;

View File

@ -103,7 +103,10 @@ namespace skyscraper8.DvbNip
if (isValidXml)
{
FDTInstanceType fdtAnnouncement = FluteUtilities.UnpackFluteFdt(fluteStream);
SetFileAssociations(fluteListener, fdtAnnouncement);
if (fdtAnnouncement != null)
{
SetFileAssociations(fluteListener, fdtAnnouncement);
}
}
fluteStream.Close();
fluteStream.Dispose();

View File

@ -26,8 +26,17 @@ namespace skyscraper8.Ietf.FLUTE
if (fdtSerializer == null)
fdtSerializer = new XmlSerializer(typeof(FDTInstanceType));
FDTInstanceType result = (FDTInstanceType)fdtSerializer.Deserialize(ms);
return result;
try
{
FDTInstanceType result = (FDTInstanceType)fdtSerializer.Deserialize(ms);
return result;
}
catch (InvalidOperationException e)
{
Console.WriteLine(e);
return null;
}
}
public static bool IsXmlWellFormed(Stream xmlStream)

View File

@ -2,7 +2,7 @@
"profiles": {
"skyscraper8": {
"commandName": "Project",
"commandLineArgs": "\"Z:\\Freebies\\Datasets\\SkyscraperLibrarian\\DVB-S Juli 2025\\movistar-000000.ts\"",
"commandLineArgs": "\"Z:\\TelephoneExchange\\11141_h_20250805_2233.ts\"",
"remoteDebugEnabled": false
},
"Container (Dockerfile)": {

View File

@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb.Descriptors;
using skyscraper5.Skyscraper.IO;
using skyscraper5.src.Sophtainer;
namespace skyscraper8.Skyscraper.Drawing
{
@ -31,8 +32,11 @@ namespace skyscraper8.Skyscraper.Drawing
return child;
}
public void SaveTo(Stream stream)
public void SaveTo(Stream outerStream)
{
Sophtainer sophtainer = Sophtainer.CreateSophtainer(outerStream, 538986066u, new Version(1, 0, 0, 0));
OffsetStream stream = sophtainer.GetStream();
foreach (RfSpectrumDataBlock block in blocks)
{
stream.WriteUInt8(0x58);
@ -47,6 +51,7 @@ namespace skyscraper8.Skyscraper.Drawing
}
stream.WriteUInt8(0x4f);
}
}

View File

@ -1460,6 +1460,11 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
throw new NotImplementedException();
}
public void StoreRfSpectrum(Guid jobGuid, RfSpectrumData rfSpectrum)
{
throw new NotImplementedException();
}
public bool DvbNipPrivateDataSpecifier(NipActualCarrierInformation currentCarrierInformation, DateTime versionUpdate,
uint privateDataSpecifier, List<string> privateDataSessions)
{

View File

@ -1493,14 +1493,21 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
_nipMulticastGatewayConfigurationTransportSessions.Add(key, multicastGatewayConfigurationTransportSession);
}
private HashSet<NipActualCarrierInformation> _nipActualCarriers;
public bool DvbNipTestForCarrier(NipActualCarrierInformation currentCarrierInformation)
{
throw new NotImplementedException();
if (_nipActualCarriers == null)
return false;
return _nipActualCarriers.Contains(currentCarrierInformation);
}
public void DvbNipInsertCarrier(NipActualCarrierInformation currentCarrierInformation)
{
throw new NotImplementedException();
if (_nipActualCarriers == null)
_nipActualCarriers = new HashSet<NipActualCarrierInformation>();
_nipActualCarriers.Add(currentCarrierInformation);
}
public void InsertDvbiServiceListEntryPoint(long sourceHash)

View File

@ -83,5 +83,10 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
{
throw new NotImplementedException();
}
public void StoreRfSpectrum(Guid jobGuid, RfSpectrumData rfSpectrum)
{
throw new NotImplementedException();
}
}
}

View File

@ -27,5 +27,6 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
bool DvbNipTestForFile(string announcedFileContentLocation);
void DvbNipFileArrival(NipActualCarrierInformation carrier, FluteListener listener);
void StoreIqGraph(Guid jobGuid, long frequency, char polarity, IqChartData plot);
void StoreRfSpectrum(Guid jobGuid, RfSpectrumData rfSpectrum);
}
}