diff --git a/src/CamBooth/.idea/.idea.CamBooth/.idea/vcs.xml b/src/CamBooth/.idea/.idea.CamBooth/.idea/vcs.xml
index fdf1fc8..b2bdec2 100644
--- a/src/CamBooth/.idea/.idea.CamBooth/.idea/vcs.xml
+++ b/src/CamBooth/.idea/.idea.CamBooth/.idea/vcs.xml
@@ -2,6 +2,5 @@
-
\ No newline at end of file
diff --git a/src/CamBooth/CamBooth.App/CamBooth.App.csproj b/src/CamBooth/CamBooth.App/CamBooth.App.csproj
index 320efae..9033bb4 100644
--- a/src/CamBooth/CamBooth.App/CamBooth.App.csproj
+++ b/src/CamBooth/CamBooth.App/CamBooth.App.csproj
@@ -29,7 +29,6 @@
-
diff --git a/src/CamBooth/CamBooth.App/Core/AppSettings/AppSettingsService.cs b/src/CamBooth/CamBooth.App/Core/AppSettings/AppSettingsService.cs
index 613db2b..0d4c6c8 100644
--- a/src/CamBooth/CamBooth.App/Core/AppSettings/AppSettingsService.cs
+++ b/src/CamBooth/CamBooth.App/Core/AppSettings/AppSettingsService.cs
@@ -32,7 +32,11 @@ public class AppSettingsService
}
public string? AppName => configuration["AppSettings:AppName"];
+
+ public bool IsDebugConsoleVisible => bool.Parse(configuration["AppSettings:DebugConsoleVisible"] ?? string.Empty);
+
public string? PictureLocation => configuration["AppSettings:PictureLocation"];
+
public string? ConnectionString => configuration.GetConnectionString("DefaultConnection");
public string ConfigFileName => loadedConfigFile;
diff --git a/src/CamBooth/CamBooth.App/Core/AppSettings/app.settings.dev.json b/src/CamBooth/CamBooth.App/Core/AppSettings/app.settings.dev.json
index 96c84d2..99f6f84 100644
--- a/src/CamBooth/CamBooth.App/Core/AppSettings/app.settings.dev.json
+++ b/src/CamBooth/CamBooth.App/Core/AppSettings/app.settings.dev.json
@@ -2,7 +2,8 @@
"AppSettings": {
"AppName": "Meine Anwendung",
"Version": "1.0.0",
- "PictureLocation": "C:\\tmp\\cambooth"
+ "PictureLocation": "C:\\tmp\\cambooth",
+ "DebugConsoleVisible": "true"
},
"ConnectionStrings": {
"DefaultConnection": "Server=myServer;Database=myDB;User Id=myUser;Password=myPassword;"
diff --git a/src/CamBooth/CamBooth.App/Core/AppSettings/app.settings.json b/src/CamBooth/CamBooth.App/Core/AppSettings/app.settings.json
index 8657b50..bc47f37 100644
--- a/src/CamBooth/CamBooth.App/Core/AppSettings/app.settings.json
+++ b/src/CamBooth/CamBooth.App/Core/AppSettings/app.settings.json
@@ -2,7 +2,8 @@
"AppSettings": {
"AppName": "Meine Anwendung",
"Version": "1.0.0",
- "PictureLocation": "C:\\cambooth\\pictures"
+ "PictureLocation": "C:\\cambooth\\pictures",
+ "DebugConsoleVisible": "true"
},
"ConnectionStrings": {
"DefaultConnection": "Server=myServer;Database=myDB;User Id=myUser;Password=myPassword;"
diff --git a/src/CamBooth/CamBooth.App/Features/Camera/CameraService.cs b/src/CamBooth/CamBooth.App/Features/Camera/CameraService.cs
index 8f09395..6ef452a 100644
--- a/src/CamBooth/CamBooth.App/Features/Camera/CameraService.cs
+++ b/src/CamBooth/CamBooth.App/Features/Camera/CameraService.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using System.IO;
+using System.Threading.Tasks;
using System.Windows;
using CamBooth.App.Core.AppSettings;
@@ -192,6 +193,53 @@ public class CameraService : IDisposable
throw;
}
}
+ public async Task PrepareFocusAsync(int focusTimeoutMs = 1500)
+ {
+ if (this._mainCamera is not EOSDigital.API.Camera sdkCamera)
+ {
+ await Task.Delay(200);
+ return;
+ }
+
+ var focusCompleted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+
+ void FocusStateChanged(EOSDigital.API.Camera sender, StateEventID eventId, int parameter)
+ {
+ if (eventId == StateEventID.AfResult)
+ {
+ focusCompleted.TrySetResult(true);
+ }
+ }
+
+ sdkCamera.StateChanged += FocusStateChanged;
+
+ try
+ {
+ await Task.Run(() => sdkCamera.SendCommand(CameraCommand.PressShutterButton, (int)ShutterButton.Halfway));
+ var completedTask = await Task.WhenAny(focusCompleted.Task, Task.Delay(focusTimeoutMs));
+ if (completedTask != focusCompleted.Task)
+ {
+ this._logger.Info("Autofocus timeout reached, continuing with countdown.");
+ }
+ }
+ catch (Exception ex)
+ {
+ this.ReportError(ex.Message);
+ }
+ finally
+ {
+ try
+ {
+ await Task.Run(() => sdkCamera.SendCommand(CameraCommand.PressShutterButton, (int)ShutterButton.OFF));
+ }
+ catch (Exception ex)
+ {
+ this.ReportError(ex.Message);
+ }
+
+ sdkCamera.StateChanged -= FocusStateChanged;
+ }
+ }
#region API Events
@@ -290,4 +338,5 @@ public class CameraService : IDisposable
}
#endregion
-}
\ No newline at end of file
+}
+
diff --git a/src/CamBooth/CamBooth.App/MainWindow.xaml b/src/CamBooth/CamBooth.App/MainWindow.xaml
index f12942c..544cc64 100644
--- a/src/CamBooth/CamBooth.App/MainWindow.xaml
+++ b/src/CamBooth/CamBooth.App/MainWindow.xaml
@@ -41,8 +41,16 @@
Panel.ZIndex="1" />
-
+
-
\ No newline at end of file
+
diff --git a/src/CamBooth/CamBooth.App/MainWindow.xaml.cs b/src/CamBooth/CamBooth.App/MainWindow.xaml.cs
index d1634bc..db0636d 100644
--- a/src/CamBooth/CamBooth.App/MainWindow.xaml.cs
+++ b/src/CamBooth/CamBooth.App/MainWindow.xaml.cs
@@ -1,5 +1,7 @@
-using System.ComponentModel;
+using System.ComponentModel;
+using System.Threading.Tasks;
using System.Windows;
+using System.Windows.Threading;
using CamBooth.App.Core.AppSettings;
using CamBooth.App.Core.Logging;
@@ -28,6 +30,12 @@ public partial class MainWindow : Window
private bool _isPicturePanelVisible = false;
private LiveViewPage? _liveViewPage;
+
+ private bool _isPhotoProcessRunning;
+
+ private readonly DispatcherTimer _focusStatusAnimationTimer = new() { Interval = TimeSpan.FromMilliseconds(250) };
+
+ private int _focusStatusDots;
public MainWindow(
@@ -41,11 +49,16 @@ public partial class MainWindow : Window
this._pictureGalleryService = pictureGalleryService;
this._cameraService = cameraService;
InitializeComponent();
- this.SetVisibilityDebugConsole(this._isDebugConsoleVisible);
+ this.SetVisibilityDebugConsole(_appSettings.IsDebugConsoleVisible);
this.SetVisibilityPicturePanel(this._isPicturePanelVisible);
_ = this._pictureGalleryService.LoadThumbnailsToCache();
this.Closing += OnClosing;
TimerControlRectangleAnimation.OnTimerEllapsed += TimerControlRectangleAnimation_OnTimerEllapsed;
+ this._focusStatusAnimationTimer.Tick += (_, _) =>
+ {
+ this._focusStatusDots = (this._focusStatusDots + 1) % 4;
+ this.CaptureStatusText.Text = $"Scharfstellen{new string('.', this._focusStatusDots)}";
+ };
logger.Info($"config file loaded: '{appSettings.ConfigFileName}'");
logger.Info("MainWindow initialized");
}
@@ -65,7 +78,10 @@ public partial class MainWindow : Window
}
finally
{
+ this.StopFocusStatusAnimation();
+ this.CaptureStatusText.Visibility = Visibility.Collapsed;
SwitchButtonAndTimerPanel();
+ this._isPhotoProcessRunning = false;
}
}
@@ -106,6 +122,11 @@ public partial class MainWindow : Window
private void SetVisibilityDebugConsole(bool visibility)
{
+ if (!_appSettings.IsDebugConsoleVisible)
+ {
+ return;
+ }
+
if (visibility)
{
this.DebugFrame.Navigate(new DebugConsolePage(this._logger));
@@ -119,19 +140,56 @@ public partial class MainWindow : Window
}
- private void StartTakePhotoProcess(object sender, RoutedEventArgs e)
+ private async void StartTakePhotoProcess(object sender, RoutedEventArgs e)
{
+ if (this._isPhotoProcessRunning)
+ {
+ return;
+ }
+
+ this._isPhotoProcessRunning = true;
+
try
{
-#if DEBUG
- TimerControlRectangleAnimation.StartTimer(1);
-#else
- TimerControlRectangleAnimation.StartTimer(5);
-#endif
SwitchButtonAndTimerPanel();
+
+#if DEBUG
+ TimerControlRectangleAnimation.StartTimer(2);
+ this.StartFocusStatusAnimation();
+ this.CaptureStatusText.Visibility = Visibility.Visible;
+ await Task.Delay(TimeSpan.FromSeconds(1));
+ if (!this._isPhotoProcessRunning)
+ {
+ return;
+ }
+
+ await this._cameraService.PrepareFocusAsync(focusTimeoutMs: 1000);
+ this.StopFocusStatusAnimation();
+ this.CaptureStatusText.Visibility = Visibility.Collapsed;
+#else
+ TimerControlRectangleAnimation.StartTimer(5);
+ this.StartFocusStatusAnimation();
+ this.CaptureStatusText.Visibility = Visibility.Visible;
+ await Task.Delay(TimeSpan.FromSeconds(2));
+ if (!this._isPhotoProcessRunning)
+ {
+ return;
+ }
+
+ await this._cameraService.PrepareFocusAsync(focusTimeoutMs: 3000);
+ this.StopFocusStatusAnimation();
+ this.CaptureStatusText.Visibility = Visibility.Collapsed;
+#endif
}
catch (Exception exception)
{
+ this._isPhotoProcessRunning = false;
+ this.StopFocusStatusAnimation();
+ this.CaptureStatusText.Visibility = Visibility.Collapsed;
+ if (this.TimerPanel.Visibility == Visibility.Visible)
+ {
+ SwitchButtonAndTimerPanel();
+ }
this._logger.Error(exception.Message);
}
}
@@ -152,4 +210,17 @@ public partial class MainWindow : Window
{
this.Close();
}
-}
\ No newline at end of file
+
+ private void StartFocusStatusAnimation()
+ {
+ this._focusStatusDots = 0;
+ this.CaptureStatusText.Text = "Scharfstellen";
+ this._focusStatusAnimationTimer.Start();
+ }
+
+ private void StopFocusStatusAnimation()
+ {
+ this._focusStatusAnimationTimer.Stop();
+ this._focusStatusDots = 0;
+ }
+}
diff --git a/src/CamBooth/CamBooth.App/ToDos.txt b/src/CamBooth/CamBooth.App/ToDos.txt
new file mode 100644
index 0000000..10fe566
--- /dev/null
+++ b/src/CamBooth/CamBooth.App/ToDos.txt
@@ -0,0 +1,8 @@
+- Rotate Flick Picture 180°
+- Printer anschließen
+- Galerie schließen
+- Debug Window schließen
+- Kiosk Modus einrichten
+- Energiesparmodus abschalten
+- Starbildschirm mit freundlicher Begrüßung, kurzer Erklärung, und viel Spaß wünschen mit der FotoCam
+- Verschiedene Hinweise anzeigen beim Fotofrafieren (lächeln, Hasensohren, Zunge raus, Grimasse, usw.)