From e06aede5cd9f9a45d47ca78fbed2af9a82735378 Mon Sep 17 00:00:00 2001 From: Tobias Wohlleben Date: Sat, 18 Jan 2025 10:19:15 +0100 Subject: [PATCH] wip --- .../.idea/.idea.CamBooth/.idea/vcs.xml | 1 + src/CamBooth/CamBooth.App/App.xaml | 8 + src/CamBooth/CamBooth.App/App.xaml.cs | 39 + src/CamBooth/CamBooth.App/AssemblyInfo.cs | 10 + src/CamBooth/CamBooth.App/CamBooth.App.csproj | 32 + .../CamBooth.App/Core/Logging/Logger.cs | 9 + .../DebugConsole/DebugConsolePage.xaml | 12 + .../DebugConsole/DebugConsolePage.xaml.cs | 11 + .../CamBooth.App/LiveView/LiveViewPage.xaml | 14 + .../LiveView/LiveViewPage.xaml.cs | 231 +++ .../CamBooth.App/LiveView/WrappingStream.cs | 120 ++ src/CamBooth/CamBooth.App/MainWindow.xaml | 43 + src/CamBooth/CamBooth.App/MainWindow.xaml.cs | 51 + src/CamBooth/CamBooth.sln | 12 + src/CamBooth/CamBooth.sln.DotSettings.user | 12 + src/CamBooth/EDSDKLib/API/Base/Camera.cs | 1569 ++++++++++++++++ src/CamBooth/EDSDKLib/API/Base/CanonAPI.cs | 337 ++++ src/CamBooth/EDSDKLib/API/Helper/ApiThread.cs | 25 + .../EDSDKLib/API/Helper/CameraValue.cs | 282 +++ src/CamBooth/EDSDKLib/API/Helper/Delegates.cs | 69 + .../EDSDKLib/API/Helper/ExceptionHandling.cs | 421 +++++ src/CamBooth/EDSDKLib/API/Helper/IO.cs | 554 ++++++ src/CamBooth/EDSDKLib/API/Helper/STAThread.cs | 324 ++++ .../EDSDKLib/API/Helper/ValueCollections.cs | 788 ++++++++ src/CamBooth/EDSDKLib/EDSDKLib.csproj | 65 + .../EDSDKLib/Properties/AssemblyInfo.cs | 15 + src/CamBooth/EDSDKLib/SDK/SDKDelegates.cs | 44 + src/CamBooth/EDSDKLib/SDK/SDKEnums.cs | 1572 ++++++++++++++++ src/CamBooth/EDSDKLib/SDK/SDKMethods.cs | 1521 ++++++++++++++++ src/CamBooth/EDSDKLib/SDK/SDKStructs.cs | 1622 +++++++++++++++++ 30 files changed, 9813 insertions(+) create mode 100644 src/CamBooth/CamBooth.App/App.xaml create mode 100644 src/CamBooth/CamBooth.App/App.xaml.cs create mode 100644 src/CamBooth/CamBooth.App/AssemblyInfo.cs create mode 100644 src/CamBooth/CamBooth.App/CamBooth.App.csproj create mode 100644 src/CamBooth/CamBooth.App/Core/Logging/Logger.cs create mode 100644 src/CamBooth/CamBooth.App/DebugConsole/DebugConsolePage.xaml create mode 100644 src/CamBooth/CamBooth.App/DebugConsole/DebugConsolePage.xaml.cs create mode 100644 src/CamBooth/CamBooth.App/LiveView/LiveViewPage.xaml create mode 100644 src/CamBooth/CamBooth.App/LiveView/LiveViewPage.xaml.cs create mode 100644 src/CamBooth/CamBooth.App/LiveView/WrappingStream.cs create mode 100644 src/CamBooth/CamBooth.App/MainWindow.xaml create mode 100644 src/CamBooth/CamBooth.App/MainWindow.xaml.cs create mode 100644 src/CamBooth/CamBooth.sln.DotSettings.user create mode 100644 src/CamBooth/EDSDKLib/API/Base/Camera.cs create mode 100644 src/CamBooth/EDSDKLib/API/Base/CanonAPI.cs create mode 100644 src/CamBooth/EDSDKLib/API/Helper/ApiThread.cs create mode 100644 src/CamBooth/EDSDKLib/API/Helper/CameraValue.cs create mode 100644 src/CamBooth/EDSDKLib/API/Helper/Delegates.cs create mode 100644 src/CamBooth/EDSDKLib/API/Helper/ExceptionHandling.cs create mode 100644 src/CamBooth/EDSDKLib/API/Helper/IO.cs create mode 100644 src/CamBooth/EDSDKLib/API/Helper/STAThread.cs create mode 100644 src/CamBooth/EDSDKLib/API/Helper/ValueCollections.cs create mode 100644 src/CamBooth/EDSDKLib/EDSDKLib.csproj create mode 100644 src/CamBooth/EDSDKLib/Properties/AssemblyInfo.cs create mode 100644 src/CamBooth/EDSDKLib/SDK/SDKDelegates.cs create mode 100644 src/CamBooth/EDSDKLib/SDK/SDKEnums.cs create mode 100644 src/CamBooth/EDSDKLib/SDK/SDKMethods.cs create mode 100644 src/CamBooth/EDSDKLib/SDK/SDKStructs.cs diff --git a/src/CamBooth/.idea/.idea.CamBooth/.idea/vcs.xml b/src/CamBooth/.idea/.idea.CamBooth/.idea/vcs.xml index 94a25f7..fdf1fc8 100644 --- a/src/CamBooth/.idea/.idea.CamBooth/.idea/vcs.xml +++ b/src/CamBooth/.idea/.idea.CamBooth/.idea/vcs.xml @@ -1,6 +1,7 @@ + \ No newline at end of file diff --git a/src/CamBooth/CamBooth.App/App.xaml b/src/CamBooth/CamBooth.App/App.xaml new file mode 100644 index 0000000..7bb60b2 --- /dev/null +++ b/src/CamBooth/CamBooth.App/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/src/CamBooth/CamBooth.App/App.xaml.cs b/src/CamBooth/CamBooth.App/App.xaml.cs new file mode 100644 index 0000000..3b3fb3e --- /dev/null +++ b/src/CamBooth/CamBooth.App/App.xaml.cs @@ -0,0 +1,39 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +using CamBooth.App.Core.Logging; +using CamBooth.App.LiveView; + +using Microsoft.Extensions.DependencyInjection; + +namespace CamBooth.App; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ + private IServiceProvider _serviceProvider; + + protected override void OnStartup(StartupEventArgs e) + { + base.OnStartup(e); + + var services = new ServiceCollection(); + ConfigureServices(services); + + _serviceProvider = services.BuildServiceProvider(); + + var mainWindow = _serviceProvider.GetRequiredService(); + mainWindow.Show(); + } + + private void ConfigureServices(IServiceCollection services) + { + // Register your services and view models here + services.AddTransient(); + services.AddTransient(); + services.AddSingleton(); + } +} \ No newline at end of file diff --git a/src/CamBooth/CamBooth.App/AssemblyInfo.cs b/src/CamBooth/CamBooth.App/AssemblyInfo.cs new file mode 100644 index 0000000..9c66932 --- /dev/null +++ b/src/CamBooth/CamBooth.App/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/src/CamBooth/CamBooth.App/CamBooth.App.csproj b/src/CamBooth/CamBooth.App/CamBooth.App.csproj new file mode 100644 index 0000000..e18bb52 --- /dev/null +++ b/src/CamBooth/CamBooth.App/CamBooth.App.csproj @@ -0,0 +1,32 @@ + + + + WinExe + net8.0-windows + enable + enable + true + + + + x86 + + + + x86 + + + + + + + + + + + + + + + + diff --git a/src/CamBooth/CamBooth.App/Core/Logging/Logger.cs b/src/CamBooth/CamBooth.App/Core/Logging/Logger.cs new file mode 100644 index 0000000..c58d2ef --- /dev/null +++ b/src/CamBooth/CamBooth.App/Core/Logging/Logger.cs @@ -0,0 +1,9 @@ +namespace CamBooth.App.Core.Logging; + +public class Logger +{ + public void LogInfo(string message) + { + Console.WriteLine(message); + } +} \ No newline at end of file diff --git a/src/CamBooth/CamBooth.App/DebugConsole/DebugConsolePage.xaml b/src/CamBooth/CamBooth.App/DebugConsole/DebugConsolePage.xaml new file mode 100644 index 0000000..02cbb96 --- /dev/null +++ b/src/CamBooth/CamBooth.App/DebugConsole/DebugConsolePage.xaml @@ -0,0 +1,12 @@ + + + Debug Console + + diff --git a/src/CamBooth/CamBooth.App/DebugConsole/DebugConsolePage.xaml.cs b/src/CamBooth/CamBooth.App/DebugConsole/DebugConsolePage.xaml.cs new file mode 100644 index 0000000..ff8db54 --- /dev/null +++ b/src/CamBooth/CamBooth.App/DebugConsole/DebugConsolePage.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace CamBooth.App.DebugConsole; + +public partial class DebugConsolePage : Page +{ + public DebugConsolePage() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/src/CamBooth/CamBooth.App/LiveView/LiveViewPage.xaml b/src/CamBooth/CamBooth.App/LiveView/LiveViewPage.xaml new file mode 100644 index 0000000..905a072 --- /dev/null +++ b/src/CamBooth/CamBooth.App/LiveView/LiveViewPage.xaml @@ -0,0 +1,14 @@ + + + LiveView CamBooth + + + diff --git a/src/CamBooth/CamBooth.App/LiveView/LiveViewPage.xaml.cs b/src/CamBooth/CamBooth.App/LiveView/LiveViewPage.xaml.cs new file mode 100644 index 0000000..9478369 --- /dev/null +++ b/src/CamBooth/CamBooth.App/LiveView/LiveViewPage.xaml.cs @@ -0,0 +1,231 @@ +using System.IO; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +using EOSDigital.API; +using EOSDigital.SDK; + +namespace CamBooth.App.LiveView; + +public partial class LiveViewPage : Page +{ + CanonAPI APIHandler; + + Camera MainCamera; + + CameraValue[] AvList; + + CameraValue[] TvList; + + CameraValue[] ISOList; + + List CamList; + + bool IsInit = false; + + int BulbTime = 30; + + ImageBrush bgbrush = new ImageBrush(); + + Action SetImageAction; + + int ErrCount; + + object ErrLock = new object(); + + + public LiveViewPage() + { + try + { + InitializeComponent(); + APIHandler = new CanonAPI(); + APIHandler.CameraAdded += APIHandler_CameraAdded; + ErrorHandler.SevereErrorHappened += ErrorHandler_SevereErrorHappened; + ErrorHandler.NonSevereErrorHappened += ErrorHandler_NonSevereErrorHappened; + //SavePathTextBox.Text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "RemotePhoto"); + SetImageAction = (BitmapImage img) => { bgbrush.ImageSource = img; }; + RefreshCamera(); + IsInit = true; + } + catch (DllNotFoundException) + { + ReportError("Canon DLLs not found!", true); + } + catch (Exception ex) + { + ReportError(ex.Message, true); + } + } + + + private void CloseSession() + { + MainCamera.CloseSession(); + // AvCoBox.Items.Clear(); + // TvCoBox.Items.Clear(); + // ISOCoBox.Items.Clear(); + // SettingsGroupBox.IsEnabled = false; + // LiveViewGroupBox.IsEnabled = false; + // SessionButton.Content = "Open Session"; + // SessionLabel.Content = "No open session"; + // StarLVButton.Content = "Start LV"; + } + + private void RefreshCamera() + { + // CameraListBox.Items.Clear(); + CamList = APIHandler.GetCameraList(); + // foreach (Camera cam in CamList) CameraListBox.Items.Add(cam.DeviceName); + // if (MainCamera?.SessionOpen == true) CameraListBox.SelectedIndex = CamList.FindIndex(t => t.ID == MainCamera.ID); + // else if (CamList.Count > 0) CameraListBox.SelectedIndex = 0; + } + + private void OpenSession() + { + + MainCamera = CamList[0]; + MainCamera.OpenSession(); + MainCamera.LiveViewUpdated += MainCamera_LiveViewUpdated; + MainCamera.ProgressChanged += MainCamera_ProgressChanged; + MainCamera.StateChanged += MainCamera_StateChanged; + MainCamera.DownloadReady += MainCamera_DownloadReady; + + + //SessionLabel.Content = MainCamera.DeviceName; + AvList = MainCamera.GetSettingsList(PropertyID.Av); + TvList = MainCamera.GetSettingsList(PropertyID.Tv); + ISOList = MainCamera.GetSettingsList(PropertyID.ISO); + // foreach (var Av in AvList) AvCoBox.Items.Add(Av.StringValue); + // foreach (var Tv in TvList) TvCoBox.Items.Add(Tv.StringValue); + // foreach (var ISO in ISOList) ISOCoBox.Items.Add(ISO.StringValue); + // AvCoBox.SelectedIndex = AvCoBox.Items.IndexOf(AvValues.GetValue(MainCamera.GetInt32Setting(PropertyID.Av)).StringValue); + // TvCoBox.SelectedIndex = TvCoBox.Items.IndexOf(TvValues.GetValue(MainCamera.GetInt32Setting(PropertyID.Tv)).StringValue); + // ISOCoBox.SelectedIndex = ISOCoBox.Items.IndexOf(ISOValues.GetValue(MainCamera.GetInt32Setting(PropertyID.ISO)).StringValue); + // SettingsGroupBox.IsEnabled = true; + // LiveViewGroupBox.IsEnabled = true; + + } + + private void ReportError(string message, bool lockdown) + { + int errc; + lock (ErrLock) { errc = ++ErrCount; } + + if (lockdown) EnableUI(false); + + if (errc < 4) MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); + else if (errc == 4) MessageBox.Show("Many errors happened!", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + + lock (ErrLock) { ErrCount--; } + } + + private void EnableUI(bool enable) + { + if (!Dispatcher.CheckAccess()) Dispatcher.Invoke((Action)delegate { EnableUI(enable); }); + else + { + // SettingsGroupBox.IsEnabled = enable; + // InitGroupBox.IsEnabled = enable; + // LiveViewGroupBox.IsEnabled = enable; + } + } + + #region API Events + + private void APIHandler_CameraAdded(CanonAPI sender) + { + try + { + + } + catch (Exception ex) + { + ReportError(ex.Message, false); + } + } + + + private void MainCamera_StateChanged(Camera sender, StateEventID eventID, int parameter) + { + try + { + if (eventID == StateEventID.Shutdown && IsInit) + { + Dispatcher.Invoke((Action)delegate { CloseSession(); }); + } + } + catch (Exception ex) + { + ReportError(ex.Message, false); + } + } + + + private void MainCamera_ProgressChanged(object sender, int progress) + { + try + { + //MainProgressBar.Dispatcher.Invoke((Action)delegate { MainProgressBar.Value = progress; }); + } + catch (Exception ex) + { + ReportError(ex.Message, false); + } + } + + + private void MainCamera_LiveViewUpdated(Camera sender, Stream img) + { + try + { + using (WrapStream s = new WrapStream(img)) + { + img.Position = 0; + BitmapImage EvfImage = new BitmapImage(); + EvfImage.BeginInit(); + EvfImage.StreamSource = s; + EvfImage.CacheOption = BitmapCacheOption.OnLoad; + EvfImage.EndInit(); + EvfImage.Freeze(); + Application.Current.Dispatcher.BeginInvoke(SetImageAction, EvfImage); + } + } + catch (Exception ex) + { + ReportError(ex.Message, false); + } + } + + + private void MainCamera_DownloadReady(Camera sender, DownloadInfo Info) + { + try + { + string dir = null; + //SavePathTextBox.Dispatcher.Invoke((Action)delegate { dir = SavePathTextBox.Text; }); + sender.DownloadFile(Info, dir); + //MainProgressBar.Dispatcher.Invoke((Action)delegate { MainProgressBar.Value = 0; }); + } + catch (Exception ex) + { + ReportError(ex.Message, false); + } + } + + + private void ErrorHandler_NonSevereErrorHappened(object sender, ErrorCode ex) + { + ReportError($"SDK Error code: {ex} ({((int)ex).ToString("X")})", false); + } + + + private void ErrorHandler_SevereErrorHappened(object sender, Exception ex) + { + ReportError(ex.Message, true); + } + + #endregion +} \ No newline at end of file diff --git a/src/CamBooth/CamBooth.App/LiveView/WrappingStream.cs b/src/CamBooth/CamBooth.App/LiveView/WrappingStream.cs new file mode 100644 index 0000000..bba5fcb --- /dev/null +++ b/src/CamBooth/CamBooth.App/LiveView/WrappingStream.cs @@ -0,0 +1,120 @@ + +using System.IO; + +namespace CamBooth.App.LiveView +{ + /// + /// A stream that does nothing more but wrap another stream (needed for a WPF memory leak) + /// + public sealed class WrapStream : Stream + { + /// + /// Gets a value indicating whether the current stream supports reading. + /// + public override bool CanRead + { + get { return this.Base.CanRead; } + } + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek + { + get { return this.Base.CanSeek; } + } + /// + /// Gets a value indicating whether the current stream supports writing. + /// + public override bool CanWrite + { + get { return this.Base.CanWrite; } + } + /// + /// Gets the length in bytes of the stream. + /// + public override long Length + { + get { return this.Base.Length; } + } + /// + /// Gets or sets the position within the current stream. + /// + public override long Position + { + get { return this.Base.Position; } + set { this.Base.Position = value; } + } + + private Stream Base; + + /// + /// Creates a new instance of the class. + /// + /// The stream that gets wrapped + public WrapStream(Stream inStream) + { + this.Base = inStream; + } + + /// + /// reads a sequence of bytes from the current stream and advances + /// the position within the stream by the number of bytes read. + /// + /// An array of bytes. When this method returns, the buffer contains the specified + /// byte array with the values between offset and (offset + count - 1) replaced + /// by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read + /// from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// The total number of bytes read into the buffer. This can be less than the + /// number of bytes requested if that many bytes are not currently available, + /// or zero (0) if the end of the stream has been reached. + public override int Read(byte[] buffer, int offset, int count) + { + return this.Base.Read(buffer, offset, count); + } + + /// + /// When overridden in a derived class, writes a sequence of bytes to the current + /// stream and advances the current position within this stream by the number + /// of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the + /// current stream. + /// The number of bytes to be written to the current stream. + public override void Write(byte[] buffer, int offset, int count) + { + this.Base.Write(buffer, offset, count); + } + + /// + /// sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type System.IO.SeekOrigin indicating the reference point used + /// to obtain the new position. + /// The new position within the current stream. + public override long Seek(long offset, System.IO.SeekOrigin origin) + { + return this.Base.Seek(offset, origin); + } + + /// + /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. + /// + public override void Flush() + { + this.Base.Flush(); + } + + /// + /// Sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + public override void SetLength(long value) + { + this.Base.SetLength(value); + } + } +} \ No newline at end of file diff --git a/src/CamBooth/CamBooth.App/MainWindow.xaml b/src/CamBooth/CamBooth.App/MainWindow.xaml new file mode 100644 index 0000000..14b3e6c --- /dev/null +++ b/src/CamBooth/CamBooth.App/MainWindow.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + +