Ideas for SDRsharp Plugins, for newer Version 1922, for example

Hello, I'm Micha from Germany, near Cologne. Some of you may already know 
my posts on RTL-SDR.com, about analog TV received via the Spy-Server 
network.

In all my attempts to get better pictures and a stronger signal, 
I've become a loyal user of SDRSharp version 1922 and the old TV plugin. 
For my purposes, especially regarding Spy-Server reception, this simply 
works best. While SDRAngel and SDR++ offer some other options, 
their compatibility with the Spy-Server is limited, making 
them unsuitable 
for my needs.
And here's my idea, which I can't implement on my own. It's about 
plugins for the newer version of the SDRsharp program 
(e.g., version 1922). 
Some requirements in the plugin programming have changed, so some 
older plugins no longer work, for example, Scytalec. Some programs 
can be integrated using a virtual audio cable (e.g., MultiPSK and 
Sorcerer). However, this only works with audio signals. Video signals 
would be better for my purposes. The old TV plugin can certainly tap 
into the video signals, so there must be a way.

Even though analog TV is on its last legs, there are already a few 
programs that would offer an improvement, such as TVsharper or 
Tempest. More tuning options could definitely result in better 
pictures. Unfortunately, these programs are designed as stand-alone 
decoders, and there's obviously no interface to work with SDRsharp, 
or rather, SDRsharp can't pass the video signals through.
Thinking about it further, it would be an absolute asset for all 
of us to develop more plugins that bring many new functions to 
Spyserver mode, e.g.
DAB(+) (the 1.5 MHz bandwidth is no obstacle, and countless radio 
stations can be received)

nrsc5 (digital radio from the USA via spy servers, for everyone, 
including weather and traffic)

Scytalec (so that this useful program works again with the new 
SDR Sharps)
Tempest (some online SDRs do transmit data signals from PCs in 
their vicinity; alternatively, analog TV signals can potentially 
be improved through many options)

TVsharper (a few more options than the conventional TVsharp)

DVB-T(2) (some online SDRs transmit a bandwidth of 8 MHz and more, 
which would be sufficient)

etc...

Ever-increasing bandwidths on online spy servers open up new 
possibilities. The source code for most of these programs exists 
on GitHub. Only the adaptations for SDRSharp and the final compilation 
are missing. I have theoretical programming knowledge, but no 
practical experience yet. Perhaps one of you has the desire 
and imagination to help.

On a Finnish forum, I found information on rewriting old plugins:

https://
teknokoodiradio.vuodatus.net/lue/2021/03/modifying-old-sdr-tetra-
demod-plug-in

teknokoodiradio.vuodatus.net/lue/2021/07/modify-sdr-ctcss-plug-in-
to-decode-ccir

teknokoodiradio.vuodatus.net/lue/2021/07/mods-for-sdr-tetra-
demod-plugin-1-0-14-0-2

teknokoodiradio.vuodatus.net/lue/2021/06/mods-for-sdr-tetra-
demod-plugin-1-0-14-0

/teknokoodiradio.vuodatus.net/lue/2021/06/modifying-sdr-tetra-
demod-plugin-1-0-14-0-ext-sub-num

teknokoodiradio.vuodatus.net/lue/2021/05/modifying-sdr-tetra-
demod-plugin-1-0-14-0-sds-type-4

teknokoodiradio.vuodatus.net/lue/2021/04/rds-data-from-sdr-to-
rdsspy-with-tcp-2

teknokoodiradio.vuodatus.net/lue/2021/04/modifying-old-sdr-tetra-
demod-plug-in-2

teknokoodiradio.vuodatus.net/lue/2021/03/sdr-tetra-demod-plug-in-
udp-output

teknokoodiradio.vuodatus.net/lue/2021/03/modifying-old-sdr-tetra-
demod-plug-in

teknokoodiradio.vuodatus.net/lue/2021/02/rds-data-from-sdr-to-
rdsspy-with-tcp

teknokoodiradio.vuodatus.net/lue/2021/01/dot-net-peeking-sdr-dcs-
decoder-plug-in

teknokoodiradio.vuodatus.net/lue/2020/04/sdrsharp-telerik-ui-
versions-fft-peek-hold-plug-in

teknokoodiradio.vuodatus.net/lue/2019/06/sdrsharp-fft-peek-hold-
plug-in-version-0-91

teknokoodiradio.vuodatus.net/lue/2019/06/sdrsharp-fft-peek-hold-
plug-in

While these aren't the required programs, this guide demonstrates
 how to modify the old plugins to make them compatible with newer 
SDRsharp versions.

It would also be necessary to determine whether the GitHub source 
code can be used.

Which function in SDRsharp passes the data stream to the TVPlugin? 
This function must occur long before the graphical display in the 
spectrum analyzer because only a few settings affect this signal.

Use full I/Q (If active - all modulation formats WFM/ NFM/ AM/.....)
Bandwidth
I/Q Format
Gain
Baseband Noise Blanker

Does anyone here have experience with coding source code? I haven't 
been able to compile even a single piece of text in Visual Studio 
so far.

Gruß Micha





Does anyone here have experience with coding source code? I haven’t
been able to compile even a single piece of text in Visual Studio
so far.

Hi Micha,

I’ve used Visual Studio very extensively, though that was back then when VS2005 and VS2008 were the current versions. :wink:

As a general rule of thumb, source code for VS should include some solution or project file(s) such as .sln -– you just load that file, and the solution should build without any issue if you use the proper version of Visual Studio and have the rest of the code available. Newer versions of VS can usually upgrade solutions created with older Versions of VS, but the reverse is obviously not true; however, you’re not likely to encounter that situation, plus it’s latest version that is available for easy download from Microsoft.

If you post some github links I could take a look to see if I can build them.

Mit herzlichen grüssen

Hi, I've compiled a few URLs here. Some lead to source code, others to 
ideas. Direct solutions are unlikely. The list isn't exhaustive.

I don't invest enough time in VB because the program runs extremely slowly 
and is very time-consuming on my PC. I can load GitHub files, install a suitable decoder (e.g., C++), and then I can't compile because VB keeps 
asking for a C++ decoder, which it claims isn't installed. Even after installing several more C++ decoders, the problem persists. After that, 
I lose time and motivation. That's my problem... unfortunately.

Hi, ich habe hier ein
paar URLs zusammengestellt. Einige führen zu Quelltexten, einige 
andere zu Ideen. Direkte Lösungen wird es kaum geben. Die Auflistung 
ist nicht komplett.

Ich investiere zu wenig Zeit in VB, weil das Programm auf meinem PC 
extrem schleppend und zeitaufwendig läuft. Ich kann GitHub Dateien 
laden, installiere einen passenden Decoder (zB C++) und danach kann 
ich nicht kompilieren, weil VB immer wieder nach einem C++ Decoder 
schreit, der angeblich nicht installiert ist. Auch nach weiteren C++ 
Decoder installationen bleibt das Problem bestehen. Danach verliere 
ich Zeit und Lust. Das ist mein Problem....leider 

Gruß Micha


https://github.com/microp11/iridiumlive/tree/master

https://github.com/theori-io/nrsc5

https://github.com/argilo/gr-nrsc5

https://github.com/theori-io/nrsc5/tree/master

https://theori.io/blog/receiving-nrsc-5

https://github.com/evuraan/yellowShoes/tree/yellowShoes_with_Webamp_Milkdrop/bin       (NRSC5 HD Radio)

https://bitbucket.org/scytalec/sdrsharp.scytalec/src/master/

https://github.com/Sultan-papagani/TVSharp-archive

https://github.com/jvde-github/AIS-catcher

https://github.com/dmitryelj/multimon-ng

https://github.com/EliasOenal/multimon-ng/blob/master/README.md

https://github.com/f4exb/sdrdaemon

https://github.com/racerxdl/gr-osmosdr/tree/master/lib/spyserver

https://github.com/Daniel-D-F-Rushton/SdrSharpPocsagPlugin-Personal-Modification/blob/master/readme.md

https://github.com/Dustify/SdrSharpPocsagPlugin/releases

https://medium.com/@rxseger/receiving-atsc-digital-television-with-an-sdr-76b03a863fea

https://github.com/emidan19/deep-tempest

https://raw.github.com/martinmarinov/TempestSDR/master/Release/JavaGUI/JTempestSDR.jar

https://github.com/jontio/JAERO/tree/master/udptextserver

https://github.com/jeroenbeijer/SDRReceiver

https://github.com/jontio/JAERO

https://github.com/muaddib1984/gr-JAERO

https://www.google.com/search?sca_esv=e6a856e083a4051b&q=jaero+github&udm=2&fbs=AIIjpHw2KGh6wpocn18KLjPMw8n5Yp8-1M0n6BD6JoVBP_K3fXXvA3S3XGyupmJLMg20um8hy4vyQEDbAMWHf807SuZaxgLfOpi71v8Q1zbdN7umsrqeZGQbNI7XItwf-0D79i_-AH8ot-XEJjC01Hhqjq6vUGH9ar_vbWVnJ-k2cFOLM82iiU6qnzdNT09K-oZM9m5dXvSU&sa=X&ved=2ahUKEwiI4pzYsd2OAxVXSvEDHc1UMWQQtKgLKAF6BAgVEAE&biw=1366&bih=615&dpr=1

https://github.com/omriiluz/NRF24-BTLE-Decoder

https://thebaldgeek.github.io/SDRReceiver.html

https://github.com/steve-m/rtltcpaccess

https://github.com/vgpastor/SDR-Tetra-Plugin

https://emeyeattack.github.io/Website/#Code

https://github.com/longyan97/EMEye_Tutorial

http://www.andreadrian.de/babyphone/index.html

https://r4uab.ru/priyom-meteosnimkov-so-sputnikov-meteor-m/

https://www.dsdplus.com/

https://www.hamspirit.de/2713/wie-du-ein-dmr-signal-mit-dem-digital-speech-decoder-und-einem-rtl-sdr-dekodieren-kannst/

https://github.com/projecthorus/radiosonde_auto_rx/wiki

https://lea.hamradio.si/~s53mv/navsats/theory.html

https://github.com/romanz/amodem

https://github.com/JvanKatwijk/qt-dab

https://www.ukwtv.de/cms/radio-dx/downloads/dab-software.html

https://qirx.softsyst.com/QIRXInstall

https://www.qsl.net/yo4tnv/HamSoftware/SDR/

https://medium.com/@rxseger/receiving-ir-signals-with-rtl-sdr-dongles-5a8658a44b90

https://stjarnhimlen.se/tv/tv.html

https://www.rtl-sdr.com/tag/dab/

https://www.rtl-sdr.com/tag/dvb-t/

https://github.com/github/gitignore/blob/master/VisualStudio.gitignore












OK, the topic is extensive and a finished solution cannot be obtained without your own initiative. Furthermore, I have to do this in many individual steps to understand it. My idea:
Use JetBrains-DotPeek to determine the source code of SharpTV.dll. The result looks good.
Then transfer this text to Visual Studio and compile it with the DLL plugin. That doesn’t work.
Although the source code must work and is comparable to all other source codes and other SDR TV programs, errors are always displayed…

// Decompiled with JetBrains decompiler

// Type: SDRSharp.TV.TVPanel

// Assembly: SDRSharp.TV, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

// MVID: B61910CA-9F13-447D-A855-75D6C2A7C66F

// Assembly location: C:\sdrsharp-x86(2)\SDRSharp.TV.dll

using SDRSharp.Common;

using SDRSharp.Radio;

using System;

using System.ComponentModel;

using System.Drawing;

using System.Threading;

using System.Windows.Forms

#nullable disable

namespace SDRSharp.TV;

public class TVPanel : UserControl

{

private IFProcessor _ifProcessor;

private ISharpControl _control;

private int _decimationRatio;

private bool _filterEnabled;

private DownConverter _complexDDC;

private UnsafeBuffer _tvBuffer;

private unsafe Complex* _tvBufferPtr;

private UnsafeBuffer _normalizedVideo;

private unsafe float* _normalizedVideoPtr;

private UnsafeBuffer _grayScaleBuffer;

private unsafe byte* _grayScaleBufferPtr;

private UnsafeBuffer _videoWindowBuffer;

private unsafe byte* _videoWindowBufferPtr;

private int _iqBufferMaxLength;

private int _partsBuffersLength;

private int _count;

private bool _isDecoding;

private int _pictureWidth;

private double _horizontalStep;

private int _pictureHeight;

private float _countryCoeff;

private int _lineInFrame;

private float _maxSignalLevel;

private float _blackLevel;

private float _bright;

private float _contrast;

private float _coeff;

private double _sampleRate;

private VideoWindow _videoWindow;

private int _lengthOfGrayScaleArray;

private ComplexFifoStream _iqBuffer;

private float _average;

private Thread _tvThread;

private readonly SharpEvent _bufferEvent = new SharpEvent(false);

private float _lastImag;

private float _lastReal;

private bool _modulationAM;

private bool _pause;

private bool _frameReady;

private byte _lastFilter;

private bool _videoFilter;

private float _ratio = 1E-05f;

private int[] _horizontalSyncArray;

private int[] _verticalSyncArray;

private float _horizontalCorrectAverage;

private int _verticalCorrectAverage;

private bool _sync;

private bool _swapIQ;

private int _positionX;

private int _positionY;

private double _indexSource;

private int _prevHorizontalIndex;

private bool _needClose;

private IContainer components;

private System.Windows.Forms.Timer displayUpdateTimer;

private CheckBox enableCheckBox;

private Label countLabel;

private TrackBar brightnesTrackBar;

private TrackBar contrastTrackBar;

private Label label1;

private Label label2;

private CheckBox pauseCheckBox;

private CheckBox videoFilterCheckBox;

private CheckBox syncOffCheckBox;

private ComboBox palNTSCComboBox;

private ComboBox AmFmComboBox;

public TVPanel(ISharpControl control)

{

this.InitializeComponent();

VideoWindow videoWindow = new VideoWindow();

videoWindow.Visible = false;

videoWindow.TopMost = true;

this._videoWindow = videoWindow;

this._videoWindow.FormClosing += new FormClosingEventHandler(this._videoWindow_FormClosing);

this._control = control;

this._ifProcessor = new IFProcessor();

this._control.PropertyChanged += new PropertyChangedEventHandler(this.NotifyPropertyChangedHandler);

this._control.RegisterStreamHook((object) this._ifProcessor, (ProcessorType) 0);

this._ifProcessor.Enabled = false;

this._ifProcessor.IQReady += new IFProcessor.IQReadyDelegate(this.BufferAvailable);

this.brightnesTrackBar.Value = Utils.GetIntSetting(“TV.Bright”, 50);

this.brightnesTrackBar_Scroll((object) null, (EventArgs) null);

this.contrastTrackBar.Value = Utils.GetIntSetting(“TV.Contrast”, 50);

this.contrastTrackBar_Scroll((object) null, (EventArgs) null);

this.AmFmComboBox.SelectedIndex = Utils.GetIntSetting(“TV.Modulation”, 0);

this.AmFmComboBox_SelectedIndexChanged((object) null, (EventArgs) null);

this.videoFilterCheckBox.Checked = Utils.GetBooleanSetting(“TV.VideoFilter”);

this.palNTSCComboBox.SelectedIndex = Utils.GetIntSetting(“TV.Pal_NTSC”, 0);

this.syncOffCheckBox.Checked = Utils.GetBooleanSetting(“TV.ManualSync”);

this.syncOffCheckBox_CheckedChanged((object) null, (EventArgs) null);

}

private void _videoWindow_FormClosing(object sender, FormClosingEventArgs e)

{

e.Cancel = true;

this._needClose = true;

}

public void StoreSettings()

{

if (this._isDecoding)

this.StopDecoding();

Utils.SaveSetting(“TV.Bright”, (object) this.brightnesTrackBar.Value);

Utils.SaveSetting(“TV.Contrast”, (object) this.contrastTrackBar.Value);

Utils.SaveSetting(“TV.Modulation”, (object) this.AmFmComboBox.SelectedIndex);

Utils.SaveSetting(“TV.VideoFilter”, (object) this.videoFilterCheckBox.Checked);

Utils.SaveSetting(“TV.Pal_NTSC”, (object) this.palNTSCComboBox.SelectedIndex);

Utils.SaveSetting(“TV.ManualSync”, (object) this.syncOffCheckBox.Checked);

}

private void NotifyPropertyChangedHandler(object sender, PropertyChangedEventArgs e)

{

switch (e.PropertyName)

{

case “StartRadio”:

this.enableCheckBox_CheckedChanged((object) null, (EventArgs) null);

break;

case “StopRadio”:

if (!this._isDecoding)

break;

this.StopDecoding();

break;

case “SwapIq”:

this._swapIQ = this._control.SwapIq;

break;

case “CenterFrequency”:

this._horizontalCorrectAverage = 0.0f;

this._verticalCorrectAverage = 0;

break;

}

}

private void StartDecoding()

{

this._sampleRate = this._ifProcessor.SampleRate;

this.palNTSCComboBox.Enabled = false;

if (this.palNTSCComboBox.SelectedIndex == 0)

{

this._countryCoeff = 15625f;

this._lineInFrame = 625;

}

else

{

this._countryCoeff = 15734.25f;

this._lineInFrame = 525;

}

this._pictureHeight = this._lineInFrame;

this._pictureWidth = 400;

this._horizontalStep = this._sampleRate / ((double) this._countryCoeff * (double) this._pictureWidth);

if (this._sampleRate >= 8000000.0)

{

this._decimationRatio = 2;

this._complexDDC = new DownConverter(this._sampleRate, this._decimationRatio);

this._horizontalStep /= (double) this._decimationRatio;

int num = -1;

if (this._swapIQ)

num = 1;

this._complexDDC.Frequency = this.palNTSCComboBox.SelectedIndex != 0 ? this._sampleRate * 0.20000000298023224 * (double) num : this._sampleRate * 0.30000001192092896 * (double) num;

this._filterEnabled = true;

}

else

{

this._decimationRatio = 1;

this._filterEnabled = false;

}

this._lengthOfGrayScaleArray = this._pictureHeight * this._pictureWidth;

this._horizontalSyncArray = new int[this._pictureWidth];

this._verticalSyncArray = new int[this._pictureHeight];

this._horizontalCorrectAverage = 0.0f;

this._verticalCorrectAverage = 0;

this.CreateBuffers();

this._videoWindow.Visible = true;

this._ifProcessor.Enabled = true;

this._isDecoding = true;

this._count = 0;

this._tvThread = new Thread(new ThreadStart(this.TVProcess))

{

Name = “TV Process”,

Priority = ThreadPriority.Highest

};

this._tvThread.Start();

}

private void StopDecoding()

{

this._isDecoding = false;

this._bufferEvent.Set();

if (this._tvThread != null)

{

this._tvThread.Join();

this._tvThread = (Thread) null;

}

this._videoWindow.Visible = false;

this._ifProcessor.Enabled = false;

this.palNTSCComboBox.Enabled = true;

this.CloseBuffers();

}

private unsafe void TVProcess()

{

while (this._isDecoding)

{

if (this._iqBuffer.Length < this._partsBuffersLength && this._isDecoding)

{

Thread.Sleep(10);

}

else

{

this._iqBuffer.Read(this._tvBufferPtr, this._tvBuffer.Length);

if (this._filterEnabled)

this._complexDDC.Process(this._tvBufferPtr, this._tvBuffer.Length);

this._maxSignalLevel = (float) ((double) this._maxSignalLevel * 0.99000000953674316 + (!this._modulationAM ? (double) this.FmDetector(this._tvBufferPtr, this._normalizedVideoPtr, this._partsBuffersLength) : (double) this.AmDetector(this._tvBufferPtr, this._normalizedVideoPtr, this._partsBuffersLength)) * 0.0099999997764825821);

this._blackLevel = this._maxSignalLevel * 0.7f;

this._coeff = 1f / this._blackLevel;

this.VideoBufferProcess(this._normalizedVideoPtr, this._grayScaleBufferPtr, this._partsBuffersLength);

}

}

}

private unsafe void SwapIQ(Complex* buffer, int length)

{

for (int index = 0; index < length; ++index)

{

float real = buffer[index].Real;

buffer[index].Real = buffer[index].Imag;

buffer[index].Imag = real;

}

}

private unsafe void VideoFilter(byte* buffer, int length)

{

for (int index = 0; index < length; ++index)

{

buffer[index] = (byte) ((double) ((int) buffer[index] + (int) this._lastFilter) * 0.5);

this._lastFilter = buffer[index];

}

}

private unsafe float AmDetector(Complex* iqBuffer, float* videoBuffer, int length)

{

float num1 = float.MinValue;

for (int index = 0; index < length; ++index)

{

float num2 = ((Complex) (IntPtr) (iqBuffer + index)).Modulus();

videoBuffer[index] = num2;

num1 = (double) num2 > (double) num1 ? num2 : num1;

}

return num1;

}

private unsafe float FmDetector(Complex* iqBuffer, float* videoBuffer, int length)

{

float num1 = float.MinValue;

for (int index = 0; index < length; ++index)

{

float real = iqBuffer[index].Real;

float imag = iqBuffer[index].Imag;

float num2 = (float) ((double) this._lastReal * (double) imag - (double) this._lastImag * (double) real / ((double) real * (double) real + (double) imag * (double) imag));

this._lastReal = real;

this._lastImag = imag;

videoBuffer[index] = num2;

num1 = (double) num2 > (double) num1 ? num2 : num1;

}

return num1;

}

private unsafe void VideoBufferProcess(float* buffer, byte* grayBuffer, int length)

{

bool flag1 = false;

while (!flag1)

{

bool flag2 = false;

this._indexSource += this._horizontalStep + (double) this._horizontalCorrectAverage;

if (this._verticalCorrectAverage != 0)

{

this._indexSource += (this._horizontalStep + (double) this._horizontalCorrectAverage) * (double) this._pictureWidth * (double) this._verticalCorrectAverage;

this._verticalCorrectAverage = 0;

}

if (this._indexSource > (double) length)

{

this._indexSource -= (double) length;

break;

}

if (this._indexSource < 0.0)

{

this._indexSource += (double) length;

break;

}

float num1 = buffer[(int) this._indexSource];

if ((double) num1 > (double) this._blackLevel)

{

++this._horizontalSyncArray[this._positionX];

++this._verticalSyncArray[this._positionY];

}

this._average += this._ratio * (num1 - this._average);

float num2 = this._bright - (num1 - this._average) * this._contrast * this._coeff;

if ((double) num2 > (double) byte.MaxValue)

num2 = (float) byte.MaxValue;

if ((double) num2 < 0.0)

num2 = 0.0f;

int index = this._positionX + this._positionY * this._pictureWidth;

grayBuffer[index] = (byte) num2;

++this._positionX;

if (this._positionX >= this._pictureWidth)

{

this._positionY += 2;

this._positionX = 0;

}

if (this._positionY >= this._pictureHeight)

{

this._positionY &= 1;

this._positionY ^= 1;

flag2 = true;

}

if (flag2)

{

if (this._videoFilter)

this.VideoFilter(grayBuffer, this._lengthOfGrayScaleArray);

if (this._sync)

this.FrameSync();

Utils.Memcpy((void*) this._videoWindowBufferPtr, (void*) grayBuffer, this._lengthOfGrayScaleArray);

this._frameReady = true;

}

}

}

private void FrameSync()

{

int num1 = 0;

int num2 = 0;

int num3 = 0;

int num4 = 0;

for (int index = 0; index < this._horizontalSyncArray.Length; ++index)

{

if (this._horizontalSyncArray[index] > num1)

{

num2 = index;

num1 = this._horizontalSyncArray[index];

}

this._horizontalSyncArray[index] = 0;

}

for (int index = 0; index < this._verticalSyncArray.Length; ++index)

{

if (this._verticalSyncArray[index] > num3)

{

num4 = index;

num3 = this._verticalSyncArray[index];

}

this._verticalSyncArray[index] = 0;

}

int num5 = this._pictureWidth / 2;

int num6 = this._pictureHeight / 2;

int num7 = num2 + num5 - (this._prevHorizontalIndex + num5);

if (num7 > num5)

num7 -= this._pictureWidth;

if (num7 < -num5)

num7 += this._pictureWidth;

int num8 = num2;

if (num8 > num5)

num8 -= this._pictureWidth;

this._horizontalCorrectAverage += (float) ((double) num7 * 9.9999999747524271E-07 + (double) num8 * 9.99999993922529E-09);

if ((double) this._horizontalCorrectAverage > 0.0099999997764825821)

this._horizontalCorrectAverage = 0.01f;

if ((double) this._horizontalCorrectAverage < -0.0099999997764825821)

this._horizontalCorrectAverage = -0.01f;

this._prevHorizontalIndex = num2;

int num9 = num4;

if (num9 > num6)

num9 -= this._pictureHeight;

this._verticalCorrectAverage = (int) ((double) num9 * 0.10000000149011612);

if (this._verticalCorrectAverage > 2)

this._verticalCorrectAverage = 2;

if (this._verticalCorrectAverage >= -2)

return;

this._verticalCorrectAverage = -2;

}

private unsafe void DisplayUpdateTimer_Tick(object sender, EventArgs e)

{

if (!this._isDecoding && !this._frameReady)

return;

this.countLabel.Text = $“Lost buffers {this._count:N0}”;

this._frameReady = false;

this._videoWindow.DrawFrame(this._videoWindowBufferPtr, this._pictureWidth, this._pictureHeight);

if (!this._needClose)

return;

this._needClose = false;

this.enableCheckBox.Checked = false;

}

private unsafe void BufferAvailable(Complex* buffer, int length)

{

if (length == 0 || this._pause)

return;

if (this._iqBuffer.Length + length <= this._iqBufferMaxLength)

this._iqBuffer.Write(buffer, length);

else

++this._count;

this._bufferEvent.Set();

}

private unsafe void CreateBuffers()

{

this._iqBufferMaxLength = (int) this._sampleRate;

this._partsBuffersLength = 65536 /*0x010000*/ / this._decimationRatio;

this._iqBuffer = new ComplexFifoStream((BlockMode) 0, this._iqBufferMaxLength);

this._tvBuffer = UnsafeBuffer.Create(this._partsBuffersLength * this._decimationRatio, sizeof (Complex));

this._tvBufferPtr = (Complex*) UnsafeBuffer.op_Implicit(this._tvBuffer);

this._normalizedVideo = UnsafeBuffer.Create(this._partsBuffersLength, 4);

this._normalizedVideoPtr = (float*) UnsafeBuffer.op_Implicit(this._normalizedVideo);

this._grayScaleBuffer = UnsafeBuffer.Create(this._lengthOfGrayScaleArray, 1);

this._grayScaleBufferPtr = (byte*) UnsafeBuffer.op_Implicit(this._grayScaleBuffer);

this._videoWindowBuffer = UnsafeBuffer.Create(this._lengthOfGrayScaleArray, 1);

this._videoWindowBufferPtr = (byte*) UnsafeBuffer.op_Implicit(this._videoWindowBuffer);

}

private unsafe void CloseBuffers()

{

this._iqBuffer.Close();

this._iqBuffer.Dispose();

this._iqBuffer = (ComplexFifoStream) null;

this._tvBuffer.Dispose();

this._tvBufferPtr = (Complex*) null;

this._normalizedVideo.Dispose();

this._normalizedVideoPtr = (float*) null;

this._grayScaleBuffer.Dispose();

this._grayScaleBufferPtr = (byte*) null;

this._videoWindowBuffer.Dispose();

this._videoWindowBufferPtr = (byte*) null;

}

private void enableCheckBox_CheckedChanged(object sender, EventArgs e)

{

if (this.enableCheckBox.Checked && !this._isDecoding)

{

this.StartDecoding();

}

else

{

if (this.enableCheckBox.Checked || !this._isDecoding)

return;

this.StopDecoding();

}

}

private void brightnesTrackBar_Scroll(object sender, EventArgs e)

{

this._bright = (float) ((this.brightnesTrackBar.Value - 50) * 10);

}

private void contrastTrackBar_Scroll(object sender, EventArgs e)

{

this._contrast = (float) (this.contrastTrackBar.Value * 10 + 100);

}

private void pauseCheckBox_CheckedChanged(object sender, EventArgs e)

{

this._pause = this.pauseCheckBox.Checked;

}

private void videoFilterCheckBox_CheckedChanged(object sender, EventArgs e)

{

this._videoFilter = this.videoFilterCheckBox.Checked;

}

private void syncOffCheckBox_CheckedChanged(object sender, EventArgs e)

{

this._sync = !this.syncOffCheckBox.Checked;

}

private void AmFmComboBox_SelectedIndexChanged(object sender, EventArgs e)

{

this._modulationAM = this.AmFmComboBox.SelectedIndex == 0;

}

protected override void Dispose(bool disposing)

{

if (disposing && this.components != null)

this.components.Dispose();

base.Dispose(disposing);

}

private void InitializeComponent()

{

this.components = (IContainer) new System.ComponentModel.Container();

this.displayUpdateTimer = new System.Windows.Forms.Timer(this.components);

this.enableCheckBox = new CheckBox();

this.countLabel = new Label();

this.brightnesTrackBar = new TrackBar();

this.contrastTrackBar = new TrackBar();

this.label1 = new Label();

this.label2 = new Label();

this.pauseCheckBox = new CheckBox();

this.videoFilterCheckBox = new CheckBox();

this.syncOffCheckBox = new CheckBox();

this.palNTSCComboBox = new ComboBox();

this.AmFmComboBox = new ComboBox();

this.brightnesTrackBar.BeginInit();

this.contrastTrackBar.BeginInit();

this.SuspendLayout();

this.displayUpdateTimer.Enabled = true;

this.displayUpdateTimer.Interval = 10;

this.displayUpdateTimer.Tick += new EventHandler(this.DisplayUpdateTimer_Tick);

this.enableCheckBox.AutoSize = true;

this.enableCheckBox.Location = new Point(3, 3);

this.enableCheckBox.Name = “enableCheckBox”;

this.enableCheckBox.Size = new Size(40, 17);

this.enableCheckBox.TabIndex = 0;

this.enableCheckBox.Text = “TV”;

this.enableCheckBox.UseVisualStyleBackColor = true;

this.enableCheckBox.CheckedChanged += new EventHandler(this.enableCheckBox_CheckedChanged);

this.countLabel.AutoSize = true;

this.countLabel.Location = new Point(0, 154);

this.countLabel.Name = “countLabel”;

this.countLabel.Size = new Size(70, 13);

this.countLabel.TabIndex = 1;

this.countLabel.Text = “Lost frames 0”;

this.brightnesTrackBar.AutoSize = false;

this.brightnesTrackBar.Location = new Point(102, 3);

this.brightnesTrackBar.Maximum = 100;

this.brightnesTrackBar.Name = “brightnesTrackBar”;

this.brightnesTrackBar.Orientation = Orientation.Vertical;

this.brightnesTrackBar.Size = new Size(41, 148);

this.brightnesTrackBar.TabIndex = 4;

this.brightnesTrackBar.TickFrequency = 10;

this.brightnesTrackBar.TickStyle = TickStyle.Both;

this.brightnesTrackBar.Value = 50;

this.brightnesTrackBar.Scroll += new EventHandler(this.brightnesTrackBar_Scroll);

this.contrastTrackBar.AutoSize = false;

this.contrastTrackBar.Location = new Point(162, 3);

this.contrastTrackBar.Maximum = 100;

this.contrastTrackBar.Name = “contrastTrackBar”;

this.contrastTrackBar.Orientation = Orientation.Vertical;

this.contrastTrackBar.Size = new Size(43, 148);

this.contrastTrackBar.TabIndex = 5;

this.contrastTrackBar.TickFrequency = 10;

this.contrastTrackBar.TickStyle = TickStyle.Both;

this.contrastTrackBar.Value = 50;

this.contrastTrackBar.Scroll += new EventHandler(this.contrastTrackBar_Scroll);

this.label1.AutoSize = true;

this.label1.Location = new Point(99, 154);

this.label1.Name = “label1”;

this.label1.Size = new Size(51, 13);

this.label1.TabIndex = 6;

this.label1.Text = “Brightnes”;

this.label2.AutoSize = true;

this.label2.Location = new Point(159, 154);

this.label2.Name = “label2”;

this.label2.Size = new Size(46, 13);

this.label2.TabIndex = 7;

this.label2.Text = “Contrast”;

this.pauseCheckBox.AutoSize = true;

this.pauseCheckBox.Location = new Point(3, 49);

this.pauseCheckBox.Name = “pauseCheckBox”;

this.pauseCheckBox.Size = new Size(56, 17);

this.pauseCheckBox.TabIndex = 8;

this.pauseCheckBox.Text = “Pause”;

this.pauseCheckBox.UseVisualStyleBackColor = true;

this.pauseCheckBox.CheckedChanged += new EventHandler(this.pauseCheckBox_CheckedChanged);

this.videoFilterCheckBox.AutoSize = true;

this.videoFilterCheckBox.Location = new Point(3, 26);

this.videoFilterCheckBox.Name = “videoFilterCheckBox”;

this.videoFilterCheckBox.Size = new Size(75, 17);

this.videoFilterCheckBox.TabIndex = 15;

this.videoFilterCheckBox.Text = “Video filter”;

this.videoFilterCheckBox.UseVisualStyleBackColor = true;

this.videoFilterCheckBox.CheckedChanged += new EventHandler(this.videoFilterCheckBox_CheckedChanged);

this.syncOffCheckBox.AutoSize = true;

this.syncOffCheckBox.Location = new Point(3, 72);

this.syncOffCheckBox.Name = “syncOffCheckBox”;

this.syncOffCheckBox.Size = new Size(65, 17);

this.syncOffCheckBox.TabIndex = 20;

this.syncOffCheckBox.Text = “Sync off”;

this.syncOffCheckBox.UseVisualStyleBackColor = true;

this.syncOffCheckBox.CheckedChanged += new EventHandler(this.syncOffCheckBox_CheckedChanged);

this.palNTSCComboBox.FormattingEnabled = true;

this.palNTSCComboBox.Items.AddRange(new object[2]

{

(object) “PAL/Secam”,

(object) “NTSC”

});

this.palNTSCComboBox.Location = new Point(0, 95);

this.palNTSCComboBox.Name = “palNTSCComboBox”;

this.palNTSCComboBox.Size = new Size(78, 21);

this.palNTSCComboBox.TabIndex = 21;

this.AmFmComboBox.FormattingEnabled = true;

this.AmFmComboBox.Items.AddRange(new object[2]

{

(object) “AM”,

(object) “FM”

});

this.AmFmComboBox.Location = new Point(0, 122);

this.AmFmComboBox.Name = “AmFmComboBox”;

this.AmFmComboBox.Size = new Size(78, 21);

this.AmFmComboBox.TabIndex = 22;

this.AmFmComboBox.SelectedIndexChanged += new EventHandler(this.AmFmComboBox_SelectedIndexChanged);

this.AutoScaleDimensions = new SizeF(6f, 13f);

this.AutoScaleMode = AutoScaleMode.Font;

this.Controls.Add((Control) this.AmFmComboBox);

this.Controls.Add((Control) this.palNTSCComboBox);

this.Controls.Add((Control) this.syncOffCheckBox);

this.Controls.Add((Control) this.videoFilterCheckBox);

this.Controls.Add((Control) this.pauseCheckBox);

this.Controls.Add((Control) this.label2);

this.Controls.Add((Control) this.label1);

this.Controls.Add((Control) this.contrastTrackBar);

this.Controls.Add((Control) this.brightnesTrackBar);

this.Controls.Add((Control) this.countLabel);

this.Controls.Add((Control) this.enableCheckBox);

this.Name = nameof (TVPanel);

this.Size = new Size(217, 193);

this.brightnesTrackBar.EndInit();

this.contrastTrackBar.EndInit();

this.ResumeLayout(false);

this.PerformLayout();

}

}

…but if SDRSharp, System, Private and #nullable, among others, are already displayed as errors, then it can’t work…but why? who can say anything about that?

Maybe mentioned again in passing, if the Tempest functions are integrated and then work via the Airspy server, we all benefit from it.

gruß Micha


OK…schade, wenig Resonanz.

Ich habe mich erstmals etwas intensiver mit dotPeek und Visual Studio beschäftigt. Bisher ist es mir noch nie gelungen, auch nur eine konstruktive Sache mit VS zu erstellen. Deshalb habe ich bewust ein funktionierendes Programm, mit bekannten Quelltext genommen. Nach anfänglichen Schwierigkeiten hat es geklappt. Trotz gefühlten 50GigaByte Plugins für VS fehlte eine Datei-

Net framework 3.5.

Danach konnte die TVsharper.exe funktionsfähig erstellt werden.

OK, soweit, sogut.

Benötigt werden aber Plugin/DLL Dateien. Also habe ich mir die

sdrsharp-plugin-sdk-vs2022-dotnet9

von der Airspy Seite besorgt. Im Debug-Modus wird SDRsharp gestartet und ein Plugin kann geöffnet werden. Im original wird das Word “Hey” angezeigt. Der Text lässt sich ändern und nach erneuter Kompilierung neu angezeigt. „New Text for example

Klar, es ist nichts grossartiges besonderes, aber in Hinblick darauf, dass ich bis vor kurzem überhapt keine Ahnung von VS hatte, bin ich für meine Verhältnisse schon etwas weiter gekommen. Ob der Rest klappen wird, weiß ich natürlich nicht. Es ist halt sehr Zeitaufwendig und Informationen von Dritten sind spärlich zu finden. Es wird noch ein weiter Weg zum Ziel.

Okay… too bad, not much response.

I’ve been working with dotPeek and Visual Studio for the first time in a more intensive way. Up until now, I’ve never managed to create anything constructive with VS. Therefore, I deliberately chose a working program with known source code. After some initial difficulties, it worked. Despite what felt like 50 gigabytes of plugins for VS, one file was missing—

NET Framework 3.5.

After that, the TVsharper.exe could be compiled to work.

Okay, so far, so good. But plugin/DLL files are needed. So I got them

sdrsharp-plugin-sdk-vs2022-dotnet9

from the Airspy website.

In debug mode, SDRsharp is started, and a plugin can be opened.

The original output displays the word “Hey.” The text can be changed and displayed again after recompiling. “New Text for example

Sure, it’s nothing groundbreaking, but considering I had absolutely no idea about VS until recently, I’ve made some progress for my standards. Of course, I don’t know if the rest will work out. It’s very time-consuming, and information from others is scarce. There’s still a long way to go.

Gruß Micha

A tiny step for me. I inserted the graphics components from the TVplugin source code into the existing SDRsharp-empty plugin and eliminated all errors displayed. The plugin could then be loaded into debug mode and started for at least 1 second. SDRsharp then immediately crashed. That’s why I documented the process the second time using a VLC desktop recording.

Unfortunately, this is all very time-consuming and I can’t find a solution for many of the error messages. There is still a long way to go until the TV plugin works for me or the functions of SDR-TVsharper are integrated.

Ein klitzekleiner Schritt für mich. Ich habe die Grafikanteile, aus dem TVplugin- Quelltext in das vorhandene SDRsharp-empty Plugin eingesetzt und alle angezeigten Fehler beseitigt. Danach konnte das Plugin in Debug-Modus geladen werden und zumindest für 1 Sekunde gestartet werden. SDRsharp ist dann sofort abgestürzt. Deshalb habe ich den Vorgang, beim zweiten Mal per VLC-Desktop Aufnahme dokumentiert.

Leider ist das alles sehr zeitaufwendig und für viele der Fehlermeldungen, finde ich keine Lösung. Bis das TVplugin bei mir funktioniert, bzw. die Funktionen von SDR-TVsharper integriert sind, ist es noch ein weiter Weg.

Gruß Micha

Es war ein weiter Weg bis hier hin und ich denke, dass ich jetzt zumindest das Panel-Design gestalten kann. Bis zu einem funktionierenden Programm, wird es aber noch eine Weile dauern.

Wie schon beschrieben, beziehe ich mich vorerst auf bekannte Programme, weil diese zumeist funktionieren. Die meisten von diesen Programmen, sind als reine EXE- Programme erstellt und arbeiten nicht mit dem SDR-Sharp- Spyserver zusammen. Gerade hier wird es doch erst interressant, wenn zB. Tempest oder NRSC5 auch als Plugin enthalten wären, also als dll.-Datei.

OK.

Der einfachste Weg zum Einstig, ist das Mini-Programm, SDR-Empty von der SDR-sharp Softwareseite.

Es ist in der sdrsharp-plugin-sdk-vs2022-dotnet enthalten.

Der große Vorteil zum Üben ist, das eine einfache Build Umgebung enthalten ist, die im Debug-Modus von Visual Studio, das SDR-SHARP-Programm startet, ein funktionierendes Plugin anzeigt und eine dll.- Datei erstellt. Die dll-Datei ist ein Plugin, das in andere SDR-Sharp Programme eingesetzt werden kann und funktioniert.

Allein um zu lernen, wie das ganze aufgebaut ist und funktioniert, ist das vollkommen OK.

Die Grunddatei sollte man sich unbedingt separrat speichern, weil einmal mit VS geöffnet, werden viele neue Dateien erstellt und das verwirrt. Deshalb speicher ich fast jede grössere Änderung in neuen Ordnern. Somit kann ich immer wieder zur letzten funktionieren Version zurückkehren.

Einige Dateien in der ZIP-Version werden im VS nicht gebraucht und können vor dem ersten Start gelöscht werden – das schafft mehr Übersicht.

der Release- Ordner

Gestartet wird mit der SDRsharp-Empty C#Project’file, das öffnet gleich das VS im richtigen Modus.

Der Debug-Modus funktioniert nur, wenn im Quelltext keine Fehler angezeigt werden, deshalb sollte man korrekte Daten zwischenspeichern. In vielen Fällen, werden Korrekturen vorgeschlagen, die zumeist auch akzeptable Ergebnisse liefern.

Eine wichtige Datei um die Grafik zu bearbeiten, ist die „Control-Panel.cs Entwurf“.

(Diese Datei wird oft erst nach einiger Laufzeit von VS dargestellt- zumindest bei mir)

Sie hat einen riesen Vorteil- hier lässt sich nicht nur die Grafik gestalten. (Nur wenn die „Control-Panel.cs Entwurf“- Datei angezeigt wird, funktioniert die ToolBox mit ihren grafischen Elementen). Es werden auch zeitgleich die Quelltexte erstellt und somit das Grundgerüst zum zukünftigen Programm. Aber es fehlt noch eine ganze Menge.

Um Fehler oder fehlende Daten zu erkennen, benutzte ich Quelltexte von anderen und ähnlichen Programmen zum Vergleich. Aber Vorsicht. Viele diese Programme sind 3-10 alt. Die Programmiersprachen ändern sich jedoch ständig. Diese Programme sind nicht mehr 1:1 kompatibel und müssen angepasst werden. Zum probieren reicht es aber.

It’s been a long road to get here, and I think I can at least design the panel layout now. However, it will still be a while before we have a fully functional program.

As already mentioned, I’m initially focusing on well-known programs because most of them work. Most of these programs are created as simple EXE files and don’t work with the SDR-Sharp Spyserver. This is precisely where things would become interesting if, for example, Tempest or NRSC5 were also included as plugins, i.e., as DLL files.OK.The easiest way to get started is with the mini-program, SDR-Empty, from the SDR software website.It’s included in the sdrsharp-plugin-sdk-vs2022.dotnet file.The great advantage for practicing is the included simple build environment. In Visual Studio’s debug mode, this starts the SDR-SHARP program, displays a working plugin, and creates a DLL file. This DLL file is a plugin that can be used in other SDR-Sharp programs and will function correctly.This is perfectly fine just for learning how everything is structured and works.You should definitely save the base file separately because opening it with VS creates many new files, which can be confusing. Therefore, I save almost every major change in new folders. This way, I can always revert to the last working version. Some files in the ZIP version are not needed in Visual Studio and can be deleted before the first launch – this improves organization.

The Release folderStart with the SDRsharp Empty C# Project file, which opens Visual Studio in the correct mode.Debug mode only works if no errors are displayed in the source code, so you should save correct data. In many cases, corrections are suggested, which usually produce acceptable results.An important file for editing the graphics is “Control-Panel.cs Draft”.(This file is often only displayed after Visual Studio has been running for a while – at least for me.)It has a huge advantage: it’s not just for designing the graphics. The Toolbox with its graphical elements only works when the “Control-Panel.cs Draft” file is displayed. The source code is also generated simultaneously, thus creating the basic framework for the future program. But there’s still a lot missing.To identify errors or missing data, I used source code from other, similar programs for comparison. However, be careful. Many of these programs are 3-10 years old. Programming languages are constantly changing, so these programs are no longer directly compatible and need to be adapted. But they’re sufficient for testing.

Tested without SDRsharp-Empty, i.e., directly via Visual Studio.

Im Test, ohne SDRsharp-Empty ausprobiert, also direkt über Visual Studio.

Gruß Micha


I spent nights trying out random code and then found the solution in a YouTube video. I tweaked the example, and the result is quite impressive. If only I could get some additional functions for it…

Da probiere ich nächtelang irgendwelche Code aus und finde die Lösung in einem YouTube-Film. Das Beispiel habe ich noch angepasst und das Ergebnis kann sich sehen lassen. Wenn ich jetzt noch Funktionen dazu bekäme,......

gruß Micha

Even though not much seems to be happening here, I’m constantly trying out new code in the background. Unfortunately, I just discovered that an important DLL file is missing. It’s not included in the decompiled TVsharp and was created by the programmer himself.

sdrsharp.digitalifprocessor.dll

This file isn’t available on any of the download sites I know. I haven’t found a source yet. Perhaps one of you can help. I would appreciate it.

Micha

Auch wenn hier offensichtlich wenig passiert, probiere ich im Hintergrund immer wieder neue Code aus. Zu meinem Bedauern habe ich gerade festgestellt, dass eine wichtige DLL Datei fehlt. Diese ist nicht im dekompilierten TVsharp enthalten und wurde vom Programierer selbst erstellt.

 sdrsharp.digitalifprocessor.dll

Auf den mir bekannten Downloadseiten ist diese Datei nicht zu bekommen. Bisher habe ich noch keine Quelle gefunden. Vielleicht kann einer von Euch weiterhelfen. Ich würde mich freuen.
Micha


....Info- Google KI....

The SDRSharp.DigitalIfProcessor.dll is a third-party plugin for SDR# (SDRSharp) developed by Vasili (typically found via rtl-sdr.ru) designed to enhance signal processing, specifically by improving the IF (Intermediate Frequency) spectrum view and providing advanced filtering capabilities. 
Key Features of the IF Processor Plugin

    Asymmetric Filter Controls: Allows fine-tuning of the filter passband, which is particularly useful for removing interference on specific sides of a signal.
    Tracking Notch Filter: Automatically identifies and reduces interfering signals that appear within the bandwidth of the signal of interest.
    Enhanced IF Spectrum: Provides a better visual representation of the IF stage for diagnostic purposes.
    FM-DX Utility: Highly useful for separating crowded FM broadcast stations. 


Hey @Micha . I found a solution for your missed dll.
Older Versions does have this DLL for x86 versions included - later Versions have a built-in Solution in SDR# :grinning_face:

I hope its ok to send you this Link here where you can find older Versions. I checked SDRSharp_v1331 and its there.

Greets / Hau rein und nette Grüße :wink:


Thank you for the tip. I wasn’t aware of this archive before.

I haven’t found the missing DLL yet, but I’ll take another look later.

JetBrains did provide some information, and I created my own file based on that. At least the previous error messages have disappeared. I’m not sure if it’s all correct yet.

I still can’t add functions to the buttons and the VideoPanel… too bad.

Vielen Dank für den Hinweis. Dieses Archiv war mir bisher unbekannt.
Ich habe die fehlende dll noch nicht gefunden, werde aber in Ruhe nochmal nachsehen.
In JetBrains sind jedoch ein paar Hinweise und daraus habe ich eine eigene Datei erstellt. Jetzt sind zumindest die vorherigen Fehlermeldungen verschwunden. Ob das alles korrekt ist, weiß ich noch nicht.
Nach wie vor, gelingt es mir nicht, den Buttons und dem VideoPanel Funktionen zuzufügen…schade

gruß Micha

(ich habe den namespace SDRSharp.Empty vorerst belassen, weil diese Datei die Grundlage für alle weiteren Programmierungen bildet.

In der Programmierung haben sich nur Kleinigkeiten geändert, zB. dass beim Panel öffnen der Videofilter, der Sync.-off, PAL/Secam und AM direkt aktiv sind.

Was mich persönlich nervt und mich in der Arbeit immer wieder zurückwirft, ist dass wenn im Designer/Entwurf ein Fehler ist, dieser nicht mehr angezeigt wird. Manche Einstellungen lassen sich hier sehr gut programmieren, andere eher im Designer.

Hilfreich ist es in jedemfall, funktionierende Programmierungen zu speichern und mit einer Kopie, weiter zu arbeiten)

using SDRSharp.Radio;
using System;

#nullable disable
namespace SDRSharp.Empty
{

public class IFProcessor : IIQProcessor, IStreamProcessor, IBaseProcessor

{
public event IFProcessor.IQReadyDelegate IQReady;

public double SampleRate { get; set; }

public bool Enabled { get; set; } }

    public unsafe void Process(Complex\* buffer, int length)
    {
        IFProcessor.IQReadyDelegate iqReady = this.IQReady;
        if (iqReady == null)
            return;
        iqReady(buffer, length);
    }

    public unsafe delegate void IQReadyDelegate(Complex\* buffer, int length);
}
public interface IBaseProcessor
{
    bool Enabled { get; set; }
}
public interface IIQProcessor : IStreamProcessor, IBaseProcessor
{
    unsafe void Process(Complex\* buffer, int length);
}
public interface IStreamProcessor : IBaseProcessor
{
    double SampleRate { set; }
}
public interface IRdsBitStreamProcessor : IBaseProcessor
{
    void Process(ref RdsFrame frame);
} 

Sorry Guys, just german at this moment:

Die DLL ist aber in der besagten ZIP drin, aber nur achte mal auf Groß-/Kleinschreibung :slight_smile:

Wie ich sehe hast du alle Nullverweise ausgeblendet für den Compiler (#nullable disable)
Hier würden sonst einige Fehler noch angezeigt werden.

Ja, wenn du den Namespace änderst, müsstest auch alle anderen Klassen ändern.
Das hat fast (aber nur fast) mit dem internen Namen zu tun.

Wie ich aber rauslesen kann, läuft hier alles auf ein BaseModel zusammen. Vielleicht sollte ich mir auch mal das empty Projekt holen. Falls ich es mit Visual Studio 2026 zum Laufen bekomme :smiley:

Ein guter Tipp ist oft, “Projekt bereinigen” und danach “Projekt neu erstellen” - so löscht VS dann den die “Cache” Ordner und baut sie neu auf - da siehst dann bestimmt diese Fehler wieder :slight_smile:

First of all, thank you very much for the tips and advice.

…more errors?..better not.

The empty file is specifically designed for further development. It serves only as a basis for creating SDRsharp plugins. Theoretically, any other plugin could be modified using the existing source code. What was important to me was that the data is recognized directly as a plugin and a working DLL is created from it. This DLL can then be directly integrated into SDRsharp as a plugin.

I’ve now found the original VideoPanel from TVPlugin in JetBrains. Up until now, I’ve been using the VideoPanel and Drawscreen from TVsharper.

I’ll try it out to see if this one works better.

What’s causing the delay is that when starting a new program (based on SDREmpty) in Visual Studio, the designer takes an extremely long time to open. Some functions can be set here or in the designer’s draft, but these are then deleted after debugging and have to be reprogrammed. Container frames that worked in previous attempts aren’t displayed at all in the new attempt. Colors are incorrect, scrollbar starting positions aren’t applied, and so on.

It could be that Empty accesses different Windows packages than TV.

I think the tab indexes can’t be the same.

Erst mal herzlichen Dank für Tips und Hinweise.
…noch mehr Fehler?..lieber nicht.
Die Empty-Datei ist extra dafür da, weiter entwickelt zu werden. Sie dient nur als Grundlage um SDRsharp Plugins zu erstellen. Theoretisch könnte man jedes andere Plugin, mit vorhandenen Quelltext abändern. Wichtig war mir, das die Daten direkt als Plugin erkannt wird und daraus direkt eine funktionierende DLL erstellt wird. Diese DLL kann somit direkt, als Plugin in SDRsharp eingefügt werden.

In JetBrains habe ich nun die original VideoPanel vom TVPlugin gefunden. Bisher habe ich die VideoPanel und Drawscreen von TVsharper benutzt.
Ob diese nun besser klappt, werde ich probieren.

Was zeitlich aufhält, ist, das bei einer neuen Programmierung (Grundlage SDREmpty) in VS, der Designer erst nach ewig langer Zeit geöffnet wird. Einige Funktionen hier, oder im Designer Entwurf einzustellen sind, diese aber im nächsten Schritt, nach dem Debug wieder gelöscht sind und erneut programmiert werden müssen. Container Rahmen, die in vorherigen Versuchen funktioniert haben, im neuen Versuch überhaupt nicht mehr angezeigt werden. Farben nicht mehr stimmen, Startpositionen der Scrollbars nicht übernommen werden, usw…

CountLabel ist in der ToolBox nicht vorhanden und wurde vom Autor selbst erstellt. Diese Daten in meinen Versuch einzubauen hat gut Funktioniert. Danach nicht mehr…

Es könnte sein, das Empty auf andere Windows Pakete zugreift, als TV…

Ich glaube das TAB-Indexe nicht gleich sein dürfen…

gruß Micha

// countLabel
// 
countLabel.AutoSize = true;
countLabel.Location = new Point(120, 421);
countLabel.Name = "countLabel";
countLabel.Size = new Size(77, 15);
countLabel.TabIndex = 1;
countLabel.Text = "Lost frames 0";
// 
// checkBox1
// 
checkBox1.AutoSize = true;
checkBox1.Location = new Point(13, 18);
checkBox1.Name = "checkBox1";
checkBox1.Size = new Size(39, 19);
checkBox1.TabIndex = 1;
checkBox1.Text = "TV";
checkBox1.UseVisualStyleBackColor = true;
checkBox1.CheckedChanged += checkBox1_CheckedChanged;


______________________________________________________________________________
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

#nullable disable
namespace SDRSharp.TV;

public class VideoWindow : Form
{
  private int _oldVideoWindowWidth;
  private int _oldVideoWindowHeight;
  private IContainer components;
  private DrawScreen videoPanel;

  public VideoWindow() => this.InitializeComponent();

  public unsafe void DrawFrame(byte* buf, int width, int height)
  {
    this.videoPanel.BufferToBitmap(buf, width, height);
    this.videoPanel.Refresh();
  }

  private void VideoWindows_ResizeBegin(object sender, EventArgs e)
  {
    Control control = (Control) sender;
    this._oldVideoWindowWidth = control.Size.Width;
    this._oldVideoWindowHeight = control.Size.Height;
  }

  private void VideoWindows_Resize(object sender, EventArgs e)
  {
    Control control = (Control) sender;
    int width = control.Size.Width;
    int height = control.Size.Height;
    if (this._oldVideoWindowWidth != width && this._oldVideoWindowHeight == height)
      height = width / 4 * 3;
    else if (this._oldVideoWindowWidth == width && this._oldVideoWindowHeight != height)
      width = height / 3 * 4;
    else
      height = width / 4 * 3;
    control.Size = new Size(width, height);
  }

  protected override void Dispose(bool disposing)
  {
    if (disposing && this.components != null)
      this.components.Dispose();
    base.Dispose(disposing);
  }

  private void InitializeComponent()
  {
    this.videoPanel = new DrawScreen();
    this.SuspendLayout();
    this.videoPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
    this.videoPanel.Location = new Point(2, 3);
    this.videoPanel.Name = "videoPanel";
    this.videoPanel.Size = new Size(421, 323);
    this.videoPanel.TabIndex = 0;
    this.AutoScaleMode = AutoScaleMode.None;
    this.AutoValidate = AutoValidate.EnableAllowFocusChange;
    this.ClientSize = new Size(424, 327);
    this.Controls.Add((Control) this.videoPanel);
    this.DoubleBuffered = true;
    this.FormBorderStyle = FormBorderStyle.SizableToolWindow;
    this.Name = nameof (VideoWindow);
    this.Text = "Video";
    this.ResizeBegin += new EventHandler(this.VideoWindows_ResizeBegin);
    this.Resize += new EventHandler(this.VideoWindows_Resize);
    this.ResumeLayout(false);
  }
}




.class public auto ansi beforefieldinit
  SDRSharp.TV.VideoWindow
    extends [System.Windows.Forms]System.Windows.Forms.Form
{

  .field private int32 _oldVideoWindowWidth

  .field private int32 _oldVideoWindowHeight

  .field private class [System]System.ComponentModel.IContainer components

  .field private class SDRSharp.TV.DrawScreen videoPanel

  .method public hidebysig specialname rtspecialname instance void
    .ctor() cil managed
  {
    .maxstack 8

    IL_0000: ldarg.0      // this
    IL_0001: call         instance void [System.Windows.Forms]System.Windows.Forms.Form::.ctor()

    // [22 27 - 22 53]
    IL_0006: ldarg.0      // this
    IL_0007: call         instance void SDRSharp.TV.VideoWindow::InitializeComponent()
    IL_000c: ret

  } // end of method VideoWindow::.ctor

  .method public hidebysig instance void
    DrawFrame(
      unsigned int8* buf,
      int32 width,
      int32 height
    ) cil managed
  {
    .maxstack 8

    // [26 5 - 26 55]
    IL_0000: ldarg.0      // this
    IL_0001: ldfld        class SDRSharp.TV.DrawScreen SDRSharp.TV.VideoWindow::videoPanel
    IL_0006: ldarg.1      // buf
    IL_0007: ldarg.2      // width
    IL_0008: ldarg.3      // height
    IL_0009: callvirt     instance void SDRSharp.TV.DrawScreen::BufferToBitmap(unsigned int8*, int32, int32)

    // [27 5 - 27 30]
    IL_000e: ldarg.0      // this
    IL_000f: ldfld        class SDRSharp.TV.DrawScreen SDRSharp.TV.VideoWindow::videoPanel
    IL_0014: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control::Refresh()
    IL_0019: ret

  } // end of method VideoWindow::DrawFrame

  .method private hidebysig instance void
    VideoWindows_ResizeBegin(
      object sender,
      class [mscorlib]System.EventArgs e
    ) cil managed
  {
    .maxstack 2
    .locals init (
      [0] class [System.Windows.Forms]System.Windows.Forms.Control control,
      [1] valuetype [System.Drawing]System.Drawing.Size V_1
    )

    // [32 5 - 32 39]
    IL_0000: ldarg.1      // sender
    IL_0001: castclass    [System.Windows.Forms]System.Windows.Forms.Control
    IL_0006: stloc.0      // control

    // [33 5 - 33 51]
    IL_0007: ldarg.0      // this
    IL_0008: ldloc.0      // control
    IL_0009: callvirt     instance valuetype [System.Drawing]System.Drawing.Size [System.Windows.Forms]System.Windows.Forms.Control::get_Size()
    IL_000e: stloc.1      // V_1
    IL_000f: ldloca.s     V_1
    IL_0011: call         instance int32 [System.Drawing]System.Drawing.Size::get_Width()
    IL_0016: stfld        int32 SDRSharp.TV.VideoWindow::_oldVideoWindowWidth

    // [34 5 - 34 53]
    IL_001b: ldarg.0      // this
    IL_001c: ldloc.0      // control
    IL_001d: callvirt     instance valuetype [System.Drawing]System.Drawing.Size [System.Windows.Forms]System.Windows.Forms.Control::get_Size()
    IL_0022: stloc.1      // V_1
    IL_0023: ldloca.s     V_1
    IL_0025: call         instance int32 [System.Drawing]System.Drawing.Size::get_Height()
    IL_002a: stfld        int32 SDRSharp.TV.VideoWindow::_oldVideoWindowHeight
    IL_002f: ret

  } // end of method VideoWindow::VideoWindows_ResizeBegin

  .method private hidebysig instance void
    VideoWindows_Resize(
      object sender,
      class [mscorlib]System.EventArgs e
    ) cil managed
  {
    .maxstack 3
    .locals init (
      [0] int32 width,
      [1] int32 height,
      [2] valuetype [System.Drawing]System.Drawing.Size V_2
    )

    // [39 5 - 39 39]
    IL_0000: ldarg.1      // sender
    IL_0001: castclass    [System.Windows.Forms]System.Windows.Forms.Control
    IL_0006: dup

    // [40 5 - 40 35]
    IL_0007: callvirt     instance valuetype [System.Drawing]System.Drawing.Size [System.Windows.Forms]System.Windows.Forms.Control::get_Size()
    IL_000c: stloc.2      // V_2
    IL_000d: ldloca.s     V_2
    IL_000f: call         instance int32 [System.Drawing]System.Drawing.Size::get_Width()
    IL_0014: stloc.0      // width
    IL_0015: dup

    // [41 5 - 41 37]
    IL_0016: callvirt     instance valuetype [System.Drawing]System.Drawing.Size [System.Windows.Forms]System.Windows.Forms.Control::get_Size()
    IL_001b: stloc.2      // V_2
    IL_001c: ldloca.s     V_2
    IL_001e: call         instance int32 [System.Drawing]System.Drawing.Size::get_Height()
    IL_0023: stloc.1      // height

    // [42 5 - 42 84]
    IL_0024: ldarg.0      // this
    IL_0025: ldfld        int32 SDRSharp.TV.VideoWindow::_oldVideoWindowWidth
    IL_002a: ldloc.0      // width
    IL_002b: beq.s        IL_003e

    IL_002d: ldarg.0      // this
    IL_002e: ldfld        int32 SDRSharp.TV.VideoWindow::_oldVideoWindowHeight
    IL_0033: ldloc.1      // height
    IL_0034: bne.un.s     IL_003e

    // [43 7 - 43 29]
    IL_0036: ldloc.0      // width
    IL_0037: ldc.i4.4
    IL_0038: div
    IL_0039: ldc.i4.3
    IL_003a: mul
    IL_003b: stloc.1      // height

    IL_003c: br.s         IL_005e

    // [44 10 - 44 89]
    IL_003e: ldarg.0      // this
    IL_003f: ldfld        int32 SDRSharp.TV.VideoWindow::_oldVideoWindowWidth
    IL_0044: ldloc.0      // width
    IL_0045: bne.un.s     IL_0058

    IL_0047: ldarg.0      // this
    IL_0048: ldfld        int32 SDRSharp.TV.VideoWindow::_oldVideoWindowHeight
    IL_004d: ldloc.1      // height
    IL_004e: beq.s        IL_0058

    // [45 7 - 45 29]
    IL_0050: ldloc.1      // height
    IL_0051: ldc.i4.3
    IL_0052: div
    IL_0053: ldc.i4.4
    IL_0054: mul
    IL_0055: stloc.0      // width

    IL_0056: br.s         IL_005e

    // [47 7 - 47 29]
    IL_0058: ldloc.0      // width
    IL_0059: ldc.i4.4
    IL_005a: div
    IL_005b: ldc.i4.3
    IL_005c: mul
    IL_005d: stloc.1      // height

    // [48 5 - 48 43]
    IL_005e: ldloc.0      // width
    IL_005f: ldloc.1      // height
    IL_0060: newobj       instance void [System.Drawing]System.Drawing.Size::.ctor(int32, int32)
    IL_0065: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Size(valuetype [System.Drawing]System.Drawing.Size)
    IL_006a: ret

  } // end of method VideoWindow::VideoWindows_Resize

  .method family hidebysig virtual instance void
    Dispose(
      bool disposing
    ) cil managed
  {
    .maxstack 8

    // [53 5 - 53 46]
    IL_0000: ldarg.1      // disposing
    IL_0001: brfalse.s    IL_0016

    IL_0003: ldarg.0      // this
    IL_0004: ldfld        class [System]System.ComponentModel.IContainer SDRSharp.TV.VideoWindow::components
    IL_0009: brfalse.s    IL_0016

    // [54 7 - 54 32]
    IL_000b: ldarg.0      // this
    IL_000c: ldfld        class [System]System.ComponentModel.IContainer SDRSharp.TV.VideoWindow::components
    IL_0011: callvirt     instance void [mscorlib]System.IDisposable::Dispose()

    // [55 5 - 55 28]
    IL_0016: ldarg.0      // this
    IL_0017: ldarg.1      // disposing
    IL_0018: call         instance void [System.Windows.Forms]System.Windows.Forms.Form::Dispose(bool)
    IL_001d: ret

  } // end of method VideoWindow::Dispose

  .method private hidebysig instance void
    InitializeComponent() cil managed
  {
    .maxstack 3

    // [60 5 - 60 39]
    IL_0000: ldarg.0      // this
    IL_0001: newobj       instance void SDRSharp.TV.DrawScreen::.ctor()
    IL_0006: stfld        class SDRSharp.TV.DrawScreen SDRSharp.TV.VideoWindow::videoPanel

    // [61 5 - 61 25]
    IL_000b: ldarg.0      // this
    IL_000c: call         instance void [System.Windows.Forms]System.Windows.Forms.Control::SuspendLayout()

    // [62 5 - 62 109]
    IL_0011: ldarg.0      // this
    IL_0012: ldfld        class SDRSharp.TV.DrawScreen SDRSharp.TV.VideoWindow::videoPanel
    IL_0017: ldc.i4.s     15 // 0x0f
    IL_0019: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Anchor(valuetype [System.Windows.Forms]System.Windows.Forms.AnchorStyles)

    // [63 5 - 63 47]
    IL_001e: ldarg.0      // this
    IL_001f: ldfld        class SDRSharp.TV.DrawScreen SDRSharp.TV.VideoWindow::videoPanel
    IL_0024: ldc.i4.2
    IL_0025: ldc.i4.3
    IL_0026: newobj       instance void [System.Drawing]System.Drawing.Point::.ctor(int32, int32)
    IL_002b: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Location(valuetype [System.Drawing]System.Drawing.Point)

    // [64 5 - 64 40]
    IL_0030: ldarg.0      // this
    IL_0031: ldfld        class SDRSharp.TV.DrawScreen SDRSharp.TV.VideoWindow::videoPanel
    IL_0036: ldstr        "videoPanel"
    IL_003b: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)

    // [65 5 - 65 46]
    IL_0040: ldarg.0      // this
    IL_0041: ldfld        class SDRSharp.TV.DrawScreen SDRSharp.TV.VideoWindow::videoPanel
    IL_0046: ldc.i4       421 // 0x000001a5
    IL_004b: ldc.i4       323 // 0x00000143
    IL_0050: newobj       instance void [System.Drawing]System.Drawing.Size::.ctor(int32, int32)
    IL_0055: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Size(valuetype [System.Drawing]System.Drawing.Size)

    // [66 5 - 66 33]
    IL_005a: ldarg.0      // this
    IL_005b: ldfld        class SDRSharp.TV.DrawScreen SDRSharp.TV.VideoWindow::videoPanel
    IL_0060: ldc.i4.0
    IL_0061: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control::set_TabIndex(int32)

    // [67 5 - 67 44]
    IL_0066: ldarg.0      // this
    IL_0067: ldc.i4.0
    IL_0068: call         instance void [System.Windows.Forms]System.Windows.Forms.ContainerControl::set_AutoScaleMode(valuetype [System.Windows.Forms]System.Windows.Forms.AutoScaleMode)

    // [68 5 - 68 60]
    IL_006d: ldarg.0      // this
    IL_006e: ldc.i4.2
    IL_006f: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.ContainerControl::set_AutoValidate(valuetype [System.Windows.Forms]System.Windows.Forms.AutoValidate)

    // [69 5 - 69 41]
    IL_0074: ldarg.0      // this
    IL_0075: ldc.i4       424 // 0x000001a8
    IL_007a: ldc.i4       327 // 0x00000147
    IL_007f: newobj       instance void [System.Drawing]System.Drawing.Size::.ctor(int32, int32)
    IL_0084: call         instance void [System.Windows.Forms]System.Windows.Forms.Form::set_ClientSize(valuetype [System.Drawing]System.Drawing.Size)

    // [70 5 - 70 49]
    IL_0089: ldarg.0      // this
    IL_008a: call         instance class [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection [System.Windows.Forms]System.Windows.Forms.Control::get_Controls()
    IL_008f: ldarg.0      // this
    IL_0090: ldfld        class SDRSharp.TV.DrawScreen SDRSharp.TV.VideoWindow::videoPanel
    IL_0095: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control/ControlCollection::Add(class [System.Windows.Forms]System.Windows.Forms.Control)

    // [71 5 - 71 31]
    IL_009a: ldarg.0      // this
    IL_009b: ldc.i4.1
    IL_009c: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control::set_DoubleBuffered(bool)

    // [72 5 - 72 61]
    IL_00a1: ldarg.0      // this
    IL_00a2: ldc.i4.6
    IL_00a3: call         instance void [System.Windows.Forms]System.Windows.Forms.Form::set_FormBorderStyle(valuetype [System.Windows.Forms]System.Windows.Forms.FormBorderStyle)

    // [73 5 - 73 37]
    IL_00a8: ldarg.0      // this
    IL_00a9: ldstr        "VideoWindow"
    IL_00ae: call         instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Name(string)

    // [74 5 - 74 24]
    IL_00b3: ldarg.0      // this
    IL_00b4: ldstr        "Video"
    IL_00b9: callvirt     instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Text(string)

    // [75 5 - 75 72]
    IL_00be: ldarg.0      // this
    IL_00bf: ldarg.0      // this
    IL_00c0: ldftn        instance void SDRSharp.TV.VideoWindow::VideoWindows_ResizeBegin(object, class [mscorlib]System.EventArgs)
    IL_00c6: newobj       instance void [mscorlib]System.EventHandler::.ctor(object, native int)
    IL_00cb: call         instance void [System.Windows.Forms]System.Windows.Forms.Form::add_ResizeBegin(class [mscorlib]System.EventHandler)

    // [76 5 - 76 62]
    IL_00d0: ldarg.0      // this
    IL_00d1: ldarg.0      // this
    IL_00d2: ldftn        instance void SDRSharp.TV.VideoWindow::VideoWindows_Resize(object, class [mscorlib]System.EventArgs)
    IL_00d8: newobj       instance void [mscorlib]System.EventHandler::.ctor(object, native int)
    IL_00dd: call         instance void [System.Windows.Forms]System.Windows.Forms.Control::add_Resize(class [mscorlib]System.EventHandler)

    // [77 5 - 77 29]
    IL_00e2: ldarg.0      // this
    IL_00e3: ldc.i4.0
    IL_00e4: call         instance void [System.Windows.Forms]System.Windows.Forms.Control::ResumeLayout(bool)
    IL_00e9: ret

  } // end of method VideoWindow::InitializeComponent
} // end of class SDRSharp.TV.VideoWindow

I have now extracted the TVPlugin data from JetBrains and saved it using the same schema as used for SDREmpty.
Unfortunately, I still have an error that I haven’t been able to resolve yet:

this._ifProcessor.IQReady += new IFProcessor.IQReadyDelegate( );

csharp// Mark the method where the event is subscribed to as ‘unsafe’
public unsafe void InitializeProcessor()
{
this._ifProcessor.IQReady += new IFProcessor.IQReadyDelegate(this.BufferAvailable);:face_vomiting:
}

// The target method must also be ‘unsafe’ if its signature contains pointers
private unsafe void BufferAvailable(float* iData, float* qData, int length)
{
// Your signal processing code
}

Why is this necessary? Pointers in signatures: If a delegate type—such as IQReadyDelegate—defines a pointer type, the entire method is considered “unverifiable” by the .NET runtime environment. Security barrier: By requiring the unsafe keyword, C# forces you to consciously acknowledge that you are taking responsibility for managing memory safety yourself (e.g., protecting against buffer overflows). Project setting: Ensure that the “Allow unsafe code” option is enabled in your project properties, under the “Build” tab. Alternatively, in the .csproj file: xmltrue

I think that once I have resolved this error, the original TVPlugin should at least function and serve as a basis for further experiments. Can anyone help me out?

Ich habe jetzt, die TVPlugin Daten aus JetBrains herausgenommen und diese im gkleichen Schema, wie bei SDREmpty, abgespeichert.
Leider habe ich noch einen Fehler drin, den ich bisher nicht beseitigt bekomme:

this._ifProcessor.IQReady += new IFProcessor.IQReadyDelegate**(this. BufferAvailable);**:grimacing:

csharp// Markiere die Methode, in der das Event abonniert wird, als unsafe
public unsafe void InitializeProcessor()
{
this._ifProcessor.IQReady += new IFProcessor.IQReadyDelegate(this.BufferAvailable);
}

// Auch die Zielmethode muss unsafe sein, wenn sie Zeiger in der Signatur hat
private unsafe void BufferAvailable(float* iData, float* qData, int length)
{
// Dein Code für die Signalverarbeitung
}

Warum ist das notwendig?Zeiger in Signaturen: Wenn ein Delegat-Typ wie IQReadyDelegate einen Zeiger-Typ definiert, gilt die gesamte Methode als “unverifizierbar” für die .NET-Laufzeitumgebung.Sicherheitsbarriere: C# zwingt dich durch das Schlüsselwort unsafe, bewusst zu bestätigen, dass du die Speichersicherheit selbst verwaltest (z.B. Schutz vor Pufferüberläufen).Projekt-Einstellung: Stelle sicher, dass in deinen Projekteigenschaften unter dem Reiter “Build” die Option “Unsicheren Code zulassen” (Allow unsafe code) aktiviert ist. Alternativ in der .csproj-Datei:xmltrue

Ich denke, wenn ich diesen Fehler beseitigt habe, könnte zumindest das original TVPlugin funktionieren und als Basis für weitere Experimente herhalten. Kann mir jemand helfen?

gruß Micha