diff --git a/Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/CaptureSettings.cs b/Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/LibcameraCaptureSettings.cs similarity index 93% rename from Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/CaptureSettings.cs rename to Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/LibcameraCaptureSettings.cs index 01be2d0..db702e3 100644 --- a/Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/CaptureSettings.cs +++ b/Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/LibcameraCaptureSettings.cs @@ -3,11 +3,11 @@ using VisionBuilder.UI.Common; namespace Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera; -public class CaptureSettings : ISettings +public class LibcameraCaptureSettings : ISettings { public string CameraName { get; } - public CaptureSettings(string cameraName) + public LibcameraCaptureSettings(string cameraName) { CameraName = cameraName; } diff --git a/Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/LibcameraImageSource.cs b/Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/LibcameraImageSource.cs index f1df722..06c8950 100644 --- a/Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/LibcameraImageSource.cs +++ b/Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera/LibcameraImageSource.cs @@ -8,9 +8,9 @@ namespace Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera { public class LibcameraImageSource : IImageSource, IVisionBuilderModule { - private CaptureSettings _settings; + private LibcameraCaptureSettings _settings; - public LibcameraImageSource(CaptureSettings settings) + public LibcameraImageSource(LibcameraCaptureSettings settings) { _settings = settings; } @@ -41,72 +41,80 @@ namespace Hawkeye.VisionBuilder.UI.Sources.Raspberry.Libcamera private void StartLoop() { - var psi = new ProcessStartInfo + try { - FileName = "rpicam-vid", - Arguments = _settings.BuildArguments(), - RedirectStandardOutput = true, - UseShellExecute = false - }; + var psi = new ProcessStartInfo + { + FileName = "rpicam-vid", + Arguments = _settings.BuildArguments(), + RedirectStandardOutput = true, + UseShellExecute = false + }; - using (Process process = Process.Start(psi)) - using (BinaryReader br = new BinaryReader(process.StandardOutput.BaseStream)) - { - - byte[] imageBuffer = new byte[1024 * 1024]; - - - // decode MJPEG buffer - var buff = br.ReadBytes(ChunkSize); - int frameId = 0; - while (true) + using (Process process = Process.Start(psi)) + using (BinaryReader br = new BinaryReader(process.StandardOutput.BaseStream)) { + byte[] imageBuffer = new byte[1024 * 1024]; - var imageStart = Find(buff, JpegHeader); - if (imageStart != -1) + + // decode MJPEG buffer + var buff = br.ReadBytes(ChunkSize); + int frameId = 0; + while (true) { - var size = buff.Length - imageStart; - Array.Copy(buff, imageStart, imageBuffer, 0, size); - while (true) + + var imageStart = Find(buff, JpegHeader); + if (imageStart != -1) { - buff = br.ReadBytes(ChunkSize); - var imageEnd = Find(buff, JpegFooter); - if (imageEnd != -1) + var size = buff.Length - imageStart; + + Array.Copy(buff, imageStart, imageBuffer, 0, size); + while (true) { - var frame = new byte[size + imageEnd]; - Array.Copy(imageBuffer, frame, size); - Array.Copy(buff, 0, frame, size, imageEnd); - // process frame - frameId++; - var decoded = Mat.ImDecode(frame); + buff = br.ReadBytes(ChunkSize); + var imageEnd = Find(buff, JpegFooter); + if (imageEnd != -1) + { + var frame = new byte[size + imageEnd]; + Array.Copy(imageBuffer, frame, size); + Array.Copy(buff, 0, frame, size, imageEnd); + // process frame + frameId++; + var decoded = Mat.ImDecode(frame); - _imageChannel.Writer.WriteAsync(decoded, CancellationToken.None); + _imageChannel.Writer.WriteAsync(decoded, CancellationToken.None); - // copy the leftover data to the start - Array.Copy(buff, imageEnd, buff, 0, buff.Length - imageEnd); - // fill the remainder of the buffer with new data and start over - var temp = br.ReadBytes(imageEnd); - Array.Copy(temp, 0, buff, buff.Length - imageEnd, temp.Length); - break; + // copy the leftover data to the start + Array.Copy(buff, imageEnd, buff, 0, buff.Length - imageEnd); + // fill the remainder of the buffer with new data and start over + var temp = br.ReadBytes(imageEnd); + Array.Copy(temp, 0, buff, buff.Length - imageEnd, temp.Length); + break; + } + + // copy all of the data to the imageBuffer + Array.Copy(buff, 0, imageBuffer, size, buff.Length); + size += buff.Length; } - // copy all of the data to the imageBuffer - Array.Copy(buff, 0, imageBuffer, size, buff.Length); - size += buff.Length; } + else + { + Console.WriteLine("JPEG header not found."); + break; + } + } - else - { - Console.WriteLine("JPEG header not found."); - break; - } + + + process.Kill(); } - - - process.Kill(); - + } + catch (Exception e) + { + Serilog.Log.Error($"Error starting libcamera: {e}"); } } diff --git a/VisionBuilder.UI.Avalonia.Uno/App.axaml.cs b/VisionBuilder.UI.Avalonia.Uno/App.axaml.cs index 4448855..bacd890 100644 --- a/VisionBuilder.UI.Avalonia.Uno/App.axaml.cs +++ b/VisionBuilder.UI.Avalonia.Uno/App.axaml.cs @@ -7,6 +7,7 @@ using Ninject.Extensions.ChildKernel; using VisionBuilder.UI.Common; using VisionBuilder.UI.Common.Plugins; using VisionBuilder.UI.Common.Processing; +using VisionBuilder.UI.Common.Services; using VisionBuilder.UI.Common.ViewModel; using VisionBuilder.UI.IOCommander; using VisionBuilder.UI.Recipes.HawkeyeRecipe; @@ -15,6 +16,7 @@ using VisionBuilder.UI.Statistics; using VisionBuilder.UI.Avalonia; using VisionBuilder.UI.Avalonia.Uno.Views; using Lindt.Colorballs.Duo.Utils; +using VisionBuilder.UI.Camera; namespace VisionBuilder.UI.Avalonia.Uno; @@ -79,10 +81,12 @@ public class App : Application ]; var avaloniaUiSettings = mainKernel.Get(); + var uiConfiguration = mainKernel.Get(); + var passwordInputService = mainKernel.Get(); settings.LoadSettings(); - desktop.MainWindow = new MainWindow(mainWindowVm, avaloniaUiSettings); + desktop.MainWindow = new MainWindow(mainWindowVm, avaloniaUiSettings, uiConfiguration, passwordInputService); } base.OnFrameworkInitializationCompleted(); diff --git a/VisionBuilder.UI.Avalonia.Uno/Program.cs b/VisionBuilder.UI.Avalonia.Uno/Program.cs index e4079e3..ef05783 100644 --- a/VisionBuilder.UI.Avalonia.Uno/Program.cs +++ b/VisionBuilder.UI.Avalonia.Uno/Program.cs @@ -1,5 +1,6 @@ using Avalonia; using Avalonia.LinuxFramebuffer; +using Serilog; namespace VisionBuilder.UI.Avalonia.Uno; @@ -8,6 +9,11 @@ public class Program [STAThread] public static void Main(string[] args) { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Debug() + .WriteTo.Console() + .CreateLogger(); + if (args.Contains("--drm")) BuildAvaloniaApp().StartLinuxDrm(args, card: null, scaling: 1.0); else diff --git a/VisionBuilder.UI.Avalonia.Uno/Views/MainWindow.axaml b/VisionBuilder.UI.Avalonia.Uno/Views/MainWindow.axaml index 174aff1..4c410ec 100644 --- a/VisionBuilder.UI.Avalonia.Uno/Views/MainWindow.axaml +++ b/VisionBuilder.UI.Avalonia.Uno/Views/MainWindow.axaml @@ -20,6 +20,16 @@ HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="8"> +