using Microsoft.Extensions.Logging; using LibCameraSharp; namespace GSS2.Core.Logging; public sealed class LibCameraLogSink : IDisposable { private readonly ILogger _logger; private readonly ILogger _loggerCamera; private readonly ILogger _loggerRPI; private readonly ILogger _loggerDeviceEnumerator; private readonly ILogger _loggerIPAProxy; private readonly ILogger _loggerV4L2; private readonly ILogger _loggerRPISTREAM; private readonly ILogger _loggerWRAPPER; private readonly ILogger _loggerRPiAgc; private bool _disposedValue; public LibCameraLogSink(ILoggerFactory loggerFactory) { _logger = loggerFactory.CreateLogger("LibCamera"); _loggerCamera = loggerFactory.CreateLogger("LibCamera-Camera"); _loggerRPI = loggerFactory.CreateLogger("LibCamera-RPI"); _loggerDeviceEnumerator = loggerFactory.CreateLogger("LibCamera-DeviceEnumerator"); _loggerIPAProxy = loggerFactory.CreateLogger("LibCamera-IPAProxy"); _loggerV4L2 = loggerFactory.CreateLogger("LibCamera-V4L2"); _loggerRPISTREAM = loggerFactory.CreateLogger("LibCamera-RPISTREAM"); _loggerWRAPPER = loggerFactory.CreateLogger("LibCamera-WRAPPER"); _loggerRPiAgc = loggerFactory.CreateLogger("LibCamera-RPiAgc"); Log.Initialize(); Log.SetLevel("Camera", Log.LogLevelEnum.DEBUG); Log.SetLevel("RPI", Log.LogLevelEnum.DEBUG); Log.SetLevel("DeviceEnumerator", Log.LogLevelEnum.DEBUG); Log.SetLevel("IPAProxy", Log.LogLevelEnum.DEBUG); Log.SetLevel("V4L2", Log.LogLevelEnum.DEBUG); Log.SetLevel("RPISTREAM", Log.LogLevelEnum.DEBUG); Log.SetLevel("WRAPPER", Log.LogLevelEnum.DEBUG); Log.SetLevel("RPiAgc", Log.LogLevelEnum.DEBUG); Log.LogReceived += OnLogReceived; } private void OnLogReceived(object? sender, Log.LogEventArgs e) { if (_disposedValue) return; try { var level = MapLogLevel(e.Level); var logger = e.Category switch { "Camera" => _loggerCamera, "RPI" => _loggerRPI, "DeviceEnumerator" => _loggerDeviceEnumerator, "IPAProxy" => _loggerIPAProxy, "V4L2" => _loggerV4L2, "RPISTREAM" => _loggerRPISTREAM, "WRAPPER" => _loggerWRAPPER, "RPiAgc" => _loggerRPiAgc, _ => null }; if (logger is not null && logger.IsEnabled(level)) logger.Log(level, new EventId(0, $"{e.ThreadId} {e.File}"), e, null, static (state, _) => $"{state.Message}"); else if (logger is null && _logger.IsEnabled(level)) _logger.Log(level, new EventId(0, $"{e.ThreadId} {e.File}"), e, null, static (state, _) => $"[{state.Category}] {state.Message}"); } catch { } } private static LogLevel MapLogLevel(Log.LogLevelEnum level) => level switch { Log.LogLevelEnum.DEBUG => LogLevel.Debug, Log.LogLevelEnum.INFO => LogLevel.Information, Log.LogLevelEnum.WARN => LogLevel.Warning, Log.LogLevelEnum.ERROR => LogLevel.Error, Log.LogLevelEnum.FATAL => LogLevel.Critical, _ => LogLevel.None }; private void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { Log.LogReceived -= OnLogReceived; } _disposedValue = true; } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } }