using System.Buffers; using System.Runtime.InteropServices; namespace RPiRgbLEDMatrix; /// /// Represents a RGB matrix. /// public class RGBLedMatrix : IDisposable { private IntPtr matrix; private bool disposedValue = false; /// /// Initializes a new matrix. /// /// Size of a single module. Can be 32, 16 or 8. /// How many modules are connected in a chain. /// How many modules are connected in a parallel. public RGBLedMatrix(int rows, int chained, int parallel) { matrix = led_matrix_create(rows, chained, parallel); if (matrix == (IntPtr)0) throw new ArgumentException("Could not initialize a new matrix"); } /// /// Initializes a new matrix. /// /// A configuration of a matrix. public RGBLedMatrix(RGBLedMatrixOptions options) { InternalRGBLedMatrixOptions opt = default; try { opt = new(options); var args = Environment.GetCommandLineArgs(); // Because gpio-slowdown is not provided in the options struct, // we manually add it. // Let's add it first to the command-line we pass to the // matrix constructor, so that it can be overridden with the // users' commandline. // As always, as the _very_ first, we need to provide the // program name argv[0]. var argv = new string[args.Length + 1]; argv[0] = args[0]; argv[1] = $"--led-slowdown-gpio={options.GpioSlowdown}"; Array.Copy(args, 1, argv, 2, args.Length - 1); matrix = led_matrix_create_from_options_const_argv(ref opt, argv.Length, argv); if (matrix == (IntPtr)0) throw new ArgumentException("Could not initialize a new matrix"); } finally { if(options.HardwareMapping is not null) Marshal.FreeHGlobal(opt.hardware_mapping); if(options.LedRgbSequence is not null) Marshal.FreeHGlobal(opt.led_rgb_sequence); if(options.PixelMapperConfig is not null) Marshal.FreeHGlobal(opt.pixel_mapper_config); if(options.PanelType is not null) Marshal.FreeHGlobal(opt.panel_type); } } /// /// Creates a new backbuffer canvas for drawing on. /// /// An instance of representing the canvas. public RGBLedCanvas CreateOffscreenCanvas() => new(led_matrix_create_offscreen_canvas(matrix)); /// /// Returns a canvas representing the current frame buffer. /// /// An instance of representing the canvas. /// Consider using instead. public RGBLedCanvas GetCanvas() => new(led_matrix_get_canvas(matrix)); /// /// Swaps this canvas with the currently active canvas. The active canvas /// becomes a backbuffer and is mapped to instance. ///
/// This operation guarantees vertical synchronization. ///
/// Backbuffer canvas to swap. public void SwapOnVsync(RGBLedCanvas canvas) => canvas._canvas = led_matrix_swap_on_vsync(matrix, canvas._canvas); /// /// The general brightness of the matrix. /// public byte Brightness { get => led_matrix_get_brightness(matrix); set => led_matrix_set_brightness(matrix, value); } protected virtual void Dispose(bool disposing) { if (disposedValue) return; led_matrix_delete(matrix); disposedValue = true; } ~RGBLedMatrix() => Dispose(false); /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } }