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 CameraService _cameraService; private readonly ILogger _logger; private readonly System.Timers.Timer _renderTimer; public event EventHandler? RenderReqested; [ObservableProperty] private Color _background = Colors.Transparent; [ObservableProperty] private Stretch _stretchMode = Stretch.Uniform; [ObservableProperty] private TileMode _tileMode = TileMode.None; public CameraViewModel(CameraService cameraService, ILogger logger) { _cameraService = cameraService; _logger = logger; _renderTimer = new System.Timers.Timer(33); _renderTimer.Elapsed += (_, _) => { if (!_cameraService.IsImageCapturing) RenderReqested?.Invoke(this, new EventArgs()); }; _logger.LogInformation("{} initialized", nameof(CameraViewModel)); } 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); } }