using Microsoft.Extensions.Logging; using LibCameraSharp; using GSS2.Core.Hardware; using CommunityToolkit.Mvvm.ComponentModel; using Avalonia.Media; namespace GSS2.UI.Core.ViewModels; public partial class CameraViewModel : ViewModelBase, IDisposable { private bool _disposedValue; private readonly ILogger _logger; private readonly CameraService _cameraService; private readonly System.Timers.Timer _renderTimer; public event EventHandler? RenderRequested; [ObservableProperty] private Color _background = Colors.Transparent; [ObservableProperty] private Stretch _stretchMode = Stretch.Uniform; [ObservableProperty] private TileMode _tileMode = TileMode.None; public CameraViewModel(ILogger logger, CameraService cameraService) { _logger = logger; _logger.LogInformation("Initialization"); _cameraService = cameraService; _renderTimer = new System.Timers.Timer(33); _renderTimer.Elapsed += (_, _) => { if (!_cameraService.IsImageCapturing) RenderRequested?.Invoke(this, new EventArgs()); }; _logger.LogInformation("Initialized"); } public void StartViewFinder() { _cameraService.StartViewFinder(); _renderTimer.Start(); } public void StopViewFinder() { _renderTimer.Stop(); _cameraService.StopViewFinder(); } public bool CanGrabViewFinderFrame() => !_cameraService.IsImageCapturing; public (FrameBuffer, StreamConfiguration)? GrabViewFinderFrame() => _cameraService.GrabViewFinderFrame(); public void ReturnViewFinderFrame(FrameBuffer frameBuffer) => _cameraService.ReturnViewFinderFrame(frameBuffer); protected virtual void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { _renderTimer.Stop(); _renderTimer.Dispose(); } _disposedValue = true; } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } }