SDRSharper/Plugins/SDRSharper.FrequencyScanner/SDRSharp.FrequencyScanner/ChannelAnalyzer.cs

382 lines
11 KiB
C#
Raw Normal View History

using SDRSharp.Radio;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
namespace SDRSharp.FrequencyScanner
{
public class ChannelAnalyzer : UserControl
{
private const float TrackingFontSize = 16f;
private const int CarrierPenWidth = 1;
private const int GradientAlpha = 180;
public const int AxisMargin = 2;
public const float DefaultCursorHeight = 32f;
private bool _drawBackgroundNeeded;
private Bitmap _bkgBuffer;
private Bitmap _buffer;
private Graphics _graphics;
private float _xIncrement;
private float _yIncrement;
private long _playFrequency;
private int _playFrequencyIndex;
private List<ChannelAnalizerMemoryEntry> _channelArray;
private int _zoom;
private int _zoomPosition;
private float _defXIncrement;
public long Frequency
{
set
{
this._playFrequency = value;
}
}
public int Zoom
{
get
{
return this._zoom;
}
set
{
this._zoom = value;
}
}
public int ZoomPosition
{
get
{
return this._zoomPosition;
}
set
{
this._zoomPosition = value;
}
}
public event CustomPaintEventHandler CustomPaint;
public ChannelAnalyzer()
{
Rectangle clientRectangle = base.ClientRectangle;
int width = clientRectangle.Width;
clientRectangle = base.ClientRectangle;
this._bkgBuffer = new Bitmap(width, clientRectangle.Height, PixelFormat.Format32bppPArgb);
clientRectangle = base.ClientRectangle;
int width2 = clientRectangle.Width;
clientRectangle = base.ClientRectangle;
this._buffer = new Bitmap(width2, clientRectangle.Height, PixelFormat.Format32bppPArgb);
this._graphics = Graphics.FromImage(this._buffer);
base.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
base.SetStyle(ControlStyles.DoubleBuffer, true);
base.SetStyle(ControlStyles.UserPaint, true);
base.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
base.UpdateStyles();
}
~ChannelAnalyzer()
{
this._buffer.Dispose();
this._graphics.Dispose();
}
public void Perform(List<ChannelAnalizerMemoryEntry> channelArray)
{
this._channelArray = channelArray;
if (this._drawBackgroundNeeded)
{
this.DrawBackground();
}
this.DrawForeground();
base.Invalidate();
this._drawBackgroundNeeded = false;
}
private void DrawBackground()
{
using (SolidBrush solidBrush = new SolidBrush(Color.Silver))
{
using (Pen pen = new Pen(Color.FromArgb(80, 80, 80)))
{
using (new Pen(Color.DarkGray))
{
using (Font font = new Font("Arial", 8f))
{
using (Graphics graphics = Graphics.FromImage(this._bkgBuffer))
{
ChannelAnalyzer.ConfigureGraphics(graphics);
graphics.Clear(Color.Black);
pen.DashStyle = DashStyle.Dash;
int num = 20;
Rectangle clientRectangle = base.ClientRectangle;
int num2 = (clientRectangle.Height - 4) / num;
for (int i = 1; i <= num2; i++)
{
Graphics graphics2 = graphics;
Pen pen2 = pen;
clientRectangle = base.ClientRectangle;
int y = clientRectangle.Height - 2 - i * num;
clientRectangle = base.ClientRectangle;
int x = clientRectangle.Width - 2;
clientRectangle = base.ClientRectangle;
graphics2.DrawLine(pen2, 2, y, x, clientRectangle.Height - 2 - i * num);
}
for (int j = 1; j <= num2; j++)
{
string text = (j * num / 2 - 10).ToString();
SizeF sizeF = graphics.MeasureString(text, font);
float width = sizeF.Width;
float height = sizeF.Height;
Graphics graphics3 = graphics;
string s = text;
Font font2 = font;
SolidBrush brush = solidBrush;
clientRectangle = base.ClientRectangle;
graphics3.DrawString(s, font2, brush, 4f, (float)(clientRectangle.Height - 2 - j * num) - height + 1f);
}
}
}
}
}
}
}
private string GetFrequencyDisplay(long frequency)
{
if (frequency == 0L)
{
return "DC";
}
if (Math.Abs(frequency) > 1500000000)
{
return $"{(double)frequency / 1000000000.0:#,0.000 000}GHz";
}
if (Math.Abs(frequency) > 30000000)
{
return $"{(double)frequency / 1000000.0:0,0.000###}MHz";
}
if (Math.Abs(frequency) > 1000)
{
return $"{(double)frequency / 1000.0:#,#.###}kHz";
}
return $"{frequency}Hz";
}
public static void ConfigureGraphics(Graphics graphics)
{
graphics.CompositingMode = CompositingMode.SourceOver;
graphics.CompositingQuality = CompositingQuality.HighSpeed;
graphics.SmoothingMode = SmoothingMode.None;
graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
graphics.InterpolationMode = InterpolationMode.High;
}
private void DrawForeground()
{
Rectangle clientRectangle = base.ClientRectangle;
if (clientRectangle.Width > 2)
{
clientRectangle = base.ClientRectangle;
if (clientRectangle.Height > 2)
{
this.CopyBackground();
this.DrawSpectrum();
this.OnCustomPaint(new CustomPaintEventArgs(this._graphics));
}
}
}
private unsafe void CopyBackground()
{
BitmapData bitmapData = this._buffer.LockBits(base.ClientRectangle, ImageLockMode.WriteOnly, this._buffer.PixelFormat);
BitmapData bitmapData2 = this._bkgBuffer.LockBits(base.ClientRectangle, ImageLockMode.ReadOnly, this._bkgBuffer.PixelFormat);
Utils.Memcpy((void*)bitmapData.Scan0, (void*)bitmapData2.Scan0, Math.Abs(bitmapData.Stride) * bitmapData.Height);
this._buffer.UnlockBits(bitmapData);
this._bkgBuffer.UnlockBits(bitmapData2);
}
private void DrawSpectrum()
{
if (this._channelArray != null && this._channelArray.Count != 0)
{
Rectangle clientRectangle = base.ClientRectangle;
this._xIncrement = (float)(clientRectangle.Width - 4) / (float)this._channelArray.Count * (float)(this._zoom + 1);
this._yIncrement = 2f;
clientRectangle = base.ClientRectangle;
this._defXIncrement = (float)(clientRectangle.Width - 4) / (float)this._channelArray.Count;
float num = 0f;
float num2 = 0f;
this._playFrequencyIndex = -1;
using (Pen pen = new Pen(Color.SkyBlue))
{
using (Pen pen4 = new Pen(Color.DarkRed))
{
using (Pen pen5 = new Pen(Color.Yellow))
{
using (Pen pen3 = new Pen(Color.Green))
{
for (int i = 0; i < this._channelArray.Count; i++)
{
float num3 = (float)Math.Max((int)this._channelArray[i].Level, 4) * this._yIncrement;
float num4 = this._xIncrement - 1f;
if (this._xIncrement < 3f)
{
num4 = this._xIncrement;
}
float num5 = 2f + (float)i * this._xIncrement - (float)(this._zoomPosition * (this._zoom + 1)) + (float)this._zoomPosition + num4 * 0.5f;
clientRectangle = base.ClientRectangle;
float num6 = (float)Math.Max(2, (int)((float)(clientRectangle.Height - 2) - num3));
float val = num3;
clientRectangle = base.ClientRectangle;
num3 = Math.Min(val, (float)(clientRectangle.Height - 4));
if (!(num5 < 2f))
{
float num7 = num5;
clientRectangle = base.ClientRectangle;
if (!(num7 > (float)(clientRectangle.Width - 2)))
{
Pen pen2 = pen;
if (this._playFrequency > this._channelArray[i].Frequency - this._channelArray[i].StepSize / 2 && this._playFrequency < this._channelArray[i].Frequency + this._channelArray[i].StepSize / 2)
{
num = num5;
num2 = num6;
this._playFrequencyIndex = i;
}
if (this._channelArray[i].IsStore)
{
pen2 = pen3;
}
if (this._channelArray[i].Skipped)
{
pen2 = ((!this._channelArray[i].IsStore) ? pen4 : pen5);
}
pen2.Width = num4;
this._graphics.DrawLine(pen2, num5, num6, num5, num6 + num3);
}
}
}
}
}
}
}
using (SolidBrush brush = new SolidBrush(Color.White))
{
using (Pen pen6 = new Pen(Color.White))
{
using (Font font = new Font("Arial", 8f))
{
if (this._playFrequencyIndex >= 0 && this._playFrequencyIndex < this._channelArray.Count)
{
string str = this.GetFrequencyDisplay(this._channelArray[this._playFrequencyIndex].Frequency) + " ";
str = ((!this._channelArray[this._playFrequencyIndex].IsStore) ? (str + "Unknown") : (str + this._channelArray[this._playFrequencyIndex].StoreName));
SizeF sizeF = this._graphics.MeasureString(str, font);
float width = sizeF.Width;
float height = sizeF.Height;
float num8 = 0f;
int num9 = 62;
this._graphics.DrawLine(pen6, num, num2 - 10f, num, (float)num9 + height + 4f);
float num10 = num + width + 10f;
clientRectangle = base.ClientRectangle;
num8 = ((!(num10 > (float)clientRectangle.Width)) ? num : (num - width));
this._graphics.DrawLine(pen6, num8, (float)num9 + height + 4f, num8 + width, (float)num9 + height + 4f);
this._graphics.DrawString(str, font, brush, num8, (float)num9);
}
}
}
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
ChannelAnalyzer.ConfigureGraphics(e.Graphics);
e.Graphics.DrawImageUnscaled(this._buffer, 0, 0);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
Rectangle clientRectangle = base.ClientRectangle;
if (clientRectangle.Width > 0)
{
clientRectangle = base.ClientRectangle;
if (clientRectangle.Height > 0)
{
this._buffer.Dispose();
this._graphics.Dispose();
this._bkgBuffer.Dispose();
clientRectangle = base.ClientRectangle;
int width = clientRectangle.Width;
clientRectangle = base.ClientRectangle;
this._buffer = new Bitmap(width, clientRectangle.Height, PixelFormat.Format32bppPArgb);
this._graphics = Graphics.FromImage(this._buffer);
ChannelAnalyzer.ConfigureGraphics(this._graphics);
clientRectangle = base.ClientRectangle;
int width2 = clientRectangle.Width;
clientRectangle = base.ClientRectangle;
this._bkgBuffer = new Bitmap(width2, clientRectangle.Height, PixelFormat.Format32bppPArgb);
this._drawBackgroundNeeded = true;
this.Perform(this._channelArray);
}
}
}
protected virtual void OnCustomPaint(CustomPaintEventArgs e)
{
CustomPaintEventHandler customPaint = this.CustomPaint;
customPaint?.Invoke(this, e);
}
public int CurrentChannelIndex()
{
return this._playFrequencyIndex;
}
public int PointToChannel(float point)
{
int num = 0;
num = (int)(((float)(this._zoomPosition * (this._zoom + 1)) + point - (float)this._zoomPosition - 2f) / this._xIncrement);
if (num < 0)
{
num = 0;
}
if (num >= this._channelArray.Count)
{
num = this._channelArray.Count - 1;
}
return num;
}
private void InitializeComponent()
{
base.SuspendLayout();
this.AutoSize = true;
this.DoubleBuffered = true;
base.Name = "ChannelAnalyzer";
base.ResumeLayout(false);
}
}
}